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,21 +224,16 @@ 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);
}
catch (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
List<NodeRef> parents = receiveObjectParents(childNode); List<NodeRef> parents = receiveObjectParents(childNode);
List<CmisObjectParentsType> result = new ArrayList<CmisObjectParentsType>(); List<CmisObjectParentsType> result = new ArrayList<CmisObjectParentsType>();
@@ -256,6 +252,11 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
} }
return result; return result;
} }
catch (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
}
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,
EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments, CMISTypesFilterEnum types) throws CmisException EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments, CMISTypesFilterEnum types) throws CmisException
@@ -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());
try
{
repositoryInfoType.setRootFolderId(propertiesUtil.getProperty(cmisService.getDefaultRootNodeRef(), CMISDictionaryModel.PROP_OBJECT_ID, (String) null)); 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: