ALF-2086: CMIS Web Service policy and aspect unit tests

- Added Alfresco-specific unit tests, actually run by the build
- Fixed exception handling in getProperty
- Fix null value handling in createProperty

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@19451 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Dave Ward
2010-03-22 12:08:30 +00:00
parent e31bab4ce7
commit 56d4c7c51a
6 changed files with 420 additions and 24 deletions

View File

@@ -25,6 +25,7 @@ import java.util.List;
import java.util.Stack; import java.util.Stack;
import org.alfresco.cmis.CMISDictionaryModel; import org.alfresco.cmis.CMISDictionaryModel;
import org.alfresco.cmis.CMISInvalidArgumentException;
import org.alfresco.cmis.CMISServiceException; import org.alfresco.cmis.CMISServiceException;
import org.alfresco.cmis.CMISTypesFilterEnum; import org.alfresco.cmis.CMISTypesFilterEnum;
import org.alfresco.cmis.PropertyFilter; import org.alfresco.cmis.PropertyFilter;
@@ -223,38 +224,38 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT, * @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, CONSTRAINT,
* FILTER_NOT_VALID) * FILTER_NOT_VALID)
*/ */
public List<CmisObjectParentsType> getObjectParents(String repositoryId, String objectId, String filter, Boolean includeAllowableActions, public List<CmisObjectParentsType> getObjectParents(String repositoryId, String objectId, String filter,
EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includeRelativePathSegment, CmisExtensionType extension) throws CmisException Boolean includeAllowableActions, EnumIncludeRelationships includeRelationships, String renditionFilter,
Boolean includeRelativePathSegment, CmisExtensionType extension) throws CmisException
{ {
checkRepositoryId(repositoryId); checkRepositoryId(repositoryId);
PropertyFilter propertyFilter = createPropertyFilter(filter); PropertyFilter propertyFilter = createPropertyFilter(filter);
NodeRef childNode;
try try
{ {
childNode = (NodeRef) cmisService.getReadableObject(objectId, NodeRef.class); NodeRef childNode = (NodeRef) cmisService.getReadableObject(objectId, NodeRef.class);
List<NodeRef> parents = receiveObjectParents(childNode);
List<CmisObjectParentsType> result = new ArrayList<CmisObjectParentsType>();
String relativePathSegment = propertiesUtil.getProperty(childNode, CMISDictionaryModel.PROP_NAME, "");
for (NodeRef objectNodeRef : parents)
{
CmisObjectType cmisObject = createCmisObject(objectNodeRef, propertyFilter, includeRelationships,
includeAllowableActions, renditionFilter);
CmisObjectParentsType cmisObjectParentsType = new CmisObjectParentsType();
cmisObjectParentsType.setObject(cmisObject);
if (includeRelativePathSegment != null && includeRelativePathSegment)
{
cmisObjectParentsType.setRelativePathSegment(relativePathSegment);
}
result.add(cmisObjectParentsType);
}
return result;
} }
catch (CMISServiceException e) catch (CMISServiceException e)
{ {
throw ExceptionUtil.createCmisException(e); throw ExceptionUtil.createCmisException(e);
} }
List<NodeRef> parents = receiveObjectParents(childNode);
List<CmisObjectParentsType> result = new ArrayList<CmisObjectParentsType>();
String relativePathSegment = propertiesUtil.getProperty(childNode, CMISDictionaryModel.PROP_NAME, "");
for (NodeRef objectNodeRef : parents)
{
CmisObjectType cmisObject = createCmisObject(objectNodeRef, propertyFilter, includeRelationships,
includeAllowableActions, renditionFilter);
CmisObjectParentsType cmisObjectParentsType = new CmisObjectParentsType();
cmisObjectParentsType.setObject(cmisObject);
if (includeRelativePathSegment != null && includeRelativePathSegment)
{
cmisObjectParentsType.setRelativePathSegment(relativePathSegment);
}
result.add(cmisObjectParentsType);
}
return result;
} }
private CmisObjectInFolderContainerType getDescendantsTree(String repositoryId, String folderId, BigInteger depth, String filter, Boolean includeAllowableActions, private CmisObjectInFolderContainerType getDescendantsTree(String repositoryId, String folderId, BigInteger depth, String filter, Boolean includeAllowableActions,
@@ -316,7 +317,15 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
objectInFolderType.setObject(cmisObject); objectInFolderType.setObject(cmisObject);
if (includePathSegments != null && includePathSegments) if (includePathSegments != null && includePathSegments)
{ {
String path = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_NAME, ""); String path;
try
{
path = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_NAME, "");
}
catch (CMISInvalidArgumentException e)
{
throw ExceptionUtil.createCmisException(e);
}
objectInFolderType.setPathSegment(path); objectInFolderType.setPathSegment(path);
} }
CmisObjectInFolderContainerType result = new CmisObjectInFolderContainerType(); CmisObjectInFolderContainerType result = new CmisObjectInFolderContainerType();

View File

@@ -38,6 +38,7 @@ import org.alfresco.cmis.CMISChoice;
import org.alfresco.cmis.CMISContentStreamAllowedEnum; import org.alfresco.cmis.CMISContentStreamAllowedEnum;
import org.alfresco.cmis.CMISDataTypeEnum; import org.alfresco.cmis.CMISDataTypeEnum;
import org.alfresco.cmis.CMISDictionaryModel; import org.alfresco.cmis.CMISDictionaryModel;
import org.alfresco.cmis.CMISInvalidArgumentException;
import org.alfresco.cmis.CMISJoinEnum; import org.alfresco.cmis.CMISJoinEnum;
import org.alfresco.cmis.CMISPermissionDefinition; import org.alfresco.cmis.CMISPermissionDefinition;
import org.alfresco.cmis.CMISPermissionMapping; import org.alfresco.cmis.CMISPermissionMapping;
@@ -457,7 +458,14 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re
repositoryInfoType.setVendorName("Alfresco"); repositoryInfoType.setVendorName("Alfresco");
repositoryInfoType.setProductName("Alfresco Repository (" + serverDescriptor.getEdition() + ")"); repositoryInfoType.setProductName("Alfresco Repository (" + serverDescriptor.getEdition() + ")");
repositoryInfoType.setProductVersion(serverDescriptor.getVersion()); repositoryInfoType.setProductVersion(serverDescriptor.getVersion());
repositoryInfoType.setRootFolderId(propertiesUtil.getProperty(cmisService.getDefaultRootNodeRef(), CMISDictionaryModel.PROP_OBJECT_ID, (String) null)); try
{
repositoryInfoType.setRootFolderId(propertiesUtil.getProperty(cmisService.getDefaultRootNodeRef(), CMISDictionaryModel.PROP_OBJECT_ID, (String) null));
}
catch (CMISInvalidArgumentException e)
{
throw ExceptionUtil.createCmisException(e);
}
repositoryInfoType.setLatestChangeLogToken(cmisChangeLogService.getLastChangeLogToken()); repositoryInfoType.setLatestChangeLogToken(cmisChangeLogService.getLastChangeLogToken());
// TODO: cmisVersionSupported is different in stubs and specification // TODO: cmisVersionSupported is different in stubs and specification
repositoryInfoType.setCmisVersionSupported("1.0"); repositoryInfoType.setCmisVersionSupported("1.0");

View File

@@ -0,0 +1,139 @@
/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.cmis.ws.test;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.xml.ws.Holder;
import org.alfresco.repo.cmis.ws.Aspects;
import org.alfresco.repo.cmis.ws.CmisExtensionType;
import org.alfresco.repo.cmis.ws.CmisPropertiesType;
import org.alfresco.repo.cmis.ws.CmisProperty;
import org.alfresco.repo.cmis.ws.CmisPropertyString;
import org.alfresco.repo.cmis.ws.SetAspects;
import org.junit.Assert;
/**
* Tests Alfresco CMIS WebService API extensions for Aspects.
*
* @author dward
*/
public class AspectTest extends BaseCMISTest
{
public void testAspectSet() throws Exception
{
// create document for checkout
Holder<String> objectId = new Holder<String>();
objectServicePort.createDocument(repositoryId, createObjectProperties(getName(), "cmis:document"),
testFolderId, null, null, null, null, null, new Holder<CmisExtensionType>(), objectId);
Assert.assertNotNull(objectId.value);
// checkout
versioningServicePort.checkOut(repositoryId, objectId, new Holder<CmisExtensionType>(), new Holder<Boolean>());
Assert.assertNotNull(objectId.value);
// Apply some aspects to the working copy
{
CmisPropertiesType properties = new CmisPropertiesType();
SetAspects extension = new SetAspects();
properties.getAny().add(extension);
extension.getAspectsToAdd().addAll(Arrays.asList(new String[]
{
"P:cm:syndication", "P:cm:summarizable"
}));
CmisPropertiesType extensionProperties = new CmisPropertiesType();
extension.setProperties(extensionProperties);
setStringProperty(extensionProperties, "cm:summary", "Aspect Test (summary)");
// Add a property without explicitly adding its aspect. Should be automatically added.
setStringProperty(extensionProperties, "cm:author", "David Ward");
objectServicePort.updateProperties(repositoryId, objectId, null, properties, null);
CmisPropertiesType updated = objectServicePort.getProperties(repositoryId, objectId.value, null, null);
Set<String> appliedAspects = new HashSet<String>(5);
Map<String, String> aspectProperties = new HashMap<String, String>(11);
extractAspectsAndProperties(updated, appliedAspects, aspectProperties);
assertContains(appliedAspects, "P:cm:syndication", "P:cm:summarizable", "P:cm:author");
assertEquals("Aspect Test (summary)", aspectProperties.get("cm:summary"));
assertEquals("David Ward", aspectProperties.get("cm:author"));
}
// check in with updated aspects
{
CmisPropertiesType properties = new CmisPropertiesType();
SetAspects extension = new SetAspects();
properties.getAny().add(extension);
extension.getAspectsToAdd().add("P:cm:countable");
extension.getAspectsToRemove().add("P:cm:author");
CmisPropertiesType extensionProperties = new CmisPropertiesType();
extension.setProperties(extensionProperties);
setStringProperty(extensionProperties, "cm:summary", "Aspect Test (new summary)");
versioningServicePort.checkIn(repositoryId, objectId, null, properties, null, null, null, null, null,
new Holder<CmisExtensionType>());
CmisPropertiesType checkedIn = objectServicePort.getProperties(repositoryId, objectId.value, null, null);
Set<String> appliedAspects = new HashSet<String>(5);
Map<String, String> aspectProperties = new HashMap<String, String>(11);
extractAspectsAndProperties(checkedIn, appliedAspects, aspectProperties);
assertContains(appliedAspects, "P:cm:syndication", "P:cm:summarizable", "P:cm:countable");
assertDoesNotContain(appliedAspects, "P:cm:author");
assertEquals("Aspect Test (new summary)", aspectProperties.get("cm:summary"));
assertNull(aspectProperties.get("cm:author"));
}
}
/**
* @param properties
* @param appliedAspects
* @param aspectProperties
*/
private void extractAspectsAndProperties(CmisPropertiesType properties, Set<String> appliedAspects,
Map<String, String> aspectProperties)
{
Aspects extension = null;
for (Object object : properties.getAny())
{
if (object instanceof Aspects)
{
extension = (Aspects) object;
break;
}
}
if (extension == null)
{
fail("alf:aspects element not included");
}
appliedAspects.addAll(extension.getAppliedAspects());
CmisPropertiesType extensionProperties = extension.getProperties();
if (extensionProperties == null)
{
return;
}
for (CmisProperty property : extensionProperties.getProperty())
{
if (property instanceof CmisPropertyString)
{
aspectProperties.put(property.getPropertyDefinitionId(), ((CmisPropertyString) property).getValue()
.get(0));
}
}
}
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.cmis.ws.test;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.xml.ws.Holder;
import junit.framework.TestCase;
import org.alfresco.cmis.CMISDictionaryModel;
import org.alfresco.repo.cmis.ws.CmisException;
import org.alfresco.repo.cmis.ws.CmisExtensionType;
import org.alfresco.repo.cmis.ws.CmisPropertiesType;
import org.alfresco.repo.cmis.ws.CmisPropertyId;
import org.alfresco.repo.cmis.ws.CmisPropertyString;
import org.alfresco.repo.cmis.ws.ObjectServicePort;
import org.alfresco.repo.cmis.ws.PolicyServicePort;
import org.alfresco.repo.cmis.ws.RepositoryServicePort;
import org.alfresco.repo.cmis.ws.VersioningServicePort;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.util.ApplicationContextHelper;
import org.junit.Assert;
import org.springframework.context.ApplicationContext;
/**
* Base class for tests to Alfresco CMIS WebService API extensions.
*
* @author dward
*/
public abstract class BaseCMISTest extends TestCase
{
protected RepositoryServicePort repositoryServicePort;
protected ObjectServicePort objectServicePort;
protected VersioningServicePort versioningServicePort;
protected PolicyServicePort policyServicePort;
protected String defaultRunAs = "admin";
protected String repositoryId;
protected String testFolderId;
public BaseCMISTest()
{
ApplicationContext ctx = ApplicationContextHelper.getApplicationContext(new String[]
{
ApplicationContextHelper.CONFIG_LOCATIONS[0], "classpath:alfresco/web-services-application-context.xml"
});
repositoryServicePort = (RepositoryServicePort) ctx.getBean("dmRepositoryService");
objectServicePort = (ObjectServicePort) ctx.getBean("dmObjectService");
versioningServicePort = (VersioningServicePort) ctx.getBean("dmVersioningService");
policyServicePort = (PolicyServicePort) ctx.getBean("dmPolicyService");
try
{
repositoryId = repositoryServicePort.getRepositories(null).get(0).getRepositoryId();
}
catch (CmisException e)
{
throw new RuntimeException(e);
}
}
public void setDefaultRunAs(String defaultRunAs)
{
this.defaultRunAs = defaultRunAs;
}
@Override
protected void setUp() throws Exception
{
AuthenticationUtil.setFullyAuthenticatedUser(defaultRunAs);
String rootFolderId = repositoryServicePort.getRepositoryInfo(repositoryId, null).getRootFolderId();
Holder<String> objectId = new Holder<String>();
String folderName = getClass().getSimpleName() + System.currentTimeMillis() + " - " + getName();
objectServicePort.createFolder(repositoryId, createObjectProperties(folderName, "cmis:folder"), rootFolderId,
null, null, null, new Holder<CmisExtensionType>(), objectId);
testFolderId = objectId.value;
}
@Override
protected void tearDown() throws Exception
{
AuthenticationUtil.clearCurrentSecurityContext();
}
protected CmisPropertiesType createObjectProperties(String name, String type)
{
CmisPropertiesType properties = new CmisPropertiesType();
CmisPropertyString stringProperty = new CmisPropertyString();
stringProperty.setPropertyDefinitionId(CMISDictionaryModel.PROP_NAME);
stringProperty.getValue().add(name);
properties.getProperty().add(stringProperty);
CmisPropertyId idProperty = new CmisPropertyId();
idProperty.setPropertyDefinitionId(CMISDictionaryModel.PROP_OBJECT_TYPE_ID);
idProperty.getValue().add(type);
properties.getProperty().add(idProperty);
return properties;
}
protected void setStringProperty(CmisPropertiesType properties, String id, String value)
{
CmisPropertyString stringProperty = new CmisPropertyString();
properties.getProperty().add(stringProperty);
stringProperty.setPropertyDefinitionId(id);
stringProperty.getValue().add(value);
}
protected void assertContains(Set<String> actual, String... expected)
{
Assert.assertTrue(actual.containsAll(Arrays.asList(expected)));
}
protected void assertDoesNotContain(Set<String> actual, String... unexpected)
{
Set<String> copy = new HashSet<String>(actual);
copy.retainAll(Arrays.asList(unexpected));
Assert.assertTrue(copy.isEmpty());
}
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.cmis.ws.test;
import java.util.List;
import javax.xml.ws.Holder;
import org.alfresco.repo.cmis.ws.CmisException;
import org.alfresco.repo.cmis.ws.CmisExtensionType;
import org.alfresco.repo.cmis.ws.CmisObjectType;
import org.alfresco.repo.cmis.ws.CmisTypeDefinitionListType;
import org.alfresco.repo.cmis.ws.CmisTypeDefinitionType;
import org.alfresco.repo.cmis.ws.EnumServiceException;
import org.junit.Assert;
/**
* Tests Alfresco CMIS Policy Web Service implementation.
*
* @author dward
*/
public class PolicyTest extends BaseCMISTest
{
public void testPolicies() throws Exception
{
// Try creating an object with the cmis:policy base type (expect a constraint exception)
Holder<String> objectId = new Holder<String>();
try
{
objectServicePort.createPolicy(repositoryId, createObjectProperties(getName(), "cmis:policy"),
testFolderId, null, null, null, new Holder<CmisExtensionType>(), objectId);
fail("Expected CmisException");
}
catch (CmisException e)
{
Assert.assertEquals(EnumServiceException.CONSTRAINT, e.getFaultInfo().getType());
}
// Try creating an object of any of the cmis:policy subtypes
CmisTypeDefinitionListType typeDefs = repositoryServicePort.getTypeChildren(repositoryId, "cmis:policy", true,
null, null, null);
List<CmisTypeDefinitionType> entries = typeDefs.getTypes();
assertNotSame(0, entries.size());
for (CmisTypeDefinitionType type : entries)
{
try
{
objectServicePort.createPolicy(repositoryId, createObjectProperties(getName(), type.getId()),
testFolderId, null, null, null, new Holder<CmisExtensionType>(), objectId);
fail("Expected CmisException");
}
catch (CmisException e)
{
Assert.assertEquals(EnumServiceException.CONSTRAINT, e.getFaultInfo().getType());
}
}
// Create a document to attempt to apply policies to
objectServicePort.createDocument(repositoryId, createObjectProperties(getName(), "cmis:document"),
testFolderId, null, null, null, null, null, new Holder<CmisExtensionType>(), objectId);
Assert.assertNotNull(objectId.value);
// retrieve list of policies applied to document (this should be empty)
List<CmisObjectType> policies = policyServicePort.getAppliedPolicies(repositoryId, objectId.value, null, null);
assertNotNull(policies);
assertEquals(0, policies.size());
// Try applying a policy (expect a constraint exception)
try
{
policyServicePort
.applyPolicy(repositoryId, "doesnotexist", objectId.value, new Holder<CmisExtensionType>());
fail("Expected CmisException");
}
catch (CmisException e)
{
Assert.assertEquals(EnumServiceException.CONSTRAINT, e.getFaultInfo().getType());
}
}
}

View File

@@ -123,17 +123,20 @@ public class PropertyUtil
* @param defaultValue - some value of the appropriate for conversion type. Also <b>null</b> may be accepted by this parameter * @param defaultValue - some value of the appropriate for conversion type. Also <b>null</b> may be accepted by this parameter
* @return value instance of the appropriate type if specified object has such property and <i>defaultValue</i> if requested property value or <i>objectNodeRef</i> or * @return value instance of the appropriate type if specified object has such property and <i>defaultValue</i> if requested property value or <i>objectNodeRef</i> or
* <i>propertyName</i> are <b>null</b> or if some exception occurred during property receiving * <i>propertyName</i> are <b>null</b> or if some exception occurred during property receiving
* @throws CMISInvalidArgumentException
*/ */
public <ResultType> ResultType getProperty(NodeRef objectNodeRef, String propertyName, ResultType defaultValue) public <ResultType> ResultType getProperty(NodeRef objectNodeRef, String propertyName, ResultType defaultValue)
throws CMISInvalidArgumentException
{ {
if ((null == objectNodeRef) || (null == propertyName)) if ((null == objectNodeRef) || (null == propertyName))
{ {
return defaultValue; return defaultValue;
} }
Serializable value = cmisService.getProperty(objectNodeRef, propertyName);
try try
{ {
return convertPropertyValue(cmisService.getProperty(objectNodeRef, propertyName), defaultValue); return convertPropertyValue(value, defaultValue);
} }
catch (Exception exception) catch (Exception exception)
{ {
@@ -511,6 +514,11 @@ public class PropertyUtil
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public CmisProperty createProperty(String pdid, CMISDataTypeEnum dataType, Serializable value) public CmisProperty createProperty(String pdid, CMISDataTypeEnum dataType, Serializable value)
{ {
if (value == null)
{
return null;
}
switch (dataType) switch (dataType)
{ {
case BOOLEAN: case BOOLEAN: