From 4860bf5ec6f87f11428bc6556230eb7ddd6c49b1 Mon Sep 17 00:00:00 2001 From: David Caruana Date: Fri, 12 Mar 2010 22:27:42 +0000 Subject: [PATCH] Merging BRANCHES/DEV/BELARUS/HEAD-2010_03_09 to HEAD: 19261: CMIS-WS: Bug fixing in WS Bindings and CMISServices Bug related to DeleteTree with "unfile" flag was fixed. - Removal of secondary parent associations was added to CMISServices.deleteObject method. Objects state verification was added to MultifillingService. - Verification of object and folder type was added. Verification of object presence in folder was added. - Checking constraints for versioning typeDef was added. DiscoveryService.query() problems were fixed. - includeRelationships feature was added to DMDiscoveryServicePort.query(). - DMAbstractServicePort was refactored and extended to introduce functionality required for includeRelationships feature in other binding port implementations. TCK bug fixing - Test cases in Java TCK tests for Query Ordering problem demonstration were developed (CmisDiscoveryServiceClient.testQueryWithAscendingOrdering() and CmisDiscoveryServiceClient.testQueryWithDescendingOrdering()). - CmisDiscoveryServiceClient.testQueryAllVersionsSearchable() was corrected. Using of invalid property "cmis:parentId" for none folder object was removed. - CmisDiscoveryServiceClient.testQueryRelationships() was fixed. Currently, this method correctly tests relationships receiving for each EnumIncludeRelationships constant. Relationships supporting by repository checking was added. Test was redeveloped against new functionality. - Expected exceptions verification was corrected. - Properties filter was corrected in concordance with CMIS Specification. - RepositoryInfo and capabilities assertion was fixed and extended. - Test for latest non-major version receiving was corrected. - TCK Build file was corrected. WSI part was removed. Target "jar" that creates one executable jar was added. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@19270 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../repo/cmis/ws/DMAbstractServicePort.java | 114 +++++++++--------- .../repo/cmis/ws/DMDiscoveryServicePort.java | 16 ++- .../cmis/ws/DMMultiFilingServicePort.java | 35 ++++++ .../repo/cmis/ws/DMObjectServicePort.java | 3 +- 4 files changed, 106 insertions(+), 62 deletions(-) diff --git a/source/java/org/alfresco/repo/cmis/ws/DMAbstractServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMAbstractServicePort.java index 6231ba3b91..ba1700bafe 100644 --- a/source/java/org/alfresco/repo/cmis/ws/DMAbstractServicePort.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMAbstractServicePort.java @@ -53,6 +53,7 @@ import org.alfresco.cmis.CMISTypeDefinition; import org.alfresco.cmis.PropertyFilter; import org.alfresco.cmis.acl.CMISAccessControlEntryImpl; import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; import org.alfresco.repo.cmis.ws.utils.ExceptionUtil; import org.alfresco.repo.cmis.ws.utils.PropertyUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil; @@ -83,7 +84,7 @@ public class DMAbstractServicePort private static final String INVALID_REPOSITORY_ID_MESSAGE = "Invalid repository id"; private static final Map ACL_PROPAGATION_ENUM_MAPPGIN; - private static final Map INCLUDE_RELATIONSHIPS_ENUM_MAPPING; + protected static final Map INCLUDE_RELATIONSHIPS_ENUM_MAPPING; private static final Map ALLOWED_ACTION_ENUM_MAPPING; static { @@ -96,7 +97,7 @@ public class DMAbstractServicePort INCLUDE_RELATIONSHIPS_ENUM_MAPPING.put(EnumIncludeRelationships.SOURCE, CMISRelationshipDirectionEnum.SOURCE); INCLUDE_RELATIONSHIPS_ENUM_MAPPING.put(EnumIncludeRelationships.TARGET, CMISRelationshipDirectionEnum.TARGET); INCLUDE_RELATIONSHIPS_ENUM_MAPPING.put(EnumIncludeRelationships.BOTH, CMISRelationshipDirectionEnum.BOTH); - + try { ALLOWED_ACTION_ENUM_MAPPING = new HashMap(97); @@ -215,73 +216,68 @@ public class DMAbstractServicePort return paging.createCursor(totalRows, window); } + /** + * Returns true if folder contains object + * + * @param object object NodeRef + * @param folder folder NodeRef + * @return returns true if folder contains object + */ + protected boolean isObjectInFolder(NodeRef object, NodeRef folder) + { + NodeRef searchedObjectNodeRef = fileFolderService.searchSimple(folder, (String) nodeService.getProperty(object, ContentModel.PROP_NAME)); + return (null != searchedObjectNodeRef) && (searchedObjectNodeRef.equals(object)); + } + /** * This method converts Alfresco's NodeRef's to CMIS objects those will be stored in resultList-parameter. Properties for returning filtering also performs * * @param filter properties filter value for filtering objects returning properties - * @param includeRelationships - * what relationships to include + * @param includeRelationships what relationships to include * @param sourceList the list that contains all returning Node References * @param resultList the list of CmisObjectType values for end response result collecting * @throws CmisException */ - protected void createCmisObjectList(PropertyFilter filter, CMISRelationshipDirectionEnum includeRelationships, - boolean includeAllowableActions, String renditionFilter, List sourceList, - List resultList) throws CmisException + protected void createCmisObjectList(PropertyFilter filter, CMISRelationshipDirectionEnum includeRelationships, boolean includeAllowableActions, String renditionFilter, + List sourceList, List resultList) throws CmisException { for (NodeRef objectNodeRef : sourceList) { - resultList.add(createCmisObject(objectNodeRef, filter, includeRelationships, includeAllowableActions, - renditionFilter)); + resultList.add(createCmisObject(objectNodeRef, filter, includeRelationships, includeAllowableActions, renditionFilter)); } } /** * This method creates and configures CMIS object against appropriate Alfresco object (NodeRef or AssociationRef). * - * @param object - * the Alfresco object - * @param filter - * accepted properties filter - * @param includeRelationships - * what relationships to include - * @param includeAllowableActions - * should we include allowable actions? - * @param renditionFilter - * the rendition filter + * @param object the Alfresco object + * @param filter accepted properties filter + * @param includeRelationships what relationships to include + * @param includeAllowableActions should we include allowable actions? + * @param renditionFilter the rendition filter * @return the converted CMIS object - * @throws CmisException - * on error + * @throws CmisException on error */ - protected CmisObjectType createCmisObject(Object object, PropertyFilter filter, - EnumIncludeRelationships includeRelationships, Boolean includeAllowableActions, String renditionFilter) - throws CmisException + protected CmisObjectType createCmisObject(Object object, PropertyFilter filter, EnumIncludeRelationships includeRelationships, Boolean includeAllowableActions, + String renditionFilter) throws CmisException { - return createCmisObject(object, filter, includeRelationships == null ? null - : INCLUDE_RELATIONSHIPS_ENUM_MAPPING.get(includeRelationships), includeAllowableActions != null + return createCmisObject(object, filter, includeRelationships == null ? null : INCLUDE_RELATIONSHIPS_ENUM_MAPPING.get(includeRelationships), includeAllowableActions != null && includeAllowableActions, renditionFilter); } /** * This method creates and configures CMIS object against appropriate Alfresco object (NodeRef or AssociationRef). * - * @param object - * the Alfresco object - * @param filter - * accepted properties filter - * @param includeRelationships - * what relationships to include - * @param includeAllowableActions - * should we include allowable actions? - * @param renditionFilter - * the rendition filter + * @param object the Alfresco object + * @param filter accepted properties filter + * @param includeRelationships what relationships to include + * @param includeAllowableActions should we include allowable actions? + * @param renditionFilter the rendition filter * @return the converted CMIS object - * @throws CmisException - * on error + * @throws CmisException on error */ - protected CmisObjectType createCmisObject(Object object, PropertyFilter filter, - CMISRelationshipDirectionEnum includeRelationships, boolean includeAllowableActions, String renditionFilter) - throws CmisException + protected CmisObjectType createCmisObject(Object object, PropertyFilter filter, CMISRelationshipDirectionEnum includeRelationships, boolean includeAllowableActions, + String renditionFilter) throws CmisException { // Get a NodeRef if we can if (object instanceof Version) @@ -292,18 +288,7 @@ public class DMAbstractServicePort result.setProperties(propertiesUtil.getProperties(object, filter)); if (object instanceof NodeRef && includeRelationships != null) { - List relationships = result.getRelationship(); - try - { - for (AssociationRef assoc : cmisService.getRelationships((NodeRef)object, null, true, includeRelationships)) - { - relationships.add(createCmisObject(assoc, filter, includeRelationships, includeAllowableActions, renditionFilter)); - } - } - catch (CMISInvalidArgumentException e) - { - throw ExceptionUtil.createCmisException(e); - } + appendWithRelationships((NodeRef) object, filter, includeRelationships, includeAllowableActions, renditionFilter, result); } if (includeAllowableActions) { @@ -320,6 +305,23 @@ public class DMAbstractServicePort return result; } + protected void appendWithRelationships(NodeRef object, PropertyFilter filter, CMISRelationshipDirectionEnum includeRelationships, boolean includeAllowableActions, + String renditionFilter, CmisObjectType result) throws CmisException + { + List relationships = result.getRelationship(); + try + { + for (AssociationRef assoc : cmisService.getRelationships(object, null, true, includeRelationships)) + { + relationships.add(createCmisObject(assoc, filter, includeRelationships, includeAllowableActions, renditionFilter)); + } + } + catch (CMISInvalidArgumentException e) + { + throw ExceptionUtil.createCmisException(e); + } + } + /** * Checks specified in CMIS request parameters repository Id. * @@ -407,11 +409,11 @@ public class DMAbstractServicePort throw ExceptionUtil.createCmisException(e); } } - } + } } - protected CmisACLType applyAclCarefully(NodeRef object, CmisAccessControlListType addACEs, CmisAccessControlListType removeACEs, EnumACLPropagation aclPropagation, List policies) - throws CmisException + protected CmisACLType applyAclCarefully(NodeRef object, CmisAccessControlListType addACEs, CmisAccessControlListType removeACEs, EnumACLPropagation aclPropagation, + List policies) throws CmisException { if (addACEs == null && removeACEs == null) { diff --git a/source/java/org/alfresco/repo/cmis/ws/DMDiscoveryServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMDiscoveryServicePort.java index 7f70d08d71..183f1311b6 100644 --- a/source/java/org/alfresco/repo/cmis/ws/DMDiscoveryServicePort.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMDiscoveryServicePort.java @@ -33,6 +33,7 @@ import org.alfresco.cmis.CMISChangeType; import org.alfresco.cmis.CMISDataTypeEnum; import org.alfresco.cmis.CMISDictionaryModel; import org.alfresco.cmis.CMISQueryOptions; +import org.alfresco.cmis.CMISRelationshipDirectionEnum; import org.alfresco.cmis.CMISResultSet; import org.alfresco.cmis.CMISResultSetColumn; import org.alfresco.cmis.CMISResultSetRow; @@ -95,6 +96,9 @@ public class DMDiscoveryServicePort extends DMAbstractServicePort implements Dis QueryResponse response = new QueryResponse(); response.setObjects(new CmisObjectListType()); + EnumIncludeRelationships cmisDirection = (null != parameters.getIncludeRelationships()) ? (parameters.getIncludeRelationships().getValue()) : (null); + CMISRelationshipDirectionEnum includeRelationships = INCLUDE_RELATIONSHIPS_ENUM_MAPPING.get(cmisDirection); + // for each row... for (CMISResultSetRow row : resultSet) { @@ -114,9 +118,10 @@ public class DMDiscoveryServicePort extends DMAbstractServicePort implements Dis CmisObjectType object = new CmisObjectType(); object.setProperties(properties); Object identifier; + NodeRef nodeRef; try { - NodeRef nodeRef = row.getNodeRef(); + nodeRef = row.getNodeRef(); identifier = cmisService.getReadableObject((String) nodeRef.toString(), Object.class); } catch (CMISServiceException e) @@ -127,6 +132,10 @@ public class DMDiscoveryServicePort extends DMAbstractServicePort implements Dis { object.setAllowableActions(determineObjectAllowableActions(identifier)); } + if (null != includeRelationships) + { + appendWithRelationships(nodeRef, createPropertyFilter((String) null), includeRelationships, includeAllowableActions, renditionFilter, object); + } if (renditionFilter != null) { List renditions = getRenditions(identifier, renditionFilter); @@ -137,7 +146,7 @@ public class DMDiscoveryServicePort extends DMAbstractServicePort implements Dis } response.getObjects().getObjects().add(object); } - // TODO: response.getObjects().setNumItems(value); + response.getObjects().setNumItems(BigInteger.valueOf(response.getObjects().getObjects().size())); response.getObjects().setHasMoreItems(resultSet.hasMore()); return response; } @@ -226,7 +235,7 @@ public class DMDiscoveryServicePort extends DMAbstractServicePort implements Dis if (nodeService.exists(event.getChangedNode()) && includeAce) { appendWithAce(event.getChangedNode(), object); - } + } CmisChangeEventType changeInfo = new CmisChangeEventType(); XMLGregorianCalendar modificationDate = propertiesUtil.convert(event.getChangeTime()); changeInfo.setChangeType(changesTypeMapping.get(event.getChangeType())); @@ -235,5 +244,4 @@ public class DMDiscoveryServicePort extends DMAbstractServicePort implements Dis result.add(object); } } - } diff --git a/source/java/org/alfresco/repo/cmis/ws/DMMultiFilingServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMMultiFilingServicePort.java index 4396d0d871..807e85b4cc 100644 --- a/source/java/org/alfresco/repo/cmis/ws/DMMultiFilingServicePort.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMMultiFilingServicePort.java @@ -20,8 +20,11 @@ package org.alfresco.repo.cmis.ws; import javax.xml.ws.Holder; +import org.alfresco.cmis.CMISDictionaryModel; import org.alfresco.cmis.CMISServiceException; +import org.alfresco.cmis.CMISTypeDefinition; import org.alfresco.repo.cmis.ws.utils.ExceptionUtil; +import org.alfresco.service.cmr.repository.NodeRef; /** * Port for Multi-Filing service. @@ -64,6 +67,8 @@ public class DMMultiFilingServicePort extends DMAbstractServicePort implements M public void removeObjectFromFolder(String repositoryId, String objectId, String folderId, Holder extension) throws CmisException { checkRepositoryId(repositoryId); + checkConstraints(objectId, folderId); + try { cmisService.removeObjectFromFolder(objectId, folderId); @@ -72,5 +77,35 @@ public class DMMultiFilingServicePort extends DMAbstractServicePort implements M { throw ExceptionUtil.createCmisException(e); } + } + + private void checkConstraints(String objectId, String folderId) throws CmisException + { + NodeRef objectNodeRef = null; + NodeRef folderNodeRef = null; + CMISTypeDefinition objectTypeDef = null; + + try + { + objectNodeRef = cmisService.getObject(objectId, NodeRef.class, true, false, false); + folderNodeRef = cmisService.getFolder(folderId); + objectTypeDef = cmisService.getTypeDefinition(objectNodeRef); + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e.getMessage(), EnumServiceException.INVALID_ARGUMENT); + } + + if (!objectTypeDef.getTypeId().getBaseTypeId().equals(CMISDictionaryModel.DOCUMENT_TYPE_ID)) + { + throw ExceptionUtil.createCmisException("Object " + objectId + " is not a document", EnumServiceException.INVALID_ARGUMENT); + } + + if (!isObjectInFolder(objectNodeRef, folderNodeRef)) + { + throw ExceptionUtil.createCmisException("Folder doesn't contain specified object", EnumServiceException.OBJECT_NOT_FOUND); + } + } + } diff --git a/source/java/org/alfresco/repo/cmis/ws/DMObjectServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMObjectServicePort.java index 2d4d857485..a2b96791f5 100644 --- a/source/java/org/alfresco/repo/cmis/ws/DMObjectServicePort.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMObjectServicePort.java @@ -813,8 +813,7 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object } } - // FIXME: change condition below to "!typeDef.isVersionable() && (null != versioningState)" when dictionary problem will be fixed - if (false) + if (!typeDef.isVersionable() && (null != versioningState)) { throw ExceptionUtil.createCmisException(("Verioning for \"" + documentTypeId + "\" document type is not allowed"), EnumServiceException.CONSTRAINT); }