Merged CMIS063 to HEAD

16930: MOB-1330: Upgrade Web Services Repository to 0.7

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@17243 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
David Caruana
2009-10-29 18:40:59 +00:00
parent 93346e262e
commit d6b8ce91a5
203 changed files with 10223 additions and 6060 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2008 Alfresco Software Limited.
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -27,6 +27,7 @@ package org.alfresco.repo.cmis.ws;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import javax.activation.DataSource;
@@ -39,53 +40,141 @@ import org.alfresco.service.cmr.repository.ContentReader;
*/
public class ContentReaderDataSource implements DataSource
{
private ContentReader contentReader;
private String mimetype;
private InputStream inputStream;
private String name;
private long offset = 0;
private long length = Long.MAX_VALUE / 2;
private long sizeToRead = 0;
public ContentReaderDataSource(ContentReader contentReader, String name)
{
this.contentReader = contentReader;
public ContentReaderDataSource(ContentReader contentReader, String name, BigInteger offset, BigInteger length, long contentSize)
{
this.name = name;
this.mimetype = contentReader.getMimetype();
if (offset != null)
{
this.offset = offset.longValue();
}
if (length != null)
{
this.length = length.longValue();
}
if (this.offset + this.length < contentSize)
{
this.sizeToRead = this.length;
}
else
{
this.sizeToRead = contentSize - this.offset;
}
if (this.sizeToRead < 0)
{
throw new RuntimeException("Offset value exceeds content size");
}
try
{
inputStream = new RangedInputStream(contentReader.getContentInputStream());
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
/*
* (non-Javadoc)
*
* @see javax.activation.DataSource#getContentType()
*/
public String getContentType()
{
return contentReader.getMimetype();
return mimetype;
}
/*
* (non-Javadoc)
*
* @see javax.activation.DataSource#getInputStream()
*/
public InputStream getInputStream() throws IOException
{
return contentReader.getContentInputStream();
return inputStream;
}
/*
* (non-Javadoc)
*
* @see javax.activation.DataSource#getName()
*/
public String getName()
{
return name;
}
/*
* (non-Javadoc)
*
* @see javax.activation.DataSource#getOutputStream()
*/
public OutputStream getOutputStream() throws IOException
{
return null;
}
public long getSizeToRead()
{
return sizeToRead;
}
private class RangedInputStream extends InputStream
{
private InputStream inputStream;
private int bytesread;
private RangedInputStream(InputStream inputStream) throws IOException
{
super();
this.inputStream = inputStream;
this.inputStream.skip(offset);
this.bytesread = 0;
}
@Override
public int read() throws IOException
{
if (bytesread < sizeToRead)
{
bytesread++;
return inputStream.read();
}
else
{
return -1;
}
}
@Override
public int read(byte[] b) throws IOException
{
return read(b, 0, b.length);
}
@Override
public int read(byte[] b, int off, int len) throws IOException
{
if (len > sizeToRead - bytesread)
{
len = (int)(sizeToRead - bytesread);
}
int readed = inputStream.read(b, off, len);
bytesread += readed;
return readed;
}
@Override
public int available() throws IOException
{
return (int)(sizeToRead - bytesread + 1);
}
@Override
public void close() throws IOException
{
inputStream.close();
}
@Override
public long skip(long n) throws IOException
{
if (bytesread + n > sizeToRead)
{
n = (sizeToRead - n) > 0 ? (sizeToRead - n) : sizeToRead - bytesread;
}
n = inputStream.skip(n);
bytesread += n;
return n;
}
}
}

View File

@@ -46,9 +46,12 @@ import org.alfresco.repo.web.util.paging.Page;
import org.alfresco.repo.web.util.paging.Paging;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.cmr.version.VersionType;
@@ -82,6 +85,7 @@ public class DMAbstractServicePort
protected SearchService searchService;
protected CmisObjectsUtils cmisObjectsUtils;
protected PropertyUtil propertiesUtil;
protected PermissionService permissionService;
public void setCmisService(CMISServices cmisService)
{
@@ -139,6 +143,11 @@ public class DMAbstractServicePort
this.searchService = searchService;
}
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
}
protected PropertyFilter createPropertyFilter(String filter) throws CmisException
{
return (filter == null) ? (new PropertyFilter()) : (new PropertyFilter(filter, cmisObjectsUtils));
@@ -168,11 +177,11 @@ public class DMAbstractServicePort
* @param resultList the list of <b>CmisObjectType</b> values for end response result collecting
* @throws CmisException
*/
protected void createCmisObjectList(PropertyFilter filter, List<NodeRef> sourceList, List<CmisObjectType> resultList) throws CmisException
protected void createCmisObjectList(PropertyFilter filter, boolean includeAllowableActions, List<NodeRef> sourceList, List<CmisObjectType> resultList) throws CmisException
{
for (NodeRef objectNodeRef : sourceList)
{
resultList.add(createCmisObject(objectNodeRef, filter));
resultList.add(createCmisObject(objectNodeRef, filter, includeAllowableActions));
}
}
@@ -183,10 +192,14 @@ public class DMAbstractServicePort
* @param filter accepted properties filter
* @return converted to CMIS object Alfresco object
*/
protected CmisObjectType createCmisObject(Object identifier, PropertyFilter filter) throws CmisException
protected CmisObjectType createCmisObject(Object identifier, PropertyFilter filter, boolean includeAllowableActions) throws CmisException
{
CmisObjectType result = new CmisObjectType();
result.setProperties(propertiesUtil.getPropertiesType(identifier.toString(), filter));
if (includeAllowableActions)
{
result.setAllowableActions(determineObjectAllowableActions(identifier));
}
return result;
}
@@ -246,4 +259,87 @@ public class DMAbstractServicePort
throw new CmisException(("Invalid typeId " + typeId), cmisObjectsUtils.createCmisException(("Invalid typeId " + typeId), EnumServiceException.INVALID_ARGUMENT));
}
}
protected CmisAllowableActionsType determineObjectAllowableActions(Object objectIdentifier) throws CmisException
{
if (objectIdentifier instanceof AssociationRef)
{
return determineRelationshipAllowableActions((AssociationRef) objectIdentifier);
}
switch (cmisObjectsUtils.determineObjectType(objectIdentifier.toString()))
{
case CMIS_DOCUMENT:
{
return determineDocumentAllowableActions((NodeRef) objectIdentifier);
}
case CMIS_FOLDER:
{
return determineFolderAllowableActions((NodeRef) objectIdentifier);
}
}
// TODO: determinePolicyAllowableActions() when Policy functionality is ready
throw cmisObjectsUtils.createCmisException("It is impossible to get Allowable actions for the specified Object", EnumServiceException.NOT_SUPPORTED);
}
private CmisAllowableActionsType determineBaseAllowableActions(NodeRef objectNodeReference)
{
CmisAllowableActionsType result = new CmisAllowableActionsType();
result.setCanGetProperties(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_PROPERTIES) == AccessStatus.ALLOWED);
result.setCanUpdateProperties(this.permissionService.hasPermission(objectNodeReference, PermissionService.WRITE_PROPERTIES) == AccessStatus.ALLOWED);
result.setCanDeleteObject(this.permissionService.hasPermission(objectNodeReference, PermissionService.DELETE) == AccessStatus.ALLOWED);
// TODO: response.setCanAddPolicy(value);
// TODO: response.setCanRemovePolicy(value);
// TODO: response.setCanGetAppliedPolicies(value);
return result;
}
private CmisAllowableActionsType determineDocumentAllowableActions(NodeRef objectNodeReference)
{
CmisAllowableActionsType result = determineBaseAllowableActions(objectNodeReference);
determineCommonFolderDocumentAllowableActions(objectNodeReference, result);
result.setCanGetObjectParents(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_ASSOCIATIONS) == AccessStatus.ALLOWED);
result.setCanGetContentStream(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_CONTENT) == AccessStatus.ALLOWED);
result.setCanSetContentStream(this.permissionService.hasPermission(objectNodeReference, PermissionService.WRITE_CONTENT) == AccessStatus.ALLOWED);
result.setCanCheckOut(this.permissionService.hasPermission(objectNodeReference, PermissionService.CHECK_OUT) == AccessStatus.ALLOWED);
result.setCanCheckIn(this.permissionService.hasPermission(objectNodeReference, PermissionService.CHECK_IN) == AccessStatus.ALLOWED);
result.setCanCancelCheckOut(this.permissionService.hasPermission(objectNodeReference, PermissionService.CANCEL_CHECK_OUT) == AccessStatus.ALLOWED);
result.setCanDeleteContentStream(result.isCanUpdateProperties() && result.isCanSetContentStream());
return result;
}
private CmisAllowableActionsType determineFolderAllowableActions(NodeRef objectNodeReference)
{
CmisAllowableActionsType result = determineBaseAllowableActions(objectNodeReference);
determineCommonFolderDocumentAllowableActions(objectNodeReference, result);
result.setCanGetChildren(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_CHILDREN) == AccessStatus.ALLOWED);
result.setCanCreateDocument(this.permissionService.hasPermission(objectNodeReference, PermissionService.ADD_CHILDREN) == AccessStatus.ALLOWED);
result.setCanGetDescendants(result.isCanGetChildren() && (this.permissionService.hasPermission(objectNodeReference, PermissionService.READ) == AccessStatus.ALLOWED));
result.setCanDeleteTree(this.permissionService.hasPermission(objectNodeReference, PermissionService.DELETE_CHILDREN) == AccessStatus.ALLOWED);
result.setCanGetFolderParent(result.isCanGetObjectRelationships());
result.setCanCreateFolder(result.isCanCreateDocument());
// TODO: response.setCanCreatePolicy(value);
return result;
}
private void determineCommonFolderDocumentAllowableActions(NodeRef objectNodeReference, CmisAllowableActionsType allowableActions)
{
allowableActions.setCanAddObjectToFolder(this.permissionService.hasPermission(objectNodeReference, PermissionService.CREATE_ASSOCIATIONS) == AccessStatus.ALLOWED);
allowableActions.setCanGetObjectRelationships(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_ASSOCIATIONS) == AccessStatus.ALLOWED);
allowableActions.setCanMoveObject(allowableActions.isCanUpdateProperties() && allowableActions.isCanAddObjectToFolder());
allowableActions.setCanRemoveObjectFromFolder(allowableActions.isCanUpdateProperties());
allowableActions.setCanCreateRelationship(allowableActions.isCanAddObjectToFolder());
}
private CmisAllowableActionsType determineRelationshipAllowableActions(AssociationRef association)
{
CmisAllowableActionsType result = new CmisAllowableActionsType();
result.setCanDeleteObject(this.permissionService.hasPermission(association.getSourceRef(), PermissionService.DELETE_ASSOCIATIONS) == AccessStatus.ALLOWED);
result.setCanGetObjectRelationships(this.permissionService.hasPermission(association.getSourceRef(), PermissionService.READ_ASSOCIATIONS) == AccessStatus.ALLOWED);
return result;
}
}

View File

@@ -24,14 +24,10 @@
*/
package org.alfresco.repo.cmis.ws;
import java.util.List;
import javax.xml.ws.Holder;
/**
* @author Dmitry Velichkevich
*/
@javax.jws.WebService(name = "ACLServicePort", serviceName = "ACLService", portName = "ACLServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200901", endpointInterface = "org.alfresco.repo.cmis.ws.ACLServicePort")
@javax.jws.WebService(name = "ACLServicePort", serviceName = "ACLService", portName = "ACLServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200908/", endpointInterface = "org.alfresco.repo.cmis.ws.ACLServicePort")
public class DMAclServicePort extends DMAbstractServicePort implements ACLServicePort
{
private static final String ACL_SERVICE_NOT_IMPLEMENTED_MESSAGE = "ACLService not implemented";
@@ -40,13 +36,13 @@ public class DMAclServicePort extends DMAbstractServicePort implements ACLServic
{
}
public void applyACL(String repositoryId, String objectId, CmisAccessControlListType addACEs, CmisAccessControlListType removeACEs, EnumACLPropagation propogationType,
Holder<List<CmisAccessControlListType>> acl, Holder<Boolean> exact) throws CmisException
public CmisACLType applyACL(String repositoryId, String objectId, CmisAccessControlListType addACEs, CmisAccessControlListType removeACEs, EnumACLPropagation aclPropagation,
CmisExtensionType extension) throws CmisException
{
throw cmisObjectsUtils.createCmisException(ACL_SERVICE_NOT_IMPLEMENTED_MESSAGE, EnumServiceException.RUNTIME);
}
public CmisAccessControlListType getACL(String repositoryId, String objectId, boolean onlyBasicPermissions) throws CmisException
public CmisACLType getACL(String repositoryId, String objectId, Boolean onlyBasicPermissions, CmisExtensionType extension) throws CmisException
{
throw cmisObjectsUtils.createCmisException(ACL_SERVICE_NOT_IMPLEMENTED_MESSAGE, EnumServiceException.RUNTIME);
}

View File

@@ -26,22 +26,23 @@ package org.alfresco.repo.cmis.ws;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import javax.xml.ws.Holder;
import org.alfresco.cmis.CMISDictionaryModel;
import org.alfresco.cmis.CMISQueryOptions;
import org.alfresco.cmis.CMISResultSet;
import org.alfresco.cmis.CMISResultSetColumn;
import org.alfresco.cmis.CMISResultSetRow;
import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType;
/**
* Port for Discovery service.
*
* @author Dmitry Lazurkin
*/
@javax.jws.WebService(name = "DiscoveryServicePort", serviceName = "DiscoveryService", portName = "DiscoveryServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200901", endpointInterface = "org.alfresco.repo.cmis.ws.DiscoveryServicePort")
@javax.jws.WebService(name = "DiscoveryServicePort", serviceName = "DiscoveryService", portName = "DiscoveryServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200908/", endpointInterface = "org.alfresco.repo.cmis.ws.DiscoveryServicePort")
public class DMDiscoveryServicePort extends DMAbstractServicePort implements DiscoveryServicePort
{
/**
@@ -58,15 +59,16 @@ public class DMDiscoveryServicePort extends DMAbstractServicePort implements Dis
// TODO: searchAllVersions, includeRelationships, includeAllowableActions, includeRenditions
CMISQueryOptions options = new CMISQueryOptions(parameters.getStatement(), cmisService.getDefaultRootStoreRef());
if (parameters.getSkipCount() != null)
if (parameters.getSkipCount() != null && parameters.getSkipCount().getValue() != null)
{
options.setSkipCount(parameters.getSkipCount().intValue());
options.setSkipCount(parameters.getSkipCount().getValue().intValue());
}
if (parameters.getMaxItems() != null)
if (parameters.getMaxItems() != null && parameters.getMaxItems().getValue() != null)
{
options.setMaxItems(parameters.getMaxItems().intValue());
options.setMaxItems(parameters.getMaxItems().getValue().intValue());
}
boolean includeAllowableActions = (null != parameters.getIncludeAllowableActions()) ? (parameters.getIncludeAllowableActions().getValue()) : (false);
// execute query
// TODO: If the select clause includes properties from more than a single type reference, then the repository SHOULD throw an exception if includeRelationships or
@@ -76,6 +78,7 @@ public class DMDiscoveryServicePort extends DMAbstractServicePort implements Dis
// build query response
QueryResponse response = new QueryResponse();
response.setObjects(new CmisObjectListType());
// for each row...
for (CMISResultSetRow row : resultSet)
@@ -95,17 +98,23 @@ public class DMDiscoveryServicePort extends DMAbstractServicePort implements Dis
CmisObjectType object = new CmisObjectType();
object.setProperties(properties);
response.getObject().add(object);
if (includeAllowableActions)
{
Object identifier = cmisObjectsUtils.getIdentifierInstance((String) values.get(CMISDictionaryModel.PROP_OBJECT_ID), AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT);
object.setAllowableActions(determineObjectAllowableActions(identifier));
}
response.getObjects().getObjects().add(object);
}
response.setHasMoreItems(resultSet.hasMore());
//TODO: response.getObjects().setNumItems(value);
response.getObjects().setHasMoreItems(resultSet.hasMore());
return response;
}
public void getContentChanges(String repositoryId, Holder<String> changeToken, BigInteger maxItems, Boolean includeACL, Boolean includeProperties, String filter,
Holder<List<CmisObjectType>> changedObject) throws CmisException
public void getContentChanges(String repositoryId, Holder<String> changeLogToken, Boolean includeProperties, String filter, Boolean includePolicyIds, Boolean includeACL,
BigInteger maxItems, CmisExtensionType extension, Holder<CmisObjectListType> objects) throws CmisException
{
// TODO
// TODO: implement me
throw cmisObjectsUtils.createCmisException("Not implemented", EnumServiceException.RUNTIME);
}
}

View File

@@ -24,6 +24,8 @@
*/
package org.alfresco.repo.cmis.ws;
import javax.xml.ws.Holder;
import org.alfresco.cmis.CMISDictionaryModel;
import org.alfresco.cmis.CMISTypeDefinition;
import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType;
@@ -35,7 +37,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
* @author Dmitry Lazurkin
* @author Dmitry Velichkevich
*/
@javax.jws.WebService(name = "MultiFilingServicePort", serviceName = "MultiFilingService", portName = "MultiFilingServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200901", endpointInterface = "org.alfresco.repo.cmis.ws.MultiFilingServicePort")
@javax.jws.WebService(name = "MultiFilingServicePort", serviceName = "MultiFilingService", portName = "MultiFilingServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200908/", endpointInterface = "org.alfresco.repo.cmis.ws.MultiFilingServicePort")
public class DMMultiFilingServicePort extends DMAbstractServicePort implements MultiFilingServicePort
{
/**
@@ -46,26 +48,28 @@ public class DMMultiFilingServicePort extends DMAbstractServicePort implements M
* @param folderId folder Id to which the object is added
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT)
*/
public void addObjectToFolder(String repositoryId, String objectId, String folderId) throws CmisException
public void addObjectToFolder(String repositoryId, String objectId, String folderId, Boolean allVersions, Holder<CmisExtensionType> extension) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef objectNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT);
NodeRef parentFolderNodeRef = cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT);
CMISTypeDefinition objectType = cmisDictionaryService.findType(propertiesUtil.getProperty(objectNodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, (String) null));
CMISTypeDefinition folderType = cmisDictionaryService.findType(propertiesUtil.getProperty(parentFolderNodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, (String) null));
if (folderType == null)
{
throw cmisObjectsUtils.createCmisException("Type of the specified parent folder can't be resovled", EnumServiceException.RUNTIME);
}
if (!folderType.getAllowedTargetTypes().isEmpty() && !folderType.getAllowedTargetTypes().contains(objectType))
{
throw cmisObjectsUtils.createCmisException("The typeId of Object is not in the list of AllowedChildObjectTypeIds of the parent-folder specified by folderId",
throw cmisObjectsUtils.createCmisException(("The Object of '" + objectType.getTypeId() + "' Type can't be child of Folder of '" + folderType.getTypeId() + "' Type"),
EnumServiceException.CONSTRAINT);
}
cmisObjectsUtils.addObjectToFolder(objectNodeRef, parentFolderNodeRef);
if (!cmisObjectsUtils.addObjectToFolder(objectNodeRef, parentFolderNodeRef))
{
Throwable exception = cmisObjectsUtils.getLastOperationException();
throw cmisObjectsUtils.createCmisException(("Can't add specified Object to specified Folder. Cause exception message: " + exception.toString()),
EnumServiceException.STORAGE, exception);
}
}
/**
@@ -76,19 +80,19 @@ public class DMMultiFilingServicePort extends DMAbstractServicePort implements M
* @param folderId The folder to be removed from.
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME)
*/
public void removeObjectFromFolder(String repositoryId, String objectId, String folderId) throws CmisException
public void removeObjectFromFolder(String repositoryId, String objectId, String folderId, Holder<CmisExtensionType> extension) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef objectNodeReference = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT);
NodeRef folderNodeReference = checkAndReceiveFolderIdentifier(folderId);
assertExistFolder(folderNodeReference);
// FIXME [BUG]: if Document is Multi-Filled then removing this Object from Primary Parent Folder MUST treat to determine Primary Parent for Document from other Parent
// Folders
checkObjectChildParentRelationships(objectNodeReference, folderNodeReference);
if (!cmisObjectsUtils.removeObject(objectNodeReference, folderNodeReference))
{
throw cmisObjectsUtils.createCmisException("The specified Object is not child of the specified Folder Object", EnumServiceException.INVALID_ARGUMENT);
Throwable exception = cmisObjectsUtils.getLastOperationException();
throw cmisObjectsUtils.createCmisException(("Can't remove specified Object from specified Folder. Cause exception message: " + exception.toString()),
EnumServiceException.STORAGE, exception);
}
}
@@ -108,7 +112,7 @@ public class DMMultiFilingServicePort extends DMAbstractServicePort implements M
{
if (cmisObjectsUtils.isPrimaryObjectParent(folderNodeReference, objectNodeReference))
{
throw cmisObjectsUtils.createCmisException("Unfiling is not supported. Use deleteObjectService instead", EnumServiceException.NOT_SUPPORTED);
throw cmisObjectsUtils.createCmisException("Unfiling is not supported. Use deleteObject() Service instead", EnumServiceException.NOT_SUPPORTED);
}
}
}

View File

@@ -26,13 +26,11 @@ package org.alfresco.repo.cmis.ws;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
import java.util.regex.Pattern;
import javax.xml.ws.Holder;
import org.alfresco.cmis.CMISDictionaryModel;
import org.alfresco.cmis.CMISTypesFilterEnum;
import org.alfresco.repo.cmis.PropertyFilter;
@@ -43,15 +41,13 @@ import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.Pair;
import com.sun.star.auth.InvalidArgumentException;
/**
* Port for navigation service
*
*
* @author Dmitry Lazurkin
* @author Dmitry Velichkevich
*/
@javax.jws.WebService(name = "NavigationServicePort", serviceName = "NavigationService", portName = "NavigationServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200901", endpointInterface = "org.alfresco.repo.cmis.ws.NavigationServicePort")
@javax.jws.WebService(name = "NavigationServicePort", serviceName = "NavigationService", portName = "NavigationServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200908/", endpointInterface = "org.alfresco.repo.cmis.ws.NavigationServicePort")
public class DMNavigationServicePort extends DMAbstractServicePort implements NavigationServicePort
{
private static final int EQUALS_CONDITION_VALUE = 0;
@@ -69,9 +65,8 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
* skipCount: 0 = start at beginning
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, FILTER_NOT_VALID)
*/
public void getCheckedOutDocs(String repositoryId, String folderId, String filter, String orderBy, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, BigInteger maxItems, BigInteger skipCount, Holder<List<CmisObjectType>> object, Holder<Boolean> hasMoreItems)
throws CmisException
public CmisObjectListType getCheckedOutDocs(String repositoryId, String folderId, String filter, String orderBy, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, String renditionFilter, BigInteger maxItems, BigInteger skipCount, CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
PropertyFilter propertyFilter = createPropertyFilter(filter);
@@ -93,18 +88,18 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
NodeRef[] nodeRefs = cmisService.getCheckedOut(AuthenticationUtil.getFullyAuthenticatedUser(), folderRef, (folderRef == null));
Cursor cursor = createCursor(nodeRefs.length, skipCount, maxItems);
object.value = new ArrayList<CmisObjectType>();
List<CmisObjectType> resultListing = object.value;
CmisObjectListType result = new CmisObjectListType();
List<CmisObjectType> resultListing = result.getObjects();
for (int index = cursor.getStartRow(); index <= cursor.getEndRow(); index++)
{
resultListing.add(createCmisObject(nodeRefs[index].toString(), propertyFilter));
resultListing.add(createCmisObject(nodeRefs[index].toString(), propertyFilter, includeAllowableActions));
}
result.setHasMoreItems(new Boolean(cursor.getEndRow() < (nodeRefs.length - 1)));
hasMoreItems.value = new Boolean(cursor.getEndRow() < (nodeRefs.length - 1));
// TODO: includeAllowableActions, includeRelationships
// TODO: includeAllowableActions, includeRelationships, renditions
return result;
}
/**
@@ -116,9 +111,9 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
* @return collection of CmisObjectType and boolean hasMoreItems
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, FILTER_NOT_VALID)
*/
public void getChildren(String repositoryId, String folderId, String filter, Boolean includeAllowableActions, EnumIncludeRelationships includeRelationships,
Boolean includeRenditions, Boolean includeACL, BigInteger maxItems, BigInteger skipCount, String orderBy, Holder<List<CmisObjectType>> object,
Holder<Boolean> hasMoreItems) throws CmisException
public CmisObjectInFolderListType getChildren(String repositoryId, String folderId, String filter, String orderBy, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments, BigInteger maxItems, BigInteger skipCount,
CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
PropertyFilter propertyFilter = createPropertyFilter(filter);
@@ -131,27 +126,194 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
{
orderingFields = checkAndParseOrderByClause(orderBy);
}
// TODO: Ordering functionality SHOULD be moved to getChildren service method
NodeRef[] listing = cmisService.getChildren(folderNodeRef, CMISTypesFilterEnum.ANY);
NodeRef[] listing = cmisService.getChildren(folderNodeRef, CMISTypesFilterEnum.ANY);
CmisObjectInFolderListType result = new CmisObjectInFolderListType();
Cursor cursor = createCursor(listing.length, skipCount, maxItems);
object.value = new ArrayList<CmisObjectType>();
List<CmisObjectType> resultListing = object.value;
for (int index = cursor.getStartRow(); index <= cursor.getEndRow(); index++)
{
resultListing.add(createCmisObject(listing[index].toString(), propertyFilter));
CmisObjectType cmisObject = createCmisObject(listing[index].toString(), propertyFilter, includeAllowableActions);
CmisObjectInFolderType cmisObjectInFolder = new CmisObjectInFolderType();
cmisObjectInFolder.setObject(cmisObject);
if (includePathSegments != null && includePathSegments)
{
cmisObjectInFolder.setPathSegment(propertiesUtil.getProperty(listing[index], CMISDictionaryModel.PROP_NAME, ""));
}
result.getObjects().add(cmisObjectInFolder);
}
hasMoreItems.value = new Boolean(cursor.getEndRow() < (listing.length - 1));
// TODO: Process includeAllowableActions, includeRelationships, includeRenditions, includeACL
result.setHasMoreItems(cursor.getEndRow() < (listing.length - 1));
result.setNumItems(BigInteger.valueOf(listing.length));
// TODO: Process includeAllowableActions, includeRelationships, includeRenditions, includeACL
return result;
}
/**
* Gets the list of descendant objects contained at one or more levels in the tree rooted at the specified folder. Only the filter-selected properties associated with each
* object are returned. The content-stream is not returned. For paging through the children (depth of 1) only use {@link #getChildren(GetChildren parameters)}.
*
* @param parameters repositoryId: repository Id; folderId: folder Id; depth: 1 this folder only (Default), N folders deep, -1 for all levels; filter: property filter;
* includeAllowableActions; includeRelationships;
* @return collection of CmisObjectType
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, FILTER_NOT_VALID)
*/
public List<CmisObjectInFolderContainerType> getDescendants(String repositoryId, String folderId, BigInteger depth, String filter, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments, CmisExtensionType extension) throws CmisException
{
CmisObjectInFolderContainerType objectInFolderContainerType = getDescedantsTree(repositoryId, folderId, depth, filter, includeAllowableActions, includeRelationships,
renditionFilter, includePathSegments, CMISTypesFilterEnum.ANY);
return objectInFolderContainerType.getChildren();
}
/**
* Gets the list of descendant objects contained at one or more levels in the tree rooted at the specified folder. Only the filter-selected properties associated with each
* object are returned. The content-stream is not returned. For paging through the children (depth of 1) only use {@link #getChildren(GetChildren parameters)}.
*
* @param parameters repositoryId: repository Id; folderId: folder Id; depth: 1 this folder only (Default), N folders deep, -1 for all levels; filter: property filter;
* includeAllowableActions; includeRelationships;
* @return collection of CmisObjectType
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, FILTER_NOT_VALID)
*/
public List<CmisObjectInFolderContainerType> getFolderTree(String repositoryId, String folderId, BigInteger depth, String filter, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments, CmisExtensionType extension) throws CmisException
{
CmisObjectInFolderContainerType objectInFolderContainerType = getDescedantsTree(repositoryId, folderId, depth, filter, includeAllowableActions, includeRelationships,
renditionFilter, includePathSegments, CMISTypesFilterEnum.FOLDERS);
return objectInFolderContainerType.getChildren();
}
/**
* Returns the parent folder object, and optionally all ancestor folder objects, above a specified folder object.
*
* @param parameters repositoryId: repository Id; folderId: folder Id; filter: property filter; includeAllowableActions; includeRelationships; returnToRoot: If false, return
* only the immediate parent of the folder. If true, return an ordered list of all ancestor folders from the specified folder to the root folder
* @return collection of CmisObjectType
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, FILTER_NOT_VALID)
*/
public CmisObjectType getFolderParent(String repositoryId, String folderId, String filter, CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
if ((filter != null) && !filter.equals("") && !filter.equals("*"))
{
if (!filter.contains(CMISDictionaryModel.PROP_PARENT_ID))
{
filter = CMISDictionaryModel.PROP_PARENT_ID + FILTER_TOKENS_DELIMETER + filter;
}
if (!filter.contains(CMISDictionaryModel.PROP_OBJECT_ID))
{
filter = CMISDictionaryModel.PROP_OBJECT_ID + FILTER_TOKENS_DELIMETER + filter;
}
}
PropertyFilter propertyFilter = createPropertyFilter(filter);
NodeRef parentRef = receiveParent(folderId);
CmisObjectType result = createCmisObject(parentRef, propertyFilter, false);
return result;
}
/**
* Returns the parent folders for the specified non-folder, fileable object.
*
* @param parameters repositoryId: repository Id; objectId: object Id; filter: property filter; includeAllowableActions; includeRelationships;
* @return collection of CmisObjectType
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT,
* FILTER_NOT_VALID)
*/
public List<CmisObjectParentsType> getObjectParents(String repositoryId, String objectId, String filter, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includeRelativePathSegment, CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
PropertyFilter propertyFilter = createPropertyFilter(filter);
NodeRef childNode = (NodeRef) cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT);
List<NodeRef> parents = receiveObjectParents(childNode);
List<CmisObjectParentsType> result = new ArrayList<CmisObjectParentsType>();
String relativePathSegment = propertiesUtil.getProperty(childNode, CMISDictionaryModel.PROP_NAME, "");
for (NodeRef objectNodeRef : parents)
{
CmisObjectType cmisObject = createCmisObject(objectNodeRef, propertyFilter, includeAllowableActions);
//TODO: includeRelationship, renditions
CmisObjectParentsType cmisObjectParentsType = new CmisObjectParentsType();
cmisObjectParentsType.setObject(cmisObject);
if (includeRelativePathSegment != null && includeRelativePathSegment)
{
cmisObjectParentsType.setRelativePathSegment(relativePathSegment);
}
result.add(cmisObjectParentsType);
}
return result;
}
private CmisObjectInFolderContainerType getDescedantsTree(String repositoryId, String folderId, BigInteger depth, String filter, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments,
CMISTypesFilterEnum types) throws CmisException
{
checkRepositoryId(repositoryId);
PropertyFilter propertyFilter = createPropertyFilter(filter);
depth = (depth == null) ? (BigInteger.ONE.add(BigInteger.ONE)) : depth;
depth = depth.equals(BigInteger.valueOf(-1)) ? BigInteger.valueOf(Integer.MAX_VALUE) : depth;
long maxDepth = depth.longValue();
checkDepthParameter(depth);
NodeRef folderNodeRef = cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT);
Stack<RecursiveElement> descedantsStack = new Stack<RecursiveElement>();
CmisObjectInFolderContainerType objectInFolderContainer = createObjectInFolderContainer(folderNodeRef, propertyFilter, includeAllowableActions, includeRelationships, renditionFilter, includePathSegments);
NodeRef[] children = cmisService.getChildren(folderNodeRef, types);
for (NodeRef childRef : children)
{
descedantsStack.push(new RecursiveElement(objectInFolderContainer, 1, childRef));
}
while (!descedantsStack.isEmpty())
{
RecursiveElement element = descedantsStack.pop();
CmisObjectInFolderContainerType currentContainer = createObjectInFolderContainer(folderNodeRef, propertyFilter, includeAllowableActions, includeRelationships,
renditionFilter, includePathSegments);
element.getParentContainerType().getChildren().add(currentContainer);
if (element.getDepth() <= maxDepth)
{
children = cmisService.getChildren(element.getCurrentNodeRef(), types);
if (children != null)
{
for (NodeRef childRef : children)
{
descedantsStack.push(new RecursiveElement(currentContainer, element.getDepth() + 1, childRef));
}
}
}
}
return objectInFolderContainer;
}
private CmisObjectInFolderContainerType createObjectInFolderContainer(NodeRef nodeRef, PropertyFilter filter, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments) throws CmisException
{
includeAllowableActions = includeAllowableActions == null ? Boolean.FALSE : includeAllowableActions;
CmisObjectType cmisObject = createCmisObject(nodeRef, filter, includeAllowableActions);
//TODO: add relationships and renditions
CmisObjectInFolderType objectInFolderType = new CmisObjectInFolderType();
objectInFolderType.setObject(cmisObject);
if (includePathSegments != null && includePathSegments)
{
String path = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_NAME, "");
objectInFolderType.setPathSegment(path);
}
CmisObjectInFolderContainerType result = new CmisObjectInFolderContainerType();
result.setObjectInFolder(objectInFolderType);
return result;
}
// TODO: This method will create appropriate Ordering fields
private List<Pair<String, Boolean>> checkAndParseOrderByClause(String orderByClause) throws CmisException
{
List<Pair<String, Boolean>> result = new LinkedList<Pair<String, Boolean>>();
@@ -174,88 +336,6 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
return result;
}
/**
* Gets the list of descendant objects contained at one or more levels in the tree rooted at the specified folder. Only the filter-selected properties associated with each
* object are returned. The content-stream is not returned. For paging through the children (depth of 1) only use {@link #getChildren(GetChildren parameters)}.
*
* @param parameters repositoryId: repository Id; folderId: folder Id; depth: 1 this folder only (Default), N folders deep, -1 for all levels; filter: property filter;
* includeAllowableActions; includeRelationships;
* @return collection of CmisObjectType
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, FILTER_NOT_VALID)
*/
public List<CmisObjectType> getDescendants(String repositoryId, String folderId, BigInteger depth, String filter, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, Boolean includeRenditions, String orderBy) throws CmisException
{
return getDescendants(repositoryId, folderId, depth, filter, includeAllowableActions, includeRelationships, includeRenditions, orderBy, null);
}
/**
* Gets the list of descendant objects contained at one or more levels in the tree rooted at the specified folder. Only the filter-selected properties associated with each
* object are returned. The content-stream is not returned. For paging through the children (depth of 1) only use {@link #getChildren(GetChildren parameters)}.
*
* @param parameters repositoryId: repository Id; folderId: folder Id; depth: 1 this folder only (Default), N folders deep, -1 for all levels; filter: property filter;
* includeAllowableActions; includeRelationships;
* @return collection of CmisObjectType
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, FILTER_NOT_VALID)
*/
public List<CmisObjectType> getFolderTree(String repositoryId, String folderId, String filter, BigInteger depth, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships) throws CmisException
{
return getDescendants(repositoryId, folderId, depth, filter, includeAllowableActions, includeRelationships, null, null, CMISTypesFilterEnum.FOLDERS);
}
/**
* Returns the parent folder object, and optionally all ancestor folder objects, above a specified folder object.
*
* @param parameters repositoryId: repository Id; folderId: folder Id; filter: property filter; includeAllowableActions; includeRelationships; returnToRoot: If false, return
* only the immediate parent of the folder. If true, return an ordered list of all ancestor folders from the specified folder to the root folder
* @return collection of CmisObjectType
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, FILTER_NOT_VALID)
*/
public CmisObjectType getFolderParent(String repositoryId, String folderId, String filter) throws CmisException
{
checkRepositoryId(repositoryId);
if ((filter != null) && !filter.equals("") && !filter.equals("*"))
{
if (!filter.contains(CMISDictionaryModel.PROP_PARENT_ID))
{
filter = CMISDictionaryModel.PROP_PARENT_ID + FILTER_TOKENS_DELIMETER + filter;
}
if (!filter.contains(CMISDictionaryModel.PROP_OBJECT_ID))
{
filter = CMISDictionaryModel.PROP_OBJECT_ID + FILTER_TOKENS_DELIMETER + filter;
}
}
PropertyFilter propertyFilter = createPropertyFilter(filter);
NodeRef parentRef = receiveParent(folderId);
CmisObjectType result = createCmisObject(parentRef, propertyFilter);
return result;
}
/**
* Returns the parent folders for the specified non-folder, fileable object.
*
* @param parameters repositoryId: repository Id; objectId: object Id; filter: property filter; includeAllowableActions; includeRelationships;
* @return collection of CmisObjectType
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT,
* FILTER_NOT_VALID)
*/
public List<CmisObjectType> getObjectParents(String repositoryId, String objectId, String filter) throws CmisException
{
checkRepositoryId(repositoryId);
PropertyFilter propertyFilter = createPropertyFilter(filter);
List<NodeRef> parents = receiveObjectParents((NodeRef) cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT));
List<CmisObjectType> result = new ArrayList<CmisObjectType>();
createCmisObjectList(propertyFilter, parents, result);
return result;
}
private NodeRef receiveParent(String targetChildIdentifier) throws CmisException
{
if (targetChildIdentifier.equals(cmisService.getDefaultRootNodeRef().toString()))
@@ -264,32 +344,7 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
}
return receiveNextParentNodeReference((NodeRef) cmisObjectsUtils.getIdentifierInstance(targetChildIdentifier, AlfrescoObjectType.FOLDER_OBJECT), new ArrayList<NodeRef>());
}
private List<CmisObjectType> getDescendants(String repositoryId, String folderId, BigInteger depth, String filter, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, Boolean includeRenditions, String orderBy, CMISTypesFilterEnum type) throws CmisException
{
checkRepositoryId(repositoryId);
PropertyFilter propertyFilter = createPropertyFilter(filter);
depth = (depth == null) ? (BigInteger.ONE) : depth;
checkDepthParameter(depth);
HierarchyReceiverStrategy receiver = createHierarchyReceiver(type, depth);
List<Pair<String, Boolean>> orderingFields = null;
if ((orderBy != null) && !orderBy.equals(""))
{
orderingFields = checkAndParseOrderByClause(orderBy);
}
List<CmisObjectType> result = new ArrayList<CmisObjectType>();
// TODO: Ordering functionality SHOULD be moved to getChildren service method
createCmisObjectList(propertyFilter, receiver.receiveHierarchy(folderId, orderingFields), result);
// TODO: includeAllowableActions, includeRelationships, includeRenditions
return result;
}
private void checkDepthParameter(BigInteger depth) throws CmisException
{
if (depth.equals(BigInteger.ZERO) || (depth.compareTo(FULL_DESCENDANTS_HIERARCHY_CONDITION) < EQUALS_CONDITION_VALUE))
@@ -318,133 +373,33 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
}
return parents;
}
private HierarchyReceiverStrategy createHierarchyReceiver(CMISTypesFilterEnum type, BigInteger finalDepth)
private class RecursiveElement
{
if (finalDepth.equals(FULL_DESCENDANTS_HIERARCHY_CONDITION))
private CmisObjectInFolderContainerType parentContainerType;
private int depth;
private NodeRef currentNodeRef;
public RecursiveElement(CmisObjectInFolderContainerType parentContainerType, int depth, NodeRef currentNodeRef)
{
return new FullHierarchyReceiver(type);
this.parentContainerType = parentContainerType;
this.depth = depth;
this.currentNodeRef = currentNodeRef;
}
else
public CmisObjectInFolderContainerType getParentContainerType()
{
return new LayerConstrainedHierarchyReceiver(type, finalDepth);
return parentContainerType;
}
public int getDepth()
{
return depth;
}
public NodeRef getCurrentNodeRef()
{
return currentNodeRef;
}
}
private void separateDescendantsObjects(List<NodeRef> descendantsFolders, List<NodeRef> currentLayerFolders, List<NodeRef> currentLayerDocuments,
List<Pair<String, Boolean>> orderingFields)
{
for (NodeRef element : descendantsFolders)
{
// TODO: Ordering functionality SHOULD be moved to getChildren service method
currentLayerFolders.addAll(Arrays.asList(cmisService.getChildren(element, CMISTypesFilterEnum.FOLDERS)));
// TODO: Ordering functionality SHOULD be moved to getChildren service method
currentLayerDocuments.addAll(Arrays.asList(cmisService.getChildren(element, CMISTypesFilterEnum.DOCUMENTS)));
}
}
private List<NodeRef> performDescendantsResultObjectsStoring(List<NodeRef> resultList, List<NodeRef> descendantsFolders, List<NodeRef> currentLayerFolders,
List<NodeRef> currentLayerDocuments, List<Pair<String, Boolean>> orderingFields, CMISTypesFilterEnum type)
{
separateDescendantsObjects(descendantsFolders, currentLayerFolders, currentLayerDocuments, orderingFields);
if (CMISTypesFilterEnum.ANY.equals(type) || CMISTypesFilterEnum.FOLDERS.equals(type))
{
resultList.addAll(currentLayerFolders);
}
if (CMISTypesFilterEnum.ANY.equals(type) || CMISTypesFilterEnum.DOCUMENTS.equals(type))
{
resultList.addAll(currentLayerDocuments);
}
return currentLayerFolders;
}
/**
* This interface introduce common type for Alfresco objects hierarchy receiving
*/
private interface HierarchyReceiverStrategy
{
/**
* @param rootFolderIdentifier the source folder Id from whose hierarchy bypassing will be started
* @return <b>List</b> that contains all appropriates layers of Alfresco objects
* @throws InvalidArgumentException
*/
public List<NodeRef> receiveHierarchy(String rootFolderIdentifier, List<Pair<String, Boolean>> orderFields) throws CmisException;
}
/**
* @see HierarchyReceiverStrategy
*/
private class FullHierarchyReceiver implements HierarchyReceiverStrategy
{
private List<NodeRef> descendantsFolders = new LinkedList<NodeRef>();
private List<NodeRef> resultList = new LinkedList<NodeRef>();
private CMISTypesFilterEnum type = CMISTypesFilterEnum.ANY;
public FullHierarchyReceiver(CMISTypesFilterEnum type)
{
if (type != null)
{
this.type = type;
}
}
/**
* Traverse Alfresco objects hierarchy until there is some Folder-objects can be found
*/
public List<NodeRef> receiveHierarchy(String rootFolderIdentifier, List<Pair<String, Boolean>> orderingFields) throws CmisException
{
descendantsFolders.add((NodeRef) cmisObjectsUtils.getIdentifierInstance(rootFolderIdentifier, AlfrescoObjectType.FOLDER_OBJECT));
while (!descendantsFolders.isEmpty())
{
descendantsFolders = performDescendantsResultObjectsStoring(resultList, descendantsFolders, new LinkedList<NodeRef>(), new LinkedList<NodeRef>(), orderingFields,
type);
}
return resultList;
}
}
/**
* @see HierarchyReceiverStrategy
*/
private class LayerConstrainedHierarchyReceiver implements HierarchyReceiverStrategy
{
private List<NodeRef> descendantsFolders = new LinkedList<NodeRef>();
private BigInteger finalDepth;
private BigInteger currentDepth = BigInteger.ZERO;
private List<NodeRef> resultList = new LinkedList<NodeRef>();
private CMISTypesFilterEnum type = CMISTypesFilterEnum.ANY;
/**
* @param returnObjectsType flag that specifies objects of which type are need to be returned
* @param finalDepth the number of final Alfresco hierarchy layer: 1 - only children of specified folder; -1 - full descendants hierarchy
*/
public LayerConstrainedHierarchyReceiver(CMISTypesFilterEnum type, BigInteger finalDepth)
{
this.finalDepth = finalDepth;
if (type != null)
{
this.type = type;
}
}
/**
* This method of this class receives Alfresco objects hierarchy until specified layer number
*/
public List<NodeRef> receiveHierarchy(String rootFolderIdentifier, List<Pair<String, Boolean>> orderingFields) throws CmisException
{
descendantsFolders.add((NodeRef) cmisObjectsUtils.getIdentifierInstance(rootFolderIdentifier, AlfrescoObjectType.FOLDER_OBJECT));
do
{
descendantsFolders = performDescendantsResultObjectsStoring(this.resultList, this.descendantsFolders, new LinkedList<NodeRef>(), new LinkedList<NodeRef>(),
orderingFields, type);
currentDepth = currentDepth.add(BigInteger.ONE);
} while (!descendantsFolders.isEmpty() && (currentDepth.compareTo(this.finalDepth) < EQUALS_CONDITION_VALUE));
return this.resultList;
}
}
}

View File

@@ -30,6 +30,8 @@ import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.activation.DataHandler;
import javax.xml.ws.Holder;
@@ -38,6 +40,7 @@ import org.alfresco.cmis.CMISContentStreamAllowedEnum;
import org.alfresco.cmis.CMISDictionaryModel;
import org.alfresco.cmis.CMISScope;
import org.alfresco.cmis.CMISTypeDefinition;
import org.alfresco.cmis.dictionary.CMISFolderTypeDefinition;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.cmis.PropertyFilter;
import org.alfresco.repo.cmis.ws.DeleteTreeResponse.FailedToDelete;
@@ -51,13 +54,9 @@ import org.alfresco.service.cmr.lock.NodeLockedException;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.service.namespace.QName;
@@ -67,20 +66,14 @@ import org.alfresco.service.namespace.QName;
* @author Dmitry Lazurkin
* @author Dmitry Velichkevich
*/
@javax.jws.WebService(name = "ObjectServicePort", serviceName = "ObjectService", portName = "ObjectServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200901", endpointInterface = "org.alfresco.repo.cmis.ws.ObjectServicePort")
@javax.jws.WebService(name = "ObjectServicePort", serviceName = "ObjectService", portName = "ObjectServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200908/", endpointInterface = "org.alfresco.repo.cmis.ws.ObjectServicePort")
public class DMObjectServicePort extends DMAbstractServicePort implements ObjectServicePort
{
private static final int SINGLE_PARENT_CONDITION = 1;
private static final String VERSION_DELIMETER = ".";
private static final String FOLDER_PATH_MATCHING_PATTERN = "^(/){1}([\\p{L}\\p{Digit} _\\-()]*(/)?)*[\\p{L}\\p{Digit} _\\-()]$";
private PermissionService permissionService;
private DictionaryService dictionaryService;
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
}
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
@@ -98,80 +91,85 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT, STORAGE,
* STREAM_NOT_SUPPORTED)
*/
public String createDocument(String repositoryId, CmisPropertiesType properties, String folderId, CmisContentStreamType contentStream, EnumVersioningState versioningState,
List<String> applyPolicies, CmisAccessControlListType addACEs, CmisAccessControlListType removeACEs) throws CmisException
public void createDocument(String repositoryId, CmisPropertiesType properties, String folderId, CmisContentStreamType contentStream, EnumVersioningState versioningState,
List<String> policies, CmisAccessControlListType addACEs, CmisAccessControlListType removeACEs, Holder<CmisExtensionType> extension, Holder<String> objectId)
throws CmisException
{
// TODO: process Policies and ACL
checkRepositoryId(repositoryId);
NodeRef parentNodeRef = safeGetFolderNodeRef(folderId);
if (null == properties)
{
throw cmisObjectsUtils.createCmisException("Properties input parameter is Mandatory", EnumServiceException.INVALID_ARGUMENT);
}
Map<String, Object> propertiesMap = propertiesUtil.getPropertiesMap(properties);
String typeId = extractAndAssertTypeId(propertiesMap);
CMISTypeDefinition typeDef = cmisDictionaryService.findType(typeId);
String documentName = checkConstraintsAndGetName(typeId, typeDef, parentNodeRef, contentStream, propertiesMap, versioningState);
NodeRef newDocumentNodeRef = fileFolderService.create(parentNodeRef, documentName, typeDef.getTypeId().getQName()).getNodeRef();
ContentWriter writer = fileFolderService.getWriter(newDocumentNodeRef);
String mimeType = (String) propertiesMap.get(CMISDictionaryModel.PROP_CONTENT_STREAM_MIME_TYPE);
if (mimeType != null)
if (null != contentStream)
{
writer.setMimetype(mimeType);
ContentWriter writer = fileFolderService.getWriter(newDocumentNodeRef);
String mimeType = (String) propertiesMap.get(CMISDictionaryModel.PROP_CONTENT_STREAM_MIME_TYPE);
mimeType = (null == mimeType) ? (contentStream.getMimeType()) : (mimeType);
if (null != mimeType)
{
writer.setMimetype(mimeType);
}
else
{
throw cmisObjectsUtils.createCmisException("Content Stream Mime Type was not specified", EnumServiceException.STORAGE);
}
InputStream inputstream = null;
try
{
inputstream = contentStream.getStream().getInputStream();
}
catch (IOException e)
{
throw cmisObjectsUtils.createCmisException(e.toString(), EnumServiceException.CONSTRAINT);
}
writer.putContent(inputstream);
}
else if ((contentStream != null) && (contentStream.getMimeType() != null))
{
writer.setMimetype(contentStream.getMimeType());
}
else
{
throw cmisObjectsUtils.createCmisException("ContentStream meime type was not specified", EnumServiceException.CONSTRAINT);
}
InputStream inputstream = null;
appendDataToDocument(newDocumentNodeRef, properties, versioningState, policies, addACEs, removeACEs, objectId);
}
/**
* Creates a document object as a copy of the given source document in the specified location
*
* @param repositoryId repository Id
* @param properties CMIS properties
* @param folderId parent folder for this new document
* @param contentStream content stream
* @param versioningState versioning state (checkedout, minor, major)
* @return Id of the created document object
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT, STORAGE,
* STREAM_NOT_SUPPORTED)
*/
public void createDocumentFromSource(String repositoryId, String sourceId, CmisPropertiesType properties, String folderId, EnumVersioningState versioningState,
List<String> policies, CmisAccessControlListType addACEs, CmisAccessControlListType removeACEs, Holder<CmisExtensionType> extension, Holder<String> objectId)
throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef folderNodeRef = cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT);
NodeRef sourceNodeRef = cmisObjectsUtils.getIdentifierInstance(sourceId, AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT);
String name = propertiesUtil.getProperty(sourceNodeRef, CMISDictionaryModel.PROP_NAME, null);
NodeRef newDocumentNodeRef;
try
{
inputstream = contentStream.getStream().getInputStream();
newDocumentNodeRef = fileFolderService.copy(sourceNodeRef, folderNodeRef, name).getNodeRef();
}
catch (IOException e)
catch (FileExistsException e)
{
throw cmisObjectsUtils.createCmisException(e.toString(), EnumServiceException.CONSTRAINT);
throw cmisObjectsUtils.createCmisException("Document already exists", EnumServiceException.CONTENT_ALREADY_EXISTS);
}
writer.putContent(inputstream);
if (versioningState == null)
catch (FileNotFoundException e)
{
versioningState = EnumVersioningState.MAJOR;
throw cmisObjectsUtils.createCmisException("Source document not found", EnumServiceException.INVALID_ARGUMENT);
}
propertiesUtil.setProperties(newDocumentNodeRef, properties, createPropertyFilter(createIgnoringFilter(new String[] { CMISDictionaryModel.PROP_NAME,
CMISDictionaryModel.PROP_OBJECT_TYPE_ID })));
switch (versioningState)
{
case CHECKEDOUT:
newDocumentNodeRef = checkoutNode(newDocumentNodeRef);
break;
case MAJOR:
this.versionService.createVersion(newDocumentNodeRef, createVersionProperties(INITIAL_VERSION_DESCRIPTION, VersionType.MAJOR));
break;
case MINOR:
this.versionService.createVersion(newDocumentNodeRef, createVersionProperties(INITIAL_VERSION_DESCRIPTION, VersionType.MINOR));
break;
}
String versionLabel = propertiesUtil.getProperty(newDocumentNodeRef, CMISDictionaryModel.PROP_VERSION_LABEL, "");
return versionLabel != null && versionLabel.contains(VERSION_DELIMETER) ? newDocumentNodeRef.toString() + CmisObjectsUtils.NODE_REFERENCE_ID_DELIMETER + versionLabel
: newDocumentNodeRef.toString();
appendDataToDocument(newDocumentNodeRef, properties, versioningState, policies, addACEs, removeACEs, objectId);
}
private String extractAndAssertTypeId(Map<String, Object> propertiesMap) throws CmisException
{
String typeId = (String) propertiesMap.get(CMISDictionaryModel.PROP_OBJECT_TYPE_ID);
if ((null == typeId) || "".equals(typeId))
{
throw cmisObjectsUtils.createCmisException("Type Id property required", EnumServiceException.INVALID_ARGUMENT);
}
return typeId;
}
/**
* Creates a folder object of the specified type.
*
@@ -181,8 +179,9 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
* @return Id of the created folder object
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT, STORAGE)
*/
public String createFolder(String repositoryId, CmisPropertiesType properties, String folderId, List<String> applyPolicies, CmisAccessControlListType addACEs,
CmisAccessControlListType removeACEs) throws CmisException
public void createFolder(String repositoryId, CmisPropertiesType properties, String folderId, List<String> policies, CmisAccessControlListType addACEs,
CmisAccessControlListType removeACEs, Holder<CmisExtensionType> extension, Holder<String> objectId) throws CmisException
{
// TODO: process Policies and ACL
@@ -215,7 +214,7 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
NodeRef newFolderNodeRef = fileFolderService.create(folderNodeRef, name, type.getTypeId().getQName()).getNodeRef();
propertiesUtil.setProperties(newFolderNodeRef, properties, createPropertyFilter(createIgnoringFilter(new String[] { CMISDictionaryModel.PROP_NAME,
CMISDictionaryModel.PROP_OBJECT_TYPE_ID })));
return propertiesUtil.getProperty(newFolderNodeRef, CMISDictionaryModel.PROP_OBJECT_ID, null);
objectId.value = propertiesUtil.getProperty(newFolderNodeRef, CMISDictionaryModel.PROP_OBJECT_ID, null);
}
catch (FileExistsException e)
{
@@ -223,27 +222,6 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
}
}
private String createIgnoringFilter(String[] propertyNames)
{
StringBuilder filter = new StringBuilder("");
for (String propertyName : propertyNames)
{
if ((null != propertyName) && !propertyName.equals(""))
{
filter.append(propertyName);
filter.append(PropertyFilter.PROPERTY_NAME_TOKENS_DELIMETER);
}
}
if (filter.length() > 0)
{
filter.deleteCharAt(filter.length() - 1);
}
return filter.toString();
}
/**
* Creates a policy object of the specified type, and optionally adds the policy to a folder.
*
@@ -253,7 +231,8 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
* @return Id of the created policy object
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT, STORAGE)
*/
public String createPolicy(String repositoryId, CmisPropertiesType properties, String folderId) throws CmisException
public void createPolicy(String repositoryId, CmisPropertiesType properties, String folderId, List<String> policies, CmisAccessControlListType addACEs,
CmisAccessControlListType removeACEs, Holder<CmisExtensionType> extension, Holder<String> objectId) throws CmisException
{
throw cmisObjectsUtils.createCmisException("Policy objects not supported", EnumServiceException.NOT_SUPPORTED);
}
@@ -269,18 +248,20 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
* @return Id of the created relationship object
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT, STORAGE)
*/
public String createRelationship(String repositoryId, CmisPropertiesType properties, String sourceObjectId, String targetObjectId, List<String> applyPolicies,
CmisAccessControlListType addACEs, CmisAccessControlListType removeACEs) throws CmisException
public void createRelationship(String repositoryId, CmisPropertiesType properties, List<String> policies, CmisAccessControlListType addACEs,
CmisAccessControlListType removeACEs, Holder<CmisExtensionType> extension, Holder<String> objectId) throws CmisException
{
// TODO: process Policies and ACL
Map<String, Object> propertiesMap = propertiesUtil.getPropertiesMap(properties);
String sourceObjectId = (String) propertiesMap.get(CMISDictionaryModel.PROP_SOURCE_ID);
String targetObjectId = (String) propertiesMap.get(CMISDictionaryModel.PROP_TARGET_ID);
checkRepositoryId(repositoryId);
NodeRef sourceNodeRef = cmisObjectsUtils.getIdentifierInstance(sourceObjectId, AlfrescoObjectType.ANY_OBJECT);
NodeRef targetNodeRef = cmisObjectsUtils.getIdentifierInstance(targetObjectId, AlfrescoObjectType.ANY_OBJECT);
Map<String, Object> propertiesMap = propertiesUtil.getPropertiesMap(properties);
String typeId = (String) propertiesMap.get(CMISDictionaryModel.PROP_OBJECT_TYPE_ID);
CMISTypeDefinition relationshipType = cmisDictionaryService.findType(typeId);
@@ -315,7 +296,8 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
throw cmisObjectsUtils.createCmisException("Target object type isn't allowed as target type", EnumServiceException.CONSTRAINT);
}
return nodeService.createAssociation(sourceNodeRef, targetNodeRef, relationshipTypeQName).toString();
String createdId = nodeService.createAssociation(sourceNodeRef, targetNodeRef, relationshipTypeQName).toString();
objectId.value = createdId;
}
else
{
@@ -332,7 +314,7 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT, STORAGE,
* UPDATE_CONFLICT, VERSIONING)
*/
public void deleteContentStream(String repositoryId, Holder<String> documentId, String changeToken) throws CmisException
public void deleteContentStream(String repositoryId, Holder<String> documentId, Holder<String> changeToken, Holder<CmisExtensionType> extension) throws CmisException
{
// TODO: Process changeToken
checkRepositoryId(repositoryId);
@@ -356,7 +338,7 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT,
* UPDATE_CONFLICT)
*/
public void deleteObject(String repositoryId, String objectId, Boolean allVersions) throws CmisException
public void deleteObject(String repositoryId, String objectId, Boolean allVersions, Holder<CmisExtensionType> extension) throws CmisException
{
// TODO: Process flag allVersions
@@ -365,11 +347,15 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
NodeRef objectNodeReference = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT);
checkForRootObject(repositoryId, objectId);
checkObjectTypeAndAppropriateStates(objectNodeReference, nodeService.getType(objectNodeReference));
if (allVersions != null && allVersions)
{
deleteAllVersions(repositoryId, objectId);
}
if (!cmisObjectsUtils.deleteObject(objectNodeReference))
{
throw cmisObjectsUtils.createCmisException("Currently authenticated User has no appropriate Permissions to delete specified Object",
EnumServiceException.PERMISSION_DENIED);
}
}
}
/**
@@ -384,22 +370,24 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
* @return collection of object IDs that failed to delete (if continueOnFailure is FALSE, then single object ID)
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, UPDATE_CONFLICT)
*/
public FailedToDelete deleteTree(String repositoryId, String folderId, EnumUnfileObject unfileObject, Boolean continueOnFailure) throws CmisException
public FailedToDelete deleteTree(String repositoryId, String folderId, Boolean allVersions, EnumUnfileObject unfileObject, Boolean continueOnFailure,
CmisExtensionType extension) throws CmisException
{
//TODO: Process allVersions
checkRepositoryId(repositoryId);
checkUnfilingIsNotRequested(unfileObject);
checkForRootObject(repositoryId, folderId);
NodeRef folderNodeReference = cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT);
FailedToDelete responce = new FailedToDelete();
cmisObjectsUtils.deleteFolder(folderNodeReference, continueOnFailure, (unfileObject == EnumUnfileObject.DELETE), responce.getObjectId());
allVersions = allVersions == null ? Boolean.FALSE : allVersions;
responce.getObjectIds().addAll(cmisObjectsUtils.deleteFolder(folderNodeReference, continueOnFailure, unfileObject, allVersions));
return responce;
}
/**
* Gets the specified Folder object
* Gets the specified object
*
* @param repositoryId repository Id
* @param folderPath The path to the folder
@@ -407,25 +395,63 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
* @return list of properties for the Folder
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND)
*/
public CmisObjectType getFolderByPath(String repositoryId, String folderPath, String filter, Boolean includeAllowableActions, EnumIncludeRelationships includeRelationships,
Boolean includeACL) throws CmisException
public CmisObjectType getObject(String repositoryId, String objectId, String filter, Boolean includeAllowableActions, EnumIncludeRelationships includeRelationships,
String renditionFilter, Boolean includePolicyIds, Boolean includeACL, CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
if (folderPath == null)
PropertyFilter propertyFilter = createPropertyFilter(filter);
Object identifierInstance = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.ANY_OBJECT);
String identifier = identifierInstance.toString();
CmisPropertiesType properties = propertiesUtil.getPropertiesType(identifier, propertyFilter);
CmisObjectType object = new CmisObjectType();
object.setProperties(properties);
if (includeAllowableActions)
{
throw cmisObjectsUtils.createCmisException("folderPath is null", EnumServiceException.INVALID_ARGUMENT);
object.setAllowableActions(determineObjectAllowableActions(identifierInstance));
}
NodeRef folderNodeRef = resolvePathInfo(cmisService.getDefaultRootNodeRef(), folderPath);
Object identifierInstance = cmisObjectsUtils.getIdentifierInstance(folderNodeRef.toString(), AlfrescoObjectType.FOLDER_OBJECT);
// TODO: process relationships
// TODO: process ACL
// TODO: process rendition
return object;
}
/**
* Gets the specified object by path
*
* @param repositoryId repository Id
* @param folderPath The path to the folder
* @param filter property filter
* @return list of properties for the Folder
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND)
*/
public CmisObjectType getObjectByPath(String repositoryId, String path, String filter, Boolean includeAllowableActions, EnumIncludeRelationships includeRelationships,
String renditionFilter, Boolean includePolicyIds, Boolean includeACL, CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef objectNodeRef = resolvePathInfo(cmisService.getDefaultRootNodeRef(), path);
if ((null == path) || (null == objectNodeRef))
{
throw cmisObjectsUtils.createCmisException("Path to Folder was not specified or Folder Path is invalid", EnumServiceException.INVALID_ARGUMENT);
}
Object identifierInstance = cmisObjectsUtils.getIdentifierInstance(objectNodeRef.toString(), AlfrescoObjectType.ANY_OBJECT);
PropertyFilter propertyFilter = createPropertyFilter(filter);
CmisObjectType object = new CmisObjectType();
object.setProperties(propertiesUtil.getPropertiesType(identifierInstance.toString(), propertyFilter));
// TODO: process allowable actions
if (includeAllowableActions)
{
object.setAllowableActions(determineObjectAllowableActions(identifierInstance));
}
// TODO: process relationships
// TODO: process ACL
// TODO: process rendition
return object;
}
@@ -439,7 +465,7 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
* @return list of allowable actions
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME)
*/
public CmisAllowableActionsType getAllowableActions(String repositoryId, String objectId) throws CmisException
public CmisAllowableActionsType getAllowableActions(String repositoryId, String objectId, CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
return determineObjectAllowableActions(cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.ANY_OBJECT));
@@ -453,20 +479,13 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
* @return content stream
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, STREAM_NOT_SUPPORTED)
*/
public CmisContentStreamType getContentStream(String repositoryId, String documentId, String streamId) throws CmisException
public CmisContentStreamType getContentStream(String repositoryId, String objectId, String streamId, BigInteger offset, BigInteger length, CmisExtensionType extension)
throws CmisException
{
// TODO: process streamId
// TODO:
// Specification says:
// Each CMIS protocol binding MAY provide a way for fetching a sub-range within
// a content stream, in a manner appropriate to that protocol.
//
// Implementation of sub-range fetching is suspended.
// See http://tools.oasis-open.org/issues/browse/CMIS-134
checkRepositoryId(repositoryId);
NodeRef nodeRef = cmisObjectsUtils.getIdentifierInstance(documentId, AlfrescoObjectType.DOCUMENT_OBJECT);
NodeRef nodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT);
CMISTypeDefinition typeDefinition = cmisDictionaryService.findType(propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, (String) null));
if (CMISContentStreamAllowedEnum.NOT_ALLOWED == typeDefinition.getContentStreamAllowed())
@@ -476,13 +495,13 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
CmisContentStreamType response = new CmisContentStreamType();
ContentReader reader = safeGetContentReader(nodeRef);
response.setLength(BigInteger.valueOf(reader.getSize()));
response.setMimeType(reader.getMimetype());
String filename = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_NAME, null);
response.setFilename(filename);
response.setStream(new DataHandler(new ContentReaderDataSource(reader, filename)));
response.setMimeType(reader.getMimetype());
ContentReaderDataSource dataSource = new ContentReaderDataSource(reader, filename, offset, length, reader.getSize());
response.setStream(new DataHandler(dataSource));
response.setLength(BigInteger.valueOf(dataSource.getSizeToRead()));
return response;
}
@@ -496,48 +515,47 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT, STORAGE,
* UPDATE_CONFLICT, VERSIONING)
*/
public void moveObject(String repositoryId, Holder<String> objectId, String targetFolderId, String sourceFolderId) throws CmisException
public void moveObject(String repositoryId, Holder<String> objectId, String targetFolderId, String sourceFolderId, Holder<CmisExtensionType> extension) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef objectNodeRef = null;
try
{
objectNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId.value, AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT);
}
catch (CmisException e)
{
e.getFaultInfo().setType(EnumServiceException.CONSTRAINT);
throw e;
}
NodeRef objectNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId.value, AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT);
// TODO: maybe this check will be need in terms of document version instead of final document (version specific filing is not supported)
// checkOnLatestVersion(objectNodeRef);
NodeRef targetFolderNodeRef = cmisObjectsUtils.getIdentifierInstance(targetFolderId, AlfrescoObjectType.FOLDER_OBJECT);
List<ChildAssociationRef> parentsAssociations = nodeService.getParentAssocs(objectNodeRef);
if ((parentsAssociations != null) && (SINGLE_PARENT_CONDITION != nodeService.getParentAssocs(objectNodeRef).size()))
String objectType = propertiesUtil.getProperty(objectNodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, null);
String targetType = propertiesUtil.getProperty(targetFolderNodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, null);
CMISFolderTypeDefinition targetTypeDef = (CMISFolderTypeDefinition) ((null != targetType) ? (cmisDictionaryService.findType(targetType)) : (null));
if (null == targetTypeDef)
{
try
{
NodeRef sourceFolderNodeRef = cmisObjectsUtils.getIdentifierInstance(sourceFolderId, AlfrescoObjectType.FOLDER_OBJECT);
if (!cmisObjectsUtils.isPrimaryObjectParent(sourceFolderNodeRef, objectNodeRef))
{
changeObjectParentAssociation(objectNodeRef, targetFolderNodeRef, sourceFolderNodeRef);
return;
}
}
catch (CmisException e)
{
e.getFaultInfo().setMessage(
"Invalid source forlder for multifiled document was specified. Multifiled document must be moved from concrete folder. Exception message: "
+ e.getFaultInfo().getMessage());
throw e;
}
throw cmisObjectsUtils.createCmisException("Type Definition for Target Folder was not found", EnumServiceException.RUNTIME);
}
// FIXME: targetTypeDef.getAllowedTargetTypes() should be changed to something like targetTypeDef.getAllowedChildTypes()
CMISTypeDefinition objectTypeDef = (null != objectType) ? (cmisDictionaryService.findType(objectType)) : (null);
if (!targetTypeDef.getAllowedTargetTypes().isEmpty() && !targetTypeDef.getAllowedTargetTypes().contains(objectTypeDef))
{
throw cmisObjectsUtils.createCmisException(("Object with '" + objectType + "' Type can't be moved to Folder with '" + targetType + "' Type"),
EnumServiceException.CONSTRAINT);
}
NodeRef sourceFolderNodeRef = null;
if ((null != sourceFolderId) && !"".equals(sourceFolderId))
{
sourceFolderNodeRef = cmisObjectsUtils.getIdentifierInstance(sourceFolderId, AlfrescoObjectType.FOLDER_OBJECT);
}
if ((null != sourceFolderNodeRef) && !cmisObjectsUtils.isPrimaryObjectParent(objectNodeRef, sourceFolderNodeRef))
{
if (!cmisObjectsUtils.isChildOfThisFolder(objectNodeRef, sourceFolderNodeRef))
{
throw cmisObjectsUtils.createCmisException("The Docuemnt is not a Child of Source Forlder that was specified", EnumServiceException.INVALID_ARGUMENT);
}
changeObjectParentAssociation(objectNodeRef, targetFolderNodeRef, sourceFolderNodeRef);
}
else
{
safeMove(objectNodeRef, targetFolderNodeRef);
}
safeMove(objectNodeRef, targetFolderNodeRef);
// TODO: Allowed_Child_Object_Types
}
@@ -552,8 +570,8 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
* CONTENT_ALREADY_EXISTS, STORAGE, STREAM_NOT_SUPPORTED, UPDATE_CONFLICT, VERSIONING)
*/
public void setContentStream(String repositoryId, Holder<String> documentId, Boolean overwriteFlag, String changeToken, CmisContentStreamType contentStream)
throws CmisException
public void setContentStream(String repositoryId, Holder<String> documentId, Boolean overwriteFlag, Holder<String> changeToken, CmisContentStreamType contentStream,
Holder<CmisExtensionType> extension) throws CmisException
{
checkRepositoryId(repositoryId);
@@ -573,7 +591,8 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
throw cmisObjectsUtils.createCmisException("New Content Stream was not provided", EnumServiceException.STORAGE);
}
if ((nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT) != null) && !overwriteFlag)
ContentReader reader = fileFolderService.getReader(nodeRef);
if ((null != reader) && !overwriteFlag)
{
throw cmisObjectsUtils.createCmisException("Content already exists", EnumServiceException.CONTENT_ALREADY_EXISTS);
}
@@ -605,7 +624,8 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT,
* UPDATE_CONFLICT, VERSIONING)
*/
public void updateProperties(String repositoryId, Holder<String> objectId, Holder<String> changeToken, CmisPropertiesType properties) throws CmisException
public void updateProperties(String repositoryId, Holder<String> objectId, Holder<String> changeToken, CmisPropertiesType properties, Holder<CmisExtensionType> extension)
throws CmisException
{
// TODO: Process changeToken
checkRepositoryId(repositoryId);
@@ -624,8 +644,7 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
* @return collection collection of CmisObjectType
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, FOLDER_NOT_VALID)
*/
public CmisObjectType getProperties(String repositoryId, String objectId, String filter, Boolean includeAllowableActions, EnumIncludeRelationships includeRelationships,
Boolean includeACL) throws CmisException
public CmisPropertiesType getProperties(String repositoryId, String objectId, String filter, CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
@@ -634,21 +653,89 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
Object identifierInstance = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.ANY_OBJECT);
String identifier = identifierInstance.toString();
CmisObjectType object = new CmisObjectType();
object.setProperties(propertiesUtil.getPropertiesType(identifier, propertyFilter));
CmisPropertiesType result = propertiesUtil.getPropertiesType(identifier, propertyFilter);
// TODO: process allowable actions
// TODO: process relationships
// TODO: process ACL
return object;
return result;
}
public List<CmisRenditionType> getRenditions(String repositoryId, String objectId, String renditionFilter, BigInteger maxItems, BigInteger skipCount) throws CmisException
/**
* Gets the renditions of an object, and optionally the operations that the user is allowed to perform on the object.
*
* @param parameters
* @return collection collection of CmisObjectType
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, FOLDER_NOT_VALID)
*/
public List<CmisRenditionType> getRenditions(String repositoryId, String objectId, String renditionFilter, BigInteger maxItems, BigInteger skipCount,
CmisExtensionType extension) throws CmisException
{
// TODO: Process renditions
throw cmisObjectsUtils.createCmisException("Renditions objects not supported", EnumServiceException.NOT_SUPPORTED);
}
private void appendDataToDocument(NodeRef targetDocumentNodeRef, CmisPropertiesType properties, EnumVersioningState versioningState,
List<String> policies, CmisAccessControlListType addACEs, CmisAccessControlListType removeACEs, Holder<String> objectId)
throws CmisException
{
// TODO: process Policies and ACE
propertiesUtil.setProperties(targetDocumentNodeRef, properties, createPropertyFilter(createIgnoringFilter(new String[] { CMISDictionaryModel.PROP_NAME,
CMISDictionaryModel.PROP_OBJECT_TYPE_ID })));
String versionLabel = null;
// FIXME: change condition below to "typeDef.isVersionable()" when dictionary problem will be fixed
if (true)
{
versioningState = (null == versioningState) ? (EnumVersioningState.MINOR) : (versioningState);
switch (versioningState)
{
case CHECKEDOUT:
targetDocumentNodeRef = checkoutNode(targetDocumentNodeRef);
break;
case MAJOR:
this.versionService.createVersion(targetDocumentNodeRef, createVersionProperties(INITIAL_VERSION_DESCRIPTION, VersionType.MAJOR));
break;
case MINOR:
this.versionService.createVersion(targetDocumentNodeRef, createVersionProperties(INITIAL_VERSION_DESCRIPTION, VersionType.MINOR));
break;
}
versionLabel = propertiesUtil.getProperty(targetDocumentNodeRef, CMISDictionaryModel.PROP_VERSION_LABEL, "");
}
String createdObjectId = ((null != versionLabel) && versionLabel.contains(VERSION_DELIMETER)) ? (targetDocumentNodeRef.toString() + CmisObjectsUtils.NODE_REFERENCE_ID_DELIMETER + versionLabel)
: (targetDocumentNodeRef.toString());
objectId.value = createdObjectId;
}
private String createIgnoringFilter(String[] propertyNames)
{
StringBuilder filter = new StringBuilder("");
for (String propertyName : propertyNames)
{
if ((null != propertyName) && !propertyName.equals(""))
{
filter.append(propertyName);
filter.append(PropertyFilter.PROPERTY_NAME_TOKENS_DELIMETER);
}
}
if (filter.length() > 0)
{
filter.deleteCharAt(filter.length() - 1);
}
return filter.toString();
}
private String extractAndAssertTypeId(Map<String, Object> propertiesMap) throws CmisException
{
String typeId = (String) propertiesMap.get(CMISDictionaryModel.PROP_OBJECT_TYPE_ID);
if ((null == typeId) || "".equals(typeId))
{
throw cmisObjectsUtils.createCmisException("Type Id property required", EnumServiceException.INVALID_ARGUMENT);
}
return typeId;
}
private String checkConstraintsAndGetName(String documentTypeId, CMISTypeDefinition typeDef, NodeRef parentNodeRef, CmisContentStreamType contentStream,
Map<String, Object> propertiesMap, EnumVersioningState versioningState) throws CmisException
@@ -658,40 +745,41 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
throw cmisObjectsUtils.createCmisException(("Type with " + documentTypeId + "typeId was not found"), EnumServiceException.RUNTIME);
}
if ((typeDef.getTypeId().getScope() != CMISScope.DOCUMENT) || !typeDef.isCreatable())
if ((CMISScope.DOCUMENT != typeDef.getTypeId().getScope()) || !typeDef.isCreatable())
{
throw cmisObjectsUtils.createCmisException(("Invalid document type \"" + documentTypeId + "\". Specified type is not Document type or type is not Creatable"),
throw cmisObjectsUtils.createCmisException(("Invalid document type \"" + documentTypeId + "\". This type is not a Creatable Document type"),
EnumServiceException.CONSTRAINT);
}
if (CMISContentStreamAllowedEnum.NOT_ALLOWED == typeDef.getContentStreamAllowed())
if ((null != contentStream) && CMISContentStreamAllowedEnum.NOT_ALLOWED == typeDef.getContentStreamAllowed())
{
throw cmisObjectsUtils.createCmisException(("Content stream not allowed for \"" + documentTypeId + "\" document object type"),
EnumServiceException.STREAM_NOT_SUPPORTED);
}
else
{
if ((CMISContentStreamAllowedEnum.REQUIRED == typeDef.getContentStreamAllowed()) && (contentStream == null))
if ((CMISContentStreamAllowedEnum.REQUIRED == typeDef.getContentStreamAllowed()) && (null == contentStream))
{
throw cmisObjectsUtils.createCmisException("Content stream for document object of " + documentTypeId + " type is required", EnumServiceException.CONSTRAINT);
}
}
if (typeDef.isVersionable() && (versioningState != null))
// FIXME: change condition below to "!typeDef.isVersionable() && (null != versioningState)" when dictionary problem will be fixed
if (false)
{
throw cmisObjectsUtils.createCmisException(("Verioning for \"" + documentTypeId + "\" document type is not allowed"), EnumServiceException.CONSTRAINT);
}
String folderTypeId = propertiesUtil.getProperty(parentNodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, null);
CMISTypeDefinition folderTypeDefinition = cmisDictionaryService.findType(folderTypeId);
if ((folderTypeDefinition.getAllowedTargetTypes() != null) && !folderTypeDefinition.getAllowedTargetTypes().isEmpty()
if ((null != folderTypeDefinition.getAllowedTargetTypes()) && !folderTypeDefinition.getAllowedTargetTypes().isEmpty()
&& !folderTypeDefinition.getAllowedTargetTypes().contains(typeDef))
{
throw cmisObjectsUtils.createCmisException(("Children of \"" + documentTypeId + "\" type are not allowed for specified folder"), EnumServiceException.CONSTRAINT);
}
String result = (String) propertiesMap.get(CMISDictionaryModel.PROP_NAME);
if (result == null)
if (null == result)
{
throw cmisObjectsUtils.createCmisException("Name property not found", EnumServiceException.INVALID_ARGUMENT);
}
@@ -708,15 +796,20 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
}
}
private NodeRef resolvePathInfo(NodeRef rootNodeRef, String folderPath)
private NodeRef resolvePathInfo(NodeRef rootNodeRef, String folderPath) throws CmisException
{
Pattern pathMatchingPattern = Pattern.compile(FOLDER_PATH_MATCHING_PATTERN);
Matcher matcher = pathMatchingPattern.matcher(folderPath);
if (!matcher.matches())
{
throw cmisObjectsUtils
.createCmisException(
"Folder path is invalid. Folder Path should be started with '/' (point of Root Folder) and containing several Path Elements (Folder Names) separated by '/'-symbol and containing no '/'-symbols in the end. Folder Path can't be resolved correctly",
EnumServiceException.INVALID_ARGUMENT);
}
NodeRef result = null;
folderPath = folderPath.replaceAll("//", "/");
if (folderPath.startsWith("/"))
folderPath = folderPath.substring(1);
if (folderPath.endsWith("/"))
folderPath = folderPath.substring(0, folderPath.length() - 1);
if (folderPath.length() == 0)
folderPath = folderPath.substring(1);
if ("".equals(folderPath))
{
result = rootNodeRef;
}
@@ -725,8 +818,8 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
FileInfo fileInfo = null;
try
{
List<String> splitPath = Arrays.asList(folderPath.split("/"));
fileInfo = fileFolderService.resolveNamePath(rootNodeRef, splitPath);
List<String> splitedPath = Arrays.asList(folderPath.split("/"));
fileInfo = fileFolderService.resolveNamePath(rootNodeRef, splitedPath);
}
catch (FileNotFoundException e)
{
@@ -759,13 +852,26 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
throw cmisObjectsUtils.createCmisException("Content Stream Deletion is not allowed for specified Object", EnumServiceException.UPDATE_CONFLICT);
}
}
public void deleteAllVersions(String repositoryId, String versionSeriesId) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(versionSeriesId, AlfrescoObjectType.DOCUMENT_OBJECT);
NodeRef workingCopyRef = (cmisObjectsUtils.isWorkingCopy(documentNodeRef)) ? (documentNodeRef) : (checkOutCheckInService.getWorkingCopy(documentNodeRef));
if ((null != workingCopyRef) && cmisObjectsUtils.isWorkingCopy(workingCopyRef))
{
documentNodeRef = checkOutCheckInService.cancelCheckout(workingCopyRef);
}
versionService.deleteVersionHistory(documentNodeRef);
}
private ContentReader safeGetContentReader(NodeRef objectNodeReference) throws CmisException
{
ContentReader reader = fileFolderService.getReader(objectNodeReference);
if (reader == null)
{
throw cmisObjectsUtils.createCmisException("The specified Document has no Content Stream", EnumServiceException.INVALID_ARGUMENT);
throw cmisObjectsUtils.createCmisException("The specified Document has no Content Stream", EnumServiceException.CONSTRAINT);
}
return reader;
}
@@ -778,7 +884,7 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
}
catch (CmisException e)
{
throw cmisObjectsUtils.createCmisException("Unfiling is not suppoerted. Each Document must have existent parent Folder", EnumServiceException.OBJECT_NOT_FOUND, e);
throw cmisObjectsUtils.createCmisException("Unfiling is not suppoerted. Each Document must have existent parent Folder", EnumServiceException.CONSTRAINT, e);
}
}
@@ -821,89 +927,6 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
// }
// }
private CmisAllowableActionsType determineObjectAllowableActions(Object objectIdentifier) throws CmisException
{
if (objectIdentifier instanceof AssociationRef)
{
return determineRelationshipAllowableActions((AssociationRef) objectIdentifier);
}
switch (cmisObjectsUtils.determineObjectType(objectIdentifier.toString()))
{
case CMIS_DOCUMENT:
{
return determineDocumentAllowableActions((NodeRef) objectIdentifier);
}
case CMIS_FOLDER:
{
return determineFolderAllowableActions((NodeRef) objectIdentifier);
}
}
// TODO: determinePolicyAllowableActions() when Policy functionality is ready
throw cmisObjectsUtils.createCmisException("It is impossible to get Allowable actions for the specified Object", EnumServiceException.NOT_SUPPORTED);
}
private CmisAllowableActionsType determineBaseAllowableActions(NodeRef objectNodeReference)
{
CmisAllowableActionsType result = new CmisAllowableActionsType();
result.setCanGetProperties(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_PROPERTIES) == AccessStatus.ALLOWED);
result.setCanUpdateProperties(this.permissionService.hasPermission(objectNodeReference, PermissionService.WRITE_PROPERTIES) == AccessStatus.ALLOWED);
result.setCanDeleteObject(this.permissionService.hasPermission(objectNodeReference, PermissionService.DELETE) == AccessStatus.ALLOWED);
// TODO: response.setCanAddPolicy(value);
// TODO: response.setCanRemovePolicy(value);
// TODO: response.setCanGetAppliedPolicies(value);
return result;
}
private CmisAllowableActionsType determineDocumentAllowableActions(NodeRef objectNodeReference)
{
CmisAllowableActionsType result = determineBaseAllowableActions(objectNodeReference);
determineCommonFolderDocumentAllowableActions(objectNodeReference, result);
result.setCanGetObjectParents(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_ASSOCIATIONS) == AccessStatus.ALLOWED);
result.setCanGetContentStream(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_CONTENT) == AccessStatus.ALLOWED);
result.setCanSetContentStream(this.permissionService.hasPermission(objectNodeReference, PermissionService.WRITE_CONTENT) == AccessStatus.ALLOWED);
result.setCanCheckOut(this.permissionService.hasPermission(objectNodeReference, PermissionService.CHECK_OUT) == AccessStatus.ALLOWED);
result.setCanCheckIn(this.permissionService.hasPermission(objectNodeReference, PermissionService.CHECK_IN) == AccessStatus.ALLOWED);
result.setCanCancelCheckOut(this.permissionService.hasPermission(objectNodeReference, PermissionService.CANCEL_CHECK_OUT) == AccessStatus.ALLOWED);
result.setCanDeleteContentStream(result.isCanUpdateProperties() && result.isCanSetContentStream());
return result;
}
private CmisAllowableActionsType determineFolderAllowableActions(NodeRef objectNodeReference)
{
CmisAllowableActionsType result = determineBaseAllowableActions(objectNodeReference);
determineCommonFolderDocumentAllowableActions(objectNodeReference, result);
result.setCanGetChildren(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_CHILDREN) == AccessStatus.ALLOWED);
result.setCanCreateDocument(this.permissionService.hasPermission(objectNodeReference, PermissionService.ADD_CHILDREN) == AccessStatus.ALLOWED);
result.setCanGetDescendants(result.isCanGetChildren() && (this.permissionService.hasPermission(objectNodeReference, PermissionService.READ) == AccessStatus.ALLOWED));
result.setCanDeleteTree(this.permissionService.hasPermission(objectNodeReference, PermissionService.DELETE_CHILDREN) == AccessStatus.ALLOWED);
result.setCanGetFolderParent(result.isCanGetRelationships());
result.setCanCreateFolder(result.isCanCreateDocument());
// TODO: response.setCanCreatePolicy(value);
return result;
}
private void determineCommonFolderDocumentAllowableActions(NodeRef objectNodeReference, CmisAllowableActionsType allowableActions)
{
allowableActions.setCanAddObjectToFolder(this.permissionService.hasPermission(objectNodeReference, PermissionService.CREATE_ASSOCIATIONS) == AccessStatus.ALLOWED);
allowableActions.setCanGetRelationships(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_ASSOCIATIONS) == AccessStatus.ALLOWED);
allowableActions.setCanMoveObject(allowableActions.isCanUpdateProperties() && allowableActions.isCanAddObjectToFolder());
allowableActions.setCanRemoveObjectFromFolder(allowableActions.isCanUpdateProperties());
allowableActions.setCanCreateRelationship(allowableActions.isCanAddObjectToFolder());
}
private CmisAllowableActionsType determineRelationshipAllowableActions(AssociationRef association)
{
CmisAllowableActionsType result = new CmisAllowableActionsType();
result.setCanDeleteObject(this.permissionService.hasPermission(association.getSourceRef(), PermissionService.DELETE_ASSOCIATIONS) == AccessStatus.ALLOWED);
result.setCanGetRelationships(this.permissionService.hasPermission(association.getSourceRef(), PermissionService.READ_ASSOCIATIONS) == AccessStatus.ALLOWED);
return result;
}
private void determineException(Throwable lastException) throws CmisException
{
if (lastException instanceof AccessDeniedException)

View File

@@ -26,7 +26,9 @@ package org.alfresco.repo.cmis.ws;
import java.util.List;
@javax.jws.WebService(name = "PolicyServicePort", serviceName = "PolicyServicePort", portName = "PolicyServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200901", endpointInterface = "org.alfresco.repo.cmis.ws.PolicyServicePort")
import javax.xml.ws.Holder;
@javax.jws.WebService(name = "PolicyServicePort", serviceName = "PolicyServicePort", portName = "PolicyServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200908/", endpointInterface = "org.alfresco.repo.cmis.ws.PolicyServicePort")
public class DMPolicyServicePort extends DMAbstractServicePort implements PolicyServicePort
{
private static final String POLICY_NOT_SUPPORTED_MESSAGE = "PolicyService not implemented";
@@ -39,7 +41,7 @@ public class DMPolicyServicePort extends DMAbstractServicePort implements Policy
* @param objectId target object Id
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT)
*/
public void applyPolicy(String repositoryId, String policyId, String objectId) throws CmisException
public void applyPolicy(String repositoryId, String policyId, String objectId, Holder<CmisExtensionType> extension) throws CmisException
{
throw cmisObjectsUtils.createCmisException(POLICY_NOT_SUPPORTED_MESSAGE, EnumServiceException.RUNTIME);
}
@@ -50,7 +52,7 @@ public class DMPolicyServicePort extends DMAbstractServicePort implements Policy
* @param parameters repositoryId: repository Id; objectId: target object Id; filter: filter specifying which properties to return
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, FILTER_NOT_VALID)
*/
public List<CmisObjectType> getAppliedPolicies(String repositoryId, String objectId, String filter) throws CmisException
public List<CmisObjectType> getAppliedPolicies(String repositoryId, String objectId, String filter, CmisExtensionType extension) throws CmisException
{
throw cmisObjectsUtils.createCmisException(POLICY_NOT_SUPPORTED_MESSAGE, EnumServiceException.RUNTIME);
}
@@ -63,7 +65,7 @@ public class DMPolicyServicePort extends DMAbstractServicePort implements Policy
* @param objectId target object Id.
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT)
*/
public void removePolicy(String repositoryId, String policyId, String objectId) throws CmisException
public void removePolicy(String repositoryId, String policyId, String objectId, Holder<CmisExtensionType> extension) throws CmisException
{
throw cmisObjectsUtils.createCmisException(POLICY_NOT_SUPPORTED_MESSAGE, EnumServiceException.RUNTIME);
}

View File

@@ -25,11 +25,8 @@
package org.alfresco.repo.cmis.ws;
import java.math.BigInteger;
import java.util.LinkedList;
import java.util.List;
import javax.xml.ws.Holder;
import org.alfresco.cmis.CMISScope;
import org.alfresco.cmis.CMISTypeDefinition;
import org.alfresco.repo.cmis.PropertyFilter;
@@ -46,7 +43,7 @@ import org.alfresco.service.namespace.QNamePattern;
*
* @author Dmitry Velichkevich
*/
@javax.jws.WebService(name = "RelationshipServicePort", serviceName = "RelationshipService", portName = "RelationshipServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200901", endpointInterface = "org.alfresco.repo.cmis.ws.RelationshipServicePort")
@javax.jws.WebService(name = "RelationshipServicePort", serviceName = "RelationshipService", portName = "RelationshipServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200908/", endpointInterface = "org.alfresco.repo.cmis.ws.RelationshipServicePort")
public class DMRelationshipServicePort extends DMAbstractServicePort implements RelationshipServicePort
{
private DictionaryService dictionaryService;
@@ -65,60 +62,48 @@ public class DMRelationshipServicePort extends DMAbstractServicePort implements
* @return collection of CmisObjectType and boolean hasMoreItems
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, FILTER_NOT_VALID)
*/
public void getRelationships(String repositoryId, String objectId, EnumRelationshipDirection direction, String typeId, Boolean includeSubRelationshipTypes, String filter,
Boolean includeAllowableActions, EnumIncludeRelationships includeRelationships, BigInteger maxItems, BigInteger skipCount, Holder<List<CmisObjectType>> object,
Holder<Boolean> hasMoreItems) throws CmisException
public CmisObjectListType getObjectRelationships(String repositoryId, String objectId, Boolean includeSubRelationshipTypes, EnumRelationshipDirection relationshipDirection,
String typeId, String filter, Boolean includeAllowableActions, BigInteger maxItems, BigInteger skipCount, CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
direction = (null != direction) ? direction : EnumRelationshipDirection.SOURCE;
NodeRef objectNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT);
if (null == includeSubRelationshipTypes)
{
throw cmisObjectsUtils.createCmisException("includeSubRelationshipTypes input parameter is required", EnumServiceException.INVALID_ARGUMENT);
}
relationshipDirection = (null != relationshipDirection) ? relationshipDirection : EnumRelationshipDirection.SOURCE;
skipCount = (null != skipCount) ? skipCount : BigInteger.ZERO;
maxItems = (null != maxItems) ? maxItems : BigInteger.ZERO;
QName associationType = null;
if ((null != typeId) && !typeId.equals(""))
if ((null != typeId) && !"".equals(typeId))
{
CMISTypeDefinition cmisTypeDef = cmisDictionaryService.findType(typeId);
associationType = cmisTypeDef.getTypeId().getQName();
}
// TODO: process 'includeAllowableActions' param, see DMObjectServicePort->determineObjectAllowableActions
PropertyFilter propertyFilter = createPropertyFilter(filter);
NodeRef objectNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT);
List<AssociationRef> assocs = null;
try
{
assocs = cmisObjectsUtils.receiveAssociations(objectNodeRef, new RelationshipTypeFilter(associationType, includeSubRelationshipTypes), direction);
assocs = cmisObjectsUtils.receiveAssociations(objectNodeRef, new RelationshipTypeFilter(associationType, includeSubRelationshipTypes), relationshipDirection);
}
catch (Exception e)
{
throw cmisObjectsUtils.createCmisException("Can't receive associations", e);
}
if (null == object)
{
object = new Holder<List<CmisObjectType>>();
}
object.value = formatResponse(propertyFilter, assocs.toArray(), skipCount, maxItems, hasMoreItems);
return createResult(propertyFilter, includeAllowableActions, assocs.toArray(), skipCount, maxItems);
}
private List<CmisObjectType> formatResponse(PropertyFilter filter, Object[] sourceArray, BigInteger skipCount, BigInteger maxItems, Holder<Boolean> hasMoreItems)
private CmisObjectListType createResult(PropertyFilter filter, boolean includeAllowableActions, Object[] sourceArray, BigInteger skipCount, BigInteger maxItems)
throws CmisException
{
Cursor cursor = createCursor(sourceArray.length, skipCount, maxItems);
List<CmisObjectType> result = new LinkedList<CmisObjectType>();
CmisObjectListType result = new CmisObjectListType();
for (int i = cursor.getStartRow(); i < cursor.getEndRow(); i++)
{
result.add(createCmisObject(sourceArray[i].toString(), filter));
result.getObjects().add(createCmisObject(sourceArray[i].toString(), filter, includeAllowableActions));
}
if (null == hasMoreItems)
{
hasMoreItems = new Holder<Boolean>();
}
hasMoreItems.value = cursor.getEndRow() < sourceArray.length;
result.setHasMoreItems(cursor.getEndRow() < sourceArray.length);
result.setNumItems(BigInteger.valueOf(cursor.getPageSize()));
return result;
}
@@ -142,7 +127,7 @@ public class DMRelationshipServicePort extends DMAbstractServicePort implements
else if (includeSubtypes)
{
// TODO: it is necessary introduce checking on descendants
return dictionaryService.getAssociation(qname) != null;
return null != dictionaryService.getAssociation(qname);
}
else
{

View File

@@ -33,8 +33,7 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.xml.ws.Holder;
import java.util.Queue;
import org.alfresco.cmis.CMISCardinalityEnum;
import org.alfresco.cmis.CMISChoice;
@@ -46,6 +45,7 @@ import org.alfresco.cmis.CMISPropertyDefinition;
import org.alfresco.cmis.CMISQueryEnum;
import org.alfresco.cmis.CMISTypeDefinition;
import org.alfresco.cmis.CMISUpdatabilityEnum;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.web.util.paging.Cursor;
import org.alfresco.service.descriptor.Descriptor;
@@ -54,7 +54,7 @@ import org.alfresco.service.descriptor.Descriptor;
*
* @author Dmitry Lazurkin
*/
@javax.jws.WebService(name = "RepositoryServicePort", serviceName = "RepositoryService", portName = "RepositoryServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200901", endpointInterface = "org.alfresco.repo.cmis.ws.RepositoryServicePort")
@javax.jws.WebService(name = "RepositoryServicePort", serviceName = "RepositoryService", portName = "RepositoryServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200908/", endpointInterface = "org.alfresco.repo.cmis.ws.RepositoryServicePort")
public class DMRepositoryServicePort extends DMAbstractServicePort implements RepositoryServicePort
{
private static Map<CMISJoinEnum, EnumCapabilityJoin> joinEnumMapping;
@@ -64,7 +64,7 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re
private static Map<CMISDataTypeEnum, EnumPropertyType> propertyTypeEnumMapping;
private static HashMap<CMISQueryEnum, EnumCapabilityQuery> queryTypeEnumMapping;
// TODO: Hardcoded! should be reteived using standart mechanism
// FIXME: Hard-coded! should be retrieved using standard mechanism
private String repositoryUri = " http://localhost:8080/alfresco/cmis";
static
@@ -108,207 +108,68 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re
}
/**
* Gets a list of available repositories for this CMIS service endpoint.
* Add property definitions to list of definitions
*
* @return collection of CmisRepositoryEntryType (repositoryId - repository Id, repositoryName: repository name, repositoryURI: Repository URI)
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME)
* @param propertyDefinition repository property definition
* @param wsPropertyDefs web service property definition
*/
public List<CmisRepositoryEntryType> getRepositories() throws CmisException
private void addPropertyDefs(CMISTypeDefinition typeDefinition, CMISPropertyDefinition propertyDefinition, List<CmisPropertyDefinitionType> wsPropertyDefs)
throws CmisException
{
CmisRepositoryEntryType repositoryEntryType = new CmisRepositoryEntryType();
Descriptor serverDescriptor = descriptorService.getCurrentRepositoryDescriptor();
repositoryEntryType.setId(serverDescriptor.getId());
repositoryEntryType.setName(serverDescriptor.getName());
repositoryEntryType.setRelationship(serverDescriptor.getName());
// TODO: Hardcoded! repositoryUri should be retrieved using standard mechanism
repositoryEntryType.setThinClientURI(repositoryUri);
List<CmisRepositoryEntryType> result = new LinkedList<CmisRepositoryEntryType>();
result.add(repositoryEntryType);
return result;
CmisPropertyDefinitionType wsPropertyDef = createPropertyDefinitionType(propertyDefinition.getDataType());
wsPropertyDef.setLocalName(propertyDefinition.getPropertyId().getLocalName());
wsPropertyDef.setId(propertyDefinition.getPropertyId().getId());
wsPropertyDef.setDisplayName(propertyDefinition.getDisplayName());
wsPropertyDef.setDescription(propertyDefinition.getDescription());
wsPropertyDef.setPropertyType(propertyTypeEnumMapping.get(propertyDefinition.getDataType()));
wsPropertyDef.setCardinality(cardinalityEnumMapping.get(propertyDefinition.getCardinality()));
wsPropertyDef.setUpdatability(updatabilityEnumMapping.get(propertyDefinition.getUpdatability()));
wsPropertyDef.setInherited(!typeDefinition.getOwnedPropertyDefinitions().containsKey(propertyDefinition.getPropertyId()));
wsPropertyDef.setRequired(propertyDefinition.isRequired());
wsPropertyDef.setQueryable(propertyDefinition.isQueryable());
wsPropertyDef.setOrderable(propertyDefinition.isOrderable());
addChoices(propertyDefinition.getDataType(), propertyDefinition.getChoices(), getChoices(wsPropertyDef));
wsPropertyDef.setOpenChoice(propertyDefinition.isOpenChoice());
wsPropertyDefs.add(wsPropertyDef);
}
/**
* Gets information about the CMIS repository and the capabilities it supports.
* Add root choices to list of choices
*
* @param parameters repositoryId: repository Id
* @return CMIS repository Info
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME)
* @param propertyType type of property
* @param choices repository choice object
* @param cmisChoices web service choice object
*/
public CmisRepositoryInfoType getRepositoryInfo(String repositoryId) throws CmisException
private void addChoices(CMISDataTypeEnum propertyType, Collection<CMISChoice> choices, List<CmisChoice> cmisChoices)
{
checkRepositoryId(repositoryId);
Descriptor serverDescriptor = descriptorService.getCurrentRepositoryDescriptor();
CmisRepositoryInfoType repositoryInfoType = new CmisRepositoryInfoType();
repositoryInfoType.setRepositoryId(serverDescriptor.getId());
repositoryInfoType.setRepositoryName(serverDescriptor.getName());
repositoryInfoType.setRepositoryRelationship("self");
repositoryInfoType.setRepositoryDescription("");
repositoryInfoType.setVendorName("Alfresco");
repositoryInfoType.setProductName("Alfresco Repository (" + serverDescriptor.getEdition() + ")");
repositoryInfoType.setProductVersion(serverDescriptor.getVersion());
repositoryInfoType.setRootFolderId(propertiesUtil.getProperty(cmisService.getDefaultRootNodeRef(), CMISDictionaryModel.PROP_OBJECT_ID, (String) null));
repositoryInfoType.setThinClientURI(repositoryId);
CmisRepositoryCapabilitiesType capabilities = new CmisRepositoryCapabilitiesType();
capabilities.setCapabilityMultifiling(true);
capabilities.setCapabilityUnfiling(false);
capabilities.setCapabilityVersionSpecificFiling(false);
capabilities.setCapabilityPWCUpdateable(true);
capabilities.setCapabilityPWCSearchable(cmisQueryService.getPwcSearchable());
capabilities.setCapabilityAllVersionsSearchable(cmisQueryService.getAllVersionsSearchable());
capabilities.setCapabilityQuery(queryTypeEnumMapping.get(cmisQueryService.getQuerySupport()));
capabilities.setCapabilityJoin(joinEnumMapping.get(cmisQueryService.getJoinSupport()));
capabilities.setCapabilityACL(EnumCapabilityACL.NONE);
capabilities.setCapabilityChanges(EnumCapabilityChanges.NONE);
capabilities.setCapabilityContentStreamUpdatability(EnumCapabilityContentStreamUpdates.ANYTIME);
capabilities.setCapabilityGetDescendants(true);
capabilities.setCapabilityRenditions(EnumCapabilityRendition.NONE);
repositoryInfoType.setCapabilities(capabilities);
repositoryInfoType.setCmisVersionSupported(BigDecimal.valueOf(0.62));
// TODO: cmisVersionSupported is different in stubs and specification
// repositoryInfoType.setCmisVersionSupported(cmisService.getCMISVersion());
return repositoryInfoType;
for (CMISChoice choice : choices)
{
CmisChoice cmisChoiceType = getCmisChoiceType(choice, propertyType);
cmisChoices.add(cmisChoiceType);
if (choice.getChildren().isEmpty() == false)
{
addChoiceChildrens(propertyType, choice.getChildren(), cmisChoices);
}
}
}
/**
* Gets the definition for specified object type
*
* @param parameters repositoryId: repository Id; typeId: type Id;
* @return CMIS type definition
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME)
*/
public CmisTypeDefinitionType getTypeDefinition(String repositoryId, String typeId) throws CmisException
@SuppressWarnings("unchecked")
private List<CmisChoice> getChoices(CmisPropertyDefinitionType propertyDef)
{
checkRepositoryId(repositoryId);
CMISTypeDefinition typeDef;
try
List<CmisChoice> result = null;
if (propertyDef != null)
{
typeDef = cmisDictionaryService.findType(typeId);
}
catch (Exception e)
{
throw cmisObjectsUtils.createCmisException(e.toString(), EnumServiceException.INVALID_ARGUMENT);
}
return getCmisTypeDefinition(typeDef, true);
}
/**
* Returns the set of descendant Object-Types defined for the Repository under the specified Type.
*
* @param parameters srepositoryId: repository Id; typeId: type Id; includePropertyDefinitions: false (default); depth: The number of levels of depth in the type hierarchy from
* which to return results;
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME)
*/
public List<CmisTypeContainer> getTypeDescendants(String repositoryId, String typeId, BigInteger depth, Boolean includePropertyDefinitions) throws CmisException
{
checkRepositoryId(repositoryId);
Collection<CMISTypeDefinition> typeDefs = new LinkedList<CMISTypeDefinition>();
if ((typeId == null) || typeId.equals(""))
{
typeDefs = cmisDictionaryService.getBaseTypes();
}
else
{
CMISTypeDefinition typeDef = null;
try
{
typeDef = cmisDictionaryService.findType(typeId);
result = (List<CmisChoice>) propertyDef.getClass().getMethod("getChoice").invoke(propertyDef);
}
catch (Exception e)
{
throw cmisObjectsUtils.createCmisException(e.toString(), EnumServiceException.INVALID_ARGUMENT);
}
if (null == typeDef)
{
throw cmisObjectsUtils.createCmisException(("Invalid type id: \"" + typeId + "\""), EnumServiceException.INVALID_ARGUMENT);
}
typeDefs.add(typeDef);
}
long depthLong = depth == null || depth.equals(BigInteger.valueOf(-1)) ? Long.MAX_VALUE : depth.longValue();
boolean includePropertyDefsBool = includePropertyDefinitions == null ? false : includePropertyDefinitions;
List<CmisTypeContainer> result = new LinkedList<CmisTypeContainer>();
for (CMISTypeDefinition typeDef : typeDefs)
{
result.add(getTypeDescedants(typeDef, depthLong, includePropertyDefsBool));
}
return result;
}
/**
* Returns the list of Object-Types defined for the Repository under the specified Type.
*
* @param parameters repositoryId: repository Id; typeId: type Id; returnPropertyDefinitions: false (default); maxItems: 0 = Repository-default number of items(Default);
* skipCount: 0 = start;
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME)
*/
public void getTypeChildren(String repositoryId, String typeId, Boolean returnPropertyDefinitions, BigInteger maxItems, BigInteger skipCount,
Holder<List<CmisTypeDefinitionType>> type, Holder<Boolean> hasMoreItems) throws CmisException
{
checkRepositoryId(repositoryId);
Collection<CMISTypeDefinition> typeDefs = new LinkedList<CMISTypeDefinition>();
if ((typeId == null) || typeId.equals(""))
{
typeDefs = cmisDictionaryService.getBaseTypes();
}
else
{
CMISTypeDefinition typeDef = null;
try
{
typeDef = cmisDictionaryService.findType(typeId);
}
catch (RuntimeException exception)
{
throw cmisObjectsUtils.createCmisException(exception.toString(), EnumServiceException.INVALID_ARGUMENT);
}
if (null == typeDef)
{
throw cmisObjectsUtils.createCmisException(("Invalid type id: \"" + typeId + "\""), EnumServiceException.INVALID_ARGUMENT);
}
typeDefs.add(typeDef);
Collection<CMISTypeDefinition> subTypes = typeDef.getSubTypes(true);
if (null != subTypes)
{
typeDefs.addAll(subTypes);
}
}
// skip
Cursor cursor = createCursor(typeDefs.size(), skipCount, maxItems);
Iterator<CMISTypeDefinition> iterTypeDefs = typeDefs.iterator();
for (int i = 0; i < cursor.getStartRow(); i++)
{
iterTypeDefs.next();
}
boolean returnPropertyDefinitionsVal = returnPropertyDefinitions == null ? false : returnPropertyDefinitions.booleanValue();
type.value = new LinkedList<CmisTypeDefinitionType>();
for (int i = cursor.getStartRow(); i <= cursor.getEndRow(); i++)
{
CmisTypeDefinitionType element = getCmisTypeDefinition(iterTypeDefs.next(), returnPropertyDefinitionsVal);
if (element != null)
{
type.value.add(element);
}
else
{
throw cmisObjectsUtils.createCmisException(("Subtypes collection is corrupted. Type id: " + typeId), EnumServiceException.STORAGE);
}
}
hasMoreItems.value = ((maxItems == null) || (maxItems.intValue() == 0)) ? (false) : ((cursor.getEndRow() < (typeDefs.size() - 1)));
}
/**
* Create web service choice object from repository choice object
*
@@ -369,27 +230,7 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re
}
/**
* Add root choices to list of choices
*
* @param propertyType type of property
* @param choices repository choice object
* @param cmisChoices web service choice object
*/
private void addChoices(CMISDataTypeEnum propertyType, Collection<CMISChoice> choices, List<CmisChoice> cmisChoices)
{
for (CMISChoice choice : choices)
{
CmisChoice cmisChoiceType = getCmisChoiceType(choice, propertyType);
cmisChoices.add(cmisChoiceType);
if (choice.getChildren().isEmpty() == false)
{
addChoiceChildrens(propertyType, choice.getChildren(), cmisChoices);
}
}
}
/**
* Add choices childrens to list of JAXBElements
* Add choices children to list of JAXBElements
*
* @param propertyType type of property
* @param choices repository choice object
@@ -409,79 +250,36 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re
}
}
/**
* Add property definitions to list of definitions
*
* @param propertyDefinition repository property definition
* @param wsPropertyDefs web service property definition
*/
private void addPropertyDefs(CMISTypeDefinition typeDefinition, CMISPropertyDefinition propertyDefinition, List<CmisPropertyDefinitionType> wsPropertyDefs)
throws CmisException
{
CmisPropertyDefinitionType wsPropertyDef = createPropertyDefinitionType(propertyDefinition.getDataType());
wsPropertyDef.setLocalName(propertyDefinition.getPropertyId().getLocalName());
wsPropertyDef.setId(propertyDefinition.getPropertyId().getId());
wsPropertyDef.setDisplayName(propertyDefinition.getDisplayName());
wsPropertyDef.setDescription(propertyDefinition.getDescription());
wsPropertyDef.setPropertyType(propertyTypeEnumMapping.get(propertyDefinition.getDataType()));
wsPropertyDef.setCardinality(cardinalityEnumMapping.get(propertyDefinition.getCardinality()));
wsPropertyDef.setUpdatability(updatabilityEnumMapping.get(propertyDefinition.getUpdatability()));
wsPropertyDef.setInherited(!typeDefinition.getOwnedPropertyDefinitions().containsKey(propertyDefinition.getPropertyId()));
wsPropertyDef.setRequired(propertyDefinition.isRequired());
wsPropertyDef.setQueryable(propertyDefinition.isQueryable());
wsPropertyDef.setOrderable(propertyDefinition.isOrderable());
addChoices(propertyDefinition.getDataType(), propertyDefinition.getChoices(), getChoices(wsPropertyDef));
wsPropertyDef.setOpenChoice(propertyDefinition.isOpenChoice());
wsPropertyDefs.add(wsPropertyDef);
}
private CmisTypeContainer getTypeDescedants(CMISTypeDefinition typeDef, long depth, boolean includePropertyDefs) throws CmisException
{
if (depth < 0)
{
return null;
}
CmisTypeContainer container = new CmisTypeContainer();
CmisTypeDefinitionType targetTypeDef = getCmisTypeDefinition(typeDef, includePropertyDefs);
if (targetTypeDef != null)
{
container.setType(targetTypeDef);
Collection<CMISTypeDefinition> subTypes = typeDef.getSubTypes(false);
if (subTypes != null)
{
for (CMISTypeDefinition subType : subTypes)
{
CmisTypeContainer child = getTypeDescedants(subType, depth - 1, includePropertyDefs);
if (child != null)
{
container.getChildren().add(child);
}
}
}
}
else
{
throw cmisObjectsUtils.createCmisException(("Subtypes collection is corrupted. Type id: " + targetTypeDef), EnumServiceException.STORAGE);
}
return container;
}
@SuppressWarnings("unchecked")
private static List<CmisChoice> getChoices(CmisPropertyDefinitionType propertyDef)
{
List<CmisChoice> result = null;
if (propertyDef != null)
{
try
{
result = (List<CmisChoice>) propertyDef.getClass().getMethod("getChoice").invoke(propertyDef);
}
catch (Exception e)
{
}
}
return result;
}
// private CmisTypeContainer getTypeDescendants(CMISTypeDefinition typeDef, long depth, boolean includePropertyDefs) throws CmisException
// {
// if (depth < 0)
// {
// return null;
// }
// CmisTypeContainer container = new CmisTypeContainer();
// CmisTypeDefinitionType targetTypeDef = getCmisTypeDefinition(typeDef, includePropertyDefs);
// if (targetTypeDef != null)
// {
// container.setType(targetTypeDef);
// Collection<CMISTypeDefinition> subTypes = typeDef.getSubTypes(false);
// if (subTypes != null)
// {
// for (CMISTypeDefinition subType : subTypes)
// {
// CmisTypeContainer child = getTypeDescendants(subType, depth - 1, includePropertyDefs);
// if (child != null)
// {
// container.getChildren().add(child);
// }
// }
// }
// }
// else
// {
// throw cmisObjectsUtils.createCmisException(("Subtypes collection is corrupted. Type id: " + targetTypeDef), EnumServiceException.STORAGE);
// }
// return container;
// }
private CmisPropertyDefinitionType createPropertyDefinitionType(CMISDataTypeEnum type) throws CmisException
{
@@ -542,7 +340,7 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re
cmisTypeDefinition.setId(typeDefinition.getTypeId().getId());
cmisTypeDefinition.setQueryName(typeDefinition.getQueryName());
cmisTypeDefinition.setDisplayName(typeDefinition.getDisplayName());
cmisTypeDefinition.setBaseTypeId(EnumBaseObjectTypeIds.fromValue(typeDefinition.getBaseType().getTypeId().getId()));
cmisTypeDefinition.setBaseId(EnumBaseObjectTypeIds.fromValue(typeDefinition.getBaseType().getTypeId().getId()));
if ((null != typeDefinition.getParentType()) && (null != typeDefinition.getParentType().getTypeId()))
{
@@ -631,4 +429,259 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re
return result;
}
/**
* Gets a list of available repositories for this CMIS service endpoint.
*
* @return collection of CmisRepositoryEntryType (repositoryId - repository Id, repositoryName: repository name, repositoryURI: Repository URI)
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME)
*/
public List<CmisRepositoryEntryType> getRepositories(CmisExtensionType extension) throws CmisException
{
CmisRepositoryEntryType repositoryEntryType = new CmisRepositoryEntryType();
Descriptor serverDescriptor = descriptorService.getCurrentRepositoryDescriptor();
repositoryEntryType.setRepositoryId(serverDescriptor.getId());
repositoryEntryType.setRepositoryName(serverDescriptor.getName());
List<CmisRepositoryEntryType> result = new LinkedList<CmisRepositoryEntryType>();
result.add(repositoryEntryType);
return result;
}
/**
* Gets information about the CMIS repository and the capabilities it supports.
*
* @param parameters repositoryId: repository Id
* @return CMIS repository Info
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME)
*/
public CmisRepositoryInfoType getRepositoryInfo(String repositoryId, CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
Descriptor serverDescriptor = descriptorService.getCurrentRepositoryDescriptor();
CmisRepositoryInfoType repositoryInfoType = new CmisRepositoryInfoType();
repositoryInfoType.setRepositoryId(serverDescriptor.getId());
repositoryInfoType.setRepositoryName(serverDescriptor.getName());
repositoryInfoType.setRepositoryDescription("");
repositoryInfoType.setVendorName("Alfresco");
repositoryInfoType.setProductName("Alfresco Repository (" + serverDescriptor.getEdition() + ")");
repositoryInfoType.setProductVersion(serverDescriptor.getVersion());
repositoryInfoType.setRootFolderId(propertiesUtil.getProperty(cmisService.getDefaultRootNodeRef(), CMISDictionaryModel.PROP_OBJECT_ID, (String) null));
repositoryInfoType.setLatestChangeLogToken(""); // TODO
// TODO: cmisVersionSupported is different in stubs and specification
repositoryInfoType.setCmisVersionSupported(BigDecimal.valueOf(0.723)); // TODO: ask how to specify supported version like '0.7b3'
repositoryInfoType.setThinClientURI(repositoryUri);
repositoryInfoType.setChangesIncomplete(true); // TODO
// TODO: set chnagedOnType via getChangesOnType().add()...
// repositoryInfoType.getChangesOnType();
// FIXME [BUG]: 'supportedPermissions' defined in spec. is absent in schema
// FIXME [BUG]: 'propagate' defined in spec. is absent in schema
// FIXME [BUG]: 'repositoryPermissions' defined in spec. is absent in schema
// FIXME [BUG]: 'mappings' defined in spec. is absent in schema
repositoryInfoType.setPrincipalAnonymous(AuthenticationUtil.getGuestUserName());
repositoryInfoType.setPrincipalAnyone(""); // TODO
CmisRepositoryCapabilitiesType capabilities = new CmisRepositoryCapabilitiesType();
capabilities.setCapabilityGetDescendants(true);
capabilities.setCapabilityGetFolderTree(true);
capabilities.setCapabilityContentStreamUpdatability(EnumCapabilityContentStreamUpdates.ANYTIME);
capabilities.setCapabilityChanges(EnumCapabilityChanges.NONE); // TODO
capabilities.setCapabilityRenditions(EnumCapabilityRendition.NONE); // TODO
capabilities.setCapabilityMultifiling(true);
capabilities.setCapabilityUnfiling(false);
capabilities.setCapabilityVersionSpecificFiling(false);
capabilities.setCapabilityPWCUpdatable(true);
capabilities.setCapabilityPWCSearchable(cmisQueryService.getPwcSearchable());
capabilities.setCapabilityAllVersionsSearchable(cmisQueryService.getAllVersionsSearchable());
capabilities.setCapabilityQuery(queryTypeEnumMapping.get(cmisQueryService.getQuerySupport()));
capabilities.setCapabilityJoin(joinEnumMapping.get(cmisQueryService.getJoinSupport()));
capabilities.setCapabilityACL(EnumCapabilityACL.NONE); // TODO
repositoryInfoType.setCapabilities(capabilities);
repositoryInfoType.setCmisVersionSupported(BigDecimal.valueOf(0.62));
return repositoryInfoType;
}
/**
* Returns the list of Object-Types defined for the Repository under the specified Type.
*
* @param parameters repositoryId: repository Id; typeId: type Id; returnPropertyDefinitions: false (default); maxItems: 0 = Repository-default number of items(Default);
* skipCount: 0 = start;
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME)
*/
public CmisTypeDefinitionListType getTypeChildren(String repositoryId, String typeId, Boolean includePropertyDefinitions, BigInteger maxItems, BigInteger skipCount,
CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
Collection<CMISTypeDefinition> typeDefs = getBaseTypesCollection(typeId, true);
// skip
Cursor cursor = createCursor(typeDefs.size(), skipCount, maxItems);
Iterator<CMISTypeDefinition> iterTypeDefs = typeDefs.iterator();
for (int i = 0; i < cursor.getStartRow(); i++)
{
iterTypeDefs.next();
}
boolean includePropertyDefinitionsVal = includePropertyDefinitions == null ? false : includePropertyDefinitions.booleanValue();
CmisTypeDefinitionListType result = new CmisTypeDefinitionListType();
for (int i = cursor.getStartRow(); i <= cursor.getEndRow(); i++)
{
CmisTypeDefinitionType element = getCmisTypeDefinition(iterTypeDefs.next(), includePropertyDefinitionsVal);
if (null != element)
{
result.getTypes().add(element);
}
else
{
throw cmisObjectsUtils.createCmisException(("Subtypes collection is corrupted. Type id: " + typeId), EnumServiceException.STORAGE);
}
}
result.setHasMoreItems(((maxItems == null) || (0 == maxItems.intValue())) ? (false) : ((cursor.getEndRow() < (typeDefs.size() - 1))));
result.setNumItems(BigInteger.valueOf(result.getTypes().size()));
return result;
}
/**
* Gets the definition for specified object type
*
* @param parameters repositoryId: repository Id; typeId: type Id;
* @return CMIS type definition
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME)
*/
public CmisTypeDefinitionType getTypeDefinition(String repositoryId, String typeId, CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
CMISTypeDefinition typeDef;
try
{
typeDef = cmisDictionaryService.findType(typeId);
}
catch (Exception e)
{
throw cmisObjectsUtils.createCmisException(e.toString(), EnumServiceException.INVALID_ARGUMENT);
}
return getCmisTypeDefinition(typeDef, true);
}
/**
* Returns the set of descendant Object-Types defined for the Repository under the specified Type.
*
* @param parameters srepositoryId: repository Id; typeId: type Id; includePropertyDefinitions: false (default); depth: The number of levels of depth in the type hierarchy from
* which to return results;
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME)
*/
public List<CmisTypeContainer> getTypeDescendants(String repositoryId, String typeId, BigInteger depth, Boolean includePropertyDefinitions, CmisExtensionType extension)
throws CmisException
{
checkRepositoryId(repositoryId);
long depthLong = (null == depth) ? (-1) : (depth.longValue());
boolean includePropertyDefsBool = (null == includePropertyDefinitions) ? (false) : (includePropertyDefinitions);
List<CmisTypeContainer> result = new LinkedList<CmisTypeContainer>();
Queue<TypeElement> typesQueue = new LinkedList<TypeElement>();
Collection<CMISTypeDefinition> typeDefs = getBaseTypesCollection(typeId, false);
for (CMISTypeDefinition typeDef : typeDefs)
{
typesQueue.add(new TypeElement(0L, typeDef, createTypeContainer(typeDef, includePropertyDefsBool)));
}
for (TypeElement element = typesQueue.peek(); !typesQueue.isEmpty(); element = (typeDefs.isEmpty()) ? (null) : (typesQueue.peek()))
{
typesQueue.poll();
result.add(element.getContainer());
long nextLevel = element.getLevel() + 1;
Collection<CMISTypeDefinition> subTypes = element.getTypeDefinition().getSubTypes(false);
if (null != subTypes)
{
for (CMISTypeDefinition typeDef : subTypes)
{
CmisTypeContainer childContainer = createTypeContainer(typeDef, includePropertyDefsBool);
element.getContainer().getChildren().add(childContainer);
if ((-1 == depthLong) || (nextLevel <= depthLong))
{
typesQueue.add(new TypeElement(nextLevel, typeDef, childContainer));
}
}
}
}
return result;
}
private CmisTypeContainer createTypeContainer(CMISTypeDefinition parentType, boolean includeProperties) throws CmisException
{
CmisTypeContainer result = new CmisTypeContainer();
result.setType(getCmisTypeDefinition(parentType, includeProperties));
return result;
}
private class TypeElement
{
private long level;
private CMISTypeDefinition typeDefinition;
private CmisTypeContainer container;
public TypeElement(long level, CMISTypeDefinition typeDefinition, CmisTypeContainer container)
{
this.level = level;
this.typeDefinition = typeDefinition;
this.container = container;
}
public long getLevel()
{
return level;
}
public CMISTypeDefinition getTypeDefinition()
{
return typeDefinition;
}
public CmisTypeContainer getContainer()
{
return container;
}
}
private Collection<CMISTypeDefinition> getBaseTypesCollection(String typeId, boolean includeSubtypes) throws CmisException
{
Collection<CMISTypeDefinition> typeDefs = new LinkedList<CMISTypeDefinition>();
if ((null == typeId) || "".equals(typeId))
{
typeDefs = cmisDictionaryService.getBaseTypes();
}
else
{
CMISTypeDefinition typeDef = null;
try
{
typeDef = cmisDictionaryService.findType(typeId);
}
catch (Exception e)
{
throw cmisObjectsUtils.createCmisException(e.toString(), EnumServiceException.INVALID_ARGUMENT);
}
if (null == typeDef)
{
throw cmisObjectsUtils.createCmisException(("Invalid type id: \"" + typeId + "\""), EnumServiceException.INVALID_ARGUMENT);
}
typeDefs.add(typeDef);
if (includeSubtypes)
{
Collection<CMISTypeDefinition> subTypes = typeDef.getSubTypes(false);
if (null != subTypes)
{
typeDefs.addAll(subTypes);
}
}
}
return typeDefs;
}
}

View File

@@ -50,7 +50,7 @@ import org.alfresco.service.cmr.version.VersionType;
* @author Dmitry Lazurkin
* @author Dmitry Velichkevich
*/
@javax.jws.WebService(name = "VersioningServicePort", serviceName = "VersioningService", portName = "VersioningServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200901", endpointInterface = "org.alfresco.repo.cmis.ws.VersioningServicePort")
@javax.jws.WebService(name = "VersioningServicePort", serviceName = "VersioningService", portName = "VersioningServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200908/", endpointInterface = "org.alfresco.repo.cmis.ws.VersioningServicePort")
public class DMVersioningServicePort extends DMAbstractServicePort implements VersioningServicePort
{
private LockService lockService;
@@ -69,7 +69,8 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT,
* UPDATE_CONFLICT, VERSIONING)
*/
public void cancelCheckOut(String repositoryId, String documentId) throws CmisException
// FIXME [~BUG]: may it is better returning id of the unchecked out document
public void cancelCheckOut(String repositoryId, String documentId, Holder<CmisExtensionType> extension) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef workingCopyNodeRef = cmisObjectsUtils.getIdentifierInstance(documentId, AlfrescoObjectType.DOCUMENT_OBJECT);
@@ -82,7 +83,7 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve
{
if (!getTypeDefinition(workingCopyNodeRef).isVersionable())
{
// TODO: uncomment this when CMIS dictionary model will be corrected
// FIXME: uncomment this when CMIS dictionary model will be corrected
// throw cmisObjectsUtils.createCmisException("Document that was specified is not versionable", EnumServiceException.CONSTRAINT);
}
}
@@ -110,8 +111,9 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT, STORAGE,
* STREAM_NOT_SUPPORTED, UPDATE_CONFLICT, VERSIONING)
*/
// FIXME [~BUG]: it is better changing 'void' to 'PWC Id' result type
public void checkIn(String repositoryId, Holder<String> documentId, Boolean major, CmisPropertiesType properties, CmisContentStreamType contentStream, String checkinComment,
List<String> applyPolicies, CmisAccessControlListType addACEs, CmisAccessControlListType removeACEs) throws CmisException
List<String> policies, CmisAccessControlListType addACEs, CmisAccessControlListType removeACEs, Holder<CmisExtensionType> extension) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef workingCopyNodeRef = cmisObjectsUtils.getIdentifierInstance(documentId.value, AlfrescoObjectType.DOCUMENT_OBJECT);
@@ -136,7 +138,7 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve
}
catch (Exception e)
{
throw cmisObjectsUtils.createCmisException("Exception while updating content stream", EnumServiceException.RUNTIME, e);
throw cmisObjectsUtils.createCmisException("Exception while updating content stream", EnumServiceException.UPDATE_CONFLICT, e);
}
}
@@ -145,7 +147,6 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve
{
nodeRef = checkOutCheckInService.checkin(workingCopyNodeRef, createVersionProperties(checkinComment, ((null == major) || major) ? (VersionType.MAJOR)
: (VersionType.MINOR)));
propertiesUtil.setProperties(nodeRef, properties, null);
}
catch (Exception e)
@@ -166,7 +167,7 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT, STORAGE,
* UPDATE_CONFLICT, VERSIONING)
*/
public void checkOut(String repositoryId, Holder<String> documentId, Holder<Boolean> contentCopied) throws CmisException
public void checkOut(String repositoryId, Holder<String> documentId, Holder<CmisExtensionType> extension, Holder<Boolean> contentCopied) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(documentId.value, AlfrescoObjectType.DOCUMENT_OBJECT);
@@ -176,7 +177,7 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve
LockStatus lockStatus = lockService.getLockStatus(documentNodeRef);
if (lockStatus.equals(LockStatus.LOCKED) || lockStatus.equals(LockStatus.LOCK_OWNER) || nodeService.hasAspect(documentNodeRef, ContentModel.ASPECT_WORKING_COPY))
{
throw cmisObjectsUtils.createCmisException("Object is already checked out", EnumServiceException.UPDATE_CONFLICT);
throw cmisObjectsUtils.createCmisException("Object is locked or already checked out", EnumServiceException.UPDATE_CONFLICT);
}
try
@@ -218,23 +219,22 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve
* @return list of CmisObjectType
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, FILTER_NOT_VALID)
*/
public List<CmisObjectType> getAllVersions(String repositoryId, String versionSeriesId, String filter, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships) throws CmisException
public List<CmisObjectType> getAllVersions(String repositoryId, String objectId, String filter, Boolean includeAllowableActions, CmisExtensionType extension)
throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(versionSeriesId, AlfrescoObjectType.DOCUMENT_OBJECT);
NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT);
documentNodeRef = cmisObjectsUtils.getLatestNode(documentNodeRef, false);
PropertyFilter propertyFilter = createPropertyFilter(filter);
List<CmisObjectType> objects = new LinkedList<CmisObjectType>();
includeAllowableActions = (null == includeAllowableActions) ? (false) : (includeAllowableActions);
try
{
NodeRef workingCopyNodeReference = cmisObjectsUtils.isWorkingCopy(documentNodeRef) ? documentNodeRef : checkOutCheckInService.getWorkingCopy(documentNodeRef);
if (null != workingCopyNodeReference)
{
objects.add(createCmisObject(workingCopyNodeReference, propertyFilter));
objects.add(createCmisObject(workingCopyNodeReference, propertyFilter, includeAllowableActions));
}
}
catch (Exception e)
@@ -250,10 +250,10 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve
{
for (Version version = versionService.getCurrentVersion(documentNodeRef); null != version; version = versionHistory.getPredecessor(version))
{
objects.add(createCmisObject(version.getFrozenStateNodeRef(), propertyFilter));
objects.add(createCmisObject(version.getFrozenStateNodeRef(), propertyFilter, includeAllowableActions));
}
}
// TODO: includeAllowableActions, includeRelationships
// TODO: includeRelationships
return objects;
}
@@ -266,25 +266,14 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve
* @return CmisObjectType with properties
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, FILTER_NOT_VALID)
*/
public CmisObjectType getPropertiesOfLatestVersion(String repositoryId, String versionSeriesId, boolean major, String filter, Boolean includeACL) throws CmisException
public CmisPropertiesType getPropertiesOfLatestVersion(String repositoryId, String objectId, Boolean major, String filter, CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT);
PropertyFilter propertyFilter = createPropertyFilter(filter);
NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(versionSeriesId, AlfrescoObjectType.DOCUMENT_OBJECT);
NodeRef latestVersionNodeRef = cmisObjectsUtils.getLatestNode(documentNodeRef, major);
Boolean majorVersionProperty = propertiesUtil.getProperty(latestVersionNodeRef, CMISDictionaryModel.PROP_IS_MAJOR_VERSION, false);
if (major && !majorVersionProperty)
{
throw cmisObjectsUtils.createCmisException("Object that was specified has no latest major version", EnumServiceException.OBJECT_NOT_FOUND);
}
CmisObjectType result = new CmisObjectType();
result.setProperties(propertiesUtil.getPropertiesType(latestVersionNodeRef.toString(), propertyFilter));
// TODO: includeACL
return result;
major = (null == major) ? (false) : (major);
NodeRef latestVersionNodeRef = getAndCheckLatestNodeRef(documentNodeRef, major);
return propertiesUtil.getPropertiesType(latestVersionNodeRef.toString(), propertyFilter);
}
private void assertLatestVersion(NodeRef nodeRef, boolean shouldBePwc) throws CmisException
@@ -305,4 +294,36 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve
}
}
}
/**
*
*/
// TODO: it is necessary to add tests for this method
public CmisObjectType getObjectOfLatestVersion(String repositoryId, String objectId, Boolean major, String filter, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePolicyIds, Boolean includeACL, CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT);
PropertyFilter propertyFilter = createPropertyFilter(filter);
includeAllowableActions = (null == includeAllowableActions) ? (false) : (includeAllowableActions);
major = (null == major) ? (false) : (major);
NodeRef latestVersionNodeRef = getAndCheckLatestNodeRef(documentNodeRef, major);
// TODO: includeACL
// TODO: includeRelationships
// TODO: includePolicyIds
// TODO: renditionFilter
CmisObjectType result = createCmisObject(latestVersionNodeRef.toString(), propertyFilter, includeAllowableActions);
return result;
}
private NodeRef getAndCheckLatestNodeRef(NodeRef documentNodeRef, Boolean major) throws CmisException
{
NodeRef latestVersionNodeRef = cmisObjectsUtils.getLatestNode(documentNodeRef, major);
Boolean majorVersionProperty = propertiesUtil.getProperty(latestVersionNodeRef, CMISDictionaryModel.PROP_IS_MAJOR_VERSION, false);
if (major && !majorVersionProperty)
{
throw cmisObjectsUtils.createCmisException("Object that was specified has no latest major version", EnumServiceException.OBJECT_NOT_FOUND);
}
return latestVersionNodeRef;
}
}

View File

@@ -40,7 +40,7 @@ import org.alfresco.repo.cmis.ws.CmisFaultType;
import org.alfresco.repo.cmis.ws.EnumBaseObjectTypeIds;
import org.alfresco.repo.cmis.ws.EnumRelationshipDirection;
import org.alfresco.repo.cmis.ws.EnumServiceException;
import org.alfresco.repo.cmis.ws.utils.DescendantsQueueManager.DescendantElement;
import org.alfresco.repo.cmis.ws.EnumUnfileObject;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
@@ -102,7 +102,7 @@ public class CmisObjectsUtils
private NodeService nodeService;
private LockService lockService;
private Throwable lastOperationException;
private Throwable lastException;
public void setCmisDictionaryService(CMISDictionaryService cmisDictionaryService)
{
@@ -204,41 +204,18 @@ public class CmisObjectsUtils
throw createCmisException(("Unexpected object type of the specified Object with \"" + identifier + "\" identifier"), EnumServiceException.INVALID_ARGUMENT);
}
public void deleteFolder(NodeRef folderNodeReference, boolean continueOnFailure, boolean totalDeletion, List<String> resultList) throws CmisException
public List<String> deleteFolder(NodeRef folderNodeReference, boolean continueOnFailure, EnumUnfileObject unfillingStrategy, boolean deleteAllVersions) throws CmisException
{
DescendantsQueueManager queueManager = new DescendantsQueueManager(new ChildAssociationRef(ContentModel.ASSOC_CONTAINS, null, null, folderNodeReference));
do
CmisObjectIterator iterator = new CmisObjectIterator(folderNodeReference, unfillingStrategy, continueOnFailure, deleteAllVersions, nodeService, fileFolderService,
versionService, checkOutCheckInService, this);
if (iterator.hasNext())
{
DescendantElement currentElement = queueManager.getNextElement();
if (!nodeService.exists(currentElement.getChildAssoc().getChildRef()))
for (; iterator.hasNext(); iterator.next())
{
continue;
iterator.remove();
}
UnlinkOperationStatus unlinkStatus = unlinkObject(currentElement.getChildAssoc().getChildRef(), currentElement.getChildAssoc().getParentRef(), totalDeletion);
if (!unlinkStatus.isObjectUnlinked())
{
processUnlinkStatus(currentElement, unlinkStatus, queueManager, resultList, continueOnFailure);
}
} while (!queueManager.isEmpty() && (continueOnFailure || resultList.isEmpty()));
}
private void processUnlinkStatus(DescendantElement currentElement, UnlinkOperationStatus unlinkStatus, DescendantsQueueManager queueManager, List<String> resultList,
boolean addAllFailedToDelete)
{
if (!unlinkStatus.getChildren().isEmpty())
{
queueManager.addLast(currentElement);
queueManager.addFirst(currentElement, unlinkStatus.getChildren());
return;
}
resultList.add(currentElement.getChildAssoc().getChildRef().toString());
if (addAllFailedToDelete)
{
queueManager.removeParents(currentElement, resultList);
}
return iterator.getFailToDelete();
}
public boolean deleteObject(NodeRef objectNodeReference)
@@ -279,7 +256,7 @@ public class CmisObjectsUtils
}
catch (Throwable e)
{
this.lastOperationException = e;
lastException = e;
return false;
}
return true;
@@ -298,7 +275,7 @@ public class CmisObjectsUtils
}
catch (Throwable e)
{
this.lastOperationException = e;
lastException = e;
return false;
}
}
@@ -472,6 +449,7 @@ public class CmisObjectsUtils
}
catch (Throwable e)
{
lastException = e;
return false;
}
return true;
@@ -483,27 +461,6 @@ public class CmisObjectsUtils
return (this.lockService.getLockStatus(objectNodeReference, currentUserName) != LockStatus.LOCKED) || authorityService.isAdminAuthority(currentUserName);
}
private UnlinkOperationStatus unlinkObject(NodeRef objectNodeReference, NodeRef parentFolderNodeReference, boolean totalDeletion)
{
if (isFolder(objectNodeReference))
{
List<ChildAssociationRef> children = nodeService.getChildAssocs(objectNodeReference);
boolean objectUnlinked = (children == null || children.isEmpty()) && deleteObject(objectNodeReference);
return new UnlinkOperationStatus(objectUnlinked, children != null ? children : new LinkedList<ChildAssociationRef>());
}
boolean objectUnlinked = false;
if (totalDeletion)
{
objectUnlinked = deleteObject(objectNodeReference);
}
else
{
objectUnlinked = !isPrimaryObjectParent(parentFolderNodeReference, objectNodeReference) && removeObject(objectNodeReference, parentFolderNodeReference);
}
return new UnlinkOperationStatus(objectUnlinked, new LinkedList<ChildAssociationRef>());
}
private AssociationRef safeGetAssociationRef(String identifier) throws CmisException
{
AssociationRef result = new AssociationRef(identifier);
@@ -604,36 +561,10 @@ public class CmisObjectsUtils
}
}
private class UnlinkOperationStatus
{
private boolean objectUnlinked;
private List<ChildAssociationRef> children;
public UnlinkOperationStatus(boolean objectUnlinked, List<ChildAssociationRef> children)
{
this.objectUnlinked = objectUnlinked;
this.children = children;
}
@SuppressWarnings("unused")
protected UnlinkOperationStatus()
{
}
public boolean isObjectUnlinked()
{
return objectUnlinked;
}
public List<ChildAssociationRef> getChildren()
{
return this.children;
}
}
public Throwable getLastOperationException()
{
return lastOperationException;
Throwable result = lastException;
lastException = null;
return result;
}
}

View File

@@ -57,7 +57,6 @@ import org.alfresco.repo.cmis.ws.CmisPropertyId;
import org.alfresco.repo.cmis.ws.CmisPropertyInteger;
import org.alfresco.repo.cmis.ws.CmisPropertyString;
import org.alfresco.repo.cmis.ws.CmisPropertyUri;
import org.alfresco.repo.cmis.ws.CmisPropertyXml;
import org.alfresco.repo.cmis.ws.EnumServiceException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.dictionary.DictionaryService;
@@ -250,10 +249,6 @@ public class PropertyUtil
{
convertedValue = ((CmisPropertyUri) cmisProperty).getValue();
}
else if (cmisProperty instanceof CmisPropertyXml)
{
convertedValue = ((CmisPropertyXml) cmisProperty).getValue();
}
if (null != convertedValue)
{
@@ -421,13 +416,13 @@ public class PropertyUtil
public String getPropertyName(CmisProperty property)
{
String propertyName = (null != property) ? (property.getPdid()) : (null);
String propertyName = (null != property) ? (property.getPropertyDefinitionId()) : (null);
if (null == propertyName)
{
propertyName = property.getLocalname();
propertyName = property.getLocalName();
if (null == propertyName)
{
propertyName = property.getDisplayname();
propertyName = property.getDisplayName();
}
}
return propertyName;
@@ -600,7 +595,7 @@ public class PropertyUtil
case BOOLEAN:
{
CmisPropertyBoolean property = new CmisPropertyBoolean();
property.setPdid(pdid);
property.setPropertyDefinitionId(pdid);
if (value instanceof Collection)
{
@@ -619,7 +614,7 @@ public class PropertyUtil
case STRING:
{
CmisPropertyString property = new CmisPropertyString();
property.setPdid(pdid);
property.setPropertyDefinitionId(pdid);
if (value instanceof Collection)
{
@@ -638,7 +633,7 @@ public class PropertyUtil
case INTEGER:
{
CmisPropertyInteger property = new CmisPropertyInteger();
property.setPdid(pdid);
property.setPropertyDefinitionId(pdid);
if (value instanceof Collection)
{
@@ -657,7 +652,7 @@ public class PropertyUtil
case DATETIME:
{
CmisPropertyDateTime property = new CmisPropertyDateTime();
property.setPdid(pdid);
property.setPropertyDefinitionId(pdid);
if (value instanceof Collection)
{
@@ -684,7 +679,7 @@ public class PropertyUtil
case ID:
{
CmisPropertyId property = new CmisPropertyId();
property.setPdid(pdid);
property.setPropertyDefinitionId(pdid);
if (value instanceof Collection)
{
@@ -703,7 +698,7 @@ public class PropertyUtil
case URI:
{
CmisPropertyUri property = new CmisPropertyUri();
property.setPdid(pdid);
property.setPropertyDefinitionId(pdid);
if (value instanceof Collection)
{
@@ -722,7 +717,7 @@ public class PropertyUtil
case DECIMAL:
{
CmisPropertyDecimal property = new CmisPropertyDecimal();
property.setPdid(pdid);
property.setPropertyDefinitionId(pdid);
if (value instanceof Collection)
{
@@ -760,18 +755,18 @@ public class PropertyUtil
case HTML:
{
CmisPropertyHtml property = new CmisPropertyHtml();
property.setPdid(pdid);
property.setPropertyDefinitionId(pdid);
if (value instanceof Collection)
{
for (CmisPropertyHtml.Value propertyValue : (Collection<CmisPropertyHtml.Value>) value)
for (String propertyValue : (Collection<String>) value)
{
property.getValue().add(propertyValue);
}
}
else
{
property.getValue().add((CmisPropertyHtml.Value) value);
property.getValue().add((String) value);
}
return property;