From 9553dd6e7c65b6e27f3797aed26ef7b1cddc7e5d Mon Sep 17 00:00:00 2001 From: David Caruana Date: Fri, 9 Jan 2009 14:30:25 +0000 Subject: [PATCH] Merged DEV/SEAMIST4 to HEAD (part 1 of 2) 11607: Make the current CMIS Web Services compliant with the CMIS v0.5 spec 12369: Remove Unusing Imports 12375: Minor fixup for testing CMIS Web Services. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@12661 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/cmis-ws-context.xml | 263 +++-- .../AuthenticationTokenCallbackHandler.java | 9 - .../repo/cmis/ws/ContentReaderDataSource.java | 1 - .../repo/cmis/ws/DMAbstractServicePort.java | 276 +++-- .../repo/cmis/ws/DMDiscoveryServicePort.java | 84 ++ .../cmis/ws/DMMultiFilingServicePort.java | 122 +++ .../repo/cmis/ws/DMNavigationServicePort.java | 381 ++++++- .../repo/cmis/ws/DMObjectServicePort.java | 998 ++++++++++++++---- .../repo/cmis/ws/DMPolicyServicePort.java | 93 ++ .../cmis/ws/DMRelationshipServicePort.java | 151 +++ .../repo/cmis/ws/DMRepositoryServicePort.java | 57 +- .../cmis/ws/DMServicePortThrowsAdvice.java | 7 +- .../repo/cmis/ws/DMVersioningServicePort.java | 281 +++++ .../alfresco/repo/cmis/ws/PropertyFilter.java | 48 +- .../alfresco/repo/cmis/ws/PropertyUtil.java | 73 +- .../cmis/ws/utils/AlfrescoObjectType.java | 75 ++ .../repo/cmis/ws/utils/CmisObjectsUtils.java | 473 +++++++++ .../ws/utils/DescendantsQueueManager.java | 156 +++ .../import-for-cmis-ws-test.acp | Bin 2751 -> 0 bytes source/test-resources/test-cmis-context.xml | 92 -- source/test-resources/test.jpg | Bin 0 -> 68436 bytes .../repo/cmis/ws/AbstractServiceTest.java | 240 +++-- .../cmis/ws/BaseServicePortContentTest.java | 160 --- .../repo/cmis/ws/BaseServicePortTest.java | 129 --- .../repo/cmis/ws/CmisServiceTestHelper.java | 753 +++++++++++++ .../ws/CmisWebServiceSuiteSystemTest.java | 52 + .../repo/cmis/ws/DMDiscoveryServiceTest.java | 88 ++ .../cmis/ws/DMMultiFilingServiceTest.java | 124 +++ .../cmis/ws/DMNavigationServicePortTest.java | 265 ----- .../repo/cmis/ws/DMNavigationServiceTest.java | 423 ++++++++ .../repo/cmis/ws/DMObjectServicePortTest.java | 203 ---- .../repo/cmis/ws/DMObjectServiceTest.java | 695 +++++++++++- .../repo/cmis/ws/DMPolicyServiceTest.java | 109 ++ .../cmis/ws/DMRelationshipServiceTest.java | 141 +++ .../cmis/ws/DMRepositoryServicePortTest.java | 73 -- .../repo/cmis/ws/DMRepositoryServiceTest.java | 110 +- .../repo/cmis/ws/DMVersioningServiceTest.java | 279 +++++ .../repo/cmis/ws/MultiThreadsServiceTest.java | 202 ++++ .../ws/WebServiceMultipleUsersSuiteTest.java | 128 +++ .../cmis/ws/filtering/PropertyFilterTest.java | 159 +++ 40 files changed, 6451 insertions(+), 1522 deletions(-) create mode 100755 source/java/org/alfresco/repo/cmis/ws/DMDiscoveryServicePort.java create mode 100755 source/java/org/alfresco/repo/cmis/ws/DMMultiFilingServicePort.java create mode 100755 source/java/org/alfresco/repo/cmis/ws/DMPolicyServicePort.java create mode 100755 source/java/org/alfresco/repo/cmis/ws/DMRelationshipServicePort.java create mode 100755 source/java/org/alfresco/repo/cmis/ws/DMVersioningServicePort.java create mode 100755 source/java/org/alfresco/repo/cmis/ws/utils/AlfrescoObjectType.java create mode 100755 source/java/org/alfresco/repo/cmis/ws/utils/CmisObjectsUtils.java create mode 100755 source/java/org/alfresco/repo/cmis/ws/utils/DescendantsQueueManager.java delete mode 100644 source/test-resources/import-for-cmis-ws-test.acp delete mode 100644 source/test-resources/test-cmis-context.xml create mode 100755 source/test-resources/test.jpg delete mode 100644 source/test/java/org/alfresco/repo/cmis/ws/BaseServicePortContentTest.java delete mode 100644 source/test/java/org/alfresco/repo/cmis/ws/BaseServicePortTest.java create mode 100755 source/test/java/org/alfresco/repo/cmis/ws/CmisServiceTestHelper.java create mode 100755 source/test/java/org/alfresco/repo/cmis/ws/CmisWebServiceSuiteSystemTest.java create mode 100755 source/test/java/org/alfresco/repo/cmis/ws/DMDiscoveryServiceTest.java create mode 100755 source/test/java/org/alfresco/repo/cmis/ws/DMMultiFilingServiceTest.java delete mode 100644 source/test/java/org/alfresco/repo/cmis/ws/DMNavigationServicePortTest.java create mode 100755 source/test/java/org/alfresco/repo/cmis/ws/DMNavigationServiceTest.java delete mode 100644 source/test/java/org/alfresco/repo/cmis/ws/DMObjectServicePortTest.java create mode 100755 source/test/java/org/alfresco/repo/cmis/ws/DMPolicyServiceTest.java create mode 100755 source/test/java/org/alfresco/repo/cmis/ws/DMRelationshipServiceTest.java delete mode 100644 source/test/java/org/alfresco/repo/cmis/ws/DMRepositoryServicePortTest.java create mode 100755 source/test/java/org/alfresco/repo/cmis/ws/DMVersioningServiceTest.java create mode 100755 source/test/java/org/alfresco/repo/cmis/ws/MultiThreadsServiceTest.java create mode 100755 source/test/java/org/alfresco/repo/cmis/ws/WebServiceMultipleUsersSuiteTest.java create mode 100755 source/test/java/org/alfresco/repo/cmis/ws/filtering/PropertyFilterTest.java diff --git a/config/alfresco/cmis-ws-context.xml b/config/alfresco/cmis-ws-context.xml index 05b81d59ad..136e6c972e 100644 --- a/config/alfresco/cmis-ws-context.xml +++ b/config/alfresco/cmis-ws-context.xml @@ -9,22 +9,20 @@ - + - - - @@ -32,24 +30,26 @@ + + + + - + - - - @@ -57,24 +57,25 @@ + + + + - - - @@ -82,51 +83,160 @@ + + + + + - - - - org.alfresco.repo.cmis.ws.RepositoryServicePort - - - - - - - - - - - - + + + + + + - - - - org.alfresco.repo.cmis.ws.NavigationServicePort - - - - - - - - - - - - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - org.alfresco.repo.cmis.ws.ObjectServicePort + dmRepositoryService + dmNavigationService + dmObjectService + dmMultiFilingService + dmVersioningService + dmDiscoveryService + dmRelationshipService + dmPolicyService - - - @@ -142,16 +252,49 @@ ${server.transaction.mode.readOnly} + ${server.transaction.mode.readOnly} ${server.transaction.mode.default} - + + + + + - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + @@ -162,20 +305,14 @@ - + + - - - - + - - - - @@ -214,9 +351,7 @@ - - - + diff --git a/source/java/org/alfresco/repo/cmis/ws/AuthenticationTokenCallbackHandler.java b/source/java/org/alfresco/repo/cmis/ws/AuthenticationTokenCallbackHandler.java index 2b0ef7f2d0..1e9c98fb17 100644 --- a/source/java/org/alfresco/repo/cmis/ws/AuthenticationTokenCallbackHandler.java +++ b/source/java/org/alfresco/repo/cmis/ws/AuthenticationTokenCallbackHandler.java @@ -30,7 +30,6 @@ import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; -import org.alfresco.service.cmr.security.AuthenticationService; import org.apache.ws.security.WSPasswordCallback; /** @@ -38,14 +37,6 @@ import org.apache.ws.security.WSPasswordCallback; */ public class AuthenticationTokenCallbackHandler implements CallbackHandler { - - private AuthenticationService authenticationService; - - public void setAuthenticationService(AuthenticationService authenticationService) - { - this.authenticationService = authenticationService; - } - public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { WSPasswordCallback wssPasswordCallback = (WSPasswordCallback) callbacks[0]; diff --git a/source/java/org/alfresco/repo/cmis/ws/ContentReaderDataSource.java b/source/java/org/alfresco/repo/cmis/ws/ContentReaderDataSource.java index 4f6f716040..1999d944d2 100755 --- a/source/java/org/alfresco/repo/cmis/ws/ContentReaderDataSource.java +++ b/source/java/org/alfresco/repo/cmis/ws/ContentReaderDataSource.java @@ -34,7 +34,6 @@ import org.alfresco.service.cmr.repository.ContentReader; /** * @author Dmitry Lazurkin - * */ public class ContentReaderDataSource implements DataSource { diff --git a/source/java/org/alfresco/repo/cmis/ws/DMAbstractServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMAbstractServicePort.java index dd61819cb6..af454565c8 100644 --- a/source/java/org/alfresco/repo/cmis/ws/DMAbstractServicePort.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMAbstractServicePort.java @@ -28,6 +28,9 @@ import java.io.Serializable; import java.math.BigInteger; import java.util.Date; import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import javax.xml.bind.JAXBElement; import javax.xml.datatype.DatatypeConfigurationException; @@ -39,13 +42,19 @@ import org.alfresco.cmis.dictionary.CMISDictionaryService; import org.alfresco.cmis.dictionary.CMISMapping; import org.alfresco.cmis.property.CMISPropertyService; import org.alfresco.cmis.search.CMISQueryService; -import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.cmis.ws.utils.CmisObjectsUtils; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.version.VersionModel; import org.alfresco.repo.web.util.paging.Cursor; 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.version.Version; import org.alfresco.service.cmr.version.VersionHistory; import org.alfresco.service.cmr.version.VersionService; @@ -58,9 +67,14 @@ import org.alfresco.service.namespace.QName; * * @author Michael Shavnev * @author Dmitry Lazurkin + * @author Dmitry Velichkevich */ public class DMAbstractServicePort { + private static final String BASE_TYPE_PROPERTY_NAME = "BaseType"; + + protected static final String INITIAL_VERSION_DESCRIPTION = "Initial version"; + private DatatypeFactory _datatypeFactory; private Paging paging = new Paging(); @@ -73,6 +87,10 @@ public class DMAbstractServicePort protected NodeService nodeService; protected VersionService versionService; protected FileFolderService fileFolderService; + protected CheckOutCheckInService checkOutCheckInService; + protected SearchService searchService; + + protected CmisObjectsUtils cmisObjectsUtils; private DatatypeFactory getDatatypeFactory() { @@ -90,6 +108,40 @@ public class DMAbstractServicePort return _datatypeFactory; } + /** + * 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 sourceList the list that contains all returning Node References + * @param resultList the list of CmisObjectType values for end response result collecting + * @throws InvalidArgumentException + * @throws FilterNotValidException + */ + protected void formatCommonResponse(PropertyFilter filter, List sourceList, List resultList) throws InvalidArgumentException, FilterNotValidException + { + + for (NodeRef objectNodeRef : sourceList) + { + resultList.add(convertAlfrescoObjectToCmisObject(objectNodeRef, filter)); + } + } + + /** + * This method creates and configures CMIS object against appropriate Alfresco object (NodeRef or AssociationRef) + * + * @param objectNodeRef the Alfresco object against those conversion must to be done + * @param filter accepted properties filter + * @return converted to CMIS object Alfresco object + */ + protected CmisObjectType convertAlfrescoObjectToCmisObject(Object identifier, PropertyFilter filter) + { + + CmisObjectType result = new CmisObjectType(); + result.setProperties(getPropertiesType(identifier.toString(), filter)); + + return result; + } + /** * Asserts "Folder with folderNodeRef exists" * @@ -98,32 +150,30 @@ public class DMAbstractServicePort */ protected void assertExistFolder(NodeRef folderNodeRef) throws FolderNotValidException { - CMISMapping cmisMapping = cmisDictionaryService.getCMISMapping(); - if (folderNodeRef == null || nodeService.exists(folderNodeRef) == false || cmisMapping.isValidCmisFolder(cmisMapping.getCmisType(nodeService.getType(folderNodeRef))) == false) + + if (!this.cmisObjectsUtils.isFolder(folderNodeRef)) { throw new FolderNotValidException("OID for non-existent object or not folder object"); } } - protected NodeRef getNodeRefFromOID(String oid) throws InvalidArgumentException + /** + * Checks specified in CMIS request parameters repository Id. + * + * @param repositoryId repository id + * @throws InvalidArgumentException repository diesn't exist + */ + protected void checkRepositoryId(String repositoryId) throws InvalidArgumentException { - NodeRef nodeRef; - - try + if (!this.descriptorService.getServerDescriptor().getId().equals(repositoryId)) { - nodeRef = new NodeRef(oid); + throw new InvalidArgumentException("Invalid repository id"); } - catch (AlfrescoRuntimeException e) - { - throw new InvalidArgumentException("Invalid OID value", e); - } - - return nodeRef; } - private void addBooleanProperty(CmisPropertiesType properties, PropertyFilter filter, String name, NodeRef nodeRef) + private void addBooleanProperty(CmisPropertiesType properties, PropertyFilter filter, String name, Map alfrescoProperties) { - Serializable value = cmisPropertyService.getProperty(nodeRef, name); + Serializable value = alfrescoProperties.get(name); if (filter.allow(name) && value != null) { CmisPropertyBoolean propBoolean = new CmisPropertyBoolean (); @@ -133,9 +183,9 @@ public class DMAbstractServicePort } } - private void addDateTimeProperty(CmisPropertiesType properties, PropertyFilter filter, String name, NodeRef nodeRef) + private void addDateTimeProperty(CmisPropertiesType properties, PropertyFilter filter, String name, Map alfrescoProperties) { - Serializable value = cmisPropertyService.getProperty(nodeRef, name); + Serializable value = alfrescoProperties.get(name); if (filter.allow(name) && value != null) { CmisPropertyDateTime propDateTime = new CmisPropertyDateTime(); @@ -145,9 +195,9 @@ public class DMAbstractServicePort } } - private void addIDProperty(CmisPropertiesType properties, PropertyFilter filter, String name, NodeRef nodeRef) + private void addIDProperty(CmisPropertiesType properties, PropertyFilter filter, String name, Map alfrescoProperties) { - Serializable value = cmisPropertyService.getProperty(nodeRef, name); + Serializable value = alfrescoProperties.get(name); if (filter.allow(name) && value != null) { CmisPropertyId propID = new CmisPropertyId(); @@ -157,9 +207,9 @@ public class DMAbstractServicePort } } - private void addIntegerProperty(CmisPropertiesType properties, PropertyFilter filter, String name, NodeRef nodeRef) + private void addIntegerProperty(CmisPropertiesType properties, PropertyFilter filter, String name, Map alfrescoProperties) { - Serializable value = cmisPropertyService.getProperty(nodeRef, name); + Serializable value = alfrescoProperties.get(name); if (filter.allow(name) && value != null) { CmisPropertyInteger propInteger = new CmisPropertyInteger(); @@ -169,9 +219,9 @@ public class DMAbstractServicePort } } - private void addStringProperty(CmisPropertiesType properties, PropertyFilter filter, String name, NodeRef nodeRef) + private void addStringProperty(CmisPropertiesType properties, PropertyFilter filter, String name, Map alfrescoProperties) { - Serializable value = cmisPropertyService.getProperty(nodeRef, name); + Serializable value = alfrescoProperties.get(name); if (filter.allow(name) && value != null) { CmisPropertyString propString = new CmisPropertyString(); @@ -192,9 +242,9 @@ public class DMAbstractServicePort } } - private void addURIProperty(CmisPropertiesType properties, PropertyFilter filter, String name, NodeRef nodeRef) + private void addURIProperty(CmisPropertiesType properties, PropertyFilter filter, String name, Map alfrescoProperties) { - Serializable value = cmisPropertyService.getProperty(nodeRef, name); + Serializable value = alfrescoProperties.get(name); if (filter.allow(name) && value != null) { CmisPropertyUri propString = new CmisPropertyUri(); @@ -211,54 +261,91 @@ public class DMAbstractServicePort * @param filter property filter * @return properties */ - public CmisPropertiesType getPropertiesType(NodeRef nodeRef, PropertyFilter filter) + public CmisPropertiesType getPropertiesType(String identifier, PropertyFilter filter) + { + + Map properties = (NodeRef.isNodeRef(identifier)) ? (cmisPropertyService.getProperties(new NodeRef(identifier))) + : (createBaseRelationshipProperties(new AssociationRef(identifier))); + + return getPropertiesType(properties, filter); + } + + public CmisPropertiesType getPropertiesType(Map alfrescoProperties, PropertyFilter filter) { CMISMapping cmisMapping = cmisDictionaryService.getCMISMapping(); - QName cmisType = cmisMapping.getCmisType(nodeService.getType(nodeRef)); + String objectTypeId = (String) alfrescoProperties.get(CMISMapping.PROP_OBJECT_TYPE_ID); + QName cmisType = cmisMapping.getCmisTypeId(objectTypeId).getQName(); CmisPropertiesType properties = new CmisPropertiesType(); if (cmisMapping.isValidCmisDocument(cmisType)) { - addBooleanProperty(properties, filter, CMISMapping.PROP_IS_IMMUTABLE, nodeRef); - addBooleanProperty(properties, filter, CMISMapping.PROP_IS_LATEST_VERSION, nodeRef); - addBooleanProperty(properties, filter, CMISMapping.PROP_IS_MAJOR_VERSION, nodeRef); - addBooleanProperty(properties, filter, CMISMapping.PROP_IS_LATEST_MAJOR_VERSION, nodeRef); - addBooleanProperty(properties, filter, CMISMapping.PROP_IS_VERSION_SERIES_CHECKED_OUT, nodeRef); - addDateTimeProperty(properties, filter, CMISMapping.PROP_CREATION_DATE, nodeRef); - addDateTimeProperty(properties, filter, CMISMapping.PROP_LAST_MODIFICATION_DATE, nodeRef); - addIDProperty(properties, filter, CMISMapping.PROP_OBJECT_ID, nodeRef); - addIDProperty(properties, filter, CMISMapping.PROP_VERSION_SERIES_ID, nodeRef); - addIDProperty(properties, filter, CMISMapping.PROP_VERSION_SERIES_CHECKED_OUT_ID, nodeRef); - addIntegerProperty(properties, filter, CMISMapping.PROP_CONTENT_STREAM_LENGTH, nodeRef); - addStringProperty(properties, filter, CMISMapping.PROP_NAME, nodeRef); - addStringProperty(properties, filter, "BaseType", "document"); - addStringProperty(properties, filter, CMISMapping.PROP_OBJECT_TYPE_ID, nodeRef); - addStringProperty(properties, filter, CMISMapping.PROP_CREATED_BY, nodeRef); - addStringProperty(properties, filter, CMISMapping.PROP_LAST_MODIFIED_BY, nodeRef); - addStringProperty(properties, filter, CMISMapping.PROP_CONTENT_STREAM_MIME_TYPE, nodeRef); - addStringProperty(properties, filter, CMISMapping.PROP_CONTENT_STREAM_FILENAME, nodeRef); - addStringProperty(properties, filter, CMISMapping.PROP_VERSION_LABEL, nodeRef); - addStringProperty(properties, filter, CMISMapping.PROP_VERSION_SERIES_CHECKED_OUT_BY, nodeRef); - addStringProperty(properties, filter, CMISMapping.PROP_CHECKIN_COMMENT, nodeRef); - addURIProperty(properties, filter, CMISMapping.PROP_CONTENT_STREAM_URI, nodeRef); + addBooleanProperty(properties, filter, CMISMapping.PROP_IS_IMMUTABLE, alfrescoProperties); + addBooleanProperty(properties, filter, CMISMapping.PROP_IS_LATEST_VERSION, alfrescoProperties); + addBooleanProperty(properties, filter, CMISMapping.PROP_IS_MAJOR_VERSION, alfrescoProperties); + addBooleanProperty(properties, filter, CMISMapping.PROP_IS_LATEST_MAJOR_VERSION, alfrescoProperties); + addBooleanProperty(properties, filter, CMISMapping.PROP_IS_VERSION_SERIES_CHECKED_OUT, alfrescoProperties); + addDateTimeProperty(properties, filter, CMISMapping.PROP_CREATION_DATE, alfrescoProperties); + addDateTimeProperty(properties, filter, CMISMapping.PROP_LAST_MODIFICATION_DATE, alfrescoProperties); + addIDProperty(properties, filter, CMISMapping.PROP_OBJECT_ID, alfrescoProperties); + addIDProperty(properties, filter, CMISMapping.PROP_VERSION_SERIES_ID, alfrescoProperties); + addIDProperty(properties, filter, CMISMapping.PROP_VERSION_SERIES_CHECKED_OUT_ID, alfrescoProperties); + addIntegerProperty(properties, filter, CMISMapping.PROP_CONTENT_STREAM_LENGTH, alfrescoProperties); + addStringProperty(properties, filter, CMISMapping.PROP_NAME, alfrescoProperties); + addStringProperty(properties, filter, BASE_TYPE_PROPERTY_NAME, "document"); + addStringProperty(properties, filter, CMISMapping.PROP_OBJECT_TYPE_ID, alfrescoProperties); + addStringProperty(properties, filter, CMISMapping.PROP_CREATED_BY, alfrescoProperties); + addStringProperty(properties, filter, CMISMapping.PROP_LAST_MODIFIED_BY, alfrescoProperties); + addStringProperty(properties, filter, CMISMapping.PROP_CONTENT_STREAM_MIME_TYPE, alfrescoProperties); + addStringProperty(properties, filter, CMISMapping.PROP_CONTENT_STREAM_FILENAME, alfrescoProperties); + addStringProperty(properties, filter, CMISMapping.PROP_VERSION_LABEL, alfrescoProperties); + addStringProperty(properties, filter, CMISMapping.PROP_VERSION_SERIES_CHECKED_OUT_BY, alfrescoProperties); + addStringProperty(properties, filter, CMISMapping.PROP_CHECKIN_COMMENT, alfrescoProperties); + addURIProperty(properties, filter, CMISMapping.PROP_CONTENT_STREAM_URI, alfrescoProperties); } else if (cmisMapping.isValidCmisFolder(cmisType)) { - addDateTimeProperty(properties, filter, CMISMapping.PROP_CREATION_DATE, nodeRef); - addDateTimeProperty(properties, filter, CMISMapping.PROP_LAST_MODIFICATION_DATE, nodeRef); - addIDProperty(properties, filter, CMISMapping.PROP_OBJECT_ID, nodeRef); - addIDProperty(properties, filter, CMISMapping.PROP_PARENT_ID, nodeRef); - addStringProperty(properties, filter, CMISMapping.PROP_NAME, nodeRef); - addStringProperty(properties, filter, "BaseType", "folder"); - addStringProperty(properties, filter, CMISMapping.PROP_OBJECT_TYPE_ID, nodeRef); - addStringProperty(properties, filter, CMISMapping.PROP_CREATED_BY, nodeRef); - addStringProperty(properties, filter, CMISMapping.PROP_LAST_MODIFIED_BY, nodeRef); + addDateTimeProperty(properties, filter, CMISMapping.PROP_CREATION_DATE, alfrescoProperties); + addDateTimeProperty(properties, filter, CMISMapping.PROP_LAST_MODIFICATION_DATE, alfrescoProperties); + addIDProperty(properties, filter, CMISMapping.PROP_OBJECT_ID, alfrescoProperties); + addIDProperty(properties, filter, CMISMapping.PROP_PARENT_ID, alfrescoProperties); + addStringProperty(properties, filter, CMISMapping.PROP_NAME, alfrescoProperties); + addStringProperty(properties, filter, BASE_TYPE_PROPERTY_NAME, "folder"); + addStringProperty(properties, filter, CMISMapping.PROP_OBJECT_TYPE_ID, alfrescoProperties); + addStringProperty(properties, filter, CMISMapping.PROP_CREATED_BY, alfrescoProperties); + addStringProperty(properties, filter, CMISMapping.PROP_LAST_MODIFIED_BY, alfrescoProperties); + } + else if (cmisMapping.isValidCmisRelationship(cmisType)) + { + addStringProperty(properties, filter, CMISMapping.PROP_OBJECT_TYPE_ID, alfrescoProperties); + addIDProperty(properties, filter, CMISMapping.PROP_OBJECT_ID, alfrescoProperties); + addStringProperty(properties, filter, BASE_TYPE_PROPERTY_NAME, alfrescoProperties); + addStringProperty(properties, filter, CMISMapping.PROP_CREATED_BY, alfrescoProperties); + addDateTimeProperty(properties, filter, CMISMapping.PROP_CREATION_DATE, alfrescoProperties); + addIDProperty(properties, filter, CMISMapping.PROP_SOURCE_ID, alfrescoProperties); + addIDProperty(properties, filter, CMISMapping.PROP_TARGET_ID, alfrescoProperties); } return properties; } + /** + * Sets all properties' fields for specified node + * + * @param nodeRef the NodeRef for node for those properties must be setted + * @param properties all necessary properties fields + */ + protected void setProperties(NodeRef nodeRef, CmisPropertiesType properties) + { + // TODO: properties setting + + String name = (String) PropertyUtil.getProperty(properties, CMISMapping.PROP_NAME); + if (name != null) + { + nodeService.setProperty(nodeRef, ContentModel.PROP_NAME, name); + } + } + /** * Returns latest minor or major version of document * @@ -286,8 +373,7 @@ public class DMAbstractServicePort do { latestVersion = versionHistory.getPredecessor(latestVersion); - } - while (latestVersion.getVersionType().equals(VersionType.MAJOR) == false); + } while (latestVersion.getVersionType().equals(VersionType.MAJOR) == false); latestVersionNodeRef = latestVersion.getFrozenStateNodeRef(); } @@ -297,9 +383,19 @@ public class DMAbstractServicePort return latestVersionNodeRef; } - public static PropertyFilter createPropertyFilter(JAXBElement filterElt) throws FilterNotValidException + public static PropertyFilter createPropertyFilter(String filter) throws FilterNotValidException { - return (filterElt == null) ? (new PropertyFilter()) : (new PropertyFilter(filterElt.getValue())); + return (filter == null) ? (new PropertyFilter()) : (new PropertyFilter(filter)); + } + + public static PropertyFilter createPropertyFilter(JAXBElement element) throws FilterNotValidException + { + String filter = null; + if (element != null) + { + filter = element.getValue(); + } + return createPropertyFilter(filter); } public Cursor createCursor(int totalRows, BigInteger skipCount, BigInteger maxItems) @@ -361,4 +457,58 @@ public class DMAbstractServicePort this.fileFolderService = fileFolderService; } + public void setCheckOutCheckInService(CheckOutCheckInService checkOutCheckInService) + { + + this.checkOutCheckInService = checkOutCheckInService; + } + + public void setCmisObjectsUtils(CmisObjectsUtils cmisObjectsUtils) + { + + this.cmisObjectsUtils = cmisObjectsUtils; + } + + public void setSearchService(SearchService searchService) + { + + this.searchService = searchService; + } + + private Map createBaseRelationshipProperties(AssociationRef association) + { + + Map result = new HashMap(); + + result.put(CMISMapping.PROP_OBJECT_TYPE_ID, cmisDictionaryService.getCMISMapping().getCmisType(association.getTypeQName())); + result.put(CMISMapping.PROP_OBJECT_ID, association.toString()); + result.put(BASE_TYPE_PROPERTY_NAME, CMISMapping.RELATIONSHIP_TYPE_ID.getTypeId()); + result.put(CMISMapping.PROP_CREATED_BY, AuthenticationUtil.getFullyAuthenticatedUser()); + result.put(CMISMapping.PROP_CREATION_DATE, new Date()); + result.put(CMISMapping.PROP_SOURCE_ID, association.getSourceRef()); + result.put(CMISMapping.PROP_TARGET_ID, association.getTargetRef()); + + return result; + } + + protected Map createVersionProperties(String versionDescription, VersionType versionType) + { + + Map result = new HashMap(); + result.put(Version.PROP_DESCRIPTION, versionDescription); + result.put(VersionModel.PROP_VERSION_TYPE, versionType); + + return result; + } + + protected NodeRef performCheckouting(NodeRef documentNodeReference) + { + + if (!this.nodeService.hasAspect(documentNodeReference, ContentModel.ASPECT_VERSIONABLE)) + { + this.versionService.createVersion(documentNodeReference, createVersionProperties(INITIAL_VERSION_DESCRIPTION, VersionType.MAJOR)); + } + + return checkOutCheckInService.checkout(documentNodeReference); + } } diff --git a/source/java/org/alfresco/repo/cmis/ws/DMDiscoveryServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMDiscoveryServicePort.java new file mode 100755 index 0000000000..1c429634f7 --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/ws/DMDiscoveryServicePort.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws; + +import org.alfresco.cmis.search.CMISQueryOptions; +import org.alfresco.cmis.search.CMISResultSet; +import org.alfresco.cmis.search.CMISResultSetRow; + +/** + * Port for Discovery service. + * + * @author Dmitry Lazurkin + */ +@javax.jws.WebService(name = "DiscoveryServicePort", serviceName = "DiscoveryService", portName = "DiscoveryServicePort", targetNamespace = "http://www.cmis.org/ns/1.0", endpointInterface = "org.alfresco.repo.cmis.ws.DiscoveryServicePort") +public class DMDiscoveryServicePort extends DMAbstractServicePort implements DiscoveryServicePort +{ + + /** + * Queries the repository for queryable object based on properties or an optional full-text string. Relationship objects are not queryable. Content-streams are not returned as + * part of query + * + * @param parameters query parameters + * @return collection of CmisObjectType and boolean hasMoreItems + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws OperationNotSupportedException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public QueryResponse query(CmisQueryType parameters) throws PermissionDeniedException, UpdateConflictException, OperationNotSupportedException, InvalidArgumentException, + RuntimeException, ConstraintViolationException + { + // TODO: searchAllVersions, returnAllowableActions, includeRelationships + CMISQueryOptions options = new CMISQueryOptions(parameters.getStatement(), cmisService.getDefaultRootStoreRef()); + + if (parameters.getSkipCount() != null) + { + options.setSkipCount(parameters.getSkipCount().intValue()); + } + + if (parameters.getPageSize() != null) + { + options.setMaxItems(parameters.getPageSize().intValue()); + } + + CMISResultSet resultSet = cmisQueryService.query(options); + + QueryResponse response = new QueryResponse(); + response.setHasMoreItems(resultSet.hasMore()); + + for (CMISResultSetRow row : resultSet) + { + CmisObjectType object = new CmisObjectType(); + object.setProperties(getPropertiesType(row.getValues(), new PropertyFilter())); + response.getObject().add(object); + } + + return response; + } + +} diff --git a/source/java/org/alfresco/repo/cmis/ws/DMMultiFilingServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMMultiFilingServicePort.java new file mode 100755 index 0000000000..fed86a286d --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/ws/DMMultiFilingServicePort.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws; + +import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType; +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * Port for Multi-Filing service. + * + * @author Dmitry Lazurkin + * @author Dmitry Velichkevich + */ +@javax.jws.WebService(name = "MultiFilingServicePort", serviceName = "MultiFilingService", portName = "MultiFilingServicePort", targetNamespace = "http://www.cmis.org/ns/1.0", endpointInterface = "org.alfresco.repo.cmis.ws.MultiFilingServicePort") +public class DMMultiFilingServicePort extends DMAbstractServicePort implements MultiFilingServicePort +{ + /** + * Adds an existing non-folder, fileable object to a folder. + * + * @param repositoryId Repository Id + * @param objectId object Id to be added to a folder + * @param folderId folder Id to which the object is added + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws ObjectNotFoundException + * @throws FolderNotValidException + * @throws OperationNotSupportedException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public void addObjectToFolder(String repositoryId, String objectId, String folderId) throws PermissionDeniedException, UpdateConflictException, ObjectNotFoundException, + FolderNotValidException, OperationNotSupportedException, InvalidArgumentException, RuntimeException, ConstraintViolationException + { + checkRepositoryId(repositoryId); + NodeRef objectNodeRef = this.cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT).getConvertedIdentifier(); + NodeRef parentFolderNodeRef = this.cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT).getConvertedIdentifier(); + + // TODO: check for allowed child object types + + this.cmisObjectsUtils.addObjectToFolder(objectNodeRef, parentFolderNodeRef); + } + + /** + * Removes a non-folder child object from a folder or from all folders. This does not delete the object and does not change the ID of the object. + * + * @param repositoryId repository Id + * @param objectId The object to be removed from a folder + * @param folderId The folder to be removed from. + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws ObjectNotFoundException + * @throws FolderNotValidException + * @throws OperationNotSupportedException + * @throws NotInFolderException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public void removeObjectFromFolder(String repositoryId, String objectId, String folderId) throws PermissionDeniedException, UpdateConflictException, ObjectNotFoundException, + FolderNotValidException, OperationNotSupportedException, NotInFolderException, InvalidArgumentException, RuntimeException, ConstraintViolationException + { + + checkRepositoryId(repositoryId); + + NodeRef objectNodeReference = this.cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT).getConvertedIdentifier(); + NodeRef folderNodeReference = checkAndReceiveFolderIdentifier(folderId); + + assertExistFolder(folderNodeReference); + + checkObjectChildParentRelationships(objectNodeReference, folderNodeReference); + + if (!this.cmisObjectsUtils.removeObject(objectNodeReference, folderNodeReference)) + { + throw new NotInFolderException("The specified Object is not child of the specified Folder Object"); + } + } + + private NodeRef checkAndReceiveFolderIdentifier(String folderIdentifier) throws OperationNotSupportedException + { + + try + { + return this.cmisObjectsUtils.getIdentifierInstance(folderIdentifier, AlfrescoObjectType.FOLDER_OBJECT).getConvertedIdentifier(); + } + catch (Throwable e) + { + throw new OperationNotSupportedException("Unfiling is not supported. Any Object can't be deleted from all Folders"); + } + } + + private void checkObjectChildParentRelationships(NodeRef objectNodeReference, NodeRef folderNodeReference) throws OperationNotSupportedException + { + + if (this.cmisObjectsUtils.isPrimaryObjectParent(folderNodeReference, objectNodeReference)) + { + throw new OperationNotSupportedException("Unfiling is not supported. User deleteObjectService instead"); + } + } +} diff --git a/source/java/org/alfresco/repo/cmis/ws/DMNavigationServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMNavigationServicePort.java index 7c4cff704a..fcabc20cd4 100644 --- a/source/java/org/alfresco/repo/cmis/ws/DMNavigationServicePort.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMNavigationServicePort.java @@ -24,35 +24,103 @@ */ package org.alfresco.repo.cmis.ws; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.LinkedList; import java.util.List; import org.alfresco.cmis.CMISTypesFilterEnum; +import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType; +import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.web.util.paging.Cursor; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.NodeRef; /** * Port for navigation service * * @author Dmitry Lazurkin + * @author Dmitry Velichkevich */ - @javax.jws.WebService(name = "NavigationServicePort", serviceName = "NavigationService", portName = "NavigationServicePort", targetNamespace = "http://www.cmis.org/ns/1.0", endpointInterface = "org.alfresco.repo.cmis.ws.NavigationServicePort") public class DMNavigationServicePort extends DMAbstractServicePort implements NavigationServicePort { + private static final String POLICIES_LISTING_UNSUPPORTED_EXCEPTION_MESSAGE = "Policies listing isn't supported"; + private static final int EQUALS_CONDITION_VALUE = 0; + + private static final BigInteger FULL_DESCENDANTS_HIERARCHY_CONDITION = BigInteger.valueOf(-1l); + + /** + * Gets the private working copies of checked-out objects that the user is allowed to update. + * + * @param parameters repositoryId: repository Id; folderID: folder Id; filter: property filter; includeAllowableActions; includeRelationships; maxItems: 0 = Unlimited; + * skipCount: 0 = start at beginning + * @return collection of CmisObjectType and boolean hasMoreItems + * @throws RuntimeException + * @throws InvalidArgumentException + * @throws ObjectNotFoundException + * @throws ConstraintViolationException + * @throws FilterNotValidException + * @throws OperationNotSupportedException + * @throws UpdateConflictException + * @throws FolderNotValidException + * @throws PermissionDeniedException + */ public GetCheckedoutDocsResponse getCheckedoutDocs(GetCheckedoutDocs parameters) throws RuntimeException, InvalidArgumentException, ObjectNotFoundException, ConstraintViolationException, FilterNotValidException, OperationNotSupportedException, UpdateConflictException, FolderNotValidException, PermissionDeniedException { - return null; + checkRepositoryId(parameters.getRepositoryId()); + + PropertyFilter propertyFilter = createPropertyFilter(parameters.getFilter()); + + NodeRef folderId = (NodeRef) (((parameters.getFolderID() != null) && (parameters.getFolderID().getValue() != null)) ? (this.cmisObjectsUtils.getIdentifierInstance( + parameters.getFolderID().getValue(), AlfrescoObjectType.FOLDER_OBJECT).getConvertedIdentifier()) : (null)); + + NodeRef[] nodeRefs = this.cmisService.getCheckedOut(AuthenticationUtil.getFullyAuthenticatedUser(), folderId, (folderId == null)); + + Cursor cursor = createCursor(nodeRefs.length, parameters.getSkipCount() != null ? parameters.getSkipCount().getValue() : null, + parameters.getMaxItems() != null ? parameters.getMaxItems().getValue() : null); + + GetCheckedoutDocsResponse response = new GetCheckedoutDocsResponse(); + List resultListing = response.getObject(); + + for (int index = cursor.getStartRow(); index <= cursor.getEndRow(); index++) + { + resultListing.add(convertAlfrescoObjectToCmisObject(nodeRefs[index].toString(), propertyFilter)); + } + + response.setHasMoreItems(cursor.getEndRow() < (nodeRefs.length - 1)); + + // TODO: includeAllowableActions, includeRelationships + + return response; } + /** + * Gets the list of child objects contained in the specified folder. Only the filter-selected properties associated with each object are returned. The content-streams of + * documents are not returned.For returning a tree of objects of a certain depth, use {@link #getDescendants(GetDescendants parameters)}. + * + * @param parameters repositoryId: repository Id; folderId: folder Id; type: DOCUMENTS, FOLDERS, POLICIES, ANY; filter: property filter; includeAllowableActions; + * includeRelationships; maxItems: 0 = Unlimited; skipCount: 0 = start at beginning + * @return collection of CmisObjectType and boolean hasMoreItems + * @throws RuntimeException + * @throws InvalidArgumentException + * @throws ObjectNotFoundException + * @throws ConstraintViolationException + * @throws FilterNotValidException + * @throws OperationNotSupportedException + * @throws UpdateConflictException + * @throws FolderNotValidException + * @throws PermissionDeniedException + */ public GetChildrenResponse getChildren(GetChildren parameters) throws RuntimeException, InvalidArgumentException, ObjectNotFoundException, ConstraintViolationException, FilterNotValidException, OperationNotSupportedException, UpdateConflictException, FolderNotValidException, PermissionDeniedException { PropertyFilter propertyFilter = createPropertyFilter(parameters.getFilter()); - NodeRef folderNodeRef = getNodeRefFromOID(parameters.getFolderId()); - assertExistFolder(folderNodeRef); + NodeRef folderNodeRef = this.cmisObjectsUtils.getIdentifierInstance(parameters.getFolderId(), AlfrescoObjectType.FOLDER_OBJECT).getConvertedIdentifier(); NodeRef[] listing = null; @@ -72,50 +140,327 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na listing = cmisService.getChildren(folderNodeRef, CMISTypesFilterEnum.FOLDERS); break; case POLICIES: - throw new OperationNotSupportedException("Policies listing isn't supported"); + throw new OperationNotSupportedException(POLICIES_LISTING_UNSUPPORTED_EXCEPTION_MESSAGE); case ANY: listing = cmisService.getChildren(folderNodeRef, CMISTypesFilterEnum.ANY); break; } - Cursor cursor = createCursor(listing.length, parameters.getSkipCount() != null ? parameters.getSkipCount().getValue() : null, parameters.getMaxItems() != null ? parameters - .getMaxItems().getValue() : null); + Cursor cursor = createCursor(listing.length, (parameters.getSkipCount() != null ? parameters.getSkipCount().getValue() : null), + (parameters.getMaxItems() != null ? parameters.getMaxItems().getValue() : null)); GetChildrenResponse response = new GetChildrenResponse(); List resultListing = response.getObject(); for (int index = cursor.getStartRow(); index <= cursor.getEndRow(); index++) { - NodeRef currentNodeRef = listing[index]; - CmisObjectType cmisObject = new CmisObjectType(); - cmisObject.setProperties(getPropertiesType(currentNodeRef, propertyFilter)); - resultListing.add(cmisObject); + resultListing.add(convertAlfrescoObjectToCmisObject(listing[index].toString(), propertyFilter)); } - if (parameters.getMaxItems() != null && cursor.getRowCount() > 0) - { - response.setHasMoreItems(cursor.getRowCount() < listing.length); - } + response.setHasMoreItems(cursor.getEndRow() < (listing.length - 1)); return response; } + /** + * 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 RuntimeException + * @throws InvalidArgumentException + * @throws ObjectNotFoundException + * @throws ConstraintViolationException + * @throws FilterNotValidException + * @throws OperationNotSupportedException + * @throws UpdateConflictException + * @throws FolderNotValidException + * @throws PermissionDeniedException + */ public GetDescendantsResponse getDescendants(GetDescendants parameters) throws RuntimeException, InvalidArgumentException, ObjectNotFoundException, ConstraintViolationException, FilterNotValidException, OperationNotSupportedException, UpdateConflictException, FolderNotValidException, PermissionDeniedException { - return null; + + BigInteger depth = ((parameters.getDepth() != null) && (parameters.getDepth().getValue() != null)) ? (parameters.getDepth().getValue()) : (BigInteger.ONE); + + checkRepositoryId(parameters.getRepositoryId()); + checkDepthParameter(depth); + + GetDescendantsResponse response = new GetDescendantsResponse(); + + formatCommonResponse(createPropertyFilter(parameters.getFilter()), createHierarchyReceiver( + (parameters.getType() != null) ? (parameters.getType()) : (EnumTypesOfFileableObjects.ANY), depth).receiveHierarchy(parameters.getFolderId()), response.getObject()); + + // TODO: includeAllowableActions, includeRelationships + + return response; } + /** + * 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 RuntimeException + * @throws InvalidArgumentException + * @throws ObjectNotFoundException + * @throws ConstraintViolationException + * @throws FilterNotValidException + * @throws OperationNotSupportedException + * @throws UpdateConflictException + * @throws FolderNotValidException + * @throws PermissionDeniedException + */ public GetFolderParentResponse getFolderParent(GetFolderParent parameters) throws RuntimeException, InvalidArgumentException, ObjectNotFoundException, ConstraintViolationException, FilterNotValidException, OperationNotSupportedException, UpdateConflictException, FolderNotValidException, PermissionDeniedException { - return null; + + checkRepositoryId(parameters.getRepositoryId()); + + GetFolderParentResponse response = new GetFolderParentResponse(); + + formatCommonResponse(createPropertyFilter(parameters.getFilter()), receiveParentList(parameters.getFolderId(), (((parameters.getReturnToRoot() != null) && (parameters + .getReturnToRoot().getValue() != null)) ? (parameters.getReturnToRoot().getValue()) : (false))), response.getObject()); + + // TODO: includeAllowableActions, includeRelationships + + return response; } + /** + * 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 RuntimeException + * @throws InvalidArgumentException + * @throws ObjectNotFoundException + * @throws ConstraintViolationException + * @throws FilterNotValidException + * @throws OperationNotSupportedException + * @throws UpdateConflictException + * @throws FolderNotValidException + * @throws PermissionDeniedException + */ public GetObjectParentsResponse getObjectParents(GetObjectParents parameters) throws RuntimeException, InvalidArgumentException, ObjectNotFoundException, ConstraintViolationException, FilterNotValidException, OperationNotSupportedException, UpdateConflictException, FolderNotValidException, PermissionDeniedException { - return null; + // TODO: Policy + + checkRepositoryId(parameters.getRepositoryId()); + + GetObjectParentsResponse response = new GetObjectParentsResponse(); + + formatCommonResponse(createPropertyFilter(parameters.getFilter()), receiveObjectParents((NodeRef) this.cmisObjectsUtils.getIdentifierInstance(parameters.getObjectId(), + AlfrescoObjectType.DOCUMENT_OBJECT).getConvertedIdentifier()), response.getObject()); + + // TODO: includeAllowableActions, includeRelationships + + return response; } + private void checkDepthParameter(BigInteger depth) throws InvalidArgumentException + { + + if (depth.equals(BigInteger.ZERO) || (depth.compareTo(FULL_DESCENDANTS_HIERARCHY_CONDITION) < EQUALS_CONDITION_VALUE)) + { + throw new InvalidArgumentException("The specified descendants retriving depth is not valid. Valid depth values are: -1 (full hierarchy), N > 0"); + } + } + + private List receiveParentList(String targetChildIdentifier, boolean fullParentsHierarchy) throws InvalidNodeRefException, InvalidArgumentException, + ObjectNotFoundException + { + + List result = new LinkedList(); + + if (targetChildIdentifier.equals(this.cmisService.getDefaultRootNodeRef().toString())) + { + return result; + } + + NodeRef currentParent = receiveNextParentNodeReference((NodeRef) this.cmisObjectsUtils.getIdentifierInstance(targetChildIdentifier, AlfrescoObjectType.FOLDER_OBJECT) + .getConvertedIdentifier(), result); + + return (fullParentsHierarchy) ? (receiveFullAncestorsHierachy(currentParent, result)) : (result); + } + + private List receiveFullAncestorsHierachy(NodeRef currentParent, List parents) + { + + String lastAncestorIdentifier = this.cmisService.getDefaultRootNodeRef().toString(); + + while ((currentParent != null) && !currentParent.toString().equals(lastAncestorIdentifier)) + { + currentParent = receiveNextParentNodeReference(currentParent, parents); + } + + return parents; + } + + private NodeRef receiveNextParentNodeReference(NodeRef currentParent, List parents) + { + + currentParent = this.nodeService.getPrimaryParent(currentParent).getParentRef(); + + if (currentParent != null) + { + parents.add(currentParent); + } + + return currentParent; + } + + private List receiveObjectParents(NodeRef objectId) throws InvalidArgumentException + { + + List parents = new LinkedList(); + + for (ChildAssociationRef childParentAssociation : this.nodeService.getParentAssocs(objectId)) + { + parents.add(childParentAssociation.getParentRef()); + } + + return parents; + } + + private HierarchyReceiverStrategy createHierarchyReceiver(EnumTypesOfFileableObjects returnObjectsType, BigInteger finalDepth) + { + + return (finalDepth.equals(FULL_DESCENDANTS_HIERARCHY_CONDITION)) ? (new FullHierarchyReceiver(returnObjectsType)) : (new LayerConstrainedHierarchyReceiver( + returnObjectsType, finalDepth)); + } + + private void separateDescendantsObjects(EnumTypesOfFileableObjects returnObjectsType, List descendantsFolders, List currentLayerFolders, + List currentLayerDocuments) + { + + for (NodeRef element : descendantsFolders) + { + // TODO: OrderBy functionality processing. Instead Arrays.asList() it is necessary to add ordering processing method to store each new element where it should go + currentLayerFolders.addAll(Arrays.asList(this.cmisService.getChildren(element, CMISTypesFilterEnum.FOLDERS))); + + // TODO: OrderBy functionality processing. Instead Arrays.asList() it is necessary to add ordering processing method to store each new element where it should go + if ((returnObjectsType == EnumTypesOfFileableObjects.ANY) || (returnObjectsType == EnumTypesOfFileableObjects.DOCUMENTS)) + { + currentLayerDocuments.addAll(Arrays.asList(this.cmisService.getChildren(element, CMISTypesFilterEnum.DOCUMENTS))); + } + } + } + + private List performDescendantsResultObjectsStoring(EnumTypesOfFileableObjects returnObjectsType, List resultList, List descendantsFolders, + List currentLayerFolders, List currentLayerDocuments) + { + + separateDescendantsObjects(returnObjectsType, descendantsFolders, currentLayerFolders, currentLayerDocuments); + + if ((returnObjectsType == EnumTypesOfFileableObjects.ANY) || (returnObjectsType == EnumTypesOfFileableObjects.FOLDERS)) + { + resultList.addAll(currentLayerFolders); + } + + 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 List that contains all appropriates layers of Alfresco objects + * @throws InvalidArgumentException + */ + public List receiveHierarchy(String rootFolderIdentifier) throws InvalidArgumentException; + } + + /** + * @see HierarchyReceiverStrategy + */ + private class LayerConstrainedHierarchyReceiver implements HierarchyReceiverStrategy + { + private List descendantsFolders = new LinkedList(); + + private EnumTypesOfFileableObjects returnObjectsType; + + private BigInteger finalDepth; + + private BigInteger currentDepth = BigInteger.ZERO; + + private List resultList = new LinkedList(); + + /** + * @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(EnumTypesOfFileableObjects returnObjectsType, BigInteger finalDepth) + { + + this.returnObjectsType = returnObjectsType; + this.finalDepth = finalDepth; + } + + /** + * This method of this class receives Alfresco objects hierarchy until specified layer number + */ + public List receiveHierarchy(String rootFolderIdentifier) throws InvalidArgumentException + { + + this.descendantsFolders.add((NodeRef) cmisObjectsUtils.getIdentifierInstance(rootFolderIdentifier, AlfrescoObjectType.FOLDER_OBJECT).getConvertedIdentifier()); + + do + { + this.descendantsFolders = performDescendantsResultObjectsStoring(this.returnObjectsType, this.resultList, this.descendantsFolders, new LinkedList(), + new LinkedList()); + + this.currentDepth = this.currentDepth.add(BigInteger.ONE); + } while (!this.descendantsFolders.isEmpty() && (this.currentDepth.compareTo(this.finalDepth) < EQUALS_CONDITION_VALUE)); + + return this.resultList; + } + } + + /** + * @see HierarchyReceiverStrategy + */ + private class FullHierarchyReceiver implements HierarchyReceiverStrategy + { + private EnumTypesOfFileableObjects returnObjectsType; + + private List descendantsFolders = new LinkedList(); + + private List resultList = new LinkedList(); + + /** + * @param returnObjectsType flag that specifies objects of which type are need to be returned + */ + public FullHierarchyReceiver(EnumTypesOfFileableObjects returnObjectsType) + { + + this.returnObjectsType = returnObjectsType; + } + + /** + * This method of this class bypass Alfresco objects hierarchy until there is some Folder-objects can be found + */ + public List receiveHierarchy(String rootFolderIdentifier) throws InvalidArgumentException + { + + this.descendantsFolders.add((NodeRef) cmisObjectsUtils.getIdentifierInstance(rootFolderIdentifier, AlfrescoObjectType.FOLDER_OBJECT).getConvertedIdentifier()); + + while (!this.descendantsFolders.isEmpty()) + { + this.descendantsFolders = performDescendantsResultObjectsStoring(this.returnObjectsType, this.resultList, this.descendantsFolders, new LinkedList(), + new LinkedList()); + } + + return this.resultList; + } + } } diff --git a/source/java/org/alfresco/repo/cmis/ws/DMObjectServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMObjectServicePort.java index 80c80d67e4..6a8c0953be 100644 --- a/source/java/org/alfresco/repo/cmis/ws/DMObjectServicePort.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMObjectServicePort.java @@ -34,24 +34,612 @@ import java.util.Map; import javax.activation.DataHandler; import javax.xml.ws.Holder; +import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.cmis.dictionary.CMISMapping; import org.alfresco.cmis.dictionary.CMISTypeId; +import org.alfresco.model.ContentModel; import org.alfresco.repo.cmis.ws.DeleteTreeResponse.FailedToDelete; +import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType; +import org.alfresco.repo.cmis.ws.utils.CmisObjectsUtils; +import org.alfresco.repo.cmis.ws.utils.CmisObjectsUtils.IdentifierConversionResults; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.lock.NodeLockedException; import org.alfresco.service.cmr.model.FileExistsException; +import org.alfresco.service.cmr.repository.AssociationRef; 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; /** * Port for object service - * + * * @author Dmitry Lazurkin + * @author Dmitry Velichkevich */ - @javax.jws.WebService(name = "ObjectServicePort", serviceName = "ObjectService", portName = "ObjectServicePort", targetNamespace = "http://www.cmis.org/ns/1.0", 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 PermissionService permissionService; + private DictionaryService dictionaryService; + + /** + * Creates a document object of the specified type, and optionally adds the document to a folder + * + * @param repositoryId repository Id + * @param typeId document type + * @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 PermissionDeniedException + * @throws UpdateConflictException + * @throws StorageException + * @throws StreamNotSupportedException + * @throws FolderNotValidException + * @throws OperationNotSupportedException + * @throws TypeNotFoundException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public String createDocument(String repositoryId, String typeId, CmisPropertiesType properties, String folderId, CmisContentStreamType contentStream, + EnumVersioningState versioningState) throws PermissionDeniedException, UpdateConflictException, StorageException, StreamNotSupportedException, FolderNotValidException, + OperationNotSupportedException, TypeNotFoundException, InvalidArgumentException, RuntimeException, ConstraintViolationException + { + checkRepositoryId(repositoryId); + + Map propertiesMap = getPropertiesMap(properties); + CMISMapping cmisMapping = cmisDictionaryService.getCMISMapping(); + CMISTypeId cmisTypeId = cmisMapping.getCmisTypeId(typeId); + + if (cmisMapping.getCmisTypeId(typeId).equals(CMISMapping.DOCUMENT_TYPE_ID) == false) + { + throw new ConstraintViolationException("Invalid document type " + typeId); + } + + NodeRef parentNodeRef = receiveMandatoryFolderNodeReference(folderId); + + String documentName = (String) propertiesMap.get(CMISMapping.PROP_NAME); + if (documentName == null) + { + throw new InvalidArgumentException("Name property not found"); + } + + NodeRef newDocumentNodeRef = fileFolderService.create(parentNodeRef, documentName, cmisMapping.getAlfrescoType(cmisTypeId.getQName())).getNodeRef(); + ContentWriter writer = fileFolderService.getWriter(newDocumentNodeRef); + String mimeType = (String) propertiesMap.get(CMISMapping.PROP_CONTENT_STREAM_MIME_TYPE); + if (mimeType != null) + { + writer.setMimetype(mimeType); + } + InputStream inputstream = null; + try + { + inputstream = contentStream.getStream().getInputStream(); + } + catch (IOException e) + { + throw new ConstraintViolationException("", e.getCause()); + } + writer.putContent(inputstream); + + if (versioningState == null) + { + versioningState = EnumVersioningState.MAJOR; + } + + // TODO: + // cmisPropertyService.setProperties(newDocumentNodeRef, propertiesMap); + + switch (versioningState) + { + case CHECKEDOUT: + newDocumentNodeRef = performCheckouting(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 = (String) cmisPropertyService.getProperty(newDocumentNodeRef, CMISMapping.PROP_VERSION_LABEL); + + return ((versionLabel instanceof String) && versionLabel.contains(VERSION_DELIMETER)) ? (newDocumentNodeRef.toString() + CmisObjectsUtils.NODE_REFERENCE_ID_DELIMETER + versionLabel) + : (newDocumentNodeRef.toString()); + } + + /** + * Creates a folder object of the specified type. + * + * @param repositoryId repository Id + * @param typeId document type + * @param properties CMIS properties + * @param folderId parent folder for this new folder + * @return Id of the created folder object + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws FolderNotValidException + * @throws OperationNotSupportedException + * @throws TypeNotFoundException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public String createFolder(String repositoryId, String typeId, CmisPropertiesType properties, String folderId) throws PermissionDeniedException, UpdateConflictException, + FolderNotValidException, OperationNotSupportedException, TypeNotFoundException, InvalidArgumentException, RuntimeException, ConstraintViolationException + { + checkRepositoryId(repositoryId); + + NodeRef folderNodeRef = this.cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT).getConvertedIdentifier(); + + CMISTypeId cmisTypeId = getCmisTypeId(typeId); + assertExistType(cmisTypeId); + + CMISMapping cmisMapping = cmisDictionaryService.getCMISMapping(); + + if (cmisMapping.isValidCmisFolder(cmisTypeId.getQName()) == false) + { + throw new InvalidArgumentException(typeId + " isn't folder type"); + } + + Map propertiesMap = getPropertiesMap(properties); + + String name = (String) propertiesMap.get(CMISMapping.PROP_NAME); + if (name == null) + { + throw new InvalidArgumentException("Name property not found"); + } + + assertExistFolder(folderNodeRef); + + try + { + NodeRef newFolderNodeRef = fileFolderService.create(folderNodeRef, name, cmisMapping.getAlfrescoType(cmisTypeId.getQName())).getNodeRef(); + // TODO: + // cmisPropertyService.setProperties(newFolderNodeRef, propertiesMap); + return (String) cmisPropertyService.getProperty(newFolderNodeRef, CMISMapping.PROP_OBJECT_ID); + } + catch (FileExistsException e) + { + throw new UpdateConflictException("Folder already exists"); + } + } + + /** + * Creates a policy object of the specified type, and optionally adds the policy to a folder. + * + * @param repositoryId repository Id + * @param typeId policy type + * @param properties CMIS properties + * @param folderId parent folder for this new policy + * @return Id of the created policy object + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws FolderNotValidException + * @throws OperationNotSupportedException + * @throws TypeNotFoundException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public String createPolicy(String repositoryId, String typeId, CmisPropertiesType properties, String folderId) throws PermissionDeniedException, UpdateConflictException, + FolderNotValidException, OperationNotSupportedException, TypeNotFoundException, InvalidArgumentException, RuntimeException, ConstraintViolationException + { + + // TODO: + + return null; + } + + /** + * Creates a relationship object of the specified type. + * + * @param repositoryId repository Id + * @param typeId relationship type + * @param properties CMIS properties + * @param sourceObjectId source object Id + * @param targetObjectId target object Id + * @return Id of the created relationship object + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws ObjectNotFoundException + * @throws OperationNotSupportedException + * @throws TypeNotFoundException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public String createRelationship(String repositoryId, String typeId, CmisPropertiesType properties, String sourceObjectId, String targetObjectId) + throws PermissionDeniedException, UpdateConflictException, ObjectNotFoundException, OperationNotSupportedException, TypeNotFoundException, InvalidArgumentException, + RuntimeException, ConstraintViolationException + { + checkRepositoryId(repositoryId); + + NodeRef sourceNodeRef; + NodeRef targetNodeRef; + + try + { + sourceNodeRef = this.cmisObjectsUtils.getIdentifierInstance(sourceObjectId, AlfrescoObjectType.ANY_OBJECT).getConvertedIdentifier(); + targetNodeRef = this.cmisObjectsUtils.getIdentifierInstance(targetObjectId, AlfrescoObjectType.ANY_OBJECT).getConvertedIdentifier(); + } + catch (InvalidArgumentException e) + { + if (e.getCause() instanceof ObjectNotFoundException) + { + throw new ObjectNotFoundException(e.getMessage()); + } + + throw e; + } + + CMISTypeId relationshipTypeId; + + try + { + relationshipTypeId = cmisDictionaryService.getCMISMapping().getCmisTypeId(typeId); + } + catch (Exception e) + { + throw new InvalidArgumentException("Invalid typeId format: " + typeId); + } + + QName relationshipTypeQName = cmisDictionaryService.getCMISMapping().getAlfrescoType(relationshipTypeId.getQName()); + + AssociationDefinition associationDef = dictionaryService.getAssociation(relationshipTypeQName); + if (associationDef != null) + { + if (!dictionaryService.isSubClass(nodeService.getType(sourceNodeRef), associationDef.getSourceClass().getName())) + { + throw new ConstraintViolationException("Source object type isn't allowed as source type"); + } + + if (!dictionaryService.isSubClass(nodeService.getType(targetNodeRef), associationDef.getTargetClass().getName())) + { + throw new ConstraintViolationException("Target object type isn't allowed as target type"); + } + + return nodeService.createAssociation(sourceNodeRef, targetNodeRef, relationshipTypeQName).toString(); + } + else + { + throw new TypeNotFoundException(relationshipTypeId.getQName() + " Relationship type not found"); + } + } + + /** + * Deletes the content-stream of the specified document. This does not delete properties. If there are other versions this does not affect them, their properties or content. + * This does not change the ID of the document. + * + * @param repositoryId repository Id + * @param documentId document Id + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws StorageException + * @throws StreamNotSupportedException + * @throws ObjectNotFoundException + * @throws OperationNotSupportedException + * @throws VersioningException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public void deleteContentStream(String repositoryId, String documentId) throws PermissionDeniedException, UpdateConflictException, StorageException, + StreamNotSupportedException, ObjectNotFoundException, OperationNotSupportedException, VersioningException, InvalidArgumentException, RuntimeException, + ConstraintViolationException + { + + checkRepositoryId(repositoryId); + + performContentStreamDeletion((NodeRef) this.cmisObjectsUtils.getIdentifierInstance(documentId, AlfrescoObjectType.DOCUMENT_OBJECT).getConvertedIdentifier()); + } + + /** + * Deletes specified object. + * + * @param repositoryId repository Id + * @param objectId object Id + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws ObjectNotFoundException + * @throws OperationNotSupportedException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public void deleteObject(String repositoryId, String objectId) throws PermissionDeniedException, UpdateConflictException, ObjectNotFoundException, + OperationNotSupportedException, InvalidArgumentException, RuntimeException, ConstraintViolationException + { + + checkRepositoryId(repositoryId); + + NodeRef objectNodeReference = this.cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT).getConvertedIdentifier(); + + checkForRootObject(repositoryId, objectId); + checkObjectTypeAndAppropriateStates(objectNodeReference, this.cmisDictionaryService.getCMISMapping().getCmisType(this.nodeService.getType(objectNodeReference))); + + if (!this.cmisObjectsUtils.deleteObject(objectNodeReference)) + { + throw new PermissionDeniedException("Currently authenticated User has no appropriate Permissions to delete specified Object"); + } + } + + /** + * Deletes the tree rooted at specified folder (including that folder) + * + * @param repositoryId repository Id + * @param folderId folder Id + * @param unfileNonfolderObjects unfile : unfile all non-folder objects from folders in this tree. They may remain filed in other folders, or may become unfiled, + * deletesinglefiled : delete non-folder objects filed only in this tree, and unfile the others so they remain filed in other folders, delete : delete all non-folder + * objects in this tree (Default) + * @param continueOnFailure flag + * @return collection of object IDs that failed to delete (if continueOnFailure is FALSE, then single object ID) + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws FolderNotValidException + * @throws OperationNotSupportedException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public FailedToDelete deleteTree(String repositoryId, String folderId, EnumUnfileNonfolderObjects unfileNonfolderObjects, Boolean continueOnFailure) + throws PermissionDeniedException, UpdateConflictException, FolderNotValidException, OperationNotSupportedException, InvalidArgumentException, RuntimeException, + ConstraintViolationException + { + + checkRepositoryId(repositoryId); + checkUnfilingIsNotRequested(unfileNonfolderObjects); + checkForRootObject(repositoryId, folderId); + + NodeRef folderNodeReference = this.cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT).getConvertedIdentifier(); + + FailedToDelete responce = new FailedToDelete(); + + this.cmisObjectsUtils.deleteFolder(folderNodeReference, continueOnFailure, (unfileNonfolderObjects == EnumUnfileNonfolderObjects.DELETE), responce.getObjectId()); + + return responce; + } + + /** + * Gets the list of allowable actions (CMIS service calls) for an object based on the current user�s context, subject to any access constraints that are currently imposed by + * the repository. + * + * @param repositoryId repository Id + * @param objectId object Id + * @return list of allowable actions + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws ObjectNotFoundException + * @throws OperationNotSupportedException + * @throws InvalidArgumentException + * @throws RuntimeException + */ + public CmisAllowableActionsType getAllowableActions(String repositoryId, String objectId) throws PermissionDeniedException, UpdateConflictException, ObjectNotFoundException, + OperationNotSupportedException, InvalidArgumentException, RuntimeException + { + + checkRepositoryId(repositoryId); + + return determineObjectAllowableActions(this.cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.ANY_OBJECT)); + } + + /** + * Gets the content-stream for a document. + * + * @param repositoryId repository Id + * @param documentId document to return the content-stream + * @return content stream + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws StorageException + * @throws StreamNotSupportedException + * @throws ObjectNotFoundException + * @throws OperationNotSupportedException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws OffsetException + */ + public CmisContentStreamType getContentStream(String repositoryId, String documentId) throws PermissionDeniedException, UpdateConflictException, StorageException, + StreamNotSupportedException, ObjectNotFoundException, OperationNotSupportedException, InvalidArgumentException, RuntimeException, OffsetException + { + NodeRef nodeRef = this.cmisObjectsUtils.getIdentifierInstance(documentId, AlfrescoObjectType.DOCUMENT_OBJECT).getConvertedIdentifier(); + + CmisContentStreamType response = new CmisContentStreamType(); + + ContentReader reader = safelyReceiveContentReader(nodeRef); + + response.setLength(BigInteger.valueOf(reader.getSize())); + response.setMimeType(reader.getMimetype()); + String filename = (String) cmisPropertyService.getProperty(nodeRef, CMISMapping.PROP_NAME); + response.setFilename(filename); + response.setStream(new DataHandler(new ContentReaderDataSource(reader, filename))); + + return response; + } + + /** + * Moves the specified filed object from one folder to another + * + * @param repositoryId repository Id + * @param objectId object Id + * @param targetFolderId the target folder to be moved into + * @param sourceFolderId the source folder to be moved out of + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws ObjectNotFoundException + * @throws FolderNotValidException + * @throws OperationNotSupportedException + * @throws NotInFolderException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public void moveObject(String repositoryId, String objectId, String targetFolderId, String sourceFolderId) throws PermissionDeniedException, UpdateConflictException, + ObjectNotFoundException, FolderNotValidException, OperationNotSupportedException, NotInFolderException, InvalidArgumentException, RuntimeException, + ConstraintViolationException + { + checkRepositoryId(repositoryId); + + NodeRef objectNodeRef = this.cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT).getConvertedIdentifier(); + NodeRef targetFolderNodeRef = this.cmisObjectsUtils.getIdentifierInstance(targetFolderId, AlfrescoObjectType.FOLDER_OBJECT).getConvertedIdentifier(); + + // TODO: Allowed_Child_Object_Types + + if ((this.nodeService.getParentAssocs(objectNodeRef).size() == SINGLE_PARENT_CONDITION) + || !changeObjectParentAssociation(objectNodeRef, targetFolderNodeRef, (NodeRef) this.cmisObjectsUtils.getIdentifierInstance(sourceFolderId, + AlfrescoObjectType.FOLDER_OBJECT).getConvertedIdentifier())) + { + moveObjectToFolder(objectNodeRef, targetFolderNodeRef); + } + } + + /** + * Sets (creates or replaces) the content-stream for the specified document object. + * + * @param repositoryId repository Id + * @param documentId document Id + * @param overwriteFlag flag + * @param contentStream content stream + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws StorageException + * @throws StreamNotSupportedException + * @throws ObjectNotFoundException + * @throws OperationNotSupportedException + * @throws ContentAlreadyExistsException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public void setContentStream(String repositoryId, Holder documentId, Boolean overwriteFlag, CmisContentStreamType contentStream) throws PermissionDeniedException, + UpdateConflictException, StorageException, StreamNotSupportedException, ObjectNotFoundException, OperationNotSupportedException, ContentAlreadyExistsException, + InvalidArgumentException, RuntimeException, ConstraintViolationException + { + checkRepositoryId(repositoryId); + + NodeRef nodeRef = this.cmisObjectsUtils.getIdentifierInstance(documentId.value, AlfrescoObjectType.DOCUMENT_OBJECT).getConvertedIdentifier(); + + if (contentStream.getStream() == null) + { + throw new InvalidArgumentException("New Content Stream was not provided"); + } + + if ((nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT) != null) && !overwriteFlag) + { + throw new ContentAlreadyExistsException(); + } + + ContentWriter writer = fileFolderService.getWriter(nodeRef); + InputStream inputstream = null; + try + { + inputstream = contentStream.getStream().getInputStream(); + } + catch (IOException e) + { + throw new ConstraintViolationException("", e.getCause()); + } + + writer.setMimetype(contentStream.getMimeType()); + writer.putContent(inputstream); + } + + /** + * Updates properties of the specified object. As per the data model, content-streams are not properties. + * + * @param repositoryId repository Id + * @param objectId object Id + * @param changeToken change token + * @param properties list of properties to update + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws ObjectNotFoundException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public void updateProperties(String repositoryId, Holder objectId, String changeToken, CmisPropertiesType properties) throws PermissionDeniedException, + UpdateConflictException, ObjectNotFoundException, OperationNotSupportedException, InvalidArgumentException, RuntimeException, ConstraintViolationException + { + checkRepositoryId(repositoryId); + checkForReadOnlyProperties(properties); + + NodeRef objectNodeRef = this.cmisObjectsUtils.getIdentifierInstance(objectId.value, AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT).getConvertedIdentifier(); + + setProperties(objectNodeRef, properties); + + // TODO: change token + + // no new version + objectId.value = (String) cmisPropertyService.getProperty(objectNodeRef, CMISMapping.PROP_OBJECT_ID); + } + + /** + * Gets the properties 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 PermissionDeniedException + * @throws UpdateConflictException + * @throws FilterNotValidException + * @throws ObjectNotFoundException + * @throws OperationNotSupportedException + * @throws InvalidArgumentException + * @throws RuntimeException + */ + public GetPropertiesResponse getProperties(GetProperties parameters) throws PermissionDeniedException, UpdateConflictException, FilterNotValidException, + ObjectNotFoundException, OperationNotSupportedException, InvalidArgumentException, RuntimeException + { + checkRepositoryId(parameters.getRepositoryId()); + + PropertyFilter propertyFilter = createPropertyFilter(parameters.getFilter()); + + String identifier = ((NodeRef) this.cmisObjectsUtils.getIdentifierInstance(parameters.getObjectId(), AlfrescoObjectType.ANY_OBJECT).getConvertedIdentifier()).toString(); + + if ((this.cmisObjectsUtils.determineObjectType(identifier) == EnumObjectType.DOCUMENT) && (parameters.getReturnVersion() != null) + && (parameters.getReturnVersion().getValue() != null)) + { + identifier = getLatestVersionNodeRef(new NodeRef(identifier), (parameters.getReturnVersion().getValue() != EnumReturnVersion.LATEST)).toString(); + } + + GetPropertiesResponse response = new GetPropertiesResponse(); + response.setObject(new CmisObjectType()); + CmisObjectType object = response.getObject(); + object.setProperties(getPropertiesType(identifier, propertyFilter)); + + if (parameters.getIncludeAllowableActions() != null && parameters.getIncludeAllowableActions().getValue()) + { + // TODO: allowable actions + } + + if (parameters.getIncludeRelationships() != null && parameters.getIncludeAllowableActions().getValue()) + { + // TODO: relationships + } + + return response; + } + + public void setPermissionService(PermissionService permissionService) + { + + this.permissionService = permissionService; + } private Map getPropertiesMap(CmisPropertiesType cmisProperties) throws InvalidArgumentException { @@ -72,254 +660,248 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object return properties; } - public String createDocument(String repositoryId, String typeId, CmisPropertiesType properties, String folderId, CmisContentStreamType contentStream, - EnumVersioningState versioningState) throws PermissionDeniedException, UpdateConflictException, StorageException, StreamNotSupportedException, FolderNotValidException, - OperationNotSupportedException, TypeNotFoundException, InvalidArgumentException, RuntimeException, ConstraintViolationException + private void assertExistType(CMISTypeId cmisTypeId) throws TypeNotFoundException { - - if (descriptorService.getServerDescriptor().getId().equals(repositoryId) == false) + if (cmisDictionaryService.getCMISMapping().isValidCmisType(cmisTypeId.getQName()) == false) { - throw new InvalidArgumentException("Invalid repository id"); + throw new TypeNotFoundException(cmisTypeId.toString()); } - - Map propertiesMap = getPropertiesMap(properties); - CMISMapping cmisMapping = cmisDictionaryService.getCMISMapping(); - CMISTypeId cmisTypeId = cmisMapping.getCmisTypeId(typeId); - - if (cmisMapping.getCmisTypeId(typeId).equals(CMISMapping.DOCUMENT_TYPE_ID) == false) - { - throw new ConstraintViolationException("Invalid document type"); - } - - NodeRef parentNodeRef = getNodeRefFromOID(folderId); - - if (!nodeService.exists(parentNodeRef)) - { - throw new FolderNotValidException("Invalid parent OID"); - } - - String documentName = (String) propertiesMap.get(CMISMapping.PROP_NAME); - if (documentName == null) - { - throw new InvalidArgumentException("Name property not found"); - } - - NodeRef newDocumentNodeRef = fileFolderService.create(parentNodeRef, documentName, cmisTypeId.getQName()).getNodeRef(); - ContentWriter writer = fileFolderService.getWriter(newDocumentNodeRef); - String mimeType = (String) propertiesMap.get(CMISMapping.PROP_CONTENT_STREAM_MIME_TYPE); - if (mimeType != null) - { - writer.setMimetype(mimeType); - } - InputStream inputstream = null; - try - { - inputstream = contentStream.getStream().getInputStream(); - } - catch (IOException e) - { - e.printStackTrace(); - throw new ConstraintViolationException("", e.getCause()); - } - writer.putContent(inputstream); - - if (versioningState == null) - { - versioningState = EnumVersioningState.MAJOR; - } - - cmisPropertyService.setProperties(newDocumentNodeRef, propertiesMap); - - switch (versioningState) - { - case CHECKEDOUT: - //TODO: maybe this must be done by VersioningService - cmisPropertyService.setProperty(newDocumentNodeRef, CMISMapping.PROP_IS_VERSION_SERIES_CHECKED_OUT, Boolean.TRUE); - break; - case MAJOR: - cmisPropertyService.setProperty(newDocumentNodeRef, CMISMapping.PROP_IS_MAJOR_VERSION, Boolean.FALSE); - break; - case MINOR: - cmisPropertyService.setProperty(newDocumentNodeRef, CMISMapping.PROP_IS_MAJOR_VERSION, Boolean.TRUE); - break; - - } - - return newDocumentNodeRef.toString(); } - public String createFolder(String repositoryId, String typeId, CmisPropertiesType properties, String folderId) throws PermissionDeniedException, UpdateConflictException, - FolderNotValidException, OperationNotSupportedException, TypeNotFoundException, InvalidArgumentException, RuntimeException, ConstraintViolationException + private CMISTypeId getCmisTypeId(String typeId) throws InvalidArgumentException { - if (descriptorService.getServerDescriptor().getId().equals(repositoryId) == false) + try { - throw new InvalidArgumentException("Invalid repository id"); + return cmisDictionaryService.getCMISMapping().getCmisTypeId(typeId); } - - NodeRef folderNodeRef = getNodeRefFromOID(folderId); - assertExistFolder(folderNodeRef); - - CMISMapping cmisMapping = cmisDictionaryService.getCMISMapping(); - - CMISTypeId cmisTypeId = cmisMapping.getCmisTypeId(typeId); - - Map propertiesMap = getPropertiesMap(properties); - - String name = (String) propertiesMap.get(CMISMapping.PROP_NAME); - if (name == null) + catch (Exception e) { - throw new InvalidArgumentException("Name property not found"); + throw new InvalidArgumentException("Invalid typeId " + typeId); } + } + + private void moveObjectToFolder(NodeRef objectNodeRef, NodeRef targetFolderNodeRef) throws PermissionDeniedException, UpdateConflictException + { try { - NodeRef newFolderNodeRef = fileFolderService.create(folderNodeRef, name, cmisTypeId.getQName()).getNodeRef(); - cmisPropertyService.setProperties(newFolderNodeRef, propertiesMap); - return newFolderNodeRef.toString(); + fileFolderService.move(objectNodeRef, targetFolderNodeRef, null); } - catch (FileExistsException e) + catch (Exception e) { - throw new UpdateConflictException("Folder already exists"); + determineException(e); } } - public String createPolicy(String repositoryId, String typeId, CmisPropertiesType properties, String folderId) throws PermissionDeniedException, UpdateConflictException, - FolderNotValidException, OperationNotSupportedException, TypeNotFoundException, InvalidArgumentException, RuntimeException, ConstraintViolationException + private boolean changeObjectParentAssociation(NodeRef objectNodeRef, NodeRef targetFolderNodeRef, NodeRef sourceFolderNodeReference) throws UpdateConflictException, + PermissionDeniedException { - return null; - } - public String createRelationship(String repositoryId, String typeId, CmisPropertiesType properties, String sourceObjectId, String targetObjectId) - throws PermissionDeniedException, UpdateConflictException, ObjectNotFoundException, OperationNotSupportedException, TypeNotFoundException, InvalidArgumentException, - RuntimeException, ConstraintViolationException - { - return null; - } - - public void deleteContentStream(String repositoryId, String documentId) throws PermissionDeniedException, UpdateConflictException, StorageException, - StreamNotSupportedException, ObjectNotFoundException, OperationNotSupportedException, VersioningException, InvalidArgumentException, RuntimeException, - ConstraintViolationException - { - } - - public void deleteObject(String repositoryId, String objectId) throws PermissionDeniedException, UpdateConflictException, ObjectNotFoundException, - OperationNotSupportedException, InvalidArgumentException, RuntimeException, ConstraintViolationException - { - } - - public FailedToDelete deleteTree(String repositoryId, String folderId, EnumUnfileNonfolderObjects unfileNonfolderObjects, Boolean continueOnFailure) - throws PermissionDeniedException, UpdateConflictException, FolderNotValidException, OperationNotSupportedException, InvalidArgumentException, RuntimeException, - ConstraintViolationException - { - return null; - } - - public CmisAllowableActionsType getAllowableActions(String repositoryId, String objectId) throws PermissionDeniedException, UpdateConflictException, ObjectNotFoundException, - OperationNotSupportedException, InvalidArgumentException, RuntimeException - { - return null; - } - - public CmisContentStreamType getContentStream(String repositoryId, String documentId) throws PermissionDeniedException, UpdateConflictException, StorageException, - StreamNotSupportedException, ObjectNotFoundException, OperationNotSupportedException, InvalidArgumentException, RuntimeException, OffsetException - { - NodeRef nodeRef = getNodeRefFromOID(documentId); - - if (!nodeService.exists(nodeRef)) + if (this.cmisObjectsUtils.isPrimaryObjectParent(sourceFolderNodeReference, objectNodeRef)) { - throw new ObjectNotFoundException("Invalid document OID"); + return false; } - CMISMapping cmisMapping = cmisDictionaryService.getCMISMapping(); - - if (cmisMapping.isValidCmisDocument(cmisMapping.getCmisType(nodeService.getType(nodeRef))) == false) + if (!this.cmisObjectsUtils.removeObject(objectNodeRef, sourceFolderNodeReference) && this.cmisObjectsUtils.addObjectToFolder(objectNodeRef, targetFolderNodeRef)) { - throw new StreamNotSupportedException("Stream not supported for this type of node"); + determineException(this.cmisObjectsUtils.getLastOperationException()); } - ContentReader reader = fileFolderService.getReader(nodeRef); - - CmisContentStreamType response = new CmisContentStreamType(); - response.setLength(BigInteger.valueOf(reader.getSize())); - response.setMimeType(reader.getMimetype()); - String filename = (String) cmisPropertyService.getProperty(nodeRef, CMISMapping.PROP_NAME); - response.setFilename(filename); - response.setStream(new DataHandler(new ContentReaderDataSource(reader, filename))); - - return response; + return true; } - public void moveObject(String repositoryId, String objectId, String targetFolderId, String sourceFolderId) throws PermissionDeniedException, UpdateConflictException, - ObjectNotFoundException, FolderNotValidException, OperationNotSupportedException, NotInFolderException, InvalidArgumentException, RuntimeException, - ConstraintViolationException + private void determineException(Throwable lastException) throws PermissionDeniedException, UpdateConflictException { - } - public void setContentStream(String repositoryId, Holder documentId, Boolean overwriteFlag, CmisContentStreamType contentStream) throws PermissionDeniedException, - UpdateConflictException, StorageException, StreamNotSupportedException, ObjectNotFoundException, OperationNotSupportedException, ContentAlreadyExistsException, - InvalidArgumentException, RuntimeException, ConstraintViolationException - { - } - - public void updateProperties(String repositoryId, Holder objectId, String changeToken, CmisPropertiesType properties) throws PermissionDeniedException, - UpdateConflictException, ObjectNotFoundException, OperationNotSupportedException, InvalidArgumentException, RuntimeException, ConstraintViolationException - { - } - - public GetPropertiesResponse getProperties(GetProperties parameters) throws PermissionDeniedException, UpdateConflictException, FilterNotValidException, - ObjectNotFoundException, OperationNotSupportedException, InvalidArgumentException, RuntimeException - { - if (descriptorService.getServerDescriptor().getId().equals(parameters.getRepositoryId()) == false) + if (lastException instanceof AccessDeniedException) { - throw new InvalidArgumentException("Invalid repository id"); + throw new PermissionDeniedException(lastException.getMessage()); } - PropertyFilter propertyFilter = createPropertyFilter(parameters.getFilter()); + throw new UpdateConflictException("Couldn't to relocate multi-filed Object"); + } - NodeRef nodeRef = getNodeRefFromOID(parameters.getObjectId()); + private void performContentStreamDeletion(NodeRef documentNodeReference) throws ConstraintViolationException + { - if (nodeService.exists(nodeRef) == false) + try { - throw new ObjectNotFoundException("Object not found"); + this.nodeService.setProperty(documentNodeReference, ContentModel.PROP_CONTENT, null); + } + catch (NodeLockedException e) + { + throw new ConstraintViolationException("Content Stream Deletion is not allowed for specified Document", e); + } + } + + private void checkObjectTypeAndAppropriateStates(NodeRef objectNodeReference, QName objectType) throws InvalidArgumentException, ConstraintViolationException + { + + if (objectType == null) + { + throw new InvalidArgumentException("Specified Object has invalid Object Type"); } - QName typeQName = nodeService.getType(nodeRef); - - CMISMapping cmisMapping = cmisDictionaryService.getCMISMapping(); - - if (cmisMapping.isValidCmisDocument((cmisMapping.getCmisType(typeQName)))) + if (objectType.equals(CMISMapping.FOLDER_QNAME) && (this.nodeService.getChildAssocs(objectNodeReference).size() > 0)) { - if (parameters.getReturnVersion() != null) + throw new ConstraintViolationException("Could not delete folder with at least one Child"); + } + } + + private void checkUnfilingIsNotRequested(EnumUnfileNonfolderObjects unfileNonfolderObjects) throws OperationNotSupportedException + { + + if (unfileNonfolderObjects == EnumUnfileNonfolderObjects.UNFILE) + { + throw new OperationNotSupportedException("Unfiling is not supported"); + } + } + + private void checkForRootObject(String repositoryId, String objectId) throws OperationNotSupportedException + { + + if (this.cmisService.getDefaultRootNodeRef().toString().equals(objectId) || repositoryId.equals(objectId)) + { + throw new OperationNotSupportedException("Could not delete Repository object or Root Folder object - operation is not allowed or not supported"); + } + } + + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + private ContentReader safelyReceiveContentReader(NodeRef objectNodeReference) throws StorageException + { + + ContentReader reader = fileFolderService.getReader(objectNodeReference); + + if (reader == null) + { + throw new StorageException("The specified Document has no Content Stream"); + } + + return reader; + } + + private void checkForReadOnlyProperties(CmisPropertiesType properties) throws ConstraintViolationException + { + + for (CmisProperty property : properties.getProperty()) + { + if (PropertyUtil.isReadOnlyRepositoryProperty(property.getName())) { - EnumReturnVersion neededVersion = parameters.getReturnVersion().getValue(); - - if (neededVersion.equals(EnumReturnVersion.LATEST)) - { - nodeRef = getLatestVersionNodeRef(nodeRef, false); - } - else if (neededVersion.equals(EnumReturnVersion.LATESTMAJOR)) - { - nodeRef = getLatestVersionNodeRef(nodeRef, true); - } + throw new ConstraintViolationException("The property " + property.getName() + " is Read Only and couldn't be updated"); } } - - GetPropertiesResponse response = new GetPropertiesResponse(); - response.setObject(new CmisObjectType()); - CmisObjectType object = response.getObject(); - object.setProperties(getPropertiesType(nodeRef, propertyFilter)); - - if (parameters.getIncludeAllowableActions() != null && parameters.getIncludeAllowableActions().getValue()) - { - // TODO: allowable actions - } - - if (parameters.getIncludeRelationships() != null && parameters.getIncludeAllowableActions().getValue()) - { - // TODO: relationships - } - - return response; } + private CmisAllowableActionsType determineObjectAllowableActions(IdentifierConversionResults objectIdentifierContainer) throws OperationNotSupportedException + { + Object objectNodeReference = objectIdentifierContainer.getConvertedIdentifier(); + + if (objectNodeReference instanceof AssociationRef) + { + return determineRelationshipAllowableActions((AssociationRef) objectIdentifierContainer.getConvertedIdentifier()); + } + + switch (this.cmisObjectsUtils.determineObjectType(objectNodeReference.toString())) + { + case DOCUMENT: + { + return determineDocumentAllowableActions((NodeRef) objectNodeReference); + } + case FOLDER: + { + return determineFolderAllowableActions((NodeRef) objectNodeReference); + } + } + + // TODO: determinePolicyAllowableActions() when Policy functionality is ready + throw new OperationNotSupportedException("It is impossible to get Allowable actions for the specified Object"); + } + + private CmisAllowableActionsType determineRelationshipAllowableActions(AssociationRef association) + { + + CmisAllowableActionsType result = new CmisAllowableActionsType(); + + result.setCanDelete(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 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.setCanDelete(this.permissionService.hasPermission(objectNodeReference, PermissionService.DELETE) == AccessStatus.ALLOWED); + + // TODO: response.setCanAddPolicy(value); + // TODO: response.setCanRemovePolicy(value); + // TODO: response.setCanGetAppliedPolicies(value); + + return result; + } + + private void determineCommonFolderDocumentAllowableActions(NodeRef objectNodeReference, CmisAllowableActionsType allowableActions) + { + + allowableActions.setCanAddToFolder(this.permissionService.hasPermission(objectNodeReference, PermissionService.CREATE_ASSOCIATIONS) == AccessStatus.ALLOWED); + allowableActions.setCanGetRelationships(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_ASSOCIATIONS) == AccessStatus.ALLOWED); + allowableActions.setCanMove(allowableActions.isCanUpdateProperties() && allowableActions.isCanAddToFolder()); + allowableActions.setCanRemoveFromFolder(allowableActions.isCanUpdateProperties()); + allowableActions.setCanCreateRelationship(allowableActions.isCanAddToFolder()); + } + + private CmisAllowableActionsType determineDocumentAllowableActions(NodeRef objectNodeReference) + { + + CmisAllowableActionsType result = determineBaseAllowableActions(objectNodeReference); + determineCommonFolderDocumentAllowableActions(objectNodeReference, result); + + result.setCanGetParents(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_ASSOCIATIONS) == AccessStatus.ALLOWED); + result.setCanViewContent(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_CONTENT) == AccessStatus.ALLOWED); + result.setCanSetContent(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.setCanDeleteContent(result.isCanUpdateProperties() && result.isCanSetContent()); + + 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(result.isCanDelete() && (this.permissionService.hasPermission(objectNodeReference, PermissionService.DELETE_CHILDREN) == AccessStatus.ALLOWED)); + result.setCanGetFolderParent(result.isCanGetRelationships()); + result.setCanCreateFolder(result.isCanCreateDocument()); + // TODO: response.setCanCreatePolicy(value); + + return result; + } + + private NodeRef receiveMandatoryFolderNodeReference(String folderId) throws FolderNotValidException + { + + try + { + return this.cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT).getConvertedIdentifier(); + } + catch (InvalidArgumentException e) + { + throw new FolderNotValidException("Unfiling is not suppoerted. Each Document must have existent parent Folder"); + } + } } diff --git a/source/java/org/alfresco/repo/cmis/ws/DMPolicyServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMPolicyServicePort.java new file mode 100755 index 0000000000..a75f9a1817 --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/ws/DMPolicyServicePort.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws; + +@javax.jws.WebService(name = "PolicyServicePort", serviceName = "PolicyServicePort", portName = "PolicyServicePort", targetNamespace = "http://www.cmis.org/ns/1.0", endpointInterface = "org.alfresco.repo.cmis.ws.PolicyServicePort") +public class DMPolicyServicePort extends DMAbstractServicePort implements PolicyServicePort +{ + + /** + * Applies a policy object to a target object. + * + * @param repositoryId repository Id + * @param policyId policy Id + * @param objectId target object Id + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws ObjectNotFoundException + * @throws OperationNotSupportedException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public void applyPolicy(String repositoryId, String policyId, String objectId) throws PermissionDeniedException, UpdateConflictException, ObjectNotFoundException, + OperationNotSupportedException, InvalidArgumentException, RuntimeException, ConstraintViolationException + { + // TODO Auto-generated method stub + + } + + /** + * Gets the list of policy objects currently applied to a target object. + * + * @param parameters repositoryId: repository Id; objectId: target object Id; filter: filter specifying which properties to return + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws FilterNotValidException + * @throws ObjectNotFoundException + * @throws OperationNotSupportedException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public GetAppliedPoliciesResponse getAppliedPolicies(GetAppliedPolicies parameters) throws PermissionDeniedException, UpdateConflictException, FilterNotValidException, + ObjectNotFoundException, OperationNotSupportedException, InvalidArgumentException, RuntimeException, ConstraintViolationException + { + // TODO Auto-generated method stub + return null; + } + + /** + * Removes a previously applied policy from a target object. The policy object is not deleted, and may still be applied to other objects. + * + * @param repositoryId repository Id + * @param policyId policy Id + * @param objectId target object Id. + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws ObjectNotFoundException + * @throws OperationNotSupportedException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public void removePolicy(String repositoryId, String policyId, String objectId) throws PermissionDeniedException, UpdateConflictException, ObjectNotFoundException, + OperationNotSupportedException, InvalidArgumentException, RuntimeException, ConstraintViolationException + { + // TODO Auto-generated method stub + + } + +} diff --git a/source/java/org/alfresco/repo/cmis/ws/DMRelationshipServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMRelationshipServicePort.java new file mode 100755 index 0000000000..0a90dd0af5 --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/ws/DMRelationshipServicePort.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws; + +import java.math.BigInteger; +import java.util.LinkedList; +import java.util.List; + +import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType; +import org.alfresco.repo.web.util.paging.Cursor; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.QNamePattern; + +/** + * Port for relationship service + * + * @author Dmitry Velichkevich + */ +@javax.jws.WebService(name = "RelationshipServicePort", serviceName = "RelationshipService", portName = "RelationshipServicePort", targetNamespace = "http://www.cmis.org/ns/1.0", endpointInterface = "org.alfresco.repo.cmis.ws.RelationshipServicePort") +public class DMRelationshipServicePort extends DMAbstractServicePort implements RelationshipServicePort +{ + private DictionaryService dictionaryService; + + /** + * Gets a list of relationships associated with the object, optionally of a specified relationship type, and optionally in a specified direction. + * + * @param parameters repositoryId: Repository Id, objectId: The object with which relationships are associated with; direction: source (Default), target, both; typeId: + * Relationship Type; includeSubRelationshipTypes: false (Default); filter: property filter; includeAllowableActions: false (default); maxItems: 0 = Unlimited; + * skipCount: 0 = start at beginning + * @return collection of CmisObjectType and boolean hasMoreItems + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws FilterNotValidException + * @throws ObjectNotFoundException + * @throws OperationNotSupportedException + * @throws TypeNotFoundException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public GetRelationshipsResponse getRelationships(GetRelationships parameters) throws PermissionDeniedException, UpdateConflictException, FilterNotValidException, + ObjectNotFoundException, OperationNotSupportedException, TypeNotFoundException, InvalidArgumentException, RuntimeException, ConstraintViolationException + { + + checkRepositoryId(parameters.getRepositoryId()); + + EnumRelationshipDirection direction = ((parameters.getDirection() != null) && (parameters.getDirection().getValue() != null)) ? (parameters.getDirection().getValue()) + : (EnumRelationshipDirection.SOURCE); + Boolean includingSubtypes = ((parameters.getIncludeSubRelationshipTypes() != null) && (parameters.getIncludeSubRelationshipTypes().getValue() != null)) ? (parameters + .getIncludeSubRelationshipTypes().getValue()) : (false); + String typeId = ((parameters.getTypeId() != null) && (parameters.getTypeId().getValue() != null)) ? (parameters.getTypeId().getValue()) : (null); + BigInteger skipCount = ((parameters.getSkipCount() != null) && (parameters.getSkipCount().getValue() != null)) ? (parameters.getSkipCount().getValue()) : (BigInteger.ZERO); + BigInteger maxItems = ((parameters.getMaxItems() != null) && (parameters.getMaxItems().getValue() != null)) ? (parameters.getMaxItems().getValue()) : (BigInteger.ZERO); + + QName associationType = cmisDictionaryService.getCMISMapping().getAlfrescoType(cmisDictionaryService.getCMISMapping().getCmisTypeId(typeId).getQName()); + + return formatResponse(createPropertyFilter(parameters.getFilter()), receiveAssociations( + (NodeRef) this.cmisObjectsUtils.getIdentifierInstance(parameters.getObjectId(), AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT).getConvertedIdentifier(), + associationType, direction, includingSubtypes).toArray(), new GetRelationshipsResponse(), skipCount, maxItems); + } + + public void setDictionaryService(DictionaryService dictionaryService) + { + + this.dictionaryService = dictionaryService; + } + + private GetRelationshipsResponse formatResponse(PropertyFilter filter, Object[] sourceArray, GetRelationshipsResponse result, BigInteger skipCount, BigInteger maxItems) + throws InvalidArgumentException, FilterNotValidException + { + + Cursor cursor = createCursor(sourceArray.length, skipCount, maxItems); + + for (int i = cursor.getStartRow(); i < cursor.getEndRow(); i++) + { + result.getObject().add(convertAlfrescoObjectToCmisObject(sourceArray[i].toString(), filter)); + } + + return result; + } + + private List receiveAssociations(NodeRef objectNodeReference, QName necessaryRelationshipType, EnumRelationshipDirection direction, boolean includingSubtypes) + { + + List result = new LinkedList(); + + QNamePattern matcher = new RelationshipByTypeFilter(necessaryRelationshipType, includingSubtypes); + + if ((direction == EnumRelationshipDirection.BOTH) || (direction == EnumRelationshipDirection.TARGET)) + { + result.addAll(this.nodeService.getSourceAssocs(objectNodeReference, matcher)); + } + + if ((direction == EnumRelationshipDirection.BOTH) || (direction == EnumRelationshipDirection.SOURCE)) + { + result.addAll(this.nodeService.getTargetAssocs(objectNodeReference, matcher)); + } + + return result; + } + + private class RelationshipByTypeFilter implements QNamePattern + { + private boolean includingSubtypes; + private QName necessaryGeneralType; + + public RelationshipByTypeFilter(QName necessaryGeneralType, boolean includingSubtypes) + { + + this.includingSubtypes = includingSubtypes; + this.necessaryGeneralType = necessaryGeneralType; + } + + public boolean isMatch(QName qname) + { + + if (this.necessaryGeneralType == null) + { + return true; + } + + return ((this.includingSubtypes) ? (dictionaryService.getAssociation(qname) != null) + : (cmisDictionaryService.getCMISMapping().isValidCmisRelationship(qname) && this.necessaryGeneralType.equals(qname))); + } + } +} diff --git a/source/java/org/alfresco/repo/cmis/ws/DMRepositoryServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMRepositoryServicePort.java index 4f7cdb89c1..a07abc2ec5 100644 --- a/source/java/org/alfresco/repo/cmis/ws/DMRepositoryServicePort.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMRepositoryServicePort.java @@ -43,6 +43,7 @@ import org.alfresco.cmis.CMISJoinEnum; import org.alfresco.cmis.CMISPropertyTypeEnum; import org.alfresco.cmis.CMISUpdatabilityEnum; import org.alfresco.cmis.dictionary.CMISChoice; +import org.alfresco.cmis.dictionary.CMISMapping; import org.alfresco.cmis.dictionary.CMISPropertyDefinition; import org.alfresco.cmis.dictionary.CMISTypeDefinition; import org.alfresco.cmis.dictionary.CMISTypeId; @@ -50,11 +51,10 @@ import org.alfresco.repo.web.util.paging.Cursor; import org.alfresco.service.descriptor.Descriptor; /** - * Port for repository service + * Port for repository service. * * @author Dmitry Lazurkin */ - @javax.jws.WebService(name = "RepositoryServicePort", serviceName = "RepositoryService", portName = "RepositoryServicePort", targetNamespace = "http://www.cmis.org/ns/1.0", endpointInterface = "org.alfresco.repo.cmis.ws.RepositoryServicePort") public class DMRepositoryServicePort extends DMAbstractServicePort implements RepositoryServicePort { @@ -103,6 +103,16 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re propertyTypeEnumMapping.put(CMISPropertyTypeEnum.XML, EnumPropertyType.XML); } + /** + * 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 RuntimeException + * @throws InvalidArgumentException + * @throws OperationNotSupportedException + * @throws UpdateConflictException + * @throws PermissionDeniedException + */ public List getRepositories() throws RuntimeException, InvalidArgumentException, OperationNotSupportedException, UpdateConflictException, PermissionDeniedException { @@ -113,6 +123,19 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re return Collections.singletonList(repositoryEntryType); } + /** + * Gets information about the CMIS repository and the capabilities it supports. + * + * @param parameters repositoryId: repository Id + * @return CMIS repository Info + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws ObjectNotFoundException + * @throws OperationNotSupportedException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ public CmisRepositoryInfoType getRepositoryInfo(GetRepositoryInfo parameters) throws PermissionDeniedException, UpdateConflictException, ObjectNotFoundException, OperationNotSupportedException, InvalidArgumentException, RuntimeException, ConstraintViolationException { @@ -128,7 +151,7 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re repositoryInfoType.setRepositoryName(serverDescriptor.getName()); repositoryInfoType.setRepositoryRelationship("self"); repositoryInfoType.setRepositoryDescription(""); - repositoryInfoType.setRootFolderId(cmisService.getDefaultRootNodeRef().toString()); + repositoryInfoType.setRootFolderId((String) cmisPropertyService.getProperty(cmisService.getDefaultRootNodeRef(), CMISMapping.PROP_OBJECT_ID)); repositoryInfoType.setVendorName("Alfresco"); repositoryInfoType.setProductName("Alfresco Repository (" + serverDescriptor.getEdition() + ")"); repositoryInfoType.setProductVersion(serverDescriptor.getVersion()); @@ -370,6 +393,20 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re return result; } + /** + * Gets the list of all types in the repository. + * + * @param parameters repositoryId: repository Id; typeId: type Id; returnPropertyDefinitions: false (default); maxItems: 0 = Repository-default number of items(Default); + * skipCount: 0 = start; + * @return collection of CmisTypeDefinitionType and boolean hasMoreItems + * @throws RuntimeException + * @throws InvalidArgumentException + * @throws ObjectNotFoundException + * @throws ConstraintViolationException + * @throws OperationNotSupportedException + * @throws UpdateConflictException + * @throws PermissionDeniedException + */ public GetTypesResponse getTypes(GetTypes parameters) throws RuntimeException, InvalidArgumentException, ObjectNotFoundException, ConstraintViolationException, OperationNotSupportedException, UpdateConflictException, PermissionDeniedException { @@ -413,6 +450,20 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re return response; } + /** + * Gets the definition for specified object type + * + * @param parameters repositoryId: repository Id; typeId: type Id; + * @return CMIS type definition + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws ObjectNotFoundException + * @throws OperationNotSupportedException + * @throws TypeNotFoundException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ public GetTypeDefinitionResponse getTypeDefinition(GetTypeDefinition parameters) throws PermissionDeniedException, UpdateConflictException, ObjectNotFoundException, OperationNotSupportedException, TypeNotFoundException, InvalidArgumentException, RuntimeException, ConstraintViolationException { diff --git a/source/java/org/alfresco/repo/cmis/ws/DMServicePortThrowsAdvice.java b/source/java/org/alfresco/repo/cmis/ws/DMServicePortThrowsAdvice.java index d999ff8e54..25d65f2291 100644 --- a/source/java/org/alfresco/repo/cmis/ws/DMServicePortThrowsAdvice.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMServicePortThrowsAdvice.java @@ -31,7 +31,7 @@ import org.springframework.aop.ThrowsAdvice; /** * @author Dmitry Lazurkin - * + * @author Dmitry Velichkevich */ public class DMServicePortThrowsAdvice implements ThrowsAdvice { @@ -44,7 +44,7 @@ public class DMServicePortThrowsAdvice implements ThrowsAdvice log.info(e); } - throw new PermissionDeniedException("Access denied", e); + throw new PermissionDeniedException("Access denied. Message: " + e.getMessage(), e); } public void afterThrowing(java.lang.RuntimeException e) throws RuntimeException @@ -54,7 +54,6 @@ public class DMServicePortThrowsAdvice implements ThrowsAdvice log.error(e); } - throw new RuntimeException("Runtime error", e); + throw new RuntimeException("Runtime error. Message: " + e.getMessage(), e); } - } diff --git a/source/java/org/alfresco/repo/cmis/ws/DMVersioningServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMVersioningServicePort.java new file mode 100755 index 0000000000..e811c46dee --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/ws/DMVersioningServicePort.java @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws; + +import java.util.List; + +import javax.xml.ws.Holder; + +import org.alfresco.cmis.dictionary.CMISMapping; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType; +import org.alfresco.service.cmr.lock.LockService; +import org.alfresco.service.cmr.lock.LockStatus; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.version.Version; +import org.alfresco.service.cmr.version.VersionHistory; +import org.alfresco.service.cmr.version.VersionType; + +/** + * Port for versioning service. + * + * @author Dmitry Lazurkin + * @author Dmitry Velichkevich + */ +@javax.jws.WebService(name = "VersioningServicePort", serviceName = "VersioningService", portName = "VersioningServicePort", targetNamespace = "http://www.cmis.org/ns/1.0", endpointInterface = "org.alfresco.repo.cmis.ws.VersioningServicePort") +public class DMVersioningServicePort extends DMAbstractServicePort implements VersioningServicePort +{ + private LockService lockService; + + /** + * Reverses the effect of a check-out. Removes the private working copy of the checked-out document object, allowing other documents in the version series to be checked out + * again. + * + * @param repositoryId repository Id + * @param documentId document Id + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws ObjectNotFoundException + * @throws OperationNotSupportedException + * @throws InvalidArgumentException + * @throws RuntimeException + */ + public void cancelCheckOut(String repositoryId, String documentId) throws PermissionDeniedException, UpdateConflictException, ObjectNotFoundException, + OperationNotSupportedException, InvalidArgumentException, RuntimeException + { + checkRepositoryId(repositoryId); + NodeRef workingCopyNodeRef = this.cmisObjectsUtils.getIdentifierInstance(documentId, AlfrescoObjectType.DOCUMENT_OBJECT).getConvertedIdentifier(); + assertWorkingCopy(workingCopyNodeRef); + checkOutCheckInService.cancelCheckout(workingCopyNodeRef); + } + + /** + * Makes the private working copy the current version of the document. + * + * @param repositoryId repository Id + * @param documentId document Id + * @param major is major True (Default) + * @param properties CMIS properties + * @param contentStream content stream + * @param checkinComment check in comment + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws StorageException + * @throws StreamNotSupportedException + * @throws ObjectNotFoundException + * @throws OperationNotSupportedException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public void checkIn(String repositoryId, Holder documentId, Boolean major, CmisPropertiesType properties, CmisContentStreamType contentStream, String checkinComment) + throws PermissionDeniedException, UpdateConflictException, StorageException, StreamNotSupportedException, ObjectNotFoundException, OperationNotSupportedException, + InvalidArgumentException, RuntimeException, ConstraintViolationException + { + checkRepositoryId(repositoryId); + NodeRef workingCopyNodeRef = this.cmisObjectsUtils.getIdentifierInstance(documentId.value, AlfrescoObjectType.DOCUMENT_OBJECT).getConvertedIdentifier(); + assertWorkingCopy(workingCopyNodeRef); + + if (contentStream != null) + { + try + { + ContentWriter writer = fileFolderService.getWriter(workingCopyNodeRef); + writer.setMimetype(contentStream.getMimeType()); + writer.putContent(contentStream.getStream().getInputStream()); + } + catch (Exception e) + { + throw new RuntimeException("Exception while updating content stream"); + } + } + + if (properties != null) + { + setProperties(workingCopyNodeRef, properties); + } + + NodeRef nodeRef = checkOutCheckInService.checkin(workingCopyNodeRef, createVersionProperties(checkinComment, ((major != null) && (major)) ? (VersionType.MAJOR) + : (VersionType.MINOR))); + + documentId.value = (String) cmisPropertyService.getProperty(nodeRef, CMISMapping.PROP_OBJECT_ID); + } + + /** + * Create a private working copy of the object, copies the metadata and optionally content. + * + * @param repositoryId repository Id + * @param documentId ObjectID of document version to checkout + * @param contentCopied + * @return ObjectID of private working copy as documentId; True if succeed, False otherwise as contentCopied + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws ObjectNotFoundException + * @throws OperationNotSupportedException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public void checkOut(String repositoryId, Holder documentId, Holder contentCopied) throws PermissionDeniedException, UpdateConflictException, + ObjectNotFoundException, OperationNotSupportedException, InvalidArgumentException, RuntimeException, ConstraintViolationException + { + checkRepositoryId(repositoryId); + + NodeRef documentNodeRef = this.cmisObjectsUtils.getIdentifierInstance(documentId.value, AlfrescoObjectType.DOCUMENT_OBJECT).getConvertedIdentifier(); + + LockStatus lockStatus = lockService.getLockStatus(documentNodeRef); + + if (lockStatus.equals(LockStatus.LOCKED) || lockStatus.equals(LockStatus.LOCK_OWNER) || nodeService.hasAspect(documentNodeRef, ContentModel.ASPECT_WORKING_COPY)) + { + throw new OperationNotSupportedException("Object is already checked out"); + } + + NodeRef pwcNodeRef = performCheckouting(documentNodeRef); + + documentId.value = (String) cmisPropertyService.getProperty(pwcNodeRef, CMISMapping.PROP_OBJECT_ID); + contentCopied.value = true; + } + + /** + * Deletes all document versions in the specified version series. + * + * @param repositoryId repository Id + * @param versionSeriesId version series Id + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws ObjectNotFoundException + * @throws OperationNotSupportedException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public void deleteAllVersions(String repositoryId, String versionSeriesId) throws PermissionDeniedException, UpdateConflictException, ObjectNotFoundException, + OperationNotSupportedException, InvalidArgumentException, RuntimeException, ConstraintViolationException + { + checkRepositoryId(repositoryId); + NodeRef documentNodeRef = this.cmisObjectsUtils.getIdentifierInstance(versionSeriesId, AlfrescoObjectType.DOCUMENT_OBJECT).getConvertedIdentifier(); + + versionService.deleteVersionHistory(documentNodeRef); + } + + /** + * Gets the list of all document versions for the specified version series. + * + * @param parameters repositoryId: repository Id; versionSeriesId: version series Id; filter: property filter; includeAllowableActions; includeRelationships; + * @return list of CmisObjectType + * @throws PermissionDeniedException + * @throws UpdateConflictException + * @throws FilterNotValidException + * @throws ObjectNotFoundException + * @throws OperationNotSupportedException + * @throws InvalidArgumentException + * @throws RuntimeException + * @throws ConstraintViolationException + */ + public GetAllVersionsResponse getAllVersions(GetAllVersions parameters) throws PermissionDeniedException, UpdateConflictException, FilterNotValidException, + ObjectNotFoundException, OperationNotSupportedException, InvalidArgumentException, RuntimeException, ConstraintViolationException + { + checkRepositoryId(parameters.getRepositoryId()); + + NodeRef documentNodeRef = this.cmisObjectsUtils.getIdentifierInstance(parameters.getVersionSeriesId(), AlfrescoObjectType.DOCUMENT_OBJECT).getConvertedIdentifier(); + documentNodeRef = getLatestVersionNodeRef(documentNodeRef, false); + + PropertyFilter propertyFilter = createPropertyFilter(parameters.getFilter()); + + GetAllVersionsResponse response = new GetAllVersionsResponse(); + List objects = response.getObject(); + + searchWorkingCopy(documentNodeRef, propertyFilter, objects); + objects.add(convertAlfrescoObjectToCmisObject(documentNodeRef, propertyFilter)); + + VersionHistory versionHistory = versionService.getVersionHistory(documentNodeRef); + + if (versionHistory == null) + { + return response; + } + + Version version = this.versionService.getCurrentVersion(documentNodeRef); + + while (version != null) + { + objects.add(convertAlfrescoObjectToCmisObject(version.getFrozenStateNodeRef(), propertyFilter)); + + version = versionHistory.getPredecessor(version); + } + + return response; + } + + /** + * Gets the properties of the latest version, or the latest major version, of the specified version series. + * + * @param parameters repositoryId: repository Id; versionSeriesId: version series Id; majorVersion: whether or not to return the latest major version. Default=FALSE; filter: + * property filter + * @return CmisObjectType with properties + */ + public GetPropertiesOfLatestVersionResponse getPropertiesOfLatestVersion(GetPropertiesOfLatestVersion parameters) throws PermissionDeniedException, UpdateConflictException, + FilterNotValidException, ObjectNotFoundException, OperationNotSupportedException, InvalidArgumentException, RuntimeException + { + checkRepositoryId(parameters.getRepositoryId()); + PropertyFilter propertyFilter = createPropertyFilter(parameters.getFilter()); + + NodeRef documentNodeRef = this.cmisObjectsUtils.getIdentifierInstance(parameters.getVersionSeriesId(), AlfrescoObjectType.DOCUMENT_OBJECT).getConvertedIdentifier(); + + NodeRef latestVersionNodeRef = getLatestVersionNodeRef(documentNodeRef, parameters.isMajorVersion()); + + GetPropertiesOfLatestVersionResponse response = new GetPropertiesOfLatestVersionResponse(); + response.setObject(new CmisObjectType()); + CmisObjectType object = response.getObject(); + object.setProperties(getPropertiesType(latestVersionNodeRef.toString(), propertyFilter)); + + return response; + } + + public void setLockService(LockService lockService) + { + this.lockService = lockService; + } + + private void searchWorkingCopy(NodeRef documentNodeRef, PropertyFilter propertyFilter, List resultList) + { + + NodeRef workingCopyNodeReference = (this.cmisObjectsUtils.isWorkingCopy(documentNodeRef)) ? (documentNodeRef) : (checkOutCheckInService.getWorkingCopy(documentNodeRef)); + + if (workingCopyNodeReference instanceof NodeRef) + { + resultList.add(convertAlfrescoObjectToCmisObject(workingCopyNodeReference, propertyFilter)); + } + } + + private void assertWorkingCopy(NodeRef nodeRef) throws OperationNotSupportedException + { + if (!this.cmisObjectsUtils.isWorkingCopy(nodeRef)) + { + throw new OperationNotSupportedException("Object isn't checked out"); + } + } +} diff --git a/source/java/org/alfresco/repo/cmis/ws/PropertyFilter.java b/source/java/org/alfresco/repo/cmis/ws/PropertyFilter.java index 1249a931e0..0a8082e515 100644 --- a/source/java/org/alfresco/repo/cmis/ws/PropertyFilter.java +++ b/source/java/org/alfresco/repo/cmis/ws/PropertyFilter.java @@ -24,7 +24,6 @@ */ package org.alfresco.repo.cmis.ws; -import java.util.Arrays; import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; @@ -33,55 +32,56 @@ import java.util.regex.Pattern; * Property filter class * * @author Dmitry Lazurkin - * + * @author Dmitry Velichkevich */ public class PropertyFilter { - private static final Pattern PROPERTY_FILTER_REGEX = Pattern.compile("^(\\*)|([\\p{Upper}\\p{Digit}_]+(,[\\p{Upper}\\p{Digit}_]+)*)$"); + private static final int MINIMAL_ALLOWED_STRUCTURE_SIZE = 1; + + private static final String MATCH_ALL_FILTER = "*"; + + private static final Pattern PROPERTY_FILTER_REGEX = Pattern.compile("^(\\*)|([\\p{Alpha}\\p{Digit}_]+((,){1}( )*[\\p{Alpha}\\p{Digit}_]+)*)$"); private Set properties; - /** - * Constructor - */ public PropertyFilter() { } /** - * Constructor - * - * @param filter filter string + * @param filter filter value (case insensitive) * @throws FilterNotValidException if filter string isn't valid */ public PropertyFilter(String filter) throws FilterNotValidException { - if (filter == null) + if ((filter == null) || ((filter.length() < MINIMAL_ALLOWED_STRUCTURE_SIZE) ? (false) : (!PROPERTY_FILTER_REGEX.matcher(filter).matches()))) { - throw new FilterNotValidException(filter + " isn't valid"); + throw new FilterNotValidException("\"" + filter + "\" filter value is invalid"); } - if (filter.equals("") == false) + if (!filter.equals(MATCH_ALL_FILTER) && (filter.length() >= MINIMAL_ALLOWED_STRUCTURE_SIZE)) { - if (PROPERTY_FILTER_REGEX.matcher(filter).matches() == false) - { - throw new FilterNotValidException(filter + " isn't valid"); - } - - if (filter.equals("*") == false) - { - properties = new HashSet(Arrays.asList(filter.split(","))); - } + splitFilterOnTokens(filter.split(",")); } } /** - * @param property property - * @return if property is allow by filter then returns true else false + * @param property property token name (e.g.: name (or Name), ObjectId (or: objectid, Objectid etc)) + * @return true returns if property is allowed by filter. In other case returns false */ public boolean allow(String property) { - return properties == null || properties.contains(property); + return (properties == null) || properties.contains(property.toLowerCase()); } + private void splitFilterOnTokens(String[] tokens) + { + + properties = new HashSet(); + + for (String token : tokens) + { + properties.add(token.trim().toLowerCase()); + } + } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/cmis/ws/PropertyUtil.java b/source/java/org/alfresco/repo/cmis/ws/PropertyUtil.java index 7f246683a6..bed39dbcf7 100755 --- a/source/java/org/alfresco/repo/cmis/ws/PropertyUtil.java +++ b/source/java/org/alfresco/repo/cmis/ws/PropertyUtil.java @@ -29,46 +29,48 @@ import java.util.HashMap; import java.util.Map; import org.alfresco.cmis.dictionary.CMISMapping; +import org.alfresco.util.Pair; /** * Class for accessing CMIS properties * * @author Dmitry Lazurkin - * + * @author Dmitry Velichkevich */ public class PropertyUtil { - private static Map cmisToRepoPropertiesNamesMapping = new HashMap(); - private static Map repoToCmisPropertiesNamesMapping = new HashMap(); + private static Map> cmisToRepoPropertiesNamesMapping = new HashMap>(); + private static Map> repoToCmisPropertiesNamesMapping = new HashMap>(); static { - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_IS_IMMUTABLE, "IsImmutable"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_IS_LATEST_VERSION, "IsLatestVersion"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_IS_MAJOR_VERSION, "IsMajorVersion"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_IS_LATEST_MAJOR_VERSION, "IsLatestMajorVersion"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_IS_VERSION_SERIES_CHECKED_OUT, "IsVersionSeriesCheckedOut"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_CREATION_DATE, "CreationDate"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_LAST_MODIFICATION_DATE, "LastModificationDate"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_OBJECT_ID, "ObjectId"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_VERSION_SERIES_ID, "VersionSeriesId"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_VERSION_SERIES_CHECKED_OUT_ID, "VersionSeriesCheckedOutId"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_CONTENT_STREAM_LENGTH, "ContentStreamLength"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_NAME, "Name"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_OBJECT_TYPE_ID, "ObjectTypeId"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_CREATED_BY, "CreatedBy"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_LAST_MODIFIED_BY, "LastModifiedBy"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_CONTENT_STREAM_MIME_TYPE, "ContentStreamMimeType"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_CONTENT_STREAM_FILENAME, "ContentStreamFilename"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_VERSION_LABEL, "VersionLabel"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_CHECKIN_COMMENT, "checkinComment"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_CONTENT_STREAM_URI, "contentStreamURI"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_VERSION_SERIES_CHECKED_OUT_BY, "VersionSeriesCheckedOutBy"); - cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_PARENT_ID, "ParentId"); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_IS_IMMUTABLE, new Pair("IsImmutable", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_IS_LATEST_VERSION, new Pair("IsLatestVersion", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_IS_MAJOR_VERSION, new Pair("IsMajorVersion", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_IS_LATEST_MAJOR_VERSION, new Pair("IsLatestMajorVersion", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_IS_VERSION_SERIES_CHECKED_OUT, new Pair("IsVersionSeriesCheckedOut", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_CREATION_DATE, new Pair("CreationDate", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_LAST_MODIFICATION_DATE, new Pair("LastModificationDate", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_OBJECT_ID, new Pair("ObjectId", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_VERSION_SERIES_ID, new Pair("VersionSeriesId", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_VERSION_SERIES_CHECKED_OUT_ID, new Pair("VersionSeriesCheckedOutId", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_CONTENT_STREAM_LENGTH, new Pair("ContentStreamLength", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_NAME, new Pair("Name", false)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_OBJECT_TYPE_ID, new Pair("ObjectTypeId", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_CREATED_BY, new Pair("CreatedBy", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_LAST_MODIFIED_BY, new Pair("LastModifiedBy", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_CONTENT_STREAM_MIME_TYPE, new Pair("ContentStreamMimeType", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_CONTENT_STREAM_FILENAME, new Pair("ContentStreamFilename", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_VERSION_LABEL, new Pair("VersionLabel", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_CHECKIN_COMMENT, new Pair("checkinComment", false)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_CONTENT_STREAM_URI, new Pair("contentStreamURI", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_VERSION_SERIES_CHECKED_OUT_BY, new Pair("VersionSeriesCheckedOutBy", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_PARENT_ID, new Pair("ParentId", true)); + cmisToRepoPropertiesNamesMapping.put(CMISMapping.PROP_CONTENT_STREAM_ALLOWED, new Pair("ContentStreamAllowed", true)); - for (Map.Entry entry : cmisToRepoPropertiesNamesMapping.entrySet()) + for (Map.Entry> entry : cmisToRepoPropertiesNamesMapping.entrySet()) { - repoToCmisPropertiesNamesMapping.put(entry.getValue(), entry.getKey()); + repoToCmisPropertiesNamesMapping.put(entry.getValue().getFirst(), new Pair(entry.getKey(), entry.getValue().getSecond())); } } @@ -80,7 +82,7 @@ public class PropertyUtil */ public static String getCMISPropertyName(String internalName) { - return cmisToRepoPropertiesNamesMapping.get(internalName); + return cmisToRepoPropertiesNamesMapping.get(internalName).getFirst(); } /** @@ -91,7 +93,19 @@ public class PropertyUtil */ public static String getRepositoryPropertyName(String cmisName) { - return repoToCmisPropertiesNamesMapping.get(cmisName); + return repoToCmisPropertiesNamesMapping.get(cmisName).getFirst(); + } + + public static boolean isReadOnlyCmisProperty(String internalPropertyName) + { + + return repoToCmisPropertiesNamesMapping.get(internalPropertyName).getSecond(); + } + + public static boolean isReadOnlyRepositoryProperty(String cmisPropertyName) + { + + return repoToCmisPropertiesNamesMapping.get(cmisPropertyName).getSecond(); } public static Serializable getProperty(CmisPropertiesType cmisProperties, String property) @@ -149,5 +163,4 @@ public class PropertyUtil return value; } - } diff --git a/source/java/org/alfresco/repo/cmis/ws/utils/AlfrescoObjectType.java b/source/java/org/alfresco/repo/cmis/ws/utils/AlfrescoObjectType.java new file mode 100755 index 0000000000..5e385763f9 --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/ws/utils/AlfrescoObjectType.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws.utils; + +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.cmis.dictionary.CMISMapping; +import org.alfresco.model.ContentModel; + +/** + * @author Dmitry Velichkevich + */ +public enum AlfrescoObjectType +{ + DOCUMENT_OBJECT(ContentModel.TYPE_CONTENT.toString()), FOLDER_OBJECT(ContentModel.TYPE_FOLDER.toString()), DOCUMENT_OR_FOLDER_OBJECT("DOCUMENT_OR_FOLDER"), RELATIONSHIP_OBJECT( + CMISMapping.RELATIONSHIP_QNAME.toString()), ANY_OBJECT("ANY"); + + String value; + + final static Map VALUES; + static + { + VALUES = new HashMap(); + VALUES.put(DOCUMENT_OBJECT.getValue(), DOCUMENT_OBJECT); + VALUES.put(FOLDER_OBJECT.getValue(), FOLDER_OBJECT); + } + + AlfrescoObjectType(String value) + { + + this.value = value; + } + + public String getValue() + { + + return this.value; + } + + public static AlfrescoObjectType fromValue(String valueName) + { + + AlfrescoObjectType result = VALUES.get(valueName); + + if (result == null) + { + result = ANY_OBJECT; + } + + return result; + } +} diff --git a/source/java/org/alfresco/repo/cmis/ws/utils/CmisObjectsUtils.java b/source/java/org/alfresco/repo/cmis/ws/utils/CmisObjectsUtils.java new file mode 100755 index 0000000000..95cc7130a7 --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/ws/utils/CmisObjectsUtils.java @@ -0,0 +1,473 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws.utils; + +import java.util.LinkedList; +import java.util.List; + +import org.alfresco.cmis.dictionary.CMISDictionaryService; +import org.alfresco.cmis.dictionary.CMISMapping; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.cmis.ws.EnumObjectType; +import org.alfresco.repo.cmis.ws.InvalidArgumentException; +import org.alfresco.repo.cmis.ws.ObjectNotFoundException; +import org.alfresco.repo.cmis.ws.OperationNotSupportedException; +import org.alfresco.repo.cmis.ws.utils.DescendantsQueueManager.DescendantElement; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.service.cmr.coci.CheckOutCheckInService; +import org.alfresco.service.cmr.lock.LockService; +import org.alfresco.service.cmr.lock.LockStatus; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.AuthorityService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; + +/** + * @author Dmitry Velichkevich + */ +public class CmisObjectsUtils +{ + private static final int NODE_REFERENCE_WITH_SUFFIX_DELIMETERS_COUNT = 5; + + public static final String NODE_REFERENCE_ID_DELIMETER = "/"; + + private static final String DOUBLE_NODE_REFERENCE_ID_DELIMETER = NODE_REFERENCE_ID_DELIMETER + NODE_REFERENCE_ID_DELIMETER; + + private static final List DOCUMENT_AND_FOLDER_TYPES; + static + { + DOCUMENT_AND_FOLDER_TYPES = new LinkedList(); + DOCUMENT_AND_FOLDER_TYPES.add(ContentModel.TYPE_CONTENT); + DOCUMENT_AND_FOLDER_TYPES.add(ContentModel.TYPE_FOLDER); + } + + private CheckOutCheckInService checkOutCheckInService; + private CMISDictionaryService cmisDictionaryService; + private FileFolderService fileFolderService; + private AuthorityService authorityService; + private NodeService nodeService; + private LockService lockService; + private CMISMapping cmisMapping; + + private Throwable lastOperationException; + + public IdentifierConversionResults getIdentifierInstance(String identifier, AlfrescoObjectType expectedType) throws InvalidArgumentException + { + + if (!(identifier instanceof String)) + { + throw new InvalidArgumentException("Invalid Object Identifier was specified"); + } + + IdentifierConversionResults result; + AlfrescoObjectType actualObjectType; + + if (isRelationship(identifier)) + { + result = createAssociationIdentifierResult(identifier); + + actualObjectType = AlfrescoObjectType.RELATIONSHIP_OBJECT; + } + else + { + NodeRef nodeReference = receiveNodeReferenceOfExistenceObject(cutNodeVersionIfNecessary(identifier, identifier.split(NODE_REFERENCE_ID_DELIMETER), 1)); + + result = createNodeReferenceIdentifierResult(nodeReference); + + actualObjectType = determineActualObjectType(expectedType, this.nodeService.getType(nodeReference)); + } + + if ((expectedType == AlfrescoObjectType.ANY_OBJECT) || (actualObjectType == expectedType)) + { + return result; + } + + throw new InvalidArgumentException("Unexpected object type of the specified Object Identifier"); + } + + public void deleteFolder(NodeRef folderNodeReference, boolean continueOnFailure, boolean totalDeletion, List resultList) throws OperationNotSupportedException + { + + DescendantsQueueManager queueManager = new DescendantsQueueManager(new ChildAssociationRef(ContentModel.ASSOC_CONTAINS, null, null, folderNodeReference)); + + do + { + DescendantElement currentElement = queueManager.receiveNextElement(); + + if (!this.nodeService.exists(currentElement.getNodesAssociation().getChildRef())) + { + continue; + } + + UnlinkOperationStatus unlinkingStatus = unlinkObject(currentElement.getNodesAssociation().getChildRef(), currentElement.getNodesAssociation().getParentRef(), + totalDeletion); + + if (!unlinkingStatus.isObjectUnlinked()) + { + processNotUnlinkedObjectResults(currentElement, unlinkingStatus, queueManager, resultList, continueOnFailure); + } + } while (!queueManager.isDepleted() && (continueOnFailure || resultList.isEmpty())); + } + + public boolean deleteObject(NodeRef objectNodeReference) + { + + return isObjectLockIsNotATrouble(objectNodeReference) && performNodeDeletion(objectNodeReference); + } + + public boolean removeObject(NodeRef objectNodeReference, NodeRef folderNodeReference) + { + + if (isChildOfThisFolder(objectNodeReference, folderNodeReference)) + { + try + { + this.nodeService.removeChild(folderNodeReference, objectNodeReference); + } + catch (Throwable e) + { + this.lastOperationException = e; + + return false; + } + + return true; + } + + return false; + } + + public boolean addObjectToFolder(NodeRef objectNodeRef, NodeRef parentFolderNodeRef) + { + + try + { + this.nodeService.addChild(parentFolderNodeRef, objectNodeRef, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName + .createValidLocalName((String) this.nodeService.getProperty(objectNodeRef, ContentModel.PROP_NAME)))); + + return true; + } + catch (Throwable e) + { + this.lastOperationException = e; + + return false; + } + } + + public boolean isFolder(NodeRef folderNodeRef) + { + + return (folderNodeRef != null) && this.cmisMapping.isValidCmisFolder(this.cmisMapping.getCmisType(this.nodeService.getType(folderNodeRef))); + } + + public boolean isDocument(NodeRef documentNodeRef) + { + + return (documentNodeRef != null) && this.cmisMapping.isValidCmisDocument(this.cmisMapping.getCmisType(this.nodeService.getType(documentNodeRef))); + } + + public boolean isRelationship(String identifier) + { + + try + { + new AssociationRef(identifier); + + return true; + } + catch (Throwable e) + { + return false; + } + } + + public boolean isPolicy(NodeRef policyNodeRef) + { + + // TODO: Policy + + return false; + } + + public EnumObjectType determineObjectType(String identifier) + { + + if (isRelationship(identifier)) + { + return EnumObjectType.RELATIONSHIP; + } + + NodeRef objectNodeReference = new NodeRef(identifier); + + if (isFolder(objectNodeReference)) + { + return EnumObjectType.FOLDER; + } + + if (isDocument(objectNodeReference)) + { + return EnumObjectType.DOCUMENT; + } + + return EnumObjectType.POLICY; + } + + public boolean isChildOfThisFolder(NodeRef objectNodeReference, NodeRef folderNodeReference) + { + + NodeRef searchedObjectNodeReference = this.fileFolderService.searchSimple(folderNodeReference, (String) this.nodeService.getProperty(objectNodeReference, + ContentModel.PROP_NAME)); + + return (searchedObjectNodeReference != null) && searchedObjectNodeReference.equals(objectNodeReference); + } + + public boolean isPrimaryObjectParent(NodeRef folderNodeReference, NodeRef objectNodeReference) + { + + NodeRef searchedParentObject = this.nodeService.getPrimaryParent(objectNodeReference).getParentRef(); + + return (searchedParentObject != null) && searchedParentObject.equals(folderNodeReference); + } + + public boolean isWorkingCopy(NodeRef objectIdentifier) + { + + return nodeService.hasAspect(objectIdentifier, ContentModel.ASPECT_WORKING_COPY); + } + + public void setCmisDictionaryService(CMISDictionaryService cmisDictionaryService) + { + + this.cmisDictionaryService = cmisDictionaryService; + + this.cmisMapping = this.cmisDictionaryService.getCMISMapping(); + } + + public void setNodeService(NodeService nodeService) + { + + this.nodeService = nodeService; + } + + public void setFileFolderService(FileFolderService fileFolderService) + { + + this.fileFolderService = fileFolderService; + } + + public void setLockService(LockService lockService) + { + + this.lockService = lockService; + } + + public void setCheckOutCheckInService(CheckOutCheckInService checkOutCheckInService) + { + + this.checkOutCheckInService = checkOutCheckInService; + } + + public void setAuthorityService(AuthorityService authorityService) + { + + this.authorityService = authorityService; + } + + public Throwable getLastOperationException() + { + + return lastOperationException; + } + + private boolean performNodeDeletion(NodeRef objectNodeReference) + { + + if (this.nodeService.hasAspect(objectNodeReference, ContentModel.ASPECT_WORKING_COPY)) + { + this.checkOutCheckInService.cancelCheckout(objectNodeReference); + + return true; + } + + try + { + this.nodeService.deleteNode(objectNodeReference); + } + catch (Throwable e) + { + return false; + } + + return true; + } + + private boolean isObjectLockIsNotATrouble(NodeRef objectNodeReference) + { + + String currentUserName = AuthenticationUtil.getFullyAuthenticatedUser(); + + return (this.lockService.getLockStatus(objectNodeReference, currentUserName) != LockStatus.LOCKED) || this.authorityService.isAdminAuthority(currentUserName); + } + + private UnlinkOperationStatus unlinkObject(NodeRef objectNodeReference, NodeRef parentFolderNodeReference, boolean totalDeletion) + { + + if (isFolder(objectNodeReference)) + { + List children = this.nodeService.getChildAssocs(objectNodeReference); + + return new UnlinkOperationStatus(((children == null) || children.isEmpty()) && deleteObject(objectNodeReference), (children != null) ? (children) + : (new LinkedList())); + } + + return new UnlinkOperationStatus((totalDeletion) ? (deleteObject(objectNodeReference)) + : (!isPrimaryObjectParent(parentFolderNodeReference, objectNodeReference) && removeObject(objectNodeReference, parentFolderNodeReference)), + new LinkedList()); + } + + private void processNotUnlinkedObjectResults(DescendantElement currentElement, UnlinkOperationStatus unlinkingStatus, DescendantsQueueManager queueManager, + List resultList, boolean addAllFailedToDelete) + { + + if (!unlinkingStatus.getChildren().isEmpty()) + { + queueManager.addElementToQueueEnd(currentElement); + + queueManager.addChildren(unlinkingStatus.getChildren(), currentElement); + + return; + } + + resultList.add(currentElement.getNodesAssociation().getChildRef().toString()); + + if (addAllFailedToDelete) + { + queueManager.removeParents(currentElement, resultList); + } + } + + private NodeRef receiveNodeReferenceOfExistenceObject(String clearNodeIdentifier) throws InvalidArgumentException + { + + if (NodeRef.isNodeRef(clearNodeIdentifier)) + { + NodeRef result = new NodeRef(clearNodeIdentifier); + + if (this.nodeService.exists(result)) + { + return result; + } + } + + throw new InvalidArgumentException("Invalid Object Identifier was specified: Identifier is incorrect or Object with the specified Identifier is not exists", + new ObjectNotFoundException()); + } + + private String cutNodeVersionIfNecessary(String identifier, String[] splitedNodeIdentifier, int startIndex) + { + + String withoutVersionSuffix = identifier; + + if (splitedNodeIdentifier.length == NODE_REFERENCE_WITH_SUFFIX_DELIMETERS_COUNT) + { + withoutVersionSuffix = splitedNodeIdentifier[startIndex++ - 1] + DOUBLE_NODE_REFERENCE_ID_DELIMETER + splitedNodeIdentifier[startIndex++] + NODE_REFERENCE_ID_DELIMETER + + splitedNodeIdentifier[startIndex]; + } + + return withoutVersionSuffix; + } + + private AlfrescoObjectType determineActualObjectType(AlfrescoObjectType expectedType, QName objectType) + { + + return (expectedType != AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT) ? (AlfrescoObjectType.fromValue(objectType.toString())) : ((DOCUMENT_AND_FOLDER_TYPES + .contains(objectType)) ? (AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT) : (AlfrescoObjectType.ANY_OBJECT)); + } + + private IdentifierConversionResults createAssociationIdentifierResult(final String identifier) + { + + return new IdentifierConversionResults() + { + public AssociationRef getConvertedIdentifier() + { + + return new AssociationRef(identifier); + } + }; + } + + private IdentifierConversionResults createNodeReferenceIdentifierResult(final NodeRef identifier) + { + + return new IdentifierConversionResults() + { + public NodeRef getConvertedIdentifier() + { + + return identifier; + } + }; + } + + public interface IdentifierConversionResults + { + public I getConvertedIdentifier(); + } + + private class UnlinkOperationStatus + { + private boolean objectUnlinked; + private List children; + + public UnlinkOperationStatus(boolean objectUnlinked, List children) + { + + this.objectUnlinked = objectUnlinked; + this.children = children; + } + + public boolean isObjectUnlinked() + { + + return this.objectUnlinked; + } + + public List getChildren() + { + + return this.children; + } + + protected UnlinkOperationStatus() + { + } + } +} diff --git a/source/java/org/alfresco/repo/cmis/ws/utils/DescendantsQueueManager.java b/source/java/org/alfresco/repo/cmis/ws/utils/DescendantsQueueManager.java new file mode 100755 index 0000000000..89aab0e3e1 --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/ws/utils/DescendantsQueueManager.java @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws.utils; + +import java.util.LinkedList; +import java.util.List; + +import org.alfresco.service.cmr.repository.ChildAssociationRef; + +/** + * @author Dmitry Velichkevich + */ +public class DescendantsQueueManager +{ + private LinkedList queue; + + public DescendantsQueueManager(ChildAssociationRef headAssociation) + { + + this.queue = new LinkedList(); + this.queue.addFirst(createElement(headAssociation, null)); + } + + public DescendantElement createElement(ChildAssociationRef data, DescendantElement parent) + { + + return new DescendantElement(parent, data); + } + + public void removeParents(DescendantElement source, List undeletedNodes) + { + + while (source.getParentElement() != null) + { + source = source.getParentElement(); + + determineUndeletedObjectToPut(source.getNodesAssociation().getChildRef().toString(), undeletedNodes); + + this.queue.remove(source); + } + } + + public void addChildren(List children, DescendantElement parent) + { + + for (ChildAssociationRef child : children) + { + this.queue.addFirst(createElement(child, parent)); + } + } + + /** + * This method receives and immediately removes next element from the queue + * + * @return next DescendantElement (in this case - first element) in the queue if queue still contain any element or null if queue is empty + */ + public DescendantElement receiveNextElement() + { + + DescendantElement result = (this.queue.isEmpty()) ? (null) : (this.queue.getFirst()); + + this.queue.remove(result); + + return result; + } + + public void addElementToQueueEnd(DescendantElement element) + { + + this.queue.addLast(element); + } + + public boolean isDepleted() + { + + return this.queue.isEmpty(); + } + + protected DescendantsQueueManager() + { + } + + private void determineUndeletedObjectToPut(String undeletedObjectIdentifier, List undeletedNodes) + { + + if (!undeletedNodes.contains(undeletedObjectIdentifier)) + { + undeletedNodes.add(undeletedObjectIdentifier); + } + } + + public class DescendantElement + { + private DescendantElement parentElement; + private ChildAssociationRef nodesAssociation; + + public DescendantElement(DescendantElement parentElement, ChildAssociationRef nodesAssociation) + { + + this.parentElement = parentElement; + this.nodesAssociation = nodesAssociation; + } + + public DescendantElement getParentElement() + { + + return parentElement; + } + + public ChildAssociationRef getNodesAssociation() + { + + return nodesAssociation; + } + + @Override + public boolean equals(Object obj) + { + + if (!(obj instanceof DescendantElement)) + { + return false; + } + + DescendantElement currentElement = (DescendantElement) obj; + + return (this.nodesAssociation != null) ? (this.nodesAssociation.equals(currentElement.getNodesAssociation())) : (currentElement.getNodesAssociation() == null); + } + + protected DescendantElement() + { + } + } +} diff --git a/source/test-resources/import-for-cmis-ws-test.acp b/source/test-resources/import-for-cmis-ws-test.acp deleted file mode 100644 index fef83b5125891bb3b76ee02d630a920cada1fe08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2751 zcmbuB2{e@JAID!NSwa(I$!-W`$uK6wlm<0p9Xp{kCRAfGO{KXa%eBR*Ny^ehvQ42B zT}x8gMTVryaK$jT$eye8N9X)6{-^Ul=k|Nf`=0kb=Y2ls`+J`EoabX}0onoq_*MqO zEkhqzS28QleuT3`5?S*kk)%n+pCj+Z5&g+{f3mg~IgmU9dw0I+4Z1@Q0BkLI`GWN6 zR@+vl@UL99{{{-%0Nt_%9py_l{3WQ)DpdEK?vIRmM8pEmNXFj>36S@(QN{+K6vRF;| zdKW%UEM1KoqSl5=I;~*g5SfQKG8>qETmIOoCwU$h*fBXDYjE~N#k>W%7n82^@@ENN zk0=NIA_siSBcU#Zw(MFtYNdbYU1X)`o4KP)%{?IVD68e7d(&8_ik^Z=el&tc)|W9= z{cN9D`dBjOSk_lY;yvXS?U;7e-TO|zaLvc)Dnh9ou&R7sT`Nu`hrOWMJ#|Q?2i^RV z+9xk;QX+U|H(&*PR*I1JJ>%dAhkTa4whw??Li%Nu)V{eFbSIgqz3SN8Y8OlxzN2i| z7_wBtR&J<`e_b6zuVmFJ(pYCvw&oFEv%I1)oTgibV=prI1j_`fJrBgGn-N{q|akekH|us@d+G#lC}fkkgG~+yL=_v;oMFqpIep_ z0%BfzU(q}VtQUmDF4|;9F>Z#`92(X4n?3)*v-p6+R-gOHz3=LWN$MST8aVi~u{lPr z(}b~b#e(&b_*S<$32?92AVy7{;sLp%VWQR0m{Ii5;J59fJ`xH`)~A9V;-{xe>naDJ zj6hXAV_Gm;Up2iNnM1hu=UGRUUEt!**djZ&4cW~2QUxhTaD^}zaz^IW@q z?A*Pb2AG-_0W^slB;#>le|K~*!s|sHoj{2c$d`qr`{!{-&{c0EKkyfDQ1>ZiL_fFE zlpEG{v}c)_j6ChI8nCWj82Wj`;L)L!R48TsQip4vfI$6QOgeMG?w$7or20;@d9pdr zJPb32N|qgs71GCw)iz+C8rR%DZLphgb1+^UQN#P;l z*#z1IcI4_#nS8bQtHtHKsvk0^lRl1rL-Li3v8KzYq5YJm34@#b!z!c<>U86MO}pei zZ#;vWS+E?83D*>!K_neCIL%}+QpFD{C$J5w6`?l#T_Uqb?klJF%^SS_elLG6XndD= zelx6xgrqtN0SsWOVKD?nBF1WPkuBoRzBS43U9$)q~i_B2Yu5j6yn1>vjcR8J9(b+ z?~zWwT17h+ix?CZV$$Z0W?L09w%7WJ=2)d60=i~r+EkL;vv+r~72bAUE7?M5OUky| z1I|El9~959DisB>Lz9X5UsDtYwYz?u($F>(M!f~4`{*_&pFIcm^}J$olH}mrvzW~#zL+0{e1+wp(D)I0 z@b>5m@`3%cWkQo$daT%5ul@oeT%j?E;@I!0kL`;GFDxHsct)2bn7~z9^vwq(<8g2* z(^J+wHRwwW?x{SLX#{vUpO;vad+D+zGfyTn{x}>5(!erbI>OvWs$2beGrv7jZTs)c ztD3n4@9l z)(h{=^U}Ed_&aD-D})SKh3B>cfTqpr5zfU80sgU-^~$koD;sOm8MeV)Hj~zS#zvCk z3iKzWHDTFITCW%zNsOP9)+}W+X}wo$BrX1&v?eH - - - - - - - - org.alfresco.repo.cmis.ws.RepositoryServicePort - - - - - - - - - - - - - - - - - org.alfresco.repo.cmis.ws.NavigationServicePort - - - - - - - - - - - - - - - - - org.alfresco.repo.cmis.ws.ObjectServicePort - - - - - - - - - - - - - - - - - - - - ${server.transaction.mode.readOnly} - ${server.transaction.mode.default} - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/source/test-resources/test.jpg b/source/test-resources/test.jpg new file mode 100755 index 0000000000000000000000000000000000000000..fb1b25168fb2854f70037c10cbb4b04216115023 GIT binary patch literal 68436 zcmeFZbySsI*FL%tq+5^<>246DL?kvT2uOpZv~;r(1f)Bpk(N+81?dLq?(S~b{5C2+ z@P5zpzVG)tq(#x5D<`&ka1B^aM>OaK4SY{e_eeCV8GuSf!>3LA_LsRfP%(= zx@rWF002<;A>Lj){QC>)9yH8-SU7kDL?p<75_G^lC}`+=Fwpn!!@xjByFz{sfWf$r z`G{2r_JQ1MI5JBtws)Z^@Z`@5>agW|cPQ9(tUM49AL8KR;Zssk)6mj!aB@B7=6NFg zTtrk%94PTpK~d?IvWlv%p1y(M8zWyUAAJ47!XqN1qGLYBeo9SC z&&bTm{#;m8TvA$AUQt=!(Ad=6(%RPE*FP{gG(0joHaj=Ju(-6mvbwgrw|{VWbbNAp zc8v=P0R0QrA7uZ63j>1d9t;dL4BRy?sC)L13mOCF{v%dcOd&bA*Om{+*xtcoJqt}K zs6!xUm*2tGvFb&9NWn2nxqA)mC$j$zn8*JWvOmE7!Zij!hK7P94;lj?2+kRzX^W(6*cnn7^0RWQ`eoa!^J+#j4^);-w!uNfN08SL*yq zI#*>SN;O`tk{wTPUz1DSOA4cIC7IaO>DAC&kt&|8u>&RSMC4%U=9dYF&<^9d?4Acb z`Z)Wiu8ZU#T$0^Yvnzm`7t5L)s3)Q9@(erAUf;-hmOcAv>B>=mjN+Vh#&Z||q0Pi& zw77D@{l3!h*$y*d>5{7QZ{=S3B~Y1-A!EL8n}p4EG~V)TAmrx~>x*HCDyo(-#H&s# zuGXx~<#;6UWMw+%6cm(cE)$~Z9%8zBS(Z@0PDEQYzBx5%q zUW{ncM{tGvV4hM+8Is9v*_=;J8XIwFDAB7hrS&soPI1xg6(eJabCbqv6Yd^Zq6fbBOrDyYDlH2U)W}4xRmFOX|`!JIp+$ ztkkNg;9iy^TY5?>qz!J>&erwDy5#YO-J0xAcojeOGcOm09T5FJCCt z@jITrovh812KHwf@-u^_!Qz(bwA0ZkNq>TMi;JQh8qd_?TJucv%|%iRC4SU*K7a|b zjJFYtd_sb@{`g^sHEbw|0r@dQw&_NilLsu#QAD0|vW-DPZp+`LL6z0vrQ=7v@(OQp zj*J04mE1%Dh4~JRMst!)RJxKYfOmf07RR|WWg^(Q3U}M3T$>`6^UR zo>(imo??L{Cl)&fY5>L3UjhCi&L8&`sLNu<>^RZNbOuOq|Uh>6MYE^LZE1oS9-81a-)fq7*SWcLm7vP@pF2ef)Q|FFH3g zHyCP88uicy_0w}Y71?L(10HnSY z+rF@h-e73D(W*alsKlh+fWL8&27EI~Zl@e1p4UP9?H@!(Zl+K&`2QjPKgeQ+Erc0; z*9}Vcn#X;^kng%$N~rj=ZqY5O7SdL()!|I_3NW3b5_6PFJYbcw_lw2pUoOvn3;Xpz zB?JDfmXcqryP5GuIn*1{<;ny@ptec|$1**Ra@Y>y< z!u4~e+)ih?VB=pbge(gFzYLmQvtM$6nNfa;|4H2=%LtJ*p+PuB6le-Bra;7F-SLy2BetSAcXD1=;~6tCIXmd%G?5te1mS z;JrpCu1pGA+Wz8|$N`oIJuuRq{fmY$ZVH*A18`~@xS;XPvMT^#{t5w7m&Ge-8OKK@ zWl@Gkg{2GPn`hXd6tcuyS($=~4DI-?LmKzxCK$mLg_TIo+NFAbU!)#zL)q8M6LnOn^|D?i2K|)zR0_K z?F!)A^saesCw?uSCxt2K3Xl>?m4Y=Ug>MjNM49*AY>6kbh_W%JdFiOdqW_)R6PX#pH%sFzs%n-wRb$#qE{jw8hJb0&p~PQuR?A{xN}crBRK&RQ zkL6Su^zSt+n!#+IigjJ^%=i0MIOeamb0T#(f5dn0qT_|nRicFp`%cs5TE&&$*8r0g zm&~aKMi;~d{lK~c%qR$6D3a{FJ81yBXI=sBrCb5#a%807=rjji*E=rCCipX$a>lM8@0X{nM>xz6W@R%AqLP+aBd|c(Xv^TUR8uzw)2R&a8Mtl2I z#)02hg_-fSEP_d8;G9}D$(st61`BfWc>2>qDUy5v084RjlTZS^SfEgMdZA&%_SzQx*Df=mP@s>;p^HPqFkimw20qs;x=RJB7Kahn2Qu8)?NwN&Yt(iXH2 zn(YAqc!}_qsqx`F4S`2}GlO3Yg3ct9HW`)1Hs5)OoHJO~EHOyTgs`|jGKW*`{0}+M z?10kyR(L)feFY%%p&O~-n&jW^J*>R~P_(%SS`uf@qdc2ZNjD)f0M6OFEYP#+xjZKI zz}oLC;H(-PJRGlD`OejO&N$2m|HAAkf2lj@fg0^h62bGZG*!J`gcmK;k*@d_F9&4^ z^++TF9FUr3037O2KagS|*`JEov02;y99jrueARWf5wPZJU^AgkG+s09b2#$7;skuJ8w|3i zYDTG>_XZq(PP!{0S^tu4>AvqaxiyE&U>!wEJIT?bl{2d=z#gU6!)cXuVp8W0yx2Ff z@CpU*oAzM<0qFd^$nqy;%His}_cua}al%(?bYjRH^)LcRVLprltgGS`ll}$PzeG6S z&-!~q_;L0gRa8!1ZEL*=4wHptzKQ*c+HlFGz^==S(lWMiwg{Csc&K>Kj! zsEf?OuX|Xs&!Fs~5$LrEXKgfpUSob!QM;*aFiKU}2|3LEJ4Mhe^sdh(lq~qZ@D-p* z?ryXzE~B*C+BRQJ)ka56Tb7kHTW329M2#L-@Rt^4ihVYc>Sx)rk^Ks^D&R6(v|uqO zv=029P_aI-D_b;NoX5kFj>D!Qk~SuZ7f2d{G!*KK{*KHNmq^8(aEBdY80Mc1$EUbk zoOEn!O$U7dfC|*UhwLju&wseSdT$oB3G8q%-*A^kda{Y3Wkl;j)Sprv3dcs_QI zKbz0bjR} z)q{FQE>{F{e8FPJggqf|_E2nUAtA2))!-q>=B}&r0c10J-4GvKFFM4Acarvx1f9@6 z&w)ZOTR0c+e?fA)4%c;;yw*usNL>ELKixn6XcJ3)v2cR|0wbj_pdp#R1ce2Yi_hza?I zM?!oWzxjKMM}M2A?Q2@!@aSina3O2Lzv0oHG~IE1%E^(6)J5{HvPH+ zPaqXIeail`-Y!UMu1gDY5PPk$a(`|D|Ek*IFjtyech#P9LMjLwvTXhPyKeN0;!JKK zNn#Z=d;hu)AUhd|2nU}Cxm;JR)9Qt*L1ltf0^QWhaX@5Bn|eOMzuFdtG;IZjp=h?xPM9- z$~EOdzf*R{@R2v#KctM{n&UT7o4sv!6Pe^6GWHl!kAFf|f7|Ncrz`wAT%e!P()rzT zZp_A96Q!61bgSb$hVb?#S-+ws1xam_Jm|(!=QSnoT8e{I$Tczk_m;Nu7W>CFOUeeB zh>-*fR8PZ5JJ1f4cSnv}jN5*)>Q{KK{p{63aY&yJ&^VFk-V^^JTG-)OP#OdfP;WK2D{xTxVwYxT0;FFzvwiY*z@+Z{2gsV?Bxt(6z-Z-+E8WuCN)IYbkrbw` z?c6hdzSe2UR2^uRPYPj$!xf+}hTh>sO_SdRDH9^S^;%%@tc9I2znUHfE;sCwLKSz+ z81n`^01x0Jr4H;221R&<6h9%s~PKGLviY_YH;%zeny_DK0b@Z{lKESPYY zZ%e;w$2PF50hF7tt%5JS_Dm`#>1B{pqLEMi*zWp_hTs(d789~;7tzak-M4t;uh|!D zV#^sp$M2{$(VmD6;#wjEp;kb)`kPK;JBLS+nEc(DmAZ(~C|?PsrUIOyhNq`fxCoo`$LJNHqyRM)U|3S_ z#cdgXD#gz;b9A*5VE+lRQehaV4#fqp=1y^xEmq z-cyvwDt;D!GH#EiR-k`OHK3VExY{6mZnx46K&Y)b@m1t z$sH6TFNfP(Ea0~0V@H1!n~8~6mrWn3FkS(Q%r*`5Lp{?%%@;){*b***@~l6W{gjGo z50i+` z5LG8MCnwDJ^2|yt-j+{{+9?9`^unIJ8+a#;fBD|XfD<9LpUHeAjjOCM&8o;VFxmW3 zkob9;XJ}AK_}u8?*Q%o0QolLJi|k|;F$=5q-I~rNaq`el+KS@b%OU)t_q}~Sufu%HpKm{qdyoDjza*M9dAy_zCCR#37r9ZJ5XOyyi@{un=5RxHa zkGscG)BZA)@GNgB-ln)9)^TgzRbpDQ%D&7I>GC_8(bU<)!kD1vmK2QA_jy(`ZG?7g)PmRK~c#>rNm%18?v zYjgO_3f(>>&P>roO2SO=yj%>L8wMR3L&@xd$ol@bO4=e7GEW(QE6<^+XFb8unS5^L z8Pp3l7!LlzNt?tnMVW0!21o)OX##T804}t4E7l$-zm7&H*LfM~uEOUs%ru*vZ?LjyXDTUc^~gFuos7M@Dpe$|n>G1Gic~sA+Unpt3nlZC5@C$s zy!FC28RVCNS(+{6WR6i?0K|@K~4iZ>voLRX8P8AN=}jWj=q^ad~R+$ zU~Jt)pAhkxK@w~Y5tQ^anP}7IHCmrgeg5y`gde(+XbFs3q~-fr;?pwXZrXA29;X;R&ej+}muzAzJ31NMTjUw^)KKvrIn% zF9WZ%5b91?aq>jeC-@b*IYyP?Jw)CqMm9&Ah58=))&$lK00%zen#k7i6JaI6(cPZQ z1S}^#IkkH2(4H|2gTRi;NCH%{Ss`=fi@}^(ejK^pA?2+`^l=8cCNndX4t02sW$w^k zEu$XzrlTWL%V!eP!-rP@v<2i<kP9m0eFMu8tfHn{g@0&&P+8I|Bl2N6``_`ep&$-7|A7(V7R&YA^ zVhTD9v+$sKHlJMzVkGPpR(dNT=d!``z{n4xJdnoc@_LY!Pq-F$vKT7fZnf`A zzg^AyoR||p;`ijg>_!wrhEdX{v1|jyjCp_GhGm}&^C>F41i(niNC_ayO70cEF^uZm zb2yw#x6dr-xwb}q5+lF7zU#Nqexyh4e) zj_55cy>Rmsarw~3=5pcE+Cb^RWSLVb8`Or?XR-d>e46o-Bn3Yd?(uc6y4Spu>avSn z;h|Na)_e1%)`z(ZW2Q%M-=@;ZnWg6})mp6Y@(YR%fJ%z}ohRe)>QIvx=(Fj*JL}== z^>YqaG73G=o{hdZY7ria7V2yE|D-x%v5!wlIbFny*(p{EOiM(_+iq$qrd|9> zWr|z`N*q~p8VcR#^NX+Ui8cw@NRmLONs!LcU1AT`{BC=uTVvg%e<7wljdsW-j~MyE zgBQF@|I)SjGwJJl{_-uIuLKh6)(=`-mi;PW_){K+yBcTKAF6UmE!(DDgpQN6q zCf4p`u0R%ii^J!eho5|||ElTTdYc#QazazY>7BaJf$tJx=%T;hSrfpjnY}m#>KPz8 zK?a>v?rnRJ?9OL{D&Y2`zUkB$@<1NkXYXBv);zdgCl!(~9fRHSt^hlbGlE^4M2+o> zOQ9>k^=W{AE@WMZfva_ih+&Ck-GaRTu%6Zko9oMQjQR4{?H=r^c)z_=?)Fui#{u(H zeJjF?kaO3b!CEjh379Fo<6F;#>&-;j`(4-~A&&M*`-gBpe;s_=s4XYcn|o+X`(U?Z z$a#-0WXIEc%l-5W<2-9*B)c4}y=EeKL3$7Nmf8}dCHF^r+k(q$Xcw@87aGJG%YS*D zeJ=lkjO3rDGrK%cH47NF4qt4nc;v|71mJJ`PP|lpdiYIe$r>Eam<=r;{aJKetm;XD z?iK+18zINK3l(+&OX@CBaI|C6$r)th3Ke_>z!AIilX@|JbFnT<6Myw0STV|WWS3+c zy;`sz@^E_v$6E6QBwJDLx-V%Su<8DoRWAJ9_fPr6HjxWhmMnQY4=<{EPX9~`yanB* zKfPL-A+JR2wCVMP@he7JGJ8*c@~1w~6CsZI*2$y)6oFiBTeX;_`MD-R;%3YeGS7SWc z@sOS-BL3ddq9_QDK1FoNY{Wj=5pqWG0yG0TI-Fa%6(A9WMEgPY|astbz;H1ozKPAT?-oLT<@Qy{}TNY`) zYPA~Pg}DVeyZK!Tf*Y#A7vM3-CYm0!+b+-qIpyxz`~tpL26<5-HR9UUs(*5o@s_JP z|K8QwzX&UP{?D$`T6tY~-wH=C)AnCQ-VeU(+#Sbxp3U=B-LfJUZU0wZSFZqf{X4ql zI$?@sqQ>-Ja*%ol@D-rob}VWCH9++!l_2})2v`4GtQDi#`khYD4f8aQF%R8>!b=%6T+0p)wZ$D{}@>}cw0}U43 zu9JCVRMCQWWTPF{8j!m=co`MH_{OFqJkva7Sbec4E?X~y=7@-Z>#7EK=QvZeD`L^ zizC0%1Uw=V{!4^j4+!27A@aSgKO?E{Le=_@P;XgW<+~j;`AZ*&<2Um9KOu1K;OXTd2DQI5p(DQvQs*n?_g9pJ}xC*(JqBI3a}sd1wEZ7FpeI{r73S z1L|MH`ajYLy5XzjZBQh4@wVbX()ed2u}07BG~Pk=6Yx0bXB*_Xx1f1@Xlh5rUum&r zz6lnfnsd^Ed+fRPj*X200Dg2}7>)9mmnH2>p%4 z?5s?y4=%Uo5{tHml(5{d<*tz(pmy{OLebwD)7rSaCU))5g%gvgfDQ@Mt+9QMe@&7BhH!lOX#8eb zbqOiAp3Sn~E1pmvR&#%}>-yM2>t?^0Yzo|}+de>y{ZS-+>#~xjmr(o&y z&*fo|C}E?(HQ8?R{F`jGKU=iz<2!?cZ^I-E;Q80=SVDTqP2OLE46h5y?DxWx2Haiy zul~;e70zMCT|6pc=z)$N0%Wo8@4s9WYo7P)<=37+xdQwNtmTwI7*K%NxW-6+ZH`Sr zo2baEo6WL+sPZkV2{!Nw;3W7l(%wm4Q|i>W=Jc#r*meGT*BLK~r6yDUjuLQp6Pi(T;(q2b##l|AhPsK>Q^7JOspJ(#I)Hg(6Rhs>(Cp z=IwCe&{I~H#fN_?KpL>*8MDdv#G_r7obGIaW?1belgTyy;K@J00p^{mY z_V=K*6VYTwv1`DHDye$midA~HbPXLJ^e{Zw9&qkOWDSQK+3>B|m<*VSr3^GSr341c zC&zv--hETGYun=k>ys9m4Lq}@A6&iEQ%?Kec+>Qgx$N37Ld>$+JGSAa5vw9}sg&R~(jvZq| z#czw``KzjZKg}3OTVl2>!q6LpUY`yyZj>-_L zidHz>d<*Gb)A=Z8aSmEF#VEF2pk42&9BN~+d1uItx|4 z*FA!MB-|ASoUfJ1C}3vFrO;i{XhN>C!`v?^t^-v%Dz)&VVQv^eB<733=?W1obFwKRlNMO|3iaS^S z1=Ya`p@i3Qrc}SQjJLDzp@6O(QdL4~z5~pBK7B8JIDs5ja>99nG98ebS9Qs})Dk=U z3XstPdCB^laB6UIUQ_W`pHhpDNf|@)0pObHNUd+hI3X~TB?DWc>z*DwM9l~!f!0Mm zoVix2eD&D6(Z2D>mk4WUr`zh(md+Yo#au@P&oBqw^xdlB64}qr!M0rPK);3XArZlo zxgoxnJ@$llI0=4gitT+;fh(KbSVOvE@(4 z_E6Xx5THlgTuvY@v&*>ox~9Oukz5$M&OPiN>>&AxQ;-;O{Wru4|2JKMi-`$#pJAkY zVKTSca{^p(q55m(R#@^pQ~iP&6-%2$b62Yx->aw?S++Rm87r0cb|P-C{bV>khRJvBllNH_YJ}Q(TV^^r+^7xx30!g;2?Khl}q^tm&R*jZ)!S>GsH*P zj|weAL@gK3hb0jsys#_10D}XIK#C@Uwb4#xhtC#lY9ki>9FRv4YGviJ61M1#;Z2(?V2t1Q+%snJ*CL#N@5G#F<{z-W#Ix77%y^u(L`vo|(5N z3=fYVSMRz4XnhJDD2U&fuy0bqrp|%IaR2m{gg< zP)1SpATgJLr)&YLE+X1T-tYqJVN#lTa4ez=F%Cv

(dXJx*9L?>63ikaTG2Vu0hD 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 literal 0 HcmV?d00001 diff --git a/source/test/java/org/alfresco/repo/cmis/ws/AbstractServiceTest.java b/source/test/java/org/alfresco/repo/cmis/ws/AbstractServiceTest.java index 25805576dc..110b533019 100644 --- a/source/test/java/org/alfresco/repo/cmis/ws/AbstractServiceTest.java +++ b/source/test/java/org/alfresco/repo/cmis/ws/AbstractServiceTest.java @@ -24,102 +24,210 @@ */ package org.alfresco.repo.cmis.ws; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.UnsupportedCallbackException; +import java.util.List; import junit.framework.TestCase; -import org.alfresco.repo.security.authentication.AuthenticationComponent; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.search.ResultSet; -import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor; -import org.apache.cxf.endpoint.Client; -import org.apache.cxf.frontend.ClientProxy; -import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor; -import org.apache.ws.security.WSConstants; -import org.apache.ws.security.WSPasswordCallback; -import org.apache.ws.security.handler.WSHandlerConstants; -import org.springframework.context.support.FileSystemXmlApplicationContext; +import org.alfresco.cmis.dictionary.CMISMapping; /** * @author Michael Shavnev + * @author Alexander Tsvetkov + * */ + public abstract class AbstractServiceTest extends TestCase { - protected ServiceRegistry serviceRegistry; - protected static NodeRef ALFRESCO_TUTORIAL_NODE_REF = null; - protected static NodeRef COMPANY_HOME_NODE_REF = null; + // protected ServiceRegistry serviceRegistry; - protected static FileSystemXmlApplicationContext fContext = null; + public String companyHomeId; + public String repositoryId; + + protected String documentId; + protected String folderId; + protected String documentName; + protected String folderName; + + protected ObjectFactory cmisObjectFactory = new ObjectFactory(); protected Object servicePort = null; + protected CmisServiceTestHelper helper; + + private static boolean testAsUser = false; + + protected abstract Object getServicePort(); @Override protected void setUp() throws Exception { super.setUp(); - if (fContext == null) - { - fContext = new FileSystemXmlApplicationContext("classpath:alfresco/application-context.xml"); - - AuthenticationComponent authenticationComponent = (AuthenticationComponent) fContext.getBean("authenticationComponent"); - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - serviceRegistry = (ServiceRegistry) fContext.getBean(ServiceRegistry.SERVICE_REGISTRY); - ResultSet resultSet = serviceRegistry.getSearchService().query(new StoreRef("workspace://SpacesStore"), "lucene", "@cm\\:name:Alfresco-Tutorial.pdf"); - ALFRESCO_TUTORIAL_NODE_REF = resultSet.getNodeRef(0); - - resultSet = serviceRegistry.getSearchService().query(new StoreRef("workspace://SpacesStore"), "lucene", "@cm\\:name:Company Home"); - COMPANY_HOME_NODE_REF = resultSet.getNodeRef(0); - - authenticationComponent.clearCurrentSecurityContext(); - } } - public AbstractServiceTest() { - servicePort = getServicePort(); - - Map wss4jOutInterceptorProp = new HashMap(); - wss4jOutInterceptorProp.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN + " " + WSHandlerConstants.TIMESTAMP); - - wss4jOutInterceptorProp.put(WSHandlerConstants.USER, getUserName()); - wss4jOutInterceptorProp.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST); - - wss4jOutInterceptorProp.put(WSHandlerConstants.PW_CALLBACK_REF, new CallbackHandler() + super(); + if (testAsUser) { - public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException + helper = CmisServiceTestHelper.getInstance(CmisServiceTestHelper.USERNAME_USER1, CmisServiceTestHelper.PASSWORD_USER1); + servicePort = getServicePort(); + helper.authenticateServicePort(servicePort, CmisServiceTestHelper.USERNAME_USER1, CmisServiceTestHelper.PASSWORD_USER1); + + repositoryId = helper.getRepositoryId(); + companyHomeId = helper.getCompanyHomeId(repositoryId); + // Users could not create any content in Company Home, they should create test content in Users Hone folder + companyHomeId = helper.getUserHomeId(repositoryId, companyHomeId); + } + else + { + helper = CmisServiceTestHelper.getInstance(); + servicePort = getServicePort(); + helper.authenticateServicePort(servicePort, CmisServiceTestHelper.USERNAME_ADMIN, CmisServiceTestHelper.PASSWORD_ADMIN); + + repositoryId = helper.getRepositoryId(); + companyHomeId = helper.getCompanyHomeId(repositoryId); + } + } + + public AbstractServiceTest(String testCase, String userName, String password) + { + super(testCase); + helper = CmisServiceTestHelper.getInstance(userName, password); + servicePort = getServicePort(); + helper.authenticateServicePort(servicePort, userName, password); + repositoryId = helper.getRepositoryId(); + companyHomeId = helper.getCompanyHomeId(repositoryId); + // Users could not create any content in Company Home, they should create test content in Users Home folder + companyHomeId = helper.getUserHomeId(repositoryId, companyHomeId); + + } + + public String getObjectName(GetPropertiesResponse response) + { + String property = null; + + if (response != null && response.getObject() != null) + { + CmisObjectType object = response.getObject(); + CmisPropertiesType properties = object.getProperties(); + property = (String) PropertyUtil.getProperty(properties, CMISMapping.PROP_NAME); + } + else + { + fail("Response has no results."); + } + return property; + } + + public String getPropertyValue(GetPropertiesResponse response, String propertyName) + { + String property = null; + + if (response != null && response.getObject() != null) + { + CmisObjectType object = response.getObject(); + CmisPropertiesType properties = object.getProperties(); + if (PropertyUtil.getProperty(properties, propertyName) != null) { - WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; - pc.setPassword(getPassword()); + property = (String) PropertyUtil.getProperty(properties, propertyName); } - }); - - WSS4JOutInterceptor wss4jOutInterceptor = new WSS4JOutInterceptor(wss4jOutInterceptorProp); - - Client client = ClientProxy.getClient(servicePort); - client.getEndpoint().getOutInterceptors().add(new SAAJOutInterceptor()); - client.getEndpoint().getOutInterceptors().add(wss4jOutInterceptor); + } + else + { + fail("Response has no results."); + } + return property; } - protected abstract Object getServicePort(); - - protected String getUserName() + public Boolean getPropertyBooleanValue(GetPropertiesResponse response, String propertyName) { - return "admin"; + Boolean property = null; + + if (response != null && response.getObject() != null) + { + CmisObjectType object = response.getObject(); + CmisPropertiesType properties = object.getProperties(); + if (PropertyUtil.getProperty(properties, propertyName) != null) + { + property = (Boolean) PropertyUtil.getProperty(properties, propertyName); + } + } + else + { + fail("Response has no results."); + } + return property; } - protected String getPassword() + public String getObjectId(GetPropertiesResponse response) { - return "admin"; + String property = null; + + if (response != null && response.getObject() != null) + { + CmisObjectType object = response.getObject(); + CmisPropertiesType properties = object.getProperties(); + property = (String) PropertyUtil.getProperty(properties, CMISMapping.PROP_OBJECT_ID); + } + else + { + fail("Response has no results."); + } + return property; + } + + public void validateResponse(List objects) + { + for (CmisObjectType object : objects) + { + CmisPropertiesType properties = object.getProperties(); + String name = (String) PropertyUtil.getProperty(properties, CMISMapping.PROP_NAME); + assertNotNull(name); + } + + } + + public boolean isExistItemWithProperty(List objects, String propertyName, String propertyValue) + { + boolean isFound = false; + for (CmisObjectType object : objects) + { + CmisPropertiesType properties = object.getProperties(); + String property = (String) PropertyUtil.getProperty(properties, propertyName); + if (property.equals(propertyValue)) + { + isFound = true; + } + } + return isFound; + } + + public void createInitialContent() throws Exception + { + // create initial content + documentName = "Test cmis document (" + System.currentTimeMillis() + ")"; + documentId = helper.createDocument(documentName, companyHomeId); + + folderName = "Test Cmis Folder (" + System.currentTimeMillis() + ")"; + folderId = helper.createFolder(folderName, companyHomeId); + } + + public void deleteInitialContent() + { + try + { + helper.deleteFolder(folderId); + } + catch (Exception e) + { + } + + try + { + helper.deleteDocument(documentId); + } + catch (Exception e) + { + } } } diff --git a/source/test/java/org/alfresco/repo/cmis/ws/BaseServicePortContentTest.java b/source/test/java/org/alfresco/repo/cmis/ws/BaseServicePortContentTest.java deleted file mode 100644 index ef836f9481..0000000000 --- a/source/test/java/org/alfresco/repo/cmis/ws/BaseServicePortContentTest.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2005-2008 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 - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" - */ -package org.alfresco.repo.cmis.ws; - -import java.io.InputStream; -import java.io.Serializable; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.action.executer.ImporterActionExecuter; -import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.repo.version.VersionModel; -import org.alfresco.service.cmr.action.Action; -import org.alfresco.service.cmr.action.ActionService; -import org.alfresco.service.cmr.coci.CheckOutCheckInService; -import org.alfresco.service.cmr.model.FileFolderService; -import org.alfresco.service.cmr.repository.ContentService; -import org.alfresco.service.cmr.repository.ContentWriter; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.version.Version; -import org.alfresco.service.cmr.version.VersionService; -import org.alfresco.service.cmr.version.VersionType; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; - -/** - * Base class for all CMIS content tests - * - * @author Dmitry Lazurkin - * - */ -public class BaseServicePortContentTest extends BaseServicePortTest -{ - protected CheckOutCheckInService checkOutCheckInService; - - private static final String IMPORT = "import-for-cmis-ws-test.acp"; - - protected static final String L0_FILE_0 = "L0-File-0"; - protected static final String L0_FILE_1 = "L0-File-1"; - protected static final String L0_FILE_2 = "L0-File-2"; - protected static final String L1_FILE_0 = "L1-File-0"; - protected static final String L1_FILE_1 = "L1-File-1"; - protected static final String L1_FILE_VERSIONABLE = "L1-File-Versionable"; - protected static final String L0_FOLDER_0 = "L0-Folder-0"; - protected static final String L0_FOLDER_1 = "L0-Folder-1"; - protected static final String L0_FOLDER_2 = "L0-Folder-2"; - protected static final String L1_FOLDER_0 = "L1-Folder-0"; - protected static final String L1_FOLDER_1 = "L1-Folder-1"; - - protected NodeRef L0_FILE_0_NODEREF; - protected NodeRef L0_FILE_1_NODEREF; - protected NodeRef L0_FILE_2_NODEREF; - protected NodeRef L1_FILE_0_NODEREF; - protected NodeRef L1_FILE_1_NODEREF; - protected NodeRef L0_FOLDER_0_NODEREF; - protected NodeRef L0_FOLDER_1_NODEREF; - protected NodeRef L0_FOLDER_2_NODEREF; - protected NodeRef L1_FOLDER_0_NODEREF; - protected NodeRef L1_FOLDER_1_NODEREF; - protected NodeRef L0_NONEXISTENT_NODEREF; - - protected NodeRef L1_FILE_VERSION_2_1_NODEREF; - protected NodeRef L1_FILE_VERSION_2_0_NODEREF; - protected NodeRef L1_FILE_VERSION_1_0_NODEREF; - - @Override - protected void onSetUp() throws Exception - { - super.onSetUp(); - - checkOutCheckInService = serviceRegistry.getCheckOutCheckInService(); - - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - InputStream is = getClass().getClassLoader().getResourceAsStream(IMPORT); - if (is == null) - { - throw new NullPointerException("Test resource not found: " + IMPORT); - } - - NodeRef importForTest = nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "import-for-test.acp"), ContentModel.TYPE_CONTENT).getChildRef(); - ContentService contentService = serviceRegistry.getContentService(); - ContentWriter writer = contentService.getWriter(importForTest, ContentModel.PROP_CONTENT, true); - writer.setMimetype(MimetypeMap.MIMETYPE_ACP); - writer.setEncoding("UTF-8"); - writer.putContent(is); - - Map params = new HashMap(2, 1.0f); - params.put(ImporterActionExecuter.PARAM_DESTINATION_FOLDER, rootNodeRef); - params.put(ImporterActionExecuter.PARAM_ENCODING, "UTF-8"); - - ActionService actionService = serviceRegistry.getActionService(); - Action action = actionService.createAction(ImporterActionExecuter.NAME, params); - action.setExecuteAsynchronously(false); - - actionService.executeAction(action, importForTest); - - nodeService.deleteNode(importForTest); - - FileFolderService fileFolderService = serviceRegistry.getFileFolderService(); - VersionService versionService = serviceRegistry.getVersionService(); - - L0_FILE_0_NODEREF = fileFolderService.resolveNamePath(rootNodeRef, Collections.singletonList(L0_FILE_0)).getNodeRef(); - L0_FILE_1_NODEREF = fileFolderService.resolveNamePath(rootNodeRef, Collections.singletonList(L0_FILE_1)).getNodeRef(); - L0_FILE_2_NODEREF = fileFolderService.resolveNamePath(rootNodeRef, Collections.singletonList(L0_FILE_2)).getNodeRef(); - L0_FOLDER_0_NODEREF = fileFolderService.resolveNamePath(rootNodeRef, Collections.singletonList(L0_FOLDER_0)).getNodeRef(); - L0_FOLDER_1_NODEREF = fileFolderService.resolveNamePath(rootNodeRef, Collections.singletonList(L0_FOLDER_1)).getNodeRef(); - L0_FOLDER_2_NODEREF = fileFolderService.resolveNamePath(rootNodeRef, Collections.singletonList(L0_FOLDER_2)).getNodeRef(); - L1_FILE_0_NODEREF = fileFolderService.resolveNamePath(L0_FOLDER_0_NODEREF, Collections.singletonList(L1_FILE_0)).getNodeRef(); - L1_FILE_1_NODEREF = fileFolderService.resolveNamePath(L0_FOLDER_1_NODEREF, Collections.singletonList(L1_FILE_1)).getNodeRef(); - - L1_FILE_VERSION_2_1_NODEREF = fileFolderService.resolveNamePath(L0_FOLDER_2_NODEREF, Collections.singletonList(L1_FILE_VERSIONABLE)).getNodeRef(); - nodeService.addAspect(L1_FILE_VERSION_2_1_NODEREF, ContentModel.ASPECT_VERSIONABLE, Collections.singletonMap(ContentModel.PROP_AUTO_VERSION, (Serializable) Boolean.FALSE)); - contentService.getWriter(L1_FILE_VERSION_2_1_NODEREF, ContentModel.PROP_CONTENT, true).putContent("1.0"); - L1_FILE_VERSION_1_0_NODEREF = versionService.createVersion(L1_FILE_VERSION_2_1_NODEREF, createVersionProps("1.0", VersionType.MAJOR)).getFrozenStateNodeRef(); - contentService.getWriter(L1_FILE_VERSION_2_1_NODEREF, ContentModel.PROP_CONTENT, true).putContent("2.0"); - L1_FILE_VERSION_2_0_NODEREF = versionService.createVersion(L1_FILE_VERSION_2_1_NODEREF, createVersionProps("2.0", VersionType.MAJOR)).getFrozenStateNodeRef(); - contentService.getWriter(L1_FILE_VERSION_2_1_NODEREF, ContentModel.PROP_CONTENT, true).putContent("2.1"); - versionService.createVersion(L1_FILE_VERSION_2_1_NODEREF, createVersionProps("2.1", VersionType.MINOR)); - - L1_FOLDER_0_NODEREF = fileFolderService.resolveNamePath(L0_FOLDER_0_NODEREF, Collections.singletonList(L1_FOLDER_0)).getNodeRef(); - L1_FOLDER_1_NODEREF = fileFolderService.resolveNamePath(L0_FOLDER_0_NODEREF, Collections.singletonList(L1_FOLDER_1)).getNodeRef(); - L0_NONEXISTENT_NODEREF = importForTest; - - authenticationComponent.clearCurrentSecurityContext(); - } - - private Map createVersionProps(String comment, VersionType versionType) - { - Map props = new HashMap(1, 1.0f); - props.put(Version.PROP_DESCRIPTION, comment); - props.put(VersionModel.PROP_VERSION_TYPE, versionType); - return props; - } - -} diff --git a/source/test/java/org/alfresco/repo/cmis/ws/BaseServicePortTest.java b/source/test/java/org/alfresco/repo/cmis/ws/BaseServicePortTest.java deleted file mode 100644 index 7274be00e0..0000000000 --- a/source/test/java/org/alfresco/repo/cmis/ws/BaseServicePortTest.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2005-2008 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 - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" - */ -package org.alfresco.repo.cmis.ws; - -import javax.transaction.UserTransaction; - -import org.alfresco.cmis.CMISService; -import org.alfresco.cmis.dictionary.CMISMapping; -import org.alfresco.model.ContentModel; -import org.alfresco.repo.node.integrity.IntegrityChecker; -import org.alfresco.repo.security.authentication.AuthenticationComponent; -import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.security.AuthenticationService; -import org.alfresco.service.descriptor.DescriptorService; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.transaction.TransactionService; -import org.springframework.test.AbstractDependencyInjectionSpringContextTests; - -/** - * Base class for all CMIS tests - * - * @author Dmitry Lazurkin - * - */ -public class BaseServicePortTest extends AbstractDependencyInjectionSpringContextTests -{ - protected AuthenticationService authenticationService; - protected TransactionService transactionService; - protected NodeService nodeService; - protected ServiceRegistry serviceRegistry; - protected DictionaryService dictionaryService; - protected DescriptorService descriptorService; - protected CMISMapping cmisMapping; - protected CMISService cmisService; - - protected AuthenticationComponent authenticationComponent; - - private UserTransaction txn; - - protected NodeRef rootNodeRef; - - protected ObjectFactory cmisObjectFactory = new ObjectFactory(); - - protected String repositoryId; - - @Override - protected void onSetUp() throws Exception - { - super.onSetUp(); - - serviceRegistry = (ServiceRegistry) applicationContext.getBean(ServiceRegistry.SERVICE_REGISTRY); - - authenticationService = serviceRegistry.getAuthenticationService(); - transactionService = serviceRegistry.getTransactionService(); - nodeService = serviceRegistry.getNodeService(); - dictionaryService = serviceRegistry.getDictionaryService(); - descriptorService = serviceRegistry.getDescriptorService(); - - repositoryId = descriptorService.getServerDescriptor().getId(); - - authenticationComponent = (AuthenticationComponent) applicationContext.getBean("authenticationComponent"); - - cmisService = (CMISService) applicationContext.getBean("CMISService"); - cmisMapping = (CMISMapping) applicationContext.getBean("CMISMapping"); - - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - // start the transaction - txn = transactionService.getUserTransaction(); - txn.begin(); - - IntegrityChecker.setWarnInTransaction(); - - // authenticate - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - // create a test store if need - rootNodeRef = nodeService.createNode(cmisService.getDefaultRootNodeRef(), ContentModel.ASSOC_CHILDREN, QName.createQName(NamespaceService.ALFRESCO_URI, "cmis_test_folder"), - ContentModel.TYPE_FOLDER).getChildRef(); - - authenticationComponent.clearCurrentSecurityContext(); - } - - @Override - protected void onTearDown() throws Exception - { - try - { - txn.rollback(); - } - catch (Throwable e) - { - e.printStackTrace(); - } - } - - @Override - protected String[] getConfigLocations() - { - return new String[] { "classpath:alfresco/application-context.xml", "classpath:test-cmis-context.xml" }; - } - -} diff --git a/source/test/java/org/alfresco/repo/cmis/ws/CmisServiceTestHelper.java b/source/test/java/org/alfresco/repo/cmis/ws/CmisServiceTestHelper.java new file mode 100755 index 0000000000..50e90569cd --- /dev/null +++ b/source/test/java/org/alfresco/repo/cmis/ws/CmisServiceTestHelper.java @@ -0,0 +1,753 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws; + +import java.io.IOException; +import java.math.BigInteger; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.activation.DataHandler; +import javax.activation.DataSource; +import javax.activation.URLDataSource; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.UnsupportedCallbackException; +import javax.xml.namespace.QName; +import javax.xml.ws.Holder; +import javax.xml.ws.Service; + +import junit.framework.TestCase; + +import org.alfresco.cmis.dictionary.CMISMapping; +import org.alfresco.cmis.dictionary.CMISTypeId; +import org.alfresco.repo.content.MimetypeMap; +import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor; +import org.apache.cxf.endpoint.Client; +import org.apache.cxf.frontend.ClientProxy; +import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor; +import org.apache.ws.security.WSConstants; +import org.apache.ws.security.WSPasswordCallback; +import org.apache.ws.security.handler.WSHandlerConstants; + +public class CmisServiceTestHelper extends TestCase +{ + public final static String ALFRESCO_URL = "http://localhost:8080/alfresco"; + + public static final String USERNAME_ADMIN = "admin"; + public static final String PASSWORD_ADMIN = "admin"; + + public static final String USERNAME_GUEST = "guest"; + public static final String PASSWORD_GUEST = "guest"; + + public static final String USERNAME_USER1 = "user1"; + public static final String PASSWORD_USER1 = "user1"; + + public String companyHomeId; + public String repositoryId; + + protected ObjectFactory cmisObjectFactory = new ObjectFactory(); + + protected String documentId; + protected String folderId; + protected String documentName; + protected String folderName; + + protected RepositoryServicePort repositoryServicePort = null; + protected VersioningServicePort versioningServicePort = null; + protected ObjectServicePort objectServicePort = null; + protected MultiFilingServicePort multiFilingServicePort = null; + protected NavigationServicePort navigationServicePort = null; + + private static CmisServiceTestHelper helperInstance; + private static String previousUserName = null; + + private CmisServiceTestHelper() + { + repositoryServicePort = getRepositoryServicePort(); + authenticateServicePort(repositoryServicePort, USERNAME_ADMIN, PASSWORD_ADMIN); + + objectServicePort = getObjectServicePort(); + authenticateServicePort(objectServicePort, USERNAME_ADMIN, PASSWORD_ADMIN); + + versioningServicePort = getVersioningServicePort(); + authenticateServicePort(versioningServicePort, USERNAME_ADMIN, PASSWORD_ADMIN); + + multiFilingServicePort = getMultiFilingServicePort(); + authenticateServicePort(multiFilingServicePort, USERNAME_ADMIN, PASSWORD_ADMIN); + + navigationServicePort = getNavigationServicePort(); + authenticateServicePort(navigationServicePort, USERNAME_ADMIN, PASSWORD_ADMIN); + + repositoryId = getRepositoryId(); + companyHomeId = getCompanyHomeId(repositoryId); + } + + private CmisServiceTestHelper(String username, String password) + { + repositoryServicePort = getRepositoryServicePort(); + authenticateServicePort(repositoryServicePort, username, password); + + objectServicePort = getObjectServicePort(); + authenticateServicePort(objectServicePort, username, password); + + versioningServicePort = getVersioningServicePort(); + authenticateServicePort(versioningServicePort, username, password); + + multiFilingServicePort = getMultiFilingServicePort(); + authenticateServicePort(multiFilingServicePort, username, password); + + navigationServicePort = getNavigationServicePort(); + authenticateServicePort(navigationServicePort, username, password); + + repositoryId = getRepositoryId(); + companyHomeId = getCompanyHomeId(repositoryId); + // Users could not create any content in Company Home, they should create test content in Users Hone folder + companyHomeId = getUserHomeId(repositoryId, companyHomeId); + } + + public static CmisServiceTestHelper getInstance() + { + if (previousUserName != null && !previousUserName.equals(USERNAME_ADMIN)) + { + helperInstance = null; + } + + if (helperInstance == null) + { + helperInstance = new CmisServiceTestHelper(); + previousUserName = USERNAME_ADMIN; + } + return helperInstance; + } + + public static CmisServiceTestHelper getInstance(String userName, String password) + { + if (previousUserName != null && !previousUserName.equals(userName)) + { + helperInstance = null; + } + + if (helperInstance == null) + { + helperInstance = new CmisServiceTestHelper(userName, password); + previousUserName = userName; + } + return helperInstance; + } + + public void authenticateServicePort(Object servicePort, String username, String passwordValue) + { + final String password = passwordValue; + + Map wss4jOutInterceptorProp = new HashMap(); + wss4jOutInterceptorProp.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN + " " + WSHandlerConstants.TIMESTAMP); + + wss4jOutInterceptorProp.put(WSHandlerConstants.USER, username); + wss4jOutInterceptorProp.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST); + + wss4jOutInterceptorProp.put(WSHandlerConstants.PW_CALLBACK_REF, new CallbackHandler() + { + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException + { + WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; + pc.setPassword(password); + } + }); + + WSS4JOutInterceptor wss4jOutInterceptor = new WSS4JOutInterceptor(wss4jOutInterceptorProp); + + Client client = ClientProxy.getClient(servicePort); + client.getEndpoint().getOutInterceptors().add(new SAAJOutInterceptor()); + client.getEndpoint().getOutInterceptors().add(wss4jOutInterceptor); + } + + public String createDocument(String name, String parentFolderId) throws Exception + { + String content = "This is a test content"; + // Cmis Properties + CmisPropertiesType properties = new CmisPropertiesType(); + List propertiesList = properties.getProperty(); + CmisPropertyString cmisProperty = new CmisPropertyString(); + cmisProperty.setName(CMISMapping.PROP_NAME); + cmisProperty.setValue(name); + propertiesList.add(cmisProperty); + + CmisContentStreamType cmisStream = new CmisContentStreamType(); + cmisStream.setFilename(name); + cmisStream.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + + DataHandler dataHandler = new DataHandler(content, MimetypeMap.MIMETYPE_TEXT_PLAIN); + cmisStream.setStream(dataHandler); + + // public String createDocument(String repositoryId, String typeId, CmisPropertiesType properties, String folderId, CmisContentStreamType contentStream, + // EnumVersioningState versioningState) + String objectId = objectServicePort.createDocument(repositoryId, CMISMapping.DOCUMENT_TYPE_ID.getTypeId(), properties, parentFolderId, cmisStream, + EnumVersioningState.MAJOR); + // assertNotNull(objectId); + return objectId; + } + + public String createDocument(String name, String parentFolderId, CMISTypeId typeId, EnumVersioningState enumVersioningState) throws Exception + { + String content = "This is a test content"; + // Cmis Properties + CmisPropertiesType properties = new CmisPropertiesType(); + List propertiesList = properties.getProperty(); + CmisPropertyString cmisProperty = new CmisPropertyString(); + cmisProperty.setName(CMISMapping.PROP_NAME); + cmisProperty.setValue(name); + propertiesList.add(cmisProperty); + + CmisContentStreamType cmisStream = new CmisContentStreamType(); + cmisStream.setFilename(name); + cmisStream.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + + DataHandler dataHandler = new DataHandler(content, MimetypeMap.MIMETYPE_TEXT_PLAIN); + cmisStream.setStream(dataHandler); + + // public String createDocument(String repositoryId, String typeId, CmisPropertiesType properties, String folderId, CmisContentStreamType contentStream, + // EnumVersioningState versioningState) + String objectId = objectServicePort.createDocument(repositoryId, typeId.getTypeId(), properties, parentFolderId, cmisStream, enumVersioningState); + // assertNotNull(objectId); + return objectId; + } + + public String createDocumentImage(String name, String parentFolderId) throws Exception + { + DataSource dataSource = new URLDataSource(getClass().getResource("test.jpg")); + DataHandler dataHandler = new DataHandler(dataSource); + + CmisContentStreamType cmisStream = new CmisContentStreamType(); + cmisStream.setFilename(name + dataSource.getName()); + cmisStream.setMimeType(MimetypeMap.MIMETYPE_BINARY); + cmisStream.setStream(dataHandler); + + CmisPropertiesType properties = new CmisPropertiesType(); + List propertiesList = properties.getProperty(); + CmisPropertyString cmisProperty = new CmisPropertyString(); + cmisProperty.setName(CMISMapping.PROP_NAME); + cmisProperty.setValue(name + dataSource.getName()); + propertiesList.add(cmisProperty); + + // public String createDocument(String repositoryId, String typeId, CmisPropertiesType properties, String folderId, CmisContentStreamType contentStream, + // EnumVersioningState versioningState) + String objectId = objectServicePort.createDocument(repositoryId, CMISMapping.DOCUMENT_TYPE_ID.getTypeId(), properties, parentFolderId, cmisStream, + EnumVersioningState.MAJOR); + // assertNotNull(objectId); + return objectId; + + } + + public String createFolder(String name, String parentFolderId) throws Exception + { + // CreateFolder request = cmisObjectFactory.createCreateFolder(); + // request.setRepositoryId(repositoryId); + // request.setFolderId(CompanyHomeId); + // request.setTypeId(CMISMapping.FOLDER_TYPE_ID.getTypeId()); + // request.setProperties(properties); + + CmisPropertiesType properties = new CmisPropertiesType(); + List propertiesList = properties.getProperty(); + + CmisPropertyString cmisProperty = new CmisPropertyString(); + cmisProperty.setName(CMISMapping.PROP_NAME); + cmisProperty.setPropertyType(EnumPropertyType.STRING); + cmisProperty.setIndex(BigInteger.valueOf(1)); + cmisProperty.setValue(name); + propertiesList.add(cmisProperty); + + // public String createFolder(String repositoryId, String typeId, CmisPropertiesType properties, String folderId) + String objectId = objectServicePort.createFolder(repositoryId, CMISMapping.FOLDER_TYPE_ID.getTypeId(), properties, parentFolderId); + // assertNotNull(objectId); + return objectId; + } + + public String createFolder(String name, String parentFolderId, CMISTypeId cmisTypeId) throws Exception + { + + CmisPropertiesType properties = new CmisPropertiesType(); + List propertiesList = properties.getProperty(); + + CmisPropertyString cmisProperty = new CmisPropertyString(); + cmisProperty.setName(CMISMapping.PROP_NAME); + cmisProperty.setPropertyType(EnumPropertyType.STRING); + cmisProperty.setIndex(BigInteger.valueOf(1)); + cmisProperty.setValue(name); + propertiesList.add(cmisProperty); + + // public String createFolder(String repositoryId, String typeId, CmisPropertiesType properties, String folderId) + String objectId = objectServicePort.createFolder(repositoryId, cmisTypeId.getTypeId(), properties, parentFolderId); + // assertNotNull(objectId); + return objectId; + } + + public void deleteDocument(String documentId) throws Exception + { + objectServicePort.deleteObject(repositoryId, documentId); + assertNull("Document has not been deleted", getObjectProperties(documentId)); + } + + public void deleteFolder(String folderId) throws Exception + { + objectServicePort.deleteTree(repositoryId, folderId, EnumUnfileNonfolderObjects.DELETE, true); + assertNull("Folder has not been deleted", getObjectProperties(folderId)); + } + + public GetPropertiesResponse getObjectProperties(String objectId) + { + GetProperties request = new GetProperties(); + request.setRepositoryId(repositoryId); + + request.setObjectId(objectId); + request.setReturnVersion(cmisObjectFactory.createGetPropertiesReturnVersion(EnumReturnVersion.LATEST)); + request.setFilter(cmisObjectFactory.createGetPropertiesFilter("*")); + + request.setIncludeAllowableActions(cmisObjectFactory.createGetPropertiesIncludeAllowableActions(true)); + request.setIncludeRelationships(cmisObjectFactory.createGetPropertiesIncludeRelationships(true)); + + GetPropertiesResponse response = null; + try + { + response = objectServicePort.getProperties(request); + } + + catch (InvalidArgumentException e) + { + // e.printStackTrace(); + } + catch (ObjectNotFoundException e) + { + + } + catch (Exception e) + { + e.printStackTrace(); + } + return response; + } + + public GetPropertiesResponse getObjectProperties(String objectId, String filter) + { + GetProperties request = new GetProperties(); + request.setRepositoryId(repositoryId); + + request.setObjectId(objectId); + request.setReturnVersion(cmisObjectFactory.createGetPropertiesReturnVersion(EnumReturnVersion.LATEST)); + request.setFilter(cmisObjectFactory.createGetPropertiesFilter(filter)); + + request.setIncludeAllowableActions(cmisObjectFactory.createGetPropertiesIncludeAllowableActions(true)); + request.setIncludeRelationships(cmisObjectFactory.createGetPropertiesIncludeRelationships(true)); + + GetPropertiesResponse response = null; + try + { + response = objectServicePort.getProperties(request); + } + + catch (FilterNotValidException e) + { + fail("FilterNotValidException"); + } + catch (ObjectNotFoundException e) + { + + } + catch (Exception e) + { + e.printStackTrace(); + } + return response; + } + + /** + * This method simplify receiving of Object Identificator for Company Home Root Folder + * + * @param servicesPort - RepositoryServicePort instance that configured with WSS4J Client + * @return String representation of Object Identificator + * @throws Exception This exception throws when any CMIS Services operations was failed + */ + public String getCompanyHomeId(String repositoryId) + { + String rootFolder = null; + GetRepositoryInfo parameters = new GetRepositoryInfo(); + try + { + parameters.setRepositoryId(repositoryId); + rootFolder = repositoryServicePort.getRepositoryInfo(parameters).getRootFolderId(); + } + catch (Exception e) + { + e.printStackTrace(); + } + return rootFolder; + } + + public String getUserHomeId(String repositoryId, String companyHomeId) + { + String userHomeFolder = null; + GetRepositoryInfo parameters = new GetRepositoryInfo(); + try + { + parameters.setRepositoryId(repositoryId); + GetChildrenResponse response = getChildren(companyHomeId, EnumTypesOfFileableObjects.FOLDERS, 0, "*"); + for (CmisObjectType object : response.getObject()) + { + if (PropertyUtil.getProperty(object.getProperties(), CMISMapping.PROP_NAME).equals("User Homes")) + { + return (String) PropertyUtil.getProperty(object.getProperties(), CMISMapping.PROP_OBJECT_ID); + } + } + + userHomeFolder = repositoryServicePort.getRepositoryInfo(parameters).getRootFolderId(); + } + catch (Exception e) + { + e.printStackTrace(); + } + return userHomeFolder; + } + + public final static String REPOSITORY_SERVICE_WSDL_LOCATION = ALFRESCO_URL + "/cmis/RepositoryService?wsdl"; + public final static QName REPOSITORY_SERVICE_NAME = new QName("http://www.cmis.org/ns/1.0", "RepositoryService"); + + protected RepositoryServicePort getRepositoryServicePort() + { + URL serviceWsdlURL; + try + { + serviceWsdlURL = new URL(REPOSITORY_SERVICE_WSDL_LOCATION); + } + catch (MalformedURLException e) + { + throw new java.lang.RuntimeException("Cannot get service Wsdl URL", e); + } + + Service service = Service.create(serviceWsdlURL, REPOSITORY_SERVICE_NAME); + + return (RepositoryServicePort) service.getPort(RepositoryServicePort.class); + + } + + public final static String OBJECT_SERVICE_WSDL_LOCATION = ALFRESCO_URL + "/cmis/ObjectService?wsdl"; + public final static QName OBJECT_SERVICE_NAME = new QName("http://www.cmis.org/ns/1.0", "ObjectService"); + + protected ObjectServicePort getObjectServicePort() + { + URL serviceWsdlURL; + try + { + serviceWsdlURL = new URL(OBJECT_SERVICE_WSDL_LOCATION); + } + catch (MalformedURLException e) + { + throw new java.lang.RuntimeException("Cannot get service Wsdl URL", e); + } + + Service service = Service.create(serviceWsdlURL, OBJECT_SERVICE_NAME); + + return (ObjectServicePort) service.getPort(ObjectServicePort.class); + + } + + public final static String VERSIONING_SERVICE_WSDL_LOCATION = ALFRESCO_URL + "/cmis/VersioningService?wsdl"; + public final static QName VERSIONING_SERVICE_NAME = new QName("http://www.cmis.org/ns/1.0", "VersioningService"); + + protected VersioningServicePort getVersioningServicePort() + { + URL serviceWsdlURL; + try + { + serviceWsdlURL = new URL(VERSIONING_SERVICE_WSDL_LOCATION); + } + catch (MalformedURLException e) + { + throw new java.lang.RuntimeException("Cannot get service Wsdl URL", e); + } + + Service service = Service.create(serviceWsdlURL, VERSIONING_SERVICE_NAME); + return service.getPort(VersioningServicePort.class); + } + + public final static String MULTIFILING_SERVICE_WSDL_LOCATION = ALFRESCO_URL + "/cmis/MultiFilingService?wsdl"; + public final static QName MULTIFILING_SERVICE_NAME = new QName("http://www.cmis.org/ns/1.0", "MultiFilingService"); + + protected MultiFilingServicePort getMultiFilingServicePort() + { + URL serviceWsdlURL; + try + { + serviceWsdlURL = new URL(MULTIFILING_SERVICE_WSDL_LOCATION); + } + catch (MalformedURLException e) + { + throw new java.lang.RuntimeException("Cannot get service Wsdl URL", e); + } + + Service service = Service.create(serviceWsdlURL, MULTIFILING_SERVICE_NAME); + return service.getPort(MultiFilingServicePort.class); + } + + public final static String NAVIGATION_SERVICE_WSDL_LOCATION = ALFRESCO_URL + "/cmis/NavigationService?wsdl"; + public final static QName NAVIGATION_SERVICE_NAME = new QName("http://www.cmis.org/ns/1.0", "NavigationService"); + + protected NavigationServicePort getNavigationServicePort() + { + URL serviceWsdlURL; + try + { + serviceWsdlURL = new URL(NAVIGATION_SERVICE_WSDL_LOCATION); + } + catch (MalformedURLException e) + { + throw new java.lang.RuntimeException("Cannot get service Wsdl URL", e); + } + + Service service = Service.create(serviceWsdlURL, NAVIGATION_SERVICE_NAME); + + NavigationServicePort servicePort = service.getPort(NavigationServicePort.class); + + return servicePort; + } + + public String getRepositoryId() + { + try + { + return repositoryServicePort.getRepositories().get(0).getRepositoryID(); + } + catch (Exception e) + { + return null; + } + } + + public void checkIn(Holder documentId, String checkinComment, Boolean isMajor) + { + try + { + CmisPropertiesType properties = new CmisPropertiesType(); + CmisContentStreamType contentStream = new CmisContentStreamType(); + contentStream.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + DataHandler dataHandler = new DataHandler("Test content string :" + System.currentTimeMillis(), MimetypeMap.MIMETYPE_TEXT_PLAIN); + contentStream.setStream(dataHandler); + versioningServicePort.checkIn(repositoryId, documentId, isMajor, properties, contentStream, checkinComment); + } + catch (Throwable e) + { + e.printStackTrace(); + fail(); + } + } + + public void checkOut(Holder documentId, Holder contentCopied) + { + try + { + versioningServicePort.checkOut(repositoryId, documentId, contentCopied); + } + catch (Throwable e) + { + e.printStackTrace(); + fail(); + } + } + + public GetAllVersionsResponse getAllVersions(String documentId) + { + GetAllVersionsResponse response = null; + try + { + GetAllVersions request = new GetAllVersions(); + request.setRepositoryId(repositoryId); + request.setVersionSeriesId(documentId); + request.setFilter(cmisObjectFactory.createGetAllVersionsFilter("*")); + request.setIncludeAllowableActions(cmisObjectFactory.createGetAllVersionsIncludeAllowableActions(Boolean.FALSE)); + request.setIncludeRelationships(cmisObjectFactory.createGetAllVersionsIncludeRelationships(Boolean.FALSE)); + + response = versioningServicePort.getAllVersions(request); + assertNotNull(response.getObject()); + } + catch (Throwable e) + { + e.printStackTrace(); + fail(); + } + return response; + } + + public String createRelationship(String name, String folderId, String documentId) throws Exception + { + String objectId = null; + CmisPropertiesType properties = new CmisPropertiesType(); + List propertiesList = properties.getProperty(); + + CmisPropertyString cmisProperty = new CmisPropertyString(); + cmisProperty.setName(CMISMapping.PROP_NAME); + cmisProperty.setPropertyType(EnumPropertyType.STRING); + cmisProperty.setIndex(BigInteger.valueOf(1)); + cmisProperty.setValue(name); + propertiesList.add(cmisProperty); + + // createRelationship(String repositoryId, String typeId, CmisPropertiesType properties, String sourceObjectId, String targetObjectId) + objectId = objectServicePort.createRelationship(repositoryId, CMISMapping.RELATIONSHIP_TYPE_ID.getTypeId(), properties, documentId, folderId); + assertNotNull(objectId); + + return objectId; + + } + + public String updateProperty(String documentId, String propName, String propValue) throws Exception + { + + // Cmis Properties + CmisPropertiesType properties = new CmisPropertiesType(); + List propertiesList = properties.getProperty(); + CmisPropertyString cmisProperty = new CmisPropertyString(); + cmisProperty.setName(propName); + cmisProperty.setValue(propValue); + propertiesList.add(cmisProperty); + + Holder documentIdHolder = new Holder(documentId); + // public void updateProperties(String repositoryId, Holder objectId, String changeToken, CmisPropertiesType properties) + objectServicePort.updateProperties(repositoryId, documentIdHolder, new String(""), properties); + assertEquals(documentId, documentIdHolder.value); + + return documentIdHolder.value; + } + + public void addObjectToFolder(String documentId, String anotherFolderId) + { + try + { + multiFilingServicePort.addObjectToFolder(repositoryId, documentId, anotherFolderId); + } + catch (Throwable e) + { + fail(e.getMessage()); + } + } + + public void removeObjectFromFolder(String documentId, String folderId) + { + try + { + multiFilingServicePort.removeObjectFromFolder(repositoryId, documentId, folderId); + } + catch (Exception e) + { + fail(e.getMessage()); + } + } + + public GetObjectParentsResponse getObjectParents(String objectId, String filter) throws Exception + { + + GetObjectParents request = cmisObjectFactory.createGetObjectParents(); + request.setRepositoryId(repositoryId); + request.setObjectId(objectId); + request.setFilter("*"); + request.setIncludeAllowableActions(cmisObjectFactory.createGetObjectParentsIncludeAllowableActions(true)); + request.setIncludeRelationships(cmisObjectFactory.createGetObjectParentsIncludeRelationships(true)); + + GetObjectParentsResponse response = null; + + try + { + response = navigationServicePort.getObjectParents(request); + } + catch (FilterNotValidException e) + { + fail(e.getMessage()); + } + return response; + } + + public GetObjectParentsResponse getObjectParents(String objectId) throws Exception + { + + GetObjectParents request = cmisObjectFactory.createGetObjectParents(); + + request.setRepositoryId(repositoryId); + request.setObjectId(objectId); + + GetObjectParentsResponse response = navigationServicePort.getObjectParents(request); + + return response; + } + + public void setTextContentStream(String documentId, String newContent) throws Exception + { + String newFileName = "New file name (" + System.currentTimeMillis() + ")"; + + CmisContentStreamType contentStream = new CmisContentStreamType(); + contentStream.setFilename(newFileName); + contentStream.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + DataHandler dataHandler = new DataHandler(newContent, MimetypeMap.MIMETYPE_TEXT_PLAIN); + contentStream.setStream(dataHandler); + + Holder documentIdHolder = new Holder(documentId); + // public void setContentStream(String repositoryId, Holder documentId, Boolean overwriteFlag, CmisContentStreamType contentStream) + objectServicePort.setContentStream(repositoryId, documentIdHolder, true, contentStream); + } + + public CmisContentStreamType getContentStream(String documentId) throws Exception + { + CmisContentStreamType result = null; + result = objectServicePort.getContentStream(repositoryId, documentId); + return result; + } + + public GetChildrenResponse getChildren(String folderId, EnumTypesOfFileableObjects type, long maxItems, String filter) throws Exception + { + GetChildren request = cmisObjectFactory.createGetChildren(); + + request.setRepositoryId(repositoryId); + request.setFolderId(folderId); + + request.setFilter(cmisObjectFactory.createGetChildrenFilter(filter)); + request.setMaxItems(cmisObjectFactory.createGetChildrenMaxItems(BigInteger.valueOf(maxItems))); + request.setSkipCount(cmisObjectFactory.createGetChildrenMaxItems(BigInteger.valueOf(0))); + request.setType(cmisObjectFactory.createGetChildrenType(type)); + + GetChildrenResponse response = null; + + try + { + response = navigationServicePort.getChildren(request); + } + catch (FilterNotValidException e) + { + fail(e.getMessage()); + } + + return response; + + } + +} diff --git a/source/test/java/org/alfresco/repo/cmis/ws/CmisWebServiceSuiteSystemTest.java b/source/test/java/org/alfresco/repo/cmis/ws/CmisWebServiceSuiteSystemTest.java new file mode 100755 index 0000000000..0c324ecab6 --- /dev/null +++ b/source/test/java/org/alfresco/repo/cmis/ws/CmisWebServiceSuiteSystemTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws; + +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + * Cmis Web service system tests suite + * + * @author Alexander Tsvetkov + */ +public class CmisWebServiceSuiteSystemTest extends TestSuite +{ + public static Test suite() + { + TestSuite suite = new TestSuite(); + suite.addTestSuite(DMDiscoveryServiceTest.class); + suite.addTestSuite(DMMultiFilingServiceTest.class); + suite.addTestSuite(DMNavigationServiceTest.class); + suite.addTestSuite(DMObjectServiceTest.class); + suite.addTestSuite(DMPolicyServiceTest.class); + suite.addTestSuite(DMRelationshipServiceTest.class); + suite.addTestSuite(DMRepositoryServiceTest.class); + suite.addTestSuite(DMVersioningServiceTest.class); + suite.addTestSuite(MultiThreadsServiceTest.class); + + return suite; + } +} diff --git a/source/test/java/org/alfresco/repo/cmis/ws/DMDiscoveryServiceTest.java b/source/test/java/org/alfresco/repo/cmis/ws/DMDiscoveryServiceTest.java new file mode 100755 index 0000000000..79dab002b4 --- /dev/null +++ b/source/test/java/org/alfresco/repo/cmis/ws/DMDiscoveryServiceTest.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws; + +import java.net.MalformedURLException; +import java.net.URL; + +import javax.xml.namespace.QName; +import javax.xml.ws.Service; + +public class DMDiscoveryServiceTest extends AbstractServiceTest +{ + + public final static String SERVICE_WSDL_LOCATION = CmisServiceTestHelper.ALFRESCO_URL + "/cmis/DiscoveryService?wsdl"; + public final static QName SERVICE_NAME = new QName("http://www.cmis.org/ns/1.0", "DiscoveryService"); + public final static String STATEMENT = "SELECT * FROM DOCUMENT"; + + public DMDiscoveryServiceTest() + { + super(); + } + + public DMDiscoveryServiceTest(String testCase, String username, String password) + { + super(testCase, username, password); + } + + protected Object getServicePort() + { + URL serviceWsdlURL; + try + { + serviceWsdlURL = new URL(SERVICE_WSDL_LOCATION); + } + catch (MalformedURLException e) + { + throw new java.lang.RuntimeException("Cannot get service Wsdl URL", e); + } + + Service service = Service.create(serviceWsdlURL, SERVICE_NAME); + return service.getPort(DiscoveryServicePort.class); + } + + public void testQuery() throws Exception + { + CmisQueryType request = new CmisQueryType(); + request.setStatement(STATEMENT); + QueryResponse response = ((DiscoveryServicePort) servicePort).query(request); + assertNotNull(response); + + assertNotNull(response.getObject()); + + if (!response.getObject().isEmpty()) + { + for (CmisObjectType object : response.getObject()) + { + assertNotNull(object.getProperties()); + } + + } + else + { + fail("The query returned no results"); + } + } +} diff --git a/source/test/java/org/alfresco/repo/cmis/ws/DMMultiFilingServiceTest.java b/source/test/java/org/alfresco/repo/cmis/ws/DMMultiFilingServiceTest.java new file mode 100755 index 0000000000..1246cf4e20 --- /dev/null +++ b/source/test/java/org/alfresco/repo/cmis/ws/DMMultiFilingServiceTest.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws; + +import javax.xml.namespace.QName; + +import org.alfresco.cmis.dictionary.CMISMapping; + +public class DMMultiFilingServiceTest extends AbstractServiceTest +{ + + public final static String SERVICE_WSDL_LOCATION = CmisServiceTestHelper.ALFRESCO_URL + "/cmis/MultiFilingService?wsdl"; + public final static QName SERVICE_NAME = new QName("http://www.cmis.org/ns/1.0", "MultiFilingService"); + private String anotherFolderId; + + public DMMultiFilingServiceTest() + { + super(); + } + + public DMMultiFilingServiceTest(String testCase, String username, String password) + { + super(testCase, username, password); + } + + @Override + protected void setUp() throws Exception + { + super.setUp(); + createInitialContent(); + anotherFolderId = helper.createFolder("Test Cmis Folder (" + System.currentTimeMillis() + ")", companyHomeId); + + } + + @Override + protected void tearDown() throws Exception + { + super.tearDown(); + deleteInitialContent(); + helper.deleteFolder(anotherFolderId); + } + + protected Object getServicePort() + { + return helper.multiFilingServicePort; + } + + public void testAddObjectToFolder() throws Exception + { + ((MultiFilingServicePort) servicePort).addObjectToFolder(repositoryId, documentId, anotherFolderId); + boolean found = false; + for (CmisObjectType cmisObjectType : helper.getChildren(anotherFolderId, EnumTypesOfFileableObjects.DOCUMENTS, 0, CMISMapping.PROP_OBJECT_ID).getObject()) + { + if ((found = PropertyUtil.getProperty(cmisObjectType.getProperties(), CMISMapping.PROP_OBJECT_ID).equals(documentId))) + { + break; + } + } + assertTrue("Document was not added to folder", found); + } + + public void testRemoveObjectFromFolder() throws Exception + { + + helper.addObjectToFolder(documentId, anotherFolderId); + + try + { + // remove object from all folders expects Exception + ((MultiFilingServicePort) servicePort).removeObjectFromFolder(repositoryId, documentId, null); + fail("Expects exception"); + } + catch (Exception e) + { + assertTrue(e instanceof OperationNotSupportedException); + } + + helper.removeObjectFromFolder(documentId, anotherFolderId); + + try + { + // remove object from folder where it is not situated expects Exception + ((MultiFilingServicePort) servicePort).removeObjectFromFolder(repositoryId, documentId, folderId); + fail("Expected exception"); + } + catch (Exception e) + { + assertTrue(e instanceof NotInFolderException); + } + + try + { + // remove object from last folder expects Exception + ((MultiFilingServicePort) servicePort).removeObjectFromFolder(repositoryId, documentId, companyHomeId); + fail("Expected exception"); + } + catch (Exception e) + { + assertTrue(e instanceof OperationNotSupportedException); + } + } +} diff --git a/source/test/java/org/alfresco/repo/cmis/ws/DMNavigationServicePortTest.java b/source/test/java/org/alfresco/repo/cmis/ws/DMNavigationServicePortTest.java deleted file mode 100644 index 0a6593cf67..0000000000 --- a/source/test/java/org/alfresco/repo/cmis/ws/DMNavigationServicePortTest.java +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (C) 2005-2008 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 - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" - */ -package org.alfresco.repo.cmis.ws; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.cmis.dictionary.CMISMapping; -import org.alfresco.service.cmr.repository.NodeRef; - -/** - * @see org.alfresco.repo.cmis.ws.NavigationServicePortDM - * - * @author Dmitry Lazurkin - * - */ -public class DMNavigationServicePortTest extends BaseServicePortContentTest -{ - private NavigationServicePort navigationServicePort; - - @Override - protected void onSetUp() throws Exception - { - super.onSetUp(); - - navigationServicePort = (NavigationServicePort) applicationContext.getBean("dmNavigationService"); - } - - public void testGetChildrenFolders() throws Exception - { - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - GetChildren request = new GetChildren(); - request.setRepositoryId(repositoryId); - request.setMaxItems(cmisObjectFactory.createGetChildrenMaxItems(BigInteger.valueOf(3))); - request.setFolderId(rootNodeRef.toString()); - request.setType(cmisObjectFactory.createGetChildrenType(EnumTypesOfFileableObjects.FOLDERS)); - - GetChildrenResponse response = navigationServicePort.getChildren(request); - List listing = response.getObject(); - NodeRef[] expectedNodeRefs = new NodeRef[] { L0_FOLDER_0_NODEREF, L0_FOLDER_1_NODEREF, L0_FOLDER_2_NODEREF }; - checkListExact(listing, 0, 3, expectedNodeRefs); - } - - public void testGetChildrenDocuments() throws Exception - { - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - GetChildren request = new GetChildren(); - request.setRepositoryId(repositoryId); - request.setFolderId(rootNodeRef.toString()); - request.setType(cmisObjectFactory.createGetChildrenType(EnumTypesOfFileableObjects.DOCUMENTS)); - - GetChildrenResponse response = navigationServicePort.getChildren(request); - List listing = response.getObject(); - NodeRef[] expectedNodeRefs = new NodeRef[] { L0_FILE_0_NODEREF, L0_FILE_1_NODEREF, L0_FILE_2_NODEREF }; - checkListExact(listing, 3, 0, expectedNodeRefs); - } - - public void testGetChildrenSkipCount() throws Exception - { - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - GetChildren request = new GetChildren(); - request.setRepositoryId(repositoryId); - request.setSkipCount(cmisObjectFactory.createGetChildrenSkipCount(BigInteger.valueOf(1))); - request.setFolderId(rootNodeRef.toString()); - request.setType(cmisObjectFactory.createGetChildrenType(EnumTypesOfFileableObjects.ANY)); - - GetChildrenResponse response = navigationServicePort.getChildren(request); - List listing = response.getObject(); - NodeRef[] expectedNodeRefs = new NodeRef[] { L0_FOLDER_0_NODEREF, L0_FOLDER_1_NODEREF, L0_FOLDER_2_NODEREF, L0_FILE_0_NODEREF, L0_FILE_1_NODEREF, L0_FILE_2_NODEREF }; - checkList(listing, 5, 3, 3, expectedNodeRefs); - } - - public void testGetChildrenMaxItems() throws Exception - { - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - GetChildren request = new GetChildren(); - request.setRepositoryId(repositoryId); - request.setMaxItems(cmisObjectFactory.createGetChildrenMaxItems(BigInteger.valueOf(3))); - request.setFolderId(rootNodeRef.toString()); - request.setType(cmisObjectFactory.createGetChildrenType(EnumTypesOfFileableObjects.ANY)); - - GetChildrenResponse response = navigationServicePort.getChildren(request); - List listing = response.getObject(); - NodeRef[] expectedNodeRefs = new NodeRef[] { L0_FOLDER_0_NODEREF, L0_FOLDER_1_NODEREF, L0_FOLDER_2_NODEREF, L0_FILE_0_NODEREF, L0_FILE_1_NODEREF, L0_FILE_2_NODEREF }; - checkList(listing, 3, 3, 3, expectedNodeRefs); - } - - public void testGetChildrenMaxItemsMore() throws Exception - { - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - GetChildren request = new GetChildren(); - request.setRepositoryId(repositoryId); - request.setMaxItems(cmisObjectFactory.createGetChildrenMaxItems(BigInteger.valueOf(10))); - request.setFolderId(rootNodeRef.toString()); - request.setType(cmisObjectFactory.createGetChildrenType(EnumTypesOfFileableObjects.ANY)); - - GetChildrenResponse response = navigationServicePort.getChildren(request); - List listing = response.getObject(); - NodeRef[] expectedNodeRefs = new NodeRef[] { L0_FOLDER_0_NODEREF, L0_FOLDER_1_NODEREF, L0_FOLDER_2_NODEREF, L0_FILE_0_NODEREF, L0_FILE_1_NODEREF, L0_FILE_2_NODEREF }; - checkList(listing, 6, 3, 3, expectedNodeRefs); - } - - public void testGetChildrenSkipCountMore() throws Exception - { - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - GetChildren request = new GetChildren(); - request.setRepositoryId(repositoryId); - request.setSkipCount(cmisObjectFactory.createGetChildrenSkipCount(BigInteger.valueOf(10))); - request.setFolderId(rootNodeRef.toString()); - request.setType(cmisObjectFactory.createGetChildrenType(EnumTypesOfFileableObjects.ANY)); - - GetChildrenResponse response = navigationServicePort.getChildren(request); - List listing = response.getObject(); - NodeRef[] expectedNodeRefs = new NodeRef[] { L0_FOLDER_0_NODEREF, L0_FOLDER_1_NODEREF, L0_FOLDER_2_NODEREF, L0_FILE_0_NODEREF, L0_FILE_1_NODEREF, L0_FILE_2_NODEREF }; - checkList(listing, 0, 3, 3, expectedNodeRefs); - } - - public void testGetChildrenMaxItemsSkipCount() throws Exception - { - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - GetChildren request = new GetChildren(); - request.setRepositoryId(repositoryId); - request.setSkipCount(cmisObjectFactory.createGetChildrenSkipCount(BigInteger.valueOf(5))); - request.setMaxItems(cmisObjectFactory.createGetChildrenMaxItems(BigInteger.valueOf(4))); - request.setFolderId(rootNodeRef.toString()); - request.setType(cmisObjectFactory.createGetChildrenType(EnumTypesOfFileableObjects.ANY)); - - GetChildrenResponse response = navigationServicePort.getChildren(request); - List listing = response.getObject(); - NodeRef[] expectedNodeRefs = new NodeRef[] { L0_FOLDER_0_NODEREF, L0_FOLDER_1_NODEREF, L0_FOLDER_2_NODEREF, L0_FILE_0_NODEREF, L0_FILE_1_NODEREF, L0_FILE_2_NODEREF }; - checkList(listing, 1, 3, 3, expectedNodeRefs); - } - - public void testGetChildrenMaxItemsZero() throws Exception - { - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - GetChildren request = new GetChildren(); - request.setRepositoryId(repositoryId); - request.setMaxItems(cmisObjectFactory.createGetChildrenMaxItems(BigInteger.valueOf(0))); - request.setFolderId(rootNodeRef.toString()); - request.setType(cmisObjectFactory.createGetChildrenType(EnumTypesOfFileableObjects.ANY)); - - GetChildrenResponse response = navigationServicePort.getChildren(request); - List listing = response.getObject(); - NodeRef[] expectedNodeRefs = new NodeRef[] { L0_FOLDER_0_NODEREF, L0_FOLDER_1_NODEREF, L0_FOLDER_2_NODEREF, L0_FILE_0_NODEREF, L0_FILE_1_NODEREF, L0_FILE_2_NODEREF }; - checkListExact(listing, 3, 3, expectedNodeRefs); - } - - public void testGetChildrenForDocument() throws Exception - { - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - GetChildren request = new GetChildren(); - request.setRepositoryId(repositoryId); - request.setFolderId(L0_FILE_0_NODEREF.toString()); - request.setType(cmisObjectFactory.createGetChildrenType(EnumTypesOfFileableObjects.ANY)); - - try - { - navigationServicePort.getChildren(request); - } - catch (FolderNotValidException e) - { - return; - } - - fail("Expects exception"); - } - - private void checkListExact(List objects, int expectedFileCount, int expectedFolderCount, NodeRef[] expectedNodeRefs) - { - int fileCount = 0; - int folderCount = 0; - List check = new ArrayList(8); - - for (NodeRef nodeRef : expectedNodeRefs) - { - check.add(nodeRef); - } - - for (CmisObjectType object : objects) - { - NodeRef nodeRef = new NodeRef((String) PropertyUtil.getProperty(object.getProperties(), CMISMapping.PROP_OBJECT_ID)); - - if (cmisMapping.isValidCmisFolder(cmisMapping.getCmisType(nodeService.getType(nodeRef)))) - { - folderCount++; - } - else - { - fileCount++; - } - - assertTrue(check.remove(nodeRef)); - } - - assertTrue("Name list was not exact - remaining: " + check, check.size() == 0); - assertEquals("Incorrect number of files", expectedFileCount, fileCount); - assertEquals("Incorrect number of folders", expectedFolderCount, folderCount); - } - - private void checkList(List objects, int expectedCount, int expectedMaxFileCount, int expectedMaxFolderCount, NodeRef[] expectedNodeRefs) - { - int fileCount = 0; - int folderCount = 0; - List check = new ArrayList(8); - - for (NodeRef nodeRef : expectedNodeRefs) - { - check.add(nodeRef); - } - - for (CmisObjectType object : objects) - { - NodeRef nodeRef = new NodeRef((String) PropertyUtil.getProperty(object.getProperties(), CMISMapping.PROP_OBJECT_ID)); - - if (cmisMapping.isValidCmisFolder(cmisMapping.getCmisType(nodeService.getType(nodeRef)))) - { - folderCount++; - } - else - { - fileCount++; - } - - assertTrue(check.remove(nodeRef)); - } - - assertTrue((fileCount + folderCount) == expectedCount); - assertTrue(fileCount <= expectedMaxFileCount); - assertTrue(folderCount <= expectedMaxFolderCount); - } - -} diff --git a/source/test/java/org/alfresco/repo/cmis/ws/DMNavigationServiceTest.java b/source/test/java/org/alfresco/repo/cmis/ws/DMNavigationServiceTest.java new file mode 100755 index 0000000000..6845b1fed5 --- /dev/null +++ b/source/test/java/org/alfresco/repo/cmis/ws/DMNavigationServiceTest.java @@ -0,0 +1,423 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws; + +import java.math.BigInteger; + +import javax.xml.ws.Holder; + +import org.alfresco.cmis.dictionary.CMISMapping; + +/** + * @author Alexander Tsvetkov + * + */ + +public class DMNavigationServiceTest extends AbstractServiceTest +{ + public DMNavigationServiceTest() + { + super(); + } + + public DMNavigationServiceTest(String testCase, String username, String password) + { + super(testCase, username, password); + } + + @Override + protected void setUp() throws Exception + { + super.setUp(); + createInitialContent(); + } + + @Override + protected void tearDown() throws Exception + { + super.tearDown(); + deleteInitialContent(); + } + + protected Object getServicePort() + { + return helper.navigationServicePort; + } + + public void testGetCheckedoutDocs() throws Exception + { + // check out + Holder documentIdHolder = new Holder(documentId); + Holder contentCopied = new Holder(); + helper.versioningServicePort.checkOut(repositoryId, documentIdHolder, contentCopied); + assertTrue(contentCopied.value); + + String documentName1 = "Test cmis document (" + System.currentTimeMillis() + ")"; + String documentId1 = helper.createDocument(documentName1, folderId); + Holder documentIdHolder1 = new Holder(documentId1); + contentCopied = new Holder(); + helper.versioningServicePort.checkOut(repositoryId, documentIdHolder1, contentCopied); + assertTrue(contentCopied.value); + + GetCheckedoutDocsResponse response; + response = getCheckedoutDocs(null, 0, 0); + + if (response.getObject().size() < 2) + { + // check in + helper.versioningServicePort.checkIn(repositoryId, documentIdHolder, null, null, null, null); + fail("Not all checkout docs have been found"); + } + validateResponse(response.getObject()); + + // assertTrue("Checked out document has not been found ", isExistItemWithProperty(response.getObject(), CMISMapping.PROP_OBJECT_ID, documentId)); + // assertTrue("Checked out document has not been found ", isExistItemWithProperty(response.getObject(), CMISMapping.PROP_OBJECT_ID, documentId1)); + + response = getCheckedoutDocs(null, 1, 0); + assertTrue(response.getObject().size() == 1); + assertTrue(response.hasMoreItems); + + // check in + helper.versioningServicePort.checkIn(repositoryId, documentIdHolder, null, null, null, null); + + response = getCheckedoutDocs(companyHomeId, 0, 0); + assertFalse("Wrong results", isExistItemWithProperty(response.getObject(), CMISMapping.PROP_NAME, documentName)); + + } + + public void testGetChildren() throws Exception + { + GetChildrenResponse response; + response = getChildren(companyHomeId, EnumTypesOfFileableObjects.ANY, 0); + + if ((response != null) && (response.getObject() != null)) + { + validateResponse(response.getObject()); + } + else + { + fail("response is null"); + } + + String folderName1 = "Test Cmis Folder (" + System.currentTimeMillis() + ")"; + String folderId1 = helper.createFolder(folderName1, folderId); + String documentName1 = "Test cmis document (" + System.currentTimeMillis() + ")"; + String documentId1 = helper.createDocument(documentName1, folderId, CMISMapping.DOCUMENT_TYPE_ID, EnumVersioningState.MAJOR); + + response = getChildren(folderId, EnumTypesOfFileableObjects.ANY, 0); + assertEquals(2, response.getObject().size()); + assertTrue(PropertyUtil.getProperty(response.getObject().get(0).getProperties(), CMISMapping.PROP_NAME).equals(folderName1)); + assertTrue(PropertyUtil.getProperty(response.getObject().get(1).getProperties(), CMISMapping.PROP_NAME).equals(documentName1)); + + response = getChildren(folderId, EnumTypesOfFileableObjects.FOLDERS, 0); + assertTrue(response.getObject().size() == 1); + assertTrue(PropertyUtil.getProperty(response.getObject().get(0).getProperties(), CMISMapping.PROP_NAME).equals(folderName1)); + + response = getChildren(folderId, EnumTypesOfFileableObjects.DOCUMENTS, 0); + assertTrue(response.getObject().size() == 1); + assertTrue(PropertyUtil.getProperty(response.getObject().get(0).getProperties(), CMISMapping.PROP_NAME).equals(documentName1)); + + // FIXME: bug • If maxItems > 0, Bool hasMoreItems + // Should return 1 item + response = getChildren(folderId, EnumTypesOfFileableObjects.ANY, 1); + assertTrue("Actual size is: " + response.getObject().size(), response.getObject().size() == 1); + assertTrue(response.hasMoreItems); + + // • If “includeAllowableActions” is TRUE, the repository will return the allowable actions for the current user for each child object as part of the output. + // • "IncludeRelationships" indicates whether relationships are also returned for each returned object. If it is set to "source" or "target", relationships for which the + // returned object is a source, or respectively a target, will also be returned. If it is set to "both", relationships for which the returned object is either a source or a + // target will be returned. If it is set to "none", relationships are not returned. + + // TODO: not implemented + // assertNotNull(response.getObject().get(0).getAllowableActions()); + // assertNotNull(response.getObject().get(0).getRelationship()); + + // filters + // response = getChildren(folderId, EnumTypesOfFileableObjects.DOCUMENTS, 0, CMISMapping.PROP_NAME); + // assertNotNull(PropertyUtil.getProperty(response.getObject().get(0).getProperties(), CMISMapping.PROP_NAME)); + + response = getChildren(folderId); + assertTrue(response.getObject().size() == 2); + + } + + public void testGetDescendants() throws Exception + { + + GetDescendantsResponse response = getDescendants(companyHomeId, EnumTypesOfFileableObjects.DOCUMENTS, 10); + + if ((response != null) && (response.getObject() != null)) + { + validateResponse(response.getObject()); + } + else + { + fail("response is null"); + } + + folderName = "Test Cmis Folder (" + System.currentTimeMillis() + ")"; + String folderId1 = helper.createFolder(folderName, folderId); + documentName = "Test cmis document (" + System.currentTimeMillis() + ")"; + String documentId1 = helper.createDocument(documentName, folderId1, CMISMapping.DOCUMENT_TYPE_ID, EnumVersioningState.MAJOR); + + response = getDescendants(folderId, EnumTypesOfFileableObjects.FOLDERS, 1); + assertTrue(response.getObject().size() == 1); + assertTrue(PropertyUtil.getProperty(response.getObject().get(0).getProperties(), CMISMapping.PROP_NAME).equals(folderName)); + + response = getDescendants(folderId, EnumTypesOfFileableObjects.DOCUMENTS, 2); + assertTrue(response.getObject().size() == 1); + assertTrue(PropertyUtil.getProperty(response.getObject().get(0).getProperties(), CMISMapping.PROP_NAME).equals(documentName)); + + response = getDescendants(folderId, EnumTypesOfFileableObjects.ANY, 2); + assertTrue(response.getObject().size() == 2); + assertTrue(PropertyUtil.getProperty(response.getObject().get(0).getProperties(), CMISMapping.PROP_NAME).equals(folderName)); + assertTrue(PropertyUtil.getProperty(response.getObject().get(1).getProperties(), CMISMapping.PROP_NAME).equals(documentName)); + + response = getDescendants(folderId, EnumTypesOfFileableObjects.ANY, -1); + assertTrue(response.getObject().size() == 2); + + // test with out option parameters + response = getDescendants(folderId); + assertTrue(response.getObject().size() == 1); + + response = getDescendants(folderId, EnumTypesOfFileableObjects.DOCUMENTS, 2); + // TODO: not implemented + // assertNotNull(response.getObject().get(0).getAllowableActions()); + // assertNotNull(response.getObject().get(0).getRelationship()); + + // Filter test + // response = getDescendants(folderId, EnumTypesOfFileableObjects.DOCUMENTS, 2, CMISMapping.PROP_NAME); + // assertTrue(response.getObject().size() == 1); + // assertTrue(PropertyUtil.getProperty(response.getObject().get(0).getProperties(), CMISMapping.PROP_NAME).equals(documentName)); + + helper.deleteFolder(folderId1); + + } + + public void testGetFolderParent() throws Exception + { + GetFolderParentResponse response; + response = getFolderParent(folderId, false); + + if ((response != null) && (response.getObject() != null)) + { + validateResponse(response.getObject()); + } + else + { + fail("response is null"); + } + + String folderId1; + + String folderName1 = "Test Cmis Folder (" + System.currentTimeMillis() + ")"; + folderId1 = helper.createFolder(folderName1, folderId); + + response = getFolderParent(folderId1, false); + assertTrue(PropertyUtil.getProperty(response.getObject().get(0).getProperties(), CMISMapping.PROP_NAME).equals(folderName)); + + String folderName2 = "Test Cmis Folder (" + System.currentTimeMillis() + ")"; + String folderId2 = helper.createFolder(folderName2, folderId1); + + response = getFolderParent(folderId2, true); + assertTrue(PropertyUtil.getProperty(response.getObject().get(0).getProperties(), CMISMapping.PROP_NAME).equals(folderName1)); + assertTrue(PropertyUtil.getProperty(response.getObject().get(1).getProperties(), CMISMapping.PROP_NAME).equals(folderName)); + assertTrue(response.getObject().size() >= 3); + + } + + public void testGetObjectParents() throws Exception + { + GetObjectParentsResponse response = helper.getObjectParents(documentId, "*"); + + if ((response != null) && (response.getObject() != null)) + { + validateResponse(response.getObject()); + } + else + { + fail("response is null"); + } + + String folderId1; + String documentId1; + + String folderName1 = "Test Cmis Folder (" + System.currentTimeMillis() + ")"; + folderId1 = helper.createFolder(folderName1, folderId); + String documentName1 = "Test cmis document (" + System.currentTimeMillis() + ")"; + documentId1 = helper.createDocument(documentName1, folderId1, CMISMapping.DOCUMENT_TYPE_ID, EnumVersioningState.MAJOR); + + response = helper.getObjectParents(documentId1, "*"); + assertTrue(response.getObject().size() == 1); + assertTrue(PropertyUtil.getProperty(response.getObject().get(0).getProperties(), CMISMapping.PROP_NAME).equals(folderName1)); + + // TODO: not implemented + // assertNotNull(response.getObject().get(0).getAllowableActions()); + // assertNotNull(response.getObject().get(0).getRelationship()); + + // filters + // response = getObjectParents(documentId1, CMISMapping.PROP_NAME); + // assertTrue(response.getObject().size() >= 2); + // assertNotNull(PropertyUtil.getProperty(response.getObject().get(0).getProperties(), CMISMapping.PROP_NAME)); + + response = helper.getObjectParents(documentId1); + assertTrue(response.getObject().size() == 1); + assertTrue(PropertyUtil.getProperty(response.getObject().get(0).getProperties(), CMISMapping.PROP_NAME).equals(folderName1)); + // assertTrue(PropertyUtil.getProperty(response.getObject().get(1).getProperties(), CMISMapping.PROP_NAME).equals(folderName)); + + } + + private GetDescendantsResponse getDescendants(String folderId, EnumTypesOfFileableObjects type, long depth) throws Exception + { + GetDescendants request = cmisObjectFactory.createGetDescendants(); + + request.setRepositoryId(repositoryId); + request.setFolderId(folderId); + request.setType(type); + request.setDepth(cmisObjectFactory.createGetDescendantsDepth(BigInteger.valueOf(depth))); + request.setFilter(cmisObjectFactory.createGetPropertiesFilter("*")); + request.setIncludeAllowableActions(cmisObjectFactory.createGetDescendantsIncludeAllowableActions(true)); + request.setIncludeRelationships(cmisObjectFactory.createGetDescendantsIncludeRelationships(true)); + + GetDescendantsResponse response = ((NavigationServicePort) servicePort).getDescendants(request); + return response; + } + + private GetDescendantsResponse getDescendants(String folderId) throws Exception + { + GetDescendants request = cmisObjectFactory.createGetDescendants(); + + request.setRepositoryId(repositoryId); + request.setFolderId(folderId); + + GetDescendantsResponse response = ((NavigationServicePort) servicePort).getDescendants(request); + return response; + } + + private GetChildrenResponse getChildren(String folderId, EnumTypesOfFileableObjects type, long maxItems) throws Exception + { + + GetChildren request = cmisObjectFactory.createGetChildren(); + + request.setRepositoryId(repositoryId); + request.setFolderId(folderId); + + request.setFilter(cmisObjectFactory.createGetChildrenFilter("*")); + request.setMaxItems(cmisObjectFactory.createGetChildrenMaxItems(BigInteger.valueOf(maxItems))); + request.setSkipCount(cmisObjectFactory.createGetChildrenSkipCount(BigInteger.valueOf(0))); + request.setType(cmisObjectFactory.createGetChildrenType(type)); + + GetChildrenResponse response = ((NavigationServicePort) servicePort).getChildren(request); + + return response; + } + + private GetChildrenResponse getChildren(String folderId) throws Exception + { + + GetChildren request = cmisObjectFactory.createGetChildren(); + + request.setRepositoryId(repositoryId); + request.setFolderId(folderId); + + GetChildrenResponse response = ((NavigationServicePort) servicePort).getChildren(request); + + return response; + } + + public GetFolderParentResponse getFolderParent(String folderId, boolean setReturnToRoot) throws Exception + { + GetFolderParent request = cmisObjectFactory.createGetFolderParent(); + + request.setRepositoryId(repositoryId); + + request.setFolderId(folderId); + + request.setFilter("*"); + request.setReturnToRoot(cmisObjectFactory.createGetFolderParentReturnToRoot(setReturnToRoot)); + + request.setIncludeAllowableActions(cmisObjectFactory.createGetFolderParentIncludeAllowableActions(true)); + request.setIncludeRelationships(cmisObjectFactory.createGetFolderParentIncludeRelationships(true)); + + GetFolderParentResponse response = ((NavigationServicePort) servicePort).getFolderParent(request); + return response; + } + + public GetFolderParentResponse getFolderParent(String folderId, String filter) throws Exception + { + GetFolderParent request = cmisObjectFactory.createGetFolderParent(); + + request.setRepositoryId(repositoryId); + + request.setFolderId(folderId); + + request.setFilter(filter); + + request.setIncludeAllowableActions(cmisObjectFactory.createGetFolderParentIncludeAllowableActions(true)); + request.setIncludeRelationships(cmisObjectFactory.createGetFolderParentIncludeRelationships(true)); + + GetFolderParentResponse response = null; + try + { + response = ((NavigationServicePort) servicePort).getFolderParent(request); + } + catch (FilterNotValidException e) + { + fail(e.getMessage()); + } + return response; + } + + public GetFolderParentResponse getFolderParent(String folderId) throws Exception + { + GetFolderParent request = cmisObjectFactory.createGetFolderParent(); + + request.setRepositoryId(repositoryId); + request.setFolderId(folderId); + + GetFolderParentResponse response = ((NavigationServicePort) servicePort).getFolderParent(request); + + return response; + } + + private GetCheckedoutDocsResponse getCheckedoutDocs(String folderId, long maxItems, long skipCount) throws Exception + { + GetCheckedoutDocs request = cmisObjectFactory.createGetCheckedoutDocs(); + + request.setRepositoryId(repositoryId); + + request.setFolderID(cmisObjectFactory.createGetCheckedoutDocsFolderID(folderId)); + request.setFilter(cmisObjectFactory.createGetCheckedoutDocsFilter("*")); + request.setMaxItems(cmisObjectFactory.createGetCheckedoutDocsMaxItems(BigInteger.valueOf(maxItems))); + request.setSkipCount(cmisObjectFactory.createGetCheckedoutDocsSkipCount(BigInteger.valueOf(skipCount))); + + request.setIncludeAllowableActions(cmisObjectFactory.createGetCheckedoutDocsIncludeAllowableActions(true)); + request.setIncludeRelationships(cmisObjectFactory.createGetCheckedoutDocsIncludeRelationships(true)); + + GetCheckedoutDocsResponse response = ((NavigationServicePort) servicePort).getCheckedoutDocs(request); + + return response; + } +} diff --git a/source/test/java/org/alfresco/repo/cmis/ws/DMObjectServicePortTest.java b/source/test/java/org/alfresco/repo/cmis/ws/DMObjectServicePortTest.java deleted file mode 100644 index b17612007e..0000000000 --- a/source/test/java/org/alfresco/repo/cmis/ws/DMObjectServicePortTest.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2005-2008 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 - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" - */ -package org.alfresco.repo.cmis.ws; - -import java.util.List; - -import org.alfresco.cmis.dictionary.CMISMapping; -import org.alfresco.service.cmr.repository.NodeRef; - -/** - * @see org.alfresco.repo.cmis.ws.ObjectServicePortDM - * - * @author Dmitry Lazurkin - */ -public class DMObjectServicePortTest extends BaseServicePortContentTest -{ - private ObjectServicePort objectServicePort; - private RepositoryServicePort repositoryServicePort; - - @Override - protected void onSetUp() throws Exception - { - super.onSetUp(); - - repositoryServicePort = (RepositoryServicePort) applicationContext.getBean("dmRepositoryService"); - objectServicePort = (ObjectServicePort) applicationContext.getBean("dmObjectService"); - } - - public void testGetExistentFolderProperties() throws Exception - { - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - GetProperties request = new GetProperties(); - request.setRepositoryId(repositoryId); - request.setObjectId(L0_FOLDER_0_NODEREF.toString()); - - GetPropertiesResponse response = objectServicePort.getProperties(request); - assertNotNull(response); - assertEquals(rootNodeRef.toString(), PropertyUtil.getProperty(response.getObject().getProperties(), CMISMapping.PROP_PARENT_ID)); - assertEquals(L0_FOLDER_0, PropertyUtil.getProperty(response.getObject().getProperties(), CMISMapping.PROP_NAME)); - } - - public void testGetExistentDocumentPropertiesThis() throws Exception - { - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - GetProperties request = new GetProperties(); - request.setRepositoryId(repositoryId); - request.setObjectId(L1_FILE_VERSION_1_0_NODEREF.toString()); - - GetPropertiesResponse response = objectServicePort.getProperties(request); - assertNotNull(response); - assertEquals(PropertyUtil.getProperty(response.getObject().getProperties(), CMISMapping.PROP_CHECKIN_COMMENT), "1.0"); - assertTrue((Boolean) PropertyUtil.getProperty(response.getObject().getProperties(), CMISMapping.PROP_IS_MAJOR_VERSION)); - } - - public void testGetExistentDocumentPropertiesLatestMajor() throws Exception - { - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - GetProperties request = new GetProperties(); - request.setRepositoryId(repositoryId); - request.setReturnVersion(cmisObjectFactory.createGetPropertiesReturnVersion(EnumReturnVersion.LATESTMAJOR)); - request.setObjectId(L1_FILE_VERSION_1_0_NODEREF.toString()); - - GetPropertiesResponse response = objectServicePort.getProperties(request); - assertNotNull(response); - assertEquals(PropertyUtil.getProperty(response.getObject().getProperties(), CMISMapping.PROP_CHECKIN_COMMENT), "2.0"); - assertTrue((Boolean) PropertyUtil.getProperty(response.getObject().getProperties(), CMISMapping.PROP_IS_MAJOR_VERSION)); - } - - public void testGetExistentDocumentPropertiesLatest() throws Exception - { - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - GetProperties request = new GetProperties(); - request.setRepositoryId(repositoryId); - request.setReturnVersion(cmisObjectFactory.createGetPropertiesReturnVersion(EnumReturnVersion.LATEST)); - request.setObjectId(L1_FILE_VERSION_2_0_NODEREF.toString()); - - GetPropertiesResponse response = objectServicePort.getProperties(request); - assertNotNull(response); - assertEquals(PropertyUtil.getProperty(response.getObject().getProperties(), CMISMapping.PROP_CHECKIN_COMMENT), "2.1"); - assertFalse((Boolean) PropertyUtil.getProperty(response.getObject().getProperties(), CMISMapping.PROP_IS_MAJOR_VERSION)); - } - - public void testGetNonExistentObjectProperties() throws Exception - { - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - GetProperties request = new GetProperties(); - request.setRepositoryId(repositoryId); - request.setObjectId(L0_NONEXISTENT_NODEREF.toString()); - try - { - objectServicePort.getProperties(request); - } - catch (ObjectNotFoundException e) - { - return; - } - - fail("Expects exception"); - } - - public void testGetPropertiesForInvalidOID() throws Exception - { - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - GetProperties request = new GetProperties(); - request.setRepositoryId(repositoryId); - request.setObjectId("invalid OID"); - - try - { - objectServicePort.getProperties(request); - } - catch (InvalidArgumentException e) - { - return; - } - - fail("Expects exception"); - } - - public void testGetPropertiesCheckedout() throws Exception - { - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - NodeRef workingCopyNodeRef = checkOutCheckInService.checkout(L0_FILE_0_NODEREF); - - GetProperties request = new GetProperties(); - request.setRepositoryId(repositoryId); - request.setObjectId(L0_FILE_0_NODEREF.toString()); - - GetPropertiesResponse response = objectServicePort.getProperties(request); - assertNotNull(response); - - assertNull(PropertyUtil.getProperty(response.getObject().getProperties(), CMISMapping.PROP_CHECKIN_COMMENT)); - assertTrue((Boolean) PropertyUtil.getProperty(response.getObject().getProperties(), CMISMapping.PROP_IS_VERSION_SERIES_CHECKED_OUT)); - assertEquals(PropertyUtil.getProperty(response.getObject().getProperties(), CMISMapping.PROP_VERSION_SERIES_CHECKED_OUT_BY), authenticationComponent.getSystemUserName()); - assertEquals(PropertyUtil.getProperty(response.getObject().getProperties(), CMISMapping.PROP_VERSION_SERIES_CHECKED_OUT_ID), workingCopyNodeRef.toString()); - - request = new GetProperties(); - request.setRepositoryId(repositoryId); - request.setObjectId(workingCopyNodeRef.toString()); - - response = objectServicePort.getProperties(request); - assertNotNull(response); - assertNull(PropertyUtil.getProperty(response.getObject().getProperties(), CMISMapping.PROP_CHECKIN_COMMENT)); - assertTrue((Boolean) PropertyUtil.getProperty(response.getObject().getProperties(), CMISMapping.PROP_IS_VERSION_SERIES_CHECKED_OUT)); - assertEquals(PropertyUtil.getProperty(response.getObject().getProperties(), CMISMapping.PROP_VERSION_SERIES_CHECKED_OUT_BY), authenticationComponent.getSystemUserName()); - assertEquals(PropertyUtil.getProperty(response.getObject().getProperties(), CMISMapping.PROP_VERSION_SERIES_CHECKED_OUT_ID), workingCopyNodeRef.toString()); - } - - public void testGetContentStream() throws Exception - { - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - List repositories = repositoryServicePort.getRepositories(); - String documentId = L0_FILE_0_NODEREF.toString(); - CmisContentStreamType result = objectServicePort.getContentStream(repositories.get(0).getRepositoryID(), documentId); - assertNotNull(result); - if (result.getLength().intValue() != 9) - { - fail(); - } - - try - { - result = objectServicePort.getContentStream(repositories.get(0).getRepositoryID(), documentId + "s"); - } - catch (ObjectNotFoundException e) - { - } - catch (Throwable e) - { - fail(); - } - } - -} \ No newline at end of file diff --git a/source/test/java/org/alfresco/repo/cmis/ws/DMObjectServiceTest.java b/source/test/java/org/alfresco/repo/cmis/ws/DMObjectServiceTest.java index a3e50298ef..342c0762bb 100644 --- a/source/test/java/org/alfresco/repo/cmis/ws/DMObjectServiceTest.java +++ b/source/test/java/org/alfresco/repo/cmis/ws/DMObjectServiceTest.java @@ -15,68 +15,233 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ package org.alfresco.repo.cmis.ws; -import java.net.MalformedURLException; -import java.net.URL; +import java.math.BigInteger; +import java.util.List; -import javax.xml.namespace.QName; -import javax.xml.ws.Service; +import javax.activation.DataHandler; +import javax.xml.ws.Holder; + +import org.alfresco.cmis.dictionary.CMISMapping; +import org.alfresco.repo.content.MimetypeMap; + +/** + * @author Alexander Tsvetkov + * + */ public class DMObjectServiceTest extends AbstractServiceTest { + GetPropertiesResponse propertiesResponse; - public final static String SERVICE_WSDL_LOCATION = "http://localhost:8080/alfresco/cmis/ObjectService?wsdl"; - public final static QName SERVICE_NAME = new QName("http://www.cmis.org/ns/1.0", "ObjectService"); - - - private RepositoryServicePort repositoryServicePort; + public DMObjectServiceTest() + { + super(); + } + + public DMObjectServiceTest(String testCase, String username, String password) + { + super(testCase, username, password); + } @Override protected void setUp() throws Exception { super.setUp(); - - repositoryServicePort = (RepositoryServicePort) fContext.getBean("dmRepositoryService"); - } - - protected Object getServicePort() - { - URL serviceWsdlURL; - try - { - serviceWsdlURL = new URL(SERVICE_WSDL_LOCATION); - } - catch (MalformedURLException e) - { - throw new java.lang.RuntimeException("Cannot get service Wsdl URL", e); - } - Service service = Service.create(serviceWsdlURL, SERVICE_NAME); - - return service.getPort(ObjectServicePort.class); + createInitialContent(); } + @Override + protected void tearDown() throws Exception + { + super.tearDown(); + deleteInitialContent(); + } + + protected Object getServicePort() + { + return helper.objectServicePort; + } + + public void testCreateDocument() throws Exception + { + + documentName = "Test cmis document (" + System.currentTimeMillis() + ")"; + + String content = "This is a test content"; + // Cmis Properties + CmisPropertiesType properties = new CmisPropertiesType(); + List propertiesList = properties.getProperty(); + CmisPropertyString cmisProperty = new CmisPropertyString(); + cmisProperty.setName(CMISMapping.PROP_NAME); + cmisProperty.setValue(documentName); + propertiesList.add(cmisProperty); + + CmisContentStreamType cmisStream = new CmisContentStreamType(); + cmisStream.setFilename(documentName); + cmisStream.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + + DataHandler dataHandler = new DataHandler(content, MimetypeMap.MIMETYPE_TEXT_PLAIN); + cmisStream.setStream(dataHandler); + + // public String helper.createDocument(String repositoryId, String typeId, CmisPropertiesType properties, String folderId, CmisContentStreamType contentStream, + // EnumVersioningState versioningState) + + String documentId; + // MAJOR + documentName = "Test cmis document (" + System.currentTimeMillis() + ")"; + documentId = helper.createDocument(documentName, folderId, CMISMapping.DOCUMENT_TYPE_ID, EnumVersioningState.MAJOR); + propertiesResponse = helper.getObjectProperties(documentId); + // assertTrue(getPropertyBooleanValue(propertiesResponse, CMISMapping.PROP_IS_MAJOR_VERSION)); + assertFalse(getPropertyBooleanValue(propertiesResponse, CMISMapping.PROP_IS_VERSION_SERIES_CHECKED_OUT)); + helper.deleteDocument(documentId); + + // MINOR + documentName = "Test cmis document (" + System.currentTimeMillis() + ")"; + documentId = helper.createDocument(documentName, folderId, CMISMapping.DOCUMENT_TYPE_ID, EnumVersioningState.MINOR); + propertiesResponse = helper.getObjectProperties(documentId); + assertFalse(getPropertyBooleanValue(propertiesResponse, CMISMapping.PROP_IS_VERSION_SERIES_CHECKED_OUT)); + // assertTrue(getPropertyBooleanValue(propertiesResponse, CMISMapping.PROP_IS_MAJOR_VERSION)); + helper.deleteDocument(documentId); + + } + + public void testCreateDocument_Versioning() throws Exception + { + // CHECKEDOUT + documentName = "Test cmis document (" + System.currentTimeMillis() + ")"; + String documentId = helper.createDocument(documentName, folderId, CMISMapping.DOCUMENT_TYPE_ID, EnumVersioningState.CHECKEDOUT); + propertiesResponse = helper.getObjectProperties(documentId); + assertNotNull(getPropertyValue(propertiesResponse, CMISMapping.PROP_VERSION_SERIES_ID)); + // Bug + assertTrue(getPropertyBooleanValue(propertiesResponse, CMISMapping.PROP_IS_VERSION_SERIES_CHECKED_OUT)); + assertNotNull(getPropertyValue(propertiesResponse, CMISMapping.PROP_VERSION_SERIES_CHECKED_OUT_BY)); + assertTrue(getPropertyValue(propertiesResponse, CMISMapping.PROP_VERSION_SERIES_CHECKED_OUT_ID).equals(documentId)); + + Holder documentIdHolder = new Holder(documentId); + helper.checkIn(documentIdHolder, "checkin Comment", true); + assertTrue(getPropertyValue(propertiesResponse, CMISMapping.PROP_VERSION_LABEL).equals("1.0")); + + // documentId = (String) PropertyUtil.getProperty(response.getObject().iterator().next().getProperties(), CMISMapping.PROP_OBJECT_ID); + // deleteDocument(documentId); + } + + public void testCreateDocument_Exceptions() throws Exception + { + // • If unfiling is not supported and a Folder is not specified, throw FolderNotValidException. + try + { + documentName = "Test cmis document (" + System.currentTimeMillis() + ")"; + documentId = helper.createDocument(documentName, null, CMISMapping.DOCUMENT_TYPE_ID, EnumVersioningState.MAJOR); + fail(); + } + catch (FolderNotValidException e) + { + + } + catch (Exception e) + { // Bug + e.printStackTrace(); // org.alfresco.repo.cmis.ws.RuntimeException: Runtime error. Message: null + fail(e.getMessage()); + } + } + + public void testCreateFolder() throws Exception + { + String folderId1; + folderName = "Test Cmis Folder (" + System.currentTimeMillis() + ")" + "testCreateFolder"; + folderId1 = helper.createFolder(folderName, folderId, CMISMapping.FOLDER_TYPE_ID); + + propertiesResponse = helper.getObjectProperties(folderId1); + assertNotNull(getPropertyValue(propertiesResponse, CMISMapping.PROP_NAME)); + assertNotNull(getPropertyValue(propertiesResponse, CMISMapping.PROP_PARENT_ID)); + + helper.deleteFolder(folderId1); + } public void testGetDocumentProperties() throws Exception { - GetProperties request = new GetProperties(); - request.setObjectId(ALFRESCO_TUTORIAL_NODE_REF.toString()); - request.setRepositoryId(repositoryServicePort.getRepositories().get(0).getRepositoryID()); - - GetPropertiesResponse response = ((ObjectServicePort) servicePort).getProperties(request); - assertNotNull(response); + String filter; + filter = "*"; + propertiesResponse = helper.getObjectProperties(documentId, filter); + assertNotNull(getPropertyValue(propertiesResponse, CMISMapping.PROP_NAME)); + assertNotNull(getPropertyValue(propertiesResponse, CMISMapping.PROP_CONTENT_STREAM_FILENAME)); + assertNotNull(getPropertyValue(propertiesResponse, CMISMapping.PROP_CONTENT_STREAM_MIME_TYPE)); + assertTrue(getPropertyBooleanValue(propertiesResponse, CMISMapping.PROP_IS_LATEST_VERSION)); + + // A property filter is a string that contains either ‘*’ (to return all properties) or a comma-separated list of property names (to return selected properties). An + // arbitrary number of spaces are allowed before or after each comma. + + // filter = "*Stream*"; + // propertiesResponse = helper.getObjectProperties(documentId, filter); + // assertNotNull("filter test", getPropertyValue(propertiesResponse, CMISMapping.PROP_NAME)); + // assertNotNull("filter test", getPropertyValue(propertiesResponse, CMISMapping.PROP_CONTENT_STREAM_LENGTH)); + + } + + public void testGetDocumentProperties_Versioning() throws Exception + { + GetPropertiesResponse response = helper.getObjectProperties(documentId); + + Holder documentIdHolder = new Holder(documentId); + Holder contentCopied = new Holder(); + String checkinComment = "Test checkin" + System.currentTimeMillis(); + + helper.checkOut(documentIdHolder, contentCopied); + // new version of doc + response = helper.getObjectProperties(documentIdHolder.value); + assertNotNull(getPropertyValue(response, CMISMapping.PROP_NAME)); + assertNotNull(getPropertyValue(response, CMISMapping.PROP_CONTENT_STREAM_FILENAME)); + assertNotNull(getPropertyValue(response, CMISMapping.PROP_CONTENT_STREAM_MIME_TYPE)); + assertTrue(getPropertyBooleanValue(response, CMISMapping.PROP_IS_VERSION_SERIES_CHECKED_OUT)); + assertNotNull(getPropertyValue(response, CMISMapping.PROP_VERSION_SERIES_CHECKED_OUT_BY)); + + helper.checkIn(documentIdHolder, checkinComment, true); + + response = helper.getObjectProperties(documentId); + assertNotNull(getPropertyValue(response, CMISMapping.PROP_NAME)); + assertNotNull(getPropertyValue(response, CMISMapping.PROP_CONTENT_STREAM_FILENAME)); + assertNotNull(getPropertyValue(response, CMISMapping.PROP_CONTENT_STREAM_MIME_TYPE)); + assertTrue(getPropertyBooleanValue(response, CMISMapping.PROP_IS_LATEST_VERSION)); + assertTrue(getPropertyBooleanValue(response, CMISMapping.PROP_IS_LATEST_MAJOR_VERSION)); + assertTrue(getPropertyBooleanValue(response, CMISMapping.PROP_IS_MAJOR_VERSION)); + + // Returns the list of all document versions for the specified version series, sorted by CREATION_DATE descending. + GetAllVersionsResponse responseVersions = helper.getAllVersions(documentId); + + // Last version + + assertEquals(3, responseVersions.getObject().size()); + assertTrue("Initial version was not returned", isExistItemWithProperty(responseVersions.getObject(), CMISMapping.PROP_VERSION_LABEL, "1.0")); + assertTrue("Invalid response ordering: First object is not latest version", (Boolean) PropertyUtil.getProperty(responseVersions.getObject().get(0).getProperties(), CMISMapping.PROP_IS_LATEST_VERSION)); + assertTrue("Invalid response ordering: Second object is not head version", (Boolean) PropertyUtil.getProperty(responseVersions.getObject().get(1).getProperties(), CMISMapping.PROP_IS_LATEST_VERSION)); + } + + // This test don't asserts until CMIS setProperty()/setProperties() logic is unimplemented + public void testGetDocumentProperties_Other() throws Exception + { + // • If “includeAllowableActions” is TRUE, the repository will return the allowable actions for the current user for the object as part of the output. + // • "IncludeRelationships" indicates whether relationships are also returned for the object. If it is set to "source" or "target", relationships for which the returned + // object is a source, or respectively a target, will also be returned. If it is set to "both", relationships for which the returned object is either a source or a target + // will be returned. If it is set to "none", relationships are not returned. + + GetPropertiesResponse response = helper.getObjectProperties(documentId); + CmisObjectType object = response.getObject(); + // TODO: not implemented + // assertNotNull(object.getAllowableActions()); + // assertNotNull(object.getRelationship()); } public void testGetPropertiesForInvalidOID() throws Exception { - GetProperties request = new GetProperties(); request.setObjectId("invalid OID"); request.setRepositoryId("invalid OID"); @@ -92,36 +257,462 @@ public class DMObjectServiceTest extends AbstractServiceTest fail("Expects exception"); } - - public void testGetContentStream() throws Exception { - String documentId = ALFRESCO_TUTORIAL_NODE_REF.toString(); - String repoId = repositoryServicePort.getRepositories().get(0).getRepositoryID(); - GetContentStream contStream = new GetContentStream(); contStream.setDocumentId(documentId); - contStream.setRepositoryId(repoId); - - CmisContentStreamType result = ((ObjectServicePort) servicePort).getContentStream(repoId, documentId); - if (result.length.intValue() == 0) + contStream.setRepositoryId(repositoryId); + + CmisContentStreamType result = ((ObjectServicePort) servicePort).getContentStream(repositoryId, documentId); + if (result.getLength().intValue() == 0) { fail(); } - try { contStream.setDocumentId(documentId + "s"); { - result = ((ObjectServicePort) servicePort).getContentStream(repoId, documentId); + result = ((ObjectServicePort) servicePort).getContentStream(repositoryId, documentId); } } - catch (ObjectNotFoundException e) + catch (InvalidArgumentException e) { } catch (Throwable e) { + e.printStackTrace(); fail(); } + + // Content Stream of checked out doc + Holder documentIdHolder = new Holder(documentId); + Holder contentCopied = new Holder(); + String checkinComment = "Test checkin" + System.currentTimeMillis(); + + helper.checkOut(documentIdHolder, contentCopied); + + result = ((ObjectServicePort) servicePort).getContentStream(repositoryId, documentIdHolder.value); + if (result.getLength().intValue() == 0) + { + fail(); + } + + helper.checkIn(documentIdHolder, checkinComment, true); + } -} + + // this method is not implemented yet + public void testCreatePolicy() throws Exception + { + CreatePolicy request = cmisObjectFactory.createCreatePolicy(); + + request.setRepositoryId(repositoryId); + request.setFolderId(cmisObjectFactory.createCreatePolicyFolderId(companyHomeId)); + // there is no CMISMapping.POLICY_TYPE_ID + request.setTypeId("policy"); + + CmisPropertiesType properties = new CmisPropertiesType(); + List propertiesList = properties.getProperty(); + + CmisPropertyString cmisProperty = new CmisPropertyString(); + cmisProperty.setName(CMISMapping.PROP_NAME); + cmisProperty.setPropertyType(EnumPropertyType.STRING); + cmisProperty.setIndex(BigInteger.valueOf(1)); + cmisProperty.setValue("Cmis Test Policy"); + propertiesList.add(cmisProperty); + request.setProperties(properties); + + // TODO: not implemented + // String createPolicy(String repositoryId, String typeId, CmisPropertiesType properties, String folderId) + String response = ((ObjectServicePort) servicePort).createPolicy(repositoryId, request.getTypeId(), request.getProperties(), companyHomeId); + + // assertNotNull(response); + } + + public void testCreateRelationship() throws Exception + { + // TODO: uncomment + // String name = "Cmis Test Relationship"; + // String objectId = null; + // try + // { + // objectId = helper.createRelationship(name, folderId, documentId); + // } + // catch (Exception e) + // { + // fail(e.getMessage()); + // } + // + // GetPropertiesResponse response = helper.getObjectProperties(objectId); + // assertEquals(name, getPropertyValue(response, CMISMapping.PROP_NAME)); + // + // helper.deleteFolder(folderId); + // + // response = helper.getObjectProperties(documentId); + // assertNull(response); + } + + public void testDeleteContentStream() throws Exception + { + // public void deleteContentStream(String repositoryId, String documentId) + ((ObjectServicePort) servicePort).deleteContentStream(repositoryId, documentId); + + try + { + CmisContentStreamType result = ((ObjectServicePort) servicePort).getContentStream(repositoryId, documentId); + } + catch (StorageException e) + { + } + catch (Exception e) + { + e.printStackTrace(); // org.alfresco.repo.cmis.ws.StorageException: The specified Document has no Content Stream + fail(e.getMessage()); + } + + // on content update and on content delete new version should be created + GetAllVersionsResponse responseVersions = helper.getAllVersions(documentId); + assertTrue("new version of document should be created", responseVersions.getObject().size() > 1); + + } + + public void testDeleteObject() throws Exception + { + // public void deleteObject(String repositoryId, String objectId) + ((ObjectServicePort) servicePort).deleteObject(repositoryId, documentId); + assertNull(helper.getObjectProperties(documentId)); + } + + public void testDeleteObject_Exceptions() throws Exception + { + // • If the object is a Folder with at least one child, throw ConstraintViolationException. + // • If the object is the Root Folder, throw OperationNotSupportedException. + + documentName = "Test cmis document (" + System.currentTimeMillis() + ")"; + String documentId = helper.createDocument(documentName, folderId); + + // Try to delere folder with child + try + { + ((ObjectServicePort) servicePort).deleteObject(repositoryId, folderId); + fail("Try to delere folder with child"); + } + catch (ConstraintViolationException e) + { + } + catch (Exception e) + { + e.printStackTrace(); + fail(e.getClass().getName() + ": " + e.getMessage()); + } + + // Try to delere root folder + try + { + ((ObjectServicePort) servicePort).deleteObject(repositoryId, helper.getCompanyHomeId(repositoryId)); + fail("Try to delere root folder"); + } + catch (OperationNotSupportedException e) + { + } + catch (Exception e) + { + e.printStackTrace();// org.alfresco.repo.cmis.ws.ConstraintViolationException: Could not delete folder with at least one Child + fail(e.getClass().getName() + ": " + e.getMessage()); + } + + } + + public void testDeleteTree() throws Exception + { + String folderName; + String folderId1; + String folderId2; + String documentId2; + + folderName = "Test Cmis Folder (" + System.currentTimeMillis() + ")"; + folderId1 = helper.createFolder(folderName, folderId); + + folderName = "Test Cmis Folder (" + System.currentTimeMillis() + ")"; + folderId2 = helper.createFolder(folderName, folderId1); + + documentName = "Test cmis document (" + System.currentTimeMillis() + ")"; + documentId2 = helper.createDocument(documentName, folderId2); + + // public FailedToDelete deleteTree(String repositoryId, String folderId, EnumUnfileNonfolderObjects unfileNonfolderObjects, Boolean continueOnFailure) + DeleteTreeResponse.FailedToDelete response = ((ObjectServicePort) servicePort).deleteTree(repositoryId, folderId1, EnumUnfileNonfolderObjects.DELETE, true); + assertTrue("All objects should be deleted", response.getObjectId().size() == 0); + + assertNull("DELETE", helper.getObjectProperties(folderId1)); + assertNull("DELETE", helper.getObjectProperties(folderId2)); + assertNull("DELETE", helper.getObjectProperties(documentId2)); + + // Check DELETESINGLEFILED + folderName = "Test Cmis Folder (" + System.currentTimeMillis() + ")"; + folderId1 = helper.createFolder(folderName, folderId); + + folderName = "Test Cmis Folder (" + System.currentTimeMillis() + ")"; + folderId2 = helper.createFolder(folderName, folderId1); + + documentName = "Test cmis document (" + System.currentTimeMillis() + ")"; + documentId2 = helper.createDocument(documentName, folderId2); + + response = ((ObjectServicePort) servicePort).deleteTree(repositoryId, folderId1, EnumUnfileNonfolderObjects.DELETESINGLEFILED, true); + // assertNotNull("DELETESINGLEFILED", response); + assertTrue("All objects should not be deleted", response.getObjectId().size() != 0); + assertNotNull("DELETESINGLEFILED", helper.getObjectProperties(folderId1)); + assertNotNull("DELETESINGLEFILED", helper.getObjectProperties(folderId2)); + assertNotNull("DELETESINGLEFILED", helper.getObjectProperties(documentId2)); + + helper.deleteFolder(folderId1); + + /* + // on DELETESINGLEFILED deletes only relationships and folder. Primary parent folder and contend should not be deleted + folderName = "Test Cmis Folder (" + System.currentTimeMillis() + ")"; + folderId1 = helper.createFolder(folderName, folderId); + + folderName = "Test Cmis Folder (" + System.currentTimeMillis() + ")"; + folderId2 = helper.createFolder(folderName, companyHomeId); + + documentName = "Test cmis document (" + System.currentTimeMillis() + ")"; + documentId2 = helper.createDocument(documentName, folderId2); + + String relationshipId = createRelationship("test relashionship", folderId1, documentId2); + + response = ((ObjectServicePort) servicePort).deleteTree(repositoryId, folderId1, EnumUnfileNonfolderObjects.DELETESINGLEFILED, true); + assertNotNull("DELETESINGLEFILED", response); + + assertNull("DELETESINGLEFILED", helper.getObjectProperties(folderId1)); + assertNull("DELETESINGLEFILED", helper.getObjectProperties(relationshipId)); + + assertNotNull("DELETESINGLEFILED", helper.getObjectProperties(folderId2)); + assertNotNull("DELETESINGLEFILED", helper.getObjectProperties(documentId2)); + + deleteFolder(folderId2); + + // response = ((ObjectServicePort) servicePort).deleteTree(repositoryId, folderId, EnumUnfileNonfolderObjects.UNFILE, true); + // assertNotNull("UNFILE", response); + // + // assertNull(getObjectProperties(folderId)); + + // deleteFolder(folderId); + * + */ + } + + public void testDeleteTree_Exceptions() throws Exception + { + // Try to delere root folder + try + { + DeleteTreeResponse.FailedToDelete response = ((ObjectServicePort) servicePort).deleteTree(repositoryId, helper.getCompanyHomeId(repositoryId), + EnumUnfileNonfolderObjects.DELETE, true); + fail("Try to delere root folder"); + } + catch (OperationNotSupportedException e) + { + } + catch (Exception e) + { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + public void testGetAllowableActions() throws Exception + { + CmisAllowableActionsType response; + // CmisAllowableActionsType getAllowableActions(String repositoryId, String objectId) + response = ((ObjectServicePort) servicePort).getAllowableActions(repositoryId, documentId); + assertNotNull(response); + assertTrue(response.canGetProperties); + assertTrue(response.canCheckout); + + response = ((ObjectServicePort) servicePort).getAllowableActions(repositoryId, folderId); + assertNotNull(response); + assertTrue(response.canGetProperties); + assertNull(response.canCheckout); + } + + public void testMoveObject() throws Exception + { + // public void moveObject(String repositoryId, String objectId, String targetFolderId, String sourceFolderId) + ((ObjectServicePort) servicePort).moveObject(repositoryId, documentId, folderId, companyHomeId); + + GetPropertiesResponse response = helper.getObjectProperties(documentId); + + CmisObjectType objectType = response.getObject(); + + assertNotNull(objectType); + assertNotNull(getPropertyValue(response, CMISMapping.PROP_NAME)); + + GetObjectParentsResponse parentsResponse = helper.getObjectParents(documentId, "*"); + assertTrue(parentsResponse.getObject().size() == 1); + assertTrue(PropertyUtil.getProperty(parentsResponse.getObject().get(0).getProperties(), CMISMapping.PROP_NAME).equals(folderName)); + + } + + // The moveObject() method must throw InvalidArgumentException for null SourceFolderId only if specified Object (Folder or Document) has SEVERAL parents. + // In other case this parameter may be null. + public void testMoveObject_Exceptions() throws Exception + { + // sourceFolderId is not specified - throw InvalidArgumentException + // • If Object is multi-filed and source folder is not specified, throw InvalidArgumentException. + + helper.addObjectToFolder(documentId, folderId); + + try + { + ((ObjectServicePort) servicePort).moveObject(repositoryId, documentId, folderId, null); + fail("sourceFolderId is not specified - should throw InvalidArgumentException"); + } + catch (InvalidArgumentException e) + { + + } + catch (Exception e) + { + e.printStackTrace(); + fail(e.getClass().getName() + ": " + e.getMessage()); + } + } + + public void testSetContentStream() throws Exception + { + String newFileName = "New file name (" + System.currentTimeMillis() + ")"; + String newContent = "New content test"; + + CmisContentStreamType contentStream = new CmisContentStreamType(); + contentStream.setFilename(newFileName); + contentStream.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + // contentStream.setLength(BigInteger.valueOf(256)); + // contentStream.setUri("test uri"); + // DataHandler dataHandler = new DataHandler(new FileDataSource("D:/test.txt")); + DataHandler dataHandler = new DataHandler(newContent, MimetypeMap.MIMETYPE_TEXT_PLAIN); + contentStream.setStream(dataHandler); + + Holder documentIdHolder = new Holder(documentId); + // public void setContentStream(String repositoryId, Holder documentId, Boolean overwriteFlag, CmisContentStreamType contentStream) + ((ObjectServicePort) servicePort).setContentStream(repositoryId, documentIdHolder, true, contentStream); + + CmisContentStreamType result = ((ObjectServicePort) servicePort).getContentStream(repositoryId, documentId); + if (result.getLength().intValue() == 0) + { + fail("Content Stream is empty"); + } + assertEquals(newContent, result.getStream().getContent()); + + // Alfresco create new version of document + propertiesResponse = helper.getObjectProperties(documentIdHolder.value); + assertFalse("new version of document should be created", getPropertyValue(propertiesResponse, CMISMapping.PROP_OBJECT_ID).equals(documentId)); + GetAllVersionsResponse responseVersions = helper.getAllVersions(documentId); + assertTrue("new version of document should be created", responseVersions.getObject().size() > 1); + + // assertEquals(newFileName, result.getFilename()); + + // GetPropertiesResponse response = helper.getObjectProperties(documentId); + // assertNotNull(getObjectName(response)); + // assertEquals(newFileName, getContentStreamFilename(response)); + } + + public void testSetContentStream_Exceptions() throws Exception + { + String newFileName = "New file name (" + System.currentTimeMillis() + ")"; + String newContent = "New content test"; + + CmisContentStreamType contentStream = new CmisContentStreamType(); + contentStream.setFilename(newFileName); + contentStream.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + DataHandler dataHandler = new DataHandler(newContent, MimetypeMap.MIMETYPE_TEXT_PLAIN); + contentStream.setStream(dataHandler); + + try + { + // public void setContentStream(String repositoryId, Holder documentId, Boolean overwriteFlag, CmisContentStreamType contentStream) + ((ObjectServicePort) servicePort).setContentStream(repositoryId, new Holder(documentId), false, contentStream); + fail("ContentAlreadyExists should be thrown"); + } + catch (ContentAlreadyExistsException e) + { + + } + catch (Exception e) + { + e.printStackTrace(); + fail(e.getMessage()); + } + + // now we can not set any property (beside name) when we create new document - so this case not working + propertiesResponse = helper.getObjectProperties(documentId); + Boolean contentStreamAllowed = getPropertyBooleanValue(propertiesResponse, CMISMapping.PROP_CONTENT_STREAM_ALLOWED); + if (contentStreamAllowed != null && contentStreamAllowed == false) + { + try + { + // public void setContentStream(String repositoryId, Holder documentId, Boolean overwriteFlag, CmisContentStreamType contentStream) + ((ObjectServicePort) servicePort).setContentStream(repositoryId, new Holder(documentId), true, contentStream); + fail("ConstraintViolationException should be thrown"); + } + catch (ConstraintViolationException e) + { + + } + catch (Exception e) + { + e.printStackTrace(); + fail(e.getMessage()); + } + } + + } + + public void testUpdateProperties() throws Exception + { + + String newName = "New Cmis Test Node Name (" + System.currentTimeMillis() + ")"; + + // Cmis Properties + CmisPropertiesType properties = new CmisPropertiesType(); + List propertiesList = properties.getProperty(); + CmisPropertyString cmisProperty = new CmisPropertyString(); + cmisProperty.setName(CMISMapping.PROP_NAME); + cmisProperty.setValue(newName); + propertiesList.add(cmisProperty); + + // public void updateProperties(String repositoryId, Holder objectId, String changeToken, CmisPropertiesType properties) + ((ObjectServicePort) servicePort).updateProperties(repositoryId, new Holder(documentId), new String(""), properties); + + GetPropertiesResponse response = helper.getObjectProperties(documentId); + assertEquals(newName, getObjectName(response)); + } + + public void testUpdateProperties_Exceptions() throws Exception + { + // Now we can set up only name propery + + // try to update read only property + CmisPropertiesType properties = new CmisPropertiesType(); + properties = new CmisPropertiesType(); + List propertiesList = properties.getProperty(); + CmisPropertyString cmisProperty = new CmisPropertyString(); + cmisProperty.setName(CMISMapping.PROP_OBJECT_ID); + cmisProperty.setValue("new id value"); + propertiesList.add(cmisProperty); + + try + { + // public void updateProperties(String repositoryId, Holder objectId, String changeToken, CmisPropertiesType properties) + ((ObjectServicePort) servicePort).updateProperties(repositoryId, new Holder(documentId), new String(""), properties); + fail("should not update read only propery"); + } + catch (ConstraintViolationException e) + { + + } + catch (Exception e) + { + e.printStackTrace(); + fail(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/source/test/java/org/alfresco/repo/cmis/ws/DMPolicyServiceTest.java b/source/test/java/org/alfresco/repo/cmis/ws/DMPolicyServiceTest.java new file mode 100755 index 0000000000..230646684b --- /dev/null +++ b/source/test/java/org/alfresco/repo/cmis/ws/DMPolicyServiceTest.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws; + +import java.net.MalformedURLException; +import java.net.URL; + +import javax.xml.namespace.QName; +import javax.xml.ws.Service; + +public class DMPolicyServiceTest extends AbstractServiceTest +{ + + public final static String SERVICE_WSDL_LOCATION = CmisServiceTestHelper.ALFRESCO_URL + "/cmis/PolicyService?wsdl"; + public final static QName SERVICE_NAME = new QName("http://www.cmis.org/ns/1.0", "PolicyServicePort"); + + public DMPolicyServiceTest() + { + super(); + } + + public DMPolicyServiceTest(String testCase, String username, String password) + { + super(testCase, username, password); + } + + protected Object getServicePort() + { + { + URL serviceWsdlURL; + try + { + serviceWsdlURL = new URL(SERVICE_WSDL_LOCATION); + } + catch (MalformedURLException e) + { + throw new java.lang.RuntimeException("Cannot get service Wsdl URL", e); + } + + Service service = Service.create(serviceWsdlURL, SERVICE_NAME); + return service.getPort(PolicyServicePort.class); + } + } + + public void testApplyPolicy() throws Exception + { + String documentId = helper.createDocument("Test cmis document (" + System.currentTimeMillis() + ")", companyHomeId); + assertNotNull(documentId); + ((PolicyServicePort) servicePort).applyPolicy(repositoryId, "policyId", documentId); // TODO policyId + helper.deleteDocument(documentId); + } + + public void testGetAppliedPolicies() throws Exception + { + String documentId = helper.createDocument("Test cmis document (" + System.currentTimeMillis() + ")", companyHomeId); + assertNotNull(documentId); + + GetAppliedPolicies request = new GetAppliedPolicies(); + request.setRepositoryId(repositoryId); + request.setObjectId(documentId); + request.setFilter(cmisObjectFactory.createGetAppliedPoliciesFilter("")); // TODO + GetAppliedPoliciesResponse response = ((PolicyServicePort) servicePort).getAppliedPolicies(request); + + // TODO: Uncomment + // assertNotNull(response); + // assertNotNull(response.getObject()); + // if (!response.getObject().isEmpty()) + // { + // for (CmisObjectType object : response.getObject()) + // { + // assertNotNull(object.getProperties()); + // } + // } + + helper.deleteDocument(documentId); + } + + public void testRemovePolicy() throws Exception + { + String documentId = helper.createDocument("Test cmis document (" + System.currentTimeMillis() + ")", companyHomeId); + assertNotNull(documentId); + + ((PolicyServicePort) servicePort).removePolicy(repositoryId, "policyId", documentId); // TODO policyId + + helper.deleteDocument(documentId); + } +} diff --git a/source/test/java/org/alfresco/repo/cmis/ws/DMRelationshipServiceTest.java b/source/test/java/org/alfresco/repo/cmis/ws/DMRelationshipServiceTest.java new file mode 100755 index 0000000000..1844250023 --- /dev/null +++ b/source/test/java/org/alfresco/repo/cmis/ws/DMRelationshipServiceTest.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws; + +import java.math.BigInteger; +import java.net.MalformedURLException; +import java.net.URL; + +import javax.xml.namespace.QName; +import javax.xml.ws.Service; + +import org.alfresco.cmis.dictionary.CMISMapping; + +public class DMRelationshipServiceTest extends AbstractServiceTest +{ + + public final static String SERVICE_WSDL_LOCATION = CmisServiceTestHelper.ALFRESCO_URL + "/cmis/RelationshipService?wsdl"; + public final static QName SERVICE_NAME = new QName("http://www.cmis.org/ns/1.0", "RelationshipService"); + + private String relationshipId; + private String document2Id; + + public DMRelationshipServiceTest() + { + super(); + } + + public DMRelationshipServiceTest(String testCase, String username, String password) + { + super(testCase, username, password); + } + + @Override + protected void setUp() throws Exception + { + super.setUp(); + documentId = helper.createDocument("Test cmis document (" + System.currentTimeMillis() + ")", companyHomeId); + document2Id = helper.createDocument("Test cmis document (" + System.currentTimeMillis() + ")", companyHomeId); + // TODO: uncomment + // try + // { + // relationshipId = helper.createRelationship("Test cmis relationship (" + System.currentTimeMillis() + ")", documentId, document2Id); + // } + // catch (Exception e) + // { + // if(documentId != null ){ + // helper.deleteDocument(documentId); + // } + // if(document2Id != null ){ + // helper.deleteDocument(document2Id); + // } + // throw e; + // } + } + + @Override + protected void tearDown() throws Exception + { + super.tearDown(); + helper.deleteDocument(documentId); + helper.deleteDocument(document2Id); + } + + protected Object getServicePort() + { + { + URL serviceWsdlURL; + try + { + serviceWsdlURL = new URL(SERVICE_WSDL_LOCATION); + } + catch (MalformedURLException e) + { + throw new java.lang.RuntimeException("Cannot get service Wsdl URL", e); + } + + Service service = Service.create(serviceWsdlURL, SERVICE_NAME); + return service.getPort(RelationshipServicePort.class); + } + } + + public void testGetRelationships() throws Exception + { + // TODO: uncomment +// GetRelationships request = cmisObjectFactory.createGetRelationships(); +// request.setRepositoryId(repositoryId); +// request.setObjectId(documentId); +// request.setFilter(cmisObjectFactory.createGetRelationshipsFilter("*")); +// request.setTypeId(cmisObjectFactory.createGetRelationshipsTypeId(CMISMapping.RELATIONSHIP_TYPE_ID.getTypeId())); +// request.setIncludeAllowableActions(cmisObjectFactory.createGetRelationshipsIncludeAllowableActions(true)); +// request.setIncludeSubRelationshipTypes(cmisObjectFactory.createGetRelationshipsIncludeSubRelationshipTypes(true)); +// request.setMaxItems(cmisObjectFactory.createGetRelationshipsMaxItems(BigInteger.valueOf(0))); +// request.setSkipCount(cmisObjectFactory.createGetRelationshipsSkipCount(BigInteger.valueOf(0))); +// request.setDirection(cmisObjectFactory.createGetRelationshipsDirection(EnumRelationshipDirection.SOURCE)); +// +// // public GetRelationshipsResponse getRelationships(GetRelationships parameters) +// GetRelationshipsResponse responce = ((RelationshipServicePort) servicePort).getRelationships(request); +// assertNotNull(responce.getObject()); + } + + public void testGetRelationshipObjectProperties() throws Exception + { + + // TODO: uncomment + + // GetPropertiesResponse response = helper.getObjectProperties(relationshipId); + // + // assertNotNull(response); + // assertNotNull(response.getObject()); + // assertNotNull(response.getObject().getProperties()); + // assertNotNull(response.getObject().getProperties().getProperty()); + // + // assertTrue(response.getObject().getProperties().getProperty().size() > 3); + // + // assertEquals(relationshipId.toString(), PropertyUtil.getValue((CmisProperty) PropertyUtil.getProperty(response.getObject().getProperties(), + // CMISMapping.PROP_OBJECT_ID))); + } +} + diff --git a/source/test/java/org/alfresco/repo/cmis/ws/DMRepositoryServicePortTest.java b/source/test/java/org/alfresco/repo/cmis/ws/DMRepositoryServicePortTest.java deleted file mode 100644 index 13e9dbad8c..0000000000 --- a/source/test/java/org/alfresco/repo/cmis/ws/DMRepositoryServicePortTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2005-2008 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 - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" - */ -package org.alfresco.repo.cmis.ws; - -import java.util.List; - -import org.alfresco.repo.cmis.ws.RepositoryServicePort; - -/** - * @see org.alfresco.repo.cmis.ws.RepositoryServicePortDM - * - * @author Dmitry Lazurkin - * - */ -public class DMRepositoryServicePortTest extends BaseServicePortTest -{ - private RepositoryServicePort repositoryServicePort; - - @Override - protected void onSetUp() throws Exception - { - super.onSetUp(); - - repositoryServicePort = (RepositoryServicePort) applicationContext.getBean("dmRepositoryService"); - } - - public void testGetRepositoryServicePort() throws Exception - { - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - List repositories = repositoryServicePort.getRepositories(); - assertTrue(repositories.size() == 1); - assertFalse(repositories.get(0).getRepositoryID() == null); - assertFalse(repositories.get(0).getRepositoryName() == null); - } - - public void testGetRepositoryInfo() throws Exception - { - List repositories = repositoryServicePort.getRepositories(); - GetRepositoryInfo response = new GetRepositoryInfo(); - response.setRepositoryId(repositories.get(0).getRepositoryID()); - CmisRepositoryInfoType repositoryInfo = repositoryServicePort.getRepositoryInfo(response); - - assertTrue(repositoryInfo.getRepositoryId().equals(repositories.get(0).getRepositoryID())); - assertTrue(repositoryInfo.getRepositoryName().equals(repositories.get(0).getRepositoryName())); - assertTrue("Alfresco".equals(repositoryInfo.getVendorName())); - CmisRepositoryCapabilitiesType capabilities = repositoryInfo.getCapabilities(); - assertTrue(capabilities.isCapabilityMultifiling() && capabilities.isCapabilityPWCUpdateable()); - assertFalse(capabilities.isCapabilityUnfiling() && capabilities.isCapabilityVersionSpecificFiling()); - } -} diff --git a/source/test/java/org/alfresco/repo/cmis/ws/DMRepositoryServiceTest.java b/source/test/java/org/alfresco/repo/cmis/ws/DMRepositoryServiceTest.java index 032f2c0b34..5756449f8b 100644 --- a/source/test/java/org/alfresco/repo/cmis/ws/DMRepositoryServiceTest.java +++ b/source/test/java/org/alfresco/repo/cmis/ws/DMRepositoryServiceTest.java @@ -24,79 +24,73 @@ */ package org.alfresco.repo.cmis.ws; -import java.net.MalformedURLException; -import java.net.URL; +import java.math.BigInteger; import java.util.List; -import javax.xml.namespace.QName; -import javax.xml.ws.Service; - -import org.alfresco.repo.cmis.ws.RepositoryServicePort; - -/** - * @author Michael Shavnev - */ public class DMRepositoryServiceTest extends AbstractServiceTest { + public final static String TYPE_ID = "D/wcm_avmlayeredcontent"; - public final static String SERVICE_WSDL_LOCATION = "http://localhost:8080/alfresco/cmis/RepositoryService?wsdl"; - public final static QName SERVICE_NAME = new QName("http://www.cmis.org/ns/1.0", "RepositoryService"); + public DMRepositoryServiceTest() + { + super(); + } + + public DMRepositoryServiceTest(String testCase, String username, String password) + { + super(testCase, username, password); + } protected Object getServicePort() { - URL serviceWsdlURL; - try - { - serviceWsdlURL = new URL(SERVICE_WSDL_LOCATION); - } - catch (MalformedURLException e) - { - throw new java.lang.RuntimeException("Cannot get service Wsdl URL", e); - } - Service service = Service.create(serviceWsdlURL, SERVICE_NAME); - return service.getPort(RepositoryServicePort.class); + return helper.repositoryServicePort; } - public void testGetRepositories() + public void testGetRepositories() throws Exception { - try - { - List repositories = ((RepositoryServicePort) servicePort).getRepositories(); - assertTrue(repositories.size() == 1); - assertFalse(repositories.get(0).getRepositoryID() == null); - assertFalse(repositories.get(0).getRepositoryName() == null); - } - catch (Throwable e) - { - e.printStackTrace(); - fail(); - } - + List repositories = ((RepositoryServicePort) servicePort).getRepositories(); + assertTrue(repositories.size() == 1); + assertFalse(repositories.get(0).getRepositoryID() == null); + assertFalse(repositories.get(0).getRepositoryName() == null); } - public void testGetRepositoryInfo() + public void testGetRepositoryInfo() throws Exception { - try - { - List repositories = ((RepositoryServicePort) servicePort).getRepositories(); - GetRepositoryInfo parameters = new GetRepositoryInfo(); - parameters.setRepositoryId(repositories.get(0).getRepositoryID()); - CmisRepositoryInfoType cmisRepositoryInfoType = ((RepositoryServicePort) servicePort).getRepositoryInfo(parameters); - - assertTrue(cmisRepositoryInfoType.getRepositoryId().equals(repositories.get(0).getRepositoryID())); - assertTrue(cmisRepositoryInfoType.getRepositoryName().equals(repositories.get(0).getRepositoryName())); - assertTrue("Alfresco".equals(cmisRepositoryInfoType.getVendorName())); - assertTrue(cmisRepositoryInfoType.getVendorName().indexOf("Alfresco Repository (") > -1 ); - CmisRepositoryCapabilitiesType capabilities = cmisRepositoryInfoType.getCapabilities(); - assertTrue(capabilities.isCapabilityMultifiling() && capabilities.isCapabilityPWCUpdateable()); - assertFalse(capabilities.isCapabilityUnfiling() && capabilities.isCapabilityVersionSpecificFiling()); + List repositories = ((RepositoryServicePort) servicePort).getRepositories(); + GetRepositoryInfo parameters = new GetRepositoryInfo(); + parameters.setRepositoryId(repositories.get(0).getRepositoryID()); + CmisRepositoryInfoType cmisRepositoryInfoType = ((RepositoryServicePort) servicePort).getRepositoryInfo(parameters); - } - catch (Throwable e) - { - e.printStackTrace(); - fail(); - } + assertTrue(cmisRepositoryInfoType.getRepositoryId().equals(repositories.get(0).getRepositoryID())); + assertTrue(cmisRepositoryInfoType.getRepositoryName().equals(repositories.get(0).getRepositoryName())); + CmisRepositoryCapabilitiesType capabilities = cmisRepositoryInfoType.getCapabilities(); + assertTrue(capabilities.isCapabilityMultifiling() && capabilities.isCapabilityPWCUpdateable()); + assertFalse(capabilities.isCapabilityUnfiling() && capabilities.isCapabilityVersionSpecificFiling()); + } + public void testGetTypes() throws Exception + { + GetTypes request = new GetTypes(); + request.setMaxItems(cmisObjectFactory.createGetTypesMaxItems(BigInteger.valueOf(0))); + request.setSkipCount(cmisObjectFactory.createGetTypesMaxItems(BigInteger.valueOf(0))); + request.setRepositoryId(repositoryId); + request.setReturnPropertyDefinitions(cmisObjectFactory.createGetTypesReturnPropertyDefinitions(Boolean.FALSE)); + GetTypesResponse response = ((RepositoryServicePort) servicePort).getTypes(request); + assertNotNull(response.getType()); + assertFalse(response.getType().isEmpty()); + CmisTypeDefinitionType element = response.getType().get(0).getValue(); + assertNotNull(element); + } + + public void testGetTypeDefinition() throws Exception + { + GetTypeDefinition request = new GetTypeDefinition(); + request.setRepositoryId(repositoryId); + request.setTypeId(TYPE_ID); + GetTypeDefinitionResponse response = ((RepositoryServicePort) servicePort).getTypeDefinition(request); + assertNotNull(response); + assertNotNull(response.getType()); + CmisTypeDefinitionType element = response.getType().getValue(); + assertNotNull(element); } } diff --git a/source/test/java/org/alfresco/repo/cmis/ws/DMVersioningServiceTest.java b/source/test/java/org/alfresco/repo/cmis/ws/DMVersioningServiceTest.java new file mode 100755 index 0000000000..cb85451b7d --- /dev/null +++ b/source/test/java/org/alfresco/repo/cmis/ws/DMVersioningServiceTest.java @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws; + +import javax.activation.DataHandler; +import javax.xml.ws.Holder; + +import org.alfresco.cmis.dictionary.CMISMapping; +import org.alfresco.repo.content.MimetypeMap; + +public class DMVersioningServiceTest extends AbstractServiceTest +{ + private String documentId; + + public DMVersioningServiceTest() + { + super(); + } + + public DMVersioningServiceTest(String testCase, String username, String password) + { + super(testCase, username, password); + } + + protected Object getServicePort() + { + return helper.versioningServicePort; + } + + @Override + protected void setUp() throws Exception + { + super.setUp(); + documentId = helper.createDocument("Test cmis document (" + System.currentTimeMillis() + ")", companyHomeId); + } + + @Override + protected void tearDown() throws Exception + { + super.tearDown(); + helper.deleteDocument(documentId); + } + + public void testCheckOutCheckIn() throws Exception + { + // check out + Holder documentIdHolder = new Holder(documentId); + Holder contentCopied = new Holder(); + ((VersioningServicePort) servicePort).checkOut(repositoryId, documentIdHolder, contentCopied); + assertTrue(contentCopied.value); + assertFalse(documentId.equals(documentIdHolder.value)); + + // check in + CmisPropertiesType properties = new CmisPropertiesType();// TODO + CmisContentStreamType contentStream = new CmisContentStreamType(); + contentStream.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + DataHandler dataHandler = new DataHandler("Test content string: " + System.currentTimeMillis(), MimetypeMap.MIMETYPE_TEXT_PLAIN); + contentStream.setStream(dataHandler); + String checkinComment = "Test checkin" + System.currentTimeMillis(); + ((VersioningServicePort) servicePort).checkIn(repositoryId, documentIdHolder, Boolean.TRUE, properties, contentStream, checkinComment); + + assertEquals(checkinComment, PropertyUtil.getProperty(helper.getObjectProperties(documentId).getObject().getProperties(), CMISMapping.PROP_CHECKIN_COMMENT)); + } + + public void testCheckOutCheckInDefault() throws Exception + { + // check out + Holder documentIdHolder = new Holder(documentId); + Holder contentCopied = new Holder(); + ((VersioningServicePort) servicePort).checkOut(repositoryId, documentIdHolder, contentCopied); + assertTrue(contentCopied.value); + assertFalse(documentId.equals(documentIdHolder.value)); + + // check in + ((VersioningServicePort) servicePort).checkIn(repositoryId, documentIdHolder, null, null, null, null); + } + + public void testCheckOutCancelCheckOut() throws Exception + { + // check out + Holder documentIdHolder = new Holder(documentId); + Holder contentCopied = new Holder(); + ((VersioningServicePort) servicePort).checkOut(repositoryId, documentIdHolder, contentCopied); + assertTrue(contentCopied.value); + assertFalse(documentId.equals(documentIdHolder.value)); + + // Cancel check out + ((VersioningServicePort) servicePort).cancelCheckOut(repositoryId, documentIdHolder.value); + assertFalse((Boolean) PropertyUtil.getProperty(helper.getObjectProperties(documentId).getObject().getProperties(), CMISMapping.PROP_IS_VERSION_SERIES_CHECKED_OUT)); + } + + public void testCheckinNoExistsCheckOut() throws Exception + { + try + { + Holder documentIdHolder = new Holder(documentId); + CmisPropertiesType properties = new CmisPropertiesType(); + CmisContentStreamType contentStream = new CmisContentStreamType(); + contentStream.setMimeType(MimetypeMap.MIMETYPE_TEXT_PLAIN); + DataHandler dataHandler = new DataHandler("Test content string: " + System.currentTimeMillis(), MimetypeMap.MIMETYPE_TEXT_PLAIN); + contentStream.setStream(dataHandler); + String checkinComment = "Test checkin"; + ((VersioningServicePort) servicePort).checkIn(repositoryId, documentIdHolder, Boolean.TRUE, properties, contentStream, checkinComment); + fail("Expects exception"); + + } + catch (Throwable e) + { + assertTrue(e instanceof OperationNotSupportedException); + } + } + + public void testCancelNotExistsCheckOut() throws Exception + { + try + { + Holder documentIdHolder = new Holder(documentId); + ((VersioningServicePort) servicePort).cancelCheckOut(repositoryId, documentIdHolder.value); + fail("Expects exception"); + + } + catch (Throwable e) + { + assertTrue(e instanceof OperationNotSupportedException); + } + } + + public void testGetPropertiesOfLatestVersion() throws Exception + { + GetPropertiesOfLatestVersion request = new GetPropertiesOfLatestVersion(); + request.setRepositoryId(repositoryId); + request.setFilter(cmisObjectFactory.createGetPropertiesOfLatestVersionFilter("*")); + request.setMajorVersion(Boolean.TRUE); + request.setVersionSeriesId(documentId); + GetPropertiesOfLatestVersionResponse response = ((VersioningServicePort) servicePort).getPropertiesOfLatestVersion(request); + assertNotNull(response); + assertNotNull(response.getObject()); + CmisObjectType objectType = response.getObject(); + assertNotNull(objectType.getProperties()); + assertTrue((Boolean) PropertyUtil.getProperty(objectType.getProperties(), CMISMapping.PROP_IS_LATEST_VERSION)); + } + + public void testGetPropertiesOfLatestVersionDefault() throws Exception + { + GetPropertiesOfLatestVersion request = new GetPropertiesOfLatestVersion(); + request.setRepositoryId(repositoryId); + request.setVersionSeriesId(documentId); + GetPropertiesOfLatestVersionResponse response = ((VersioningServicePort) servicePort).getPropertiesOfLatestVersion(request); + assertNotNull(response); + assertNotNull(response.getObject()); + CmisObjectType objectType = response.getObject(); + assertNotNull(objectType.getProperties()); + assertTrue((Boolean) PropertyUtil.getProperty(objectType.getProperties(), CMISMapping.PROP_IS_LATEST_VERSION)); + } + + public void testGetAllVersionsDefault() throws Exception + { + GetAllVersions request = new GetAllVersions(); + + Holder documentIdHolder = new Holder(documentId); + Holder contentCopied = new Holder(); + String checkinComment = "Test checkin" + System.currentTimeMillis(); + + helper.checkOut(documentIdHolder, contentCopied); + helper.checkIn(documentIdHolder, checkinComment, true); + + request.setRepositoryId(repositoryId); + request.setVersionSeriesId(documentId); + + GetAllVersionsResponse response = ((VersioningServicePort) servicePort).getAllVersions(request); + assertNotNull(response); + assertNotNull(response.getObject()); + assertEquals(checkinComment, PropertyUtil.getProperty(response.getObject().get(0).getProperties(), CMISMapping.PROP_CHECKIN_COMMENT)); + } + + public void testGetAllVersions() throws Exception + { + GetAllVersions request = new GetAllVersions(); + + Holder documentIdHolder = new Holder(documentId); + Holder contentCopied = new Holder(); + String checkinComment = "Test checkin" + System.currentTimeMillis(); + + helper.checkOut(documentIdHolder, contentCopied); + helper.checkIn(documentIdHolder, checkinComment, true); + + request.setRepositoryId(repositoryId); + request.setVersionSeriesId(documentId); + request.setFilter(cmisObjectFactory.createGetAllVersionsFilter("*")); + request.setIncludeAllowableActions(cmisObjectFactory.createGetAllVersionsIncludeAllowableActions(Boolean.FALSE)); + request.setIncludeRelationships(cmisObjectFactory.createGetAllVersionsIncludeRelationships(Boolean.FALSE)); + + GetAllVersionsResponse response = ((VersioningServicePort) servicePort).getAllVersions(request); + assertNotNull(response); + assertNotNull(response.getObject()); + assertEquals(checkinComment, PropertyUtil.getProperty(response.getObject().get(0).getProperties(), CMISMapping.PROP_CHECKIN_COMMENT)); + } + + public void testGetAllVersionsForNoVersionHistory() throws Exception + { + GetAllVersions request = new GetAllVersions(); + + request.setRepositoryId(repositoryId); + request.setVersionSeriesId(documentId); + request.setFilter(cmisObjectFactory.createGetAllVersionsFilter("*")); + request.setIncludeAllowableActions(cmisObjectFactory.createGetAllVersionsIncludeAllowableActions(Boolean.FALSE)); + request.setIncludeRelationships(cmisObjectFactory.createGetAllVersionsIncludeRelationships(Boolean.FALSE)); + + GetAllVersionsResponse response = ((VersioningServicePort) servicePort).getAllVersions(request); + assertNotNull(response); + assertNotNull(response.getObject()); + } + + public void testGetAllVersionsCheckedOutAndPWC() throws Exception + { + GetAllVersions request = new GetAllVersions(); + Holder documentIdHolder = new Holder(documentId); + Holder contentCopied = new Holder(); + boolean checkedOutfound = false; + boolean pwcFound = false; + try + { + helper.checkOut(documentIdHolder, contentCopied); + request.setRepositoryId(repositoryId); + request.setVersionSeriesId(documentId); + request.setFilter(cmisObjectFactory.createGetAllVersionsFilter("*")); + request.setIncludeAllowableActions(cmisObjectFactory.createGetAllVersionsIncludeAllowableActions(Boolean.FALSE)); + request.setIncludeRelationships(cmisObjectFactory.createGetAllVersionsIncludeRelationships(Boolean.FALSE)); + + GetAllVersionsResponse response = ((VersioningServicePort) servicePort).getAllVersions(request); + assertNotNull(response); + assertNotNull(response.getObject()); + for (CmisObjectType cmisObjectType : response.getObject()) + { + if (!checkedOutfound) + { + checkedOutfound = (Boolean) PropertyUtil.getProperty(cmisObjectType.getProperties(), CMISMapping.PROP_IS_VERSION_SERIES_CHECKED_OUT); + } + if (!pwcFound) + { + pwcFound = ((String) PropertyUtil.getProperty(cmisObjectType.getProperties(), CMISMapping.PROP_OBJECT_ID)).startsWith(documentIdHolder.value); + } + } + assertTrue("No checked out version found", checkedOutfound); + assertTrue("No private working copy version found", pwcFound); + } + finally + { + helper.checkIn(documentIdHolder, "Hello", true); + } + } + + public void testDeleteAllVersions() throws Exception + { + ((VersioningServicePort) servicePort).deleteAllVersions(repositoryId, documentId); + } +} diff --git a/source/test/java/org/alfresco/repo/cmis/ws/MultiThreadsServiceTest.java b/source/test/java/org/alfresco/repo/cmis/ws/MultiThreadsServiceTest.java new file mode 100755 index 0000000000..6361edb3d2 --- /dev/null +++ b/source/test/java/org/alfresco/repo/cmis/ws/MultiThreadsServiceTest.java @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws; + +import java.util.LinkedList; +import java.util.List; +import java.util.Random; + +import org.alfresco.cmis.dictionary.CMISMapping; + +public class MultiThreadsServiceTest extends AbstractServiceTest +{ + private String lastName; + private String lastContent; + private Random generator = new Random(); + private boolean isRunning; + private Thread thread; + + public MultiThreadsServiceTest(String testCase, String username, String password) + { + super(testCase, username, password); + } + + public MultiThreadsServiceTest() + { + super(); + } + + @Override + protected Object getServicePort() + { + return helper.navigationServicePort; + } + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + createInitialContent(); + + } + + @Override + protected void tearDown() throws Exception + { + super.tearDown(); + + deleteInitialContent(); + } + + public void testUpdateDocumentMultiThreaded() throws Exception + { + ThreadGroup threadGroup = new ThreadGroup("testUpdateDocumentMultiThreaded"); + List threads = new LinkedList(); + for (int i = 0; i < 5; i++) + { + AbstractBaseRunner updater = new DocumentUpdater(); + + Thread updateDocumentTread = new Thread(threadGroup, updater, "updateDocument " + i); + + threads.add(updater); + + updateDocumentTread.start(); + } + + isRunning = true; + while (isRunning) + { + isRunning = threadGroup.activeCount() != 0; + } + if (isRunning == false) + { + assertTrue("All threads done their work normally", anyFailed(threads)); + + GetPropertiesResponse propertiesResponse; + propertiesResponse = helper.getObjectProperties(documentId); + assertEquals(lastName, getPropertyValue(propertiesResponse, CMISMapping.PROP_NAME)); + } + } + + public void testSetTextContentStreamMultiThreaded() throws Exception + { + ThreadGroup threadGroup = new ThreadGroup("testSetContentStreamMultiThreaded"); + List threads = new LinkedList(); + for (int i = 0; i < 5; i++) + { + // thread = new Thread(threadGroup, updateDocument, "updateDocument again " + i); + // thread.start(); + + AbstractBaseRunner runner = new TextContentStreamSetter(); + + thread = new Thread(threadGroup, runner, "setTextContentStream" + i); + + threads.add(runner); + + thread.start(); + } + + isRunning = true; + while (isRunning) + { + isRunning = threadGroup.activeCount() != 0; + } + if (isRunning == false) + { + CmisContentStreamType result; + result = helper.getContentStream(documentId); + if (result.getLength().intValue() == 0) + { + fail("Content Stream is empty"); + } + + assertTrue("All threads done their work normally", anyFailed(threads)); + + assertEquals(lastContent, result.getStream().getContent()); + } + } + + private boolean anyFailed(List threads) + { + + for (AbstractBaseRunner runner : threads) + { + if (runner.isExecutionFailed()) + { + return true; + } + } + + return false; + } + + private abstract class AbstractBaseRunner implements Runnable + { + protected boolean executionFailed; + + public boolean isExecutionFailed() + { + + return executionFailed; + } + } + + private class DocumentUpdater extends AbstractBaseRunner + { + public void run() + { + try + { + String newName = "New Name" + System.currentTimeMillis() + generator.nextDouble(); + helper.updateProperty(documentId, CMISMapping.PROP_NAME, newName); + lastName = newName; + } + catch (Exception e) + { + // this fail() does not fail the test, just print exception message to the console + executionFailed = true; + } + } + } + + private class TextContentStreamSetter extends AbstractBaseRunner + { + public void run() + { + try + { + String newContent = "New text content for testing." + generator.nextDouble(); + helper.setTextContentStream(documentId, newContent); + lastContent = newContent; + } + catch (Exception e) + { + // this fail() does not fail the test, just print exception message to the console + executionFailed = true; + } + } + } +} diff --git a/source/test/java/org/alfresco/repo/cmis/ws/WebServiceMultipleUsersSuiteTest.java b/source/test/java/org/alfresco/repo/cmis/ws/WebServiceMultipleUsersSuiteTest.java new file mode 100755 index 0000000000..96f547de06 --- /dev/null +++ b/source/test/java/org/alfresco/repo/cmis/ws/WebServiceMultipleUsersSuiteTest.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws; + +import junit.framework.Test; +import junit.framework.TestSuite; +import static org.alfresco.repo.cmis.ws.CmisServiceTestHelper.*; + +public class WebServiceMultipleUsersSuiteTest extends TestSuite +{ + public static Test suite() + { + TestSuite suite = new TestSuite(); + + // Discovery Service tests + // suite.addTest(new DMDiscoveryServiceTest("testQuery", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMDiscoveryServiceTest("testQuery", USERNAME_USER1, PASSWORD_USER1)); + + // MultiFiling Service tests + // suite.addTest(new DMMultiFilingServiceTest("testAddObjectToFolder", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMMultiFilingServiceTest("testAddObjectToFolder", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMMultiFilingServiceTest("testRemoveObjectFromFolder", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMMultiFilingServiceTest("testRemoveObjectFromFolder", USERNAME_USER1, PASSWORD_USER1)); + + // Navigation Service tests + + // suite.addTest(new DMNavigationServiceTest("testGetChildren", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMNavigationServiceTest("testGetChildren", USERNAME_USER1, PASSWORD_USER1)); + + // suite.addTest(new DMNavigationServiceTest("testGetCheckedoutDocs", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMNavigationServiceTest("testGetCheckedoutDocs", USERNAME_USER1, PASSWORD_USER1)); + + // suite.addTest(new DMNavigationServiceTest("testGetDescendants", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMNavigationServiceTest("testGetDescendants", USERNAME_USER1, PASSWORD_USER1)); + + // suite.addTest(new DMNavigationServiceTest("testGetFolderParent", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMNavigationServiceTest("testGetFolderParent", USERNAME_USER1, PASSWORD_USER1)); + + // suite.addTest(new DMNavigationServiceTest("testGetObjectParents", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMNavigationServiceTest("testGetObjectParents", USERNAME_USER1, PASSWORD_USER1)); + + // Object Service tests + // suite.addTest(new DMObjectServiceTest("testCreateDocument", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMObjectServiceTest("testCreateDocument", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMObjectServiceTest("testCreateFolder", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMObjectServiceTest("testCreateFolder", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMObjectServiceTest("testGetDocumentProperties", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMObjectServiceTest("testGetDocumentProperties", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMObjectServiceTest("testGetContentStream", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMObjectServiceTest("testGetContentStream", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMObjectServiceTest("testCreatePolicy", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMObjectServiceTest("testCreatePolicy", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMObjectServiceTest("testCreateRelationship", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMObjectServiceTest("testCreateRelationship", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMObjectServiceTest("testDeleteContentStream", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMObjectServiceTest("testDeleteContentStream", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMObjectServiceTest("testDeleteObject", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMObjectServiceTest("testDeleteObject", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMObjectServiceTest("testDeleteTree", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMObjectServiceTest("testDeleteTree", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMObjectServiceTest("testGetAllowableActions", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMObjectServiceTest("testGetAllowableActions", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMObjectServiceTest("testMoveObject", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMObjectServiceTest("testMoveObject", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMObjectServiceTest("testSetContentStream", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMObjectServiceTest("testSetContentStream", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMObjectServiceTest("testUpdateProperties", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMObjectServiceTest("testUpdateProperties", USERNAME_USER1, PASSWORD_USER1)); + + // MultiThreadsServiceTest + // suite.addTest(new MultiThreadsServiceTest("testUpdateDocumentMultiThreaded", USERNAME_USER1, PASSWORD_USER1)); + suite.addTest(new MultiThreadsServiceTest("testSetTextContentStreamMultiThreaded", USERNAME_USER1, PASSWORD_USER1)); + + // //Policy Service tests + // suite.addTest(new DMPolicyServiceTest("testApplyPolicy", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMPolicyServiceTest("testApplyPolicy", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMPolicyServiceTest("testGetAppliedPolicies", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMPolicyServiceTest("testGetAppliedPolicies", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMPolicyServiceTest("testRemovePolicy", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMPolicyServiceTest("testRemovePolicy", USERNAME_USER1, PASSWORD_USER1)); + + // Repository Service tests + // suite.addTest(new DMRepositoryServiceTest("testGetRepositories", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMRepositoryServiceTest("testGetRepositories", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMRepositoryServiceTest("testGetRepositoryInfo", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMRepositoryServiceTest("testGetRepositoryInfo", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMRepositoryServiceTest("testGetTypes", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMRepositoryServiceTest("testGetTypes", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMRepositoryServiceTest("testGetTypeDefinition", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMRepositoryServiceTest("testGetTypeDefinition", USERNAME_USER1, PASSWORD_USER1)); + + // Versioning Service tests + // suite.addTest(new DMVersioningServiceTest("testCheckOutCheckIn", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMVersioningServiceTest("testCheckOutCheckIn", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMVersioningServiceTest("testCheckOutCancelCheckOut", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMVersioningServiceTest("testCheckOutCancelCheckOut", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMVersioningServiceTest("testGetPropertiesOfLatestVersion", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMVersioningServiceTest("testGetPropertiesOfLatestVersion", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMVersioningServiceTest("testGetAllVersions", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMVersioningServiceTest("testGetAllVersions", USERNAME_USER1, PASSWORD_USER1)); + // suite.addTest(new DMVersioningServiceTest("testDeleteAllVersions", USERNAME_ADMIN, PASSWORD_ADMIN)); + suite.addTest(new DMVersioningServiceTest("testDeleteAllVersions", USERNAME_USER1, PASSWORD_USER1)); + return suite; + + } +} diff --git a/source/test/java/org/alfresco/repo/cmis/ws/filtering/PropertyFilterTest.java b/source/test/java/org/alfresco/repo/cmis/ws/filtering/PropertyFilterTest.java new file mode 100755 index 0000000000..ee789c5b04 --- /dev/null +++ b/source/test/java/org/alfresco/repo/cmis/ws/filtering/PropertyFilterTest.java @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2005-2008 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 + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws.filtering; + +import org.alfresco.repo.cmis.ws.FilterNotValidException; +import org.alfresco.repo.cmis.ws.PropertyFilter; + +import junit.framework.TestCase; + +/** + * @author Dmitry Velichkevich + */ +public class PropertyFilterTest extends TestCase +{ + private static final String NAME_TOKEN = "name"; + + private static final String[] FILTER_TOKENS = new String[] { "Name", NAME_TOKEN, "nAmE", "ObjectId", "ObjectID", "objectId" }; + private static final String[] TOKENS_THAT_ARE_NOT_ALLOWED = new String[] { "ParentId", "parentId", "ParEnTiD", "IsMajorVersion", "iSmAJORvERSION" }; + + private static final String VALID_MATCHE_ALL_FILTER = "*"; + private static final String VALID_MATCHE_ALL_EMPTY_FILTER = ""; + private static final String VALID_FILTER_WITH_NAME = NAME_TOKEN; + private static final String VALID_FILTER_WITH_SEVERAL_TOKENS = "name, ObjectId"; + private static final String LONG_VALID_FILTER_WITH_SEVERAL_TOKENS = "ObjectId, name, CreationDate, CreatedBy"; + private static final String VALID_FILTER_WITH_SEVERAL_TOKENS_WITHOUT_BREAKS = "name,Objectid,CreationDate"; + private static final String VALID_FILTER_WITH_SEVERAL_TOKENS_AND_WITH_BREAKS_IN_SOME_PLACES = "name, Objectid,CreationDate,CreatedBy, ModifiedBy, LastModifiedBy"; + private static final String VALID_FILTER_WITH_SEVERAL_TOKENS_AND_WITH_SEVERAL_BREAKS_IN_SOME_PLACES = "name, Objectid, CreationDate,CreatedBy, ModifiedBy, LastModifiedBy"; + + private static final String INVALID_MATCHE_ALL_FILTER = "*,"; + private static final String INVALID_FILTER_WITH_NAME = "*name,"; + private static final String INVALID_FILTER_WITH_SEVERAL_TOKENS = "name ,ObjectId"; + private static final String LONG_INVALID_FILTER_WITH_SEVERAL_TOKENS = "ObjectId, name CreationDate, CreatedBy*"; + private static final String INVALID_FILTER_WITH_SEVERAL_TOKENS_WITHOUT_BREAKS = ",name,Objectid,CreationDate"; + private static final String INVALID_FILTER_WITH_SEVERAL_TOKENS_AND_WITH_BREAKS_IN_SOME_PLACES = " name, Objectid,CreationDate CreatedBy ModifiedBy, LastModifiedBy"; + private static final String INVALID_FILTER_WITH_FIRST_BREAK_SYMBOL = " name, Objectid,CreationDate, CreatedBy, ModifiedBy, LastModifiedBy"; + private static final String INVALID_FILTER_WITH_DENIED_SYMBOL = "ObjectId; name"; + private static final String INVALID_FILTER_WITH_LAST_INVALID_SYMBOL = "ObjectId, name*"; + + public void testValidFilters() throws Exception + { + + try + { + allTokensValidAssertion(new PropertyFilter()); + allTokensValidAssertion(new PropertyFilter(VALID_MATCHE_ALL_EMPTY_FILTER)); + allTokensValidAssertion(new PropertyFilter(VALID_MATCHE_ALL_FILTER)); + + onlyNameTokensAssertionValid(new PropertyFilter(VALID_FILTER_WITH_NAME)); + + nameAndObjectIdTokensAssertionValid(new PropertyFilter(VALID_FILTER_WITH_SEVERAL_TOKENS)); + nameAndObjectIdTokensAssertionValid(new PropertyFilter(LONG_VALID_FILTER_WITH_SEVERAL_TOKENS)); + nameAndObjectIdTokensAssertionValid(new PropertyFilter(VALID_FILTER_WITH_SEVERAL_TOKENS_WITHOUT_BREAKS)); + nameAndObjectIdTokensAssertionValid(new PropertyFilter(VALID_FILTER_WITH_SEVERAL_TOKENS_AND_WITH_BREAKS_IN_SOME_PLACES)); + nameAndObjectIdTokensAssertionValid(new PropertyFilter(VALID_FILTER_WITH_SEVERAL_TOKENS_AND_WITH_SEVERAL_BREAKS_IN_SOME_PLACES)); + } + catch (Throwable e) + { + fail(e.getMessage()); + } + } + + public void testInvalidFilters() throws Exception + { + + invalidFilterAssertion(INVALID_MATCHE_ALL_FILTER); + invalidFilterAssertion(INVALID_FILTER_WITH_NAME); + invalidFilterAssertion(INVALID_FILTER_WITH_SEVERAL_TOKENS); + invalidFilterAssertion(LONG_INVALID_FILTER_WITH_SEVERAL_TOKENS); + invalidFilterAssertion(INVALID_FILTER_WITH_SEVERAL_TOKENS_WITHOUT_BREAKS); + invalidFilterAssertion(INVALID_FILTER_WITH_SEVERAL_TOKENS_AND_WITH_BREAKS_IN_SOME_PLACES); + invalidFilterAssertion(INVALID_FILTER_WITH_FIRST_BREAK_SYMBOL); + invalidFilterAssertion(INVALID_FILTER_WITH_DENIED_SYMBOL); + invalidFilterAssertion(INVALID_FILTER_WITH_LAST_INVALID_SYMBOL); + } + + private void nameAndObjectIdTokensAssertionValid(PropertyFilter propertyFilter) + { + + for (String token : FILTER_TOKENS) + { + assertTrue(propertyFilter.allow(token)); + } + + for (String token : TOKENS_THAT_ARE_NOT_ALLOWED) + { + assertFalse(propertyFilter.allow(token)); + } + } + + private void onlyNameTokensAssertionValid(PropertyFilter propertyFilter) + { + + for (String token : FILTER_TOKENS) + { + if (!token.equalsIgnoreCase(NAME_TOKEN)) + { + break; + } + + assertTrue(propertyFilter.allow(token)); + } + + for (String token : TOKENS_THAT_ARE_NOT_ALLOWED) + { + assertFalse(propertyFilter.allow(token)); + } + } + + private void allTokensValidAssertion(PropertyFilter propertyFilter) + { + + for (String token : FILTER_TOKENS) + { + assertTrue(propertyFilter.allow(token)); + } + + for (String token : TOKENS_THAT_ARE_NOT_ALLOWED) + { + assertTrue(propertyFilter.allow(token)); + } + } + + private void invalidFilterAssertion(String filterValue) + { + + try + { + new PropertyFilter(filterValue); + + fail("Invalid filter \"" + filterValue + "\" was interpreted as valid"); + } + catch (Throwable e) + { + assertTrue(("Unexpected exception type was thrown: " + e.getClass().getName()), e instanceof FilterNotValidException); + } + } +}