Merging BRANCHES/DEV/CMIS_10 to HEAD (phase 2 - currently up-to-date with branch):

18717: SAIL-166: Refactor CMIS to use shared services and resolve objectIds and error codes consistently
   18731: SAIL-169: CMIS REST versioning compliance
   18732: Fix failing change log test.
   18768: Add displayName and queryName attributes to rendered properties (in CMIS AtomPub binding).
   18775: Fix exception reporting when retrieving items that do not exist (in CMIS AtomPub binding).
   18784: Fix CMIS REST change logging
   18785: SAIL-174: CMIS Relationship lookup by association ID
   18812: SAIL-183: Support orderBy argument for getChildren and getCheckedOutDocs in CMIS REST and Web Service bindings
   18823: CMIS WS Bindings were moved to 1.0 cd07 schema.
   18838: Update to latest Chemistry TCK.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@18847 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
David Caruana
2010-02-25 15:02:44 +00:00
parent fc172da640
commit bd2f2441fd
65 changed files with 2477 additions and 2782 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
* Copyright (C) 2005-2010 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
@@ -15,60 +15,61 @@
* 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 received 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.Serializable;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.bind.JAXBElement;
import javax.xml.ws.Holder;
import org.alfresco.cmis.CMISAccessControlEntry;
import org.alfresco.cmis.CMISAccessControlFormatEnum;
import org.alfresco.cmis.CMISAccessControlReport;
import org.alfresco.cmis.CMISAccessControlService;
import org.alfresco.cmis.CMISAclPropagationEnum;
import org.alfresco.cmis.CMISActionEvaluator;
import org.alfresco.cmis.CMISAllowedActionEnum;
import org.alfresco.cmis.CMISChangeLogService;
import org.alfresco.cmis.CMISDictionaryModel;
import org.alfresco.cmis.CMISDictionaryService;
import org.alfresco.cmis.CMISConstraintException;
import org.alfresco.cmis.CMISFilterNotValidException;
import org.alfresco.cmis.CMISInvalidArgumentException;
import org.alfresco.cmis.CMISQueryService;
import org.alfresco.cmis.CMISRendition;
import org.alfresco.cmis.CMISRenditionService;
import org.alfresco.cmis.CMISServices;
import org.alfresco.cmis.CMISTypeDefinition;
import org.alfresco.model.ContentModel;
import org.alfresco.cmis.acl.CMISAccessControlEntryImpl;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.cmis.PropertyFilter;
import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType;
import org.alfresco.repo.cmis.ws.utils.CmisObjectsUtils;
import org.alfresco.repo.cmis.ws.utils.ExceptionUtil;
import org.alfresco.repo.cmis.ws.utils.PropertyUtil;
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.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.service.descriptor.DescriptorService;
/**
@@ -81,24 +82,41 @@ import org.alfresco.service.descriptor.DescriptorService;
*/
public class DMAbstractServicePort
{
protected static final String INITIAL_VERSION_DESCRIPTION = "Initial version";
private static final String CMIS_USER = "cmis:user";
private static final String INVALID_REPOSITORY_ID_MESSAGE = "Invalid repository id";
private static final String INVALID_FOLDER_OBJECT_ID_MESSAGE = "OID for non-existent object or not folder object";
private static final Map<EnumACLPropagation, CMISAclPropagationEnum> ACL_PROPAGATION_ENUM_MAPPGIN;
private static final Map<CMISAllowedActionEnum, PropertyDescriptor> ALLOWED_ACTION_ENUM_MAPPING;
static
{
ACL_PROPAGATION_ENUM_MAPPGIN = new HashMap<EnumACLPropagation, CMISAclPropagationEnum>();
ACL_PROPAGATION_ENUM_MAPPGIN.put(EnumACLPropagation.OBJECTONLY, CMISAclPropagationEnum.OBJECT_ONLY);
ACL_PROPAGATION_ENUM_MAPPGIN.put(EnumACLPropagation.PROPAGATE, CMISAclPropagationEnum.PROPAGATE);
ACL_PROPAGATION_ENUM_MAPPGIN.put(EnumACLPropagation.REPOSITORYDETERMINED, CMISAclPropagationEnum.REPOSITORY_DETERMINED);
try
{
ALLOWED_ACTION_ENUM_MAPPING = new HashMap<CMISAllowedActionEnum, PropertyDescriptor>(97);
for (PropertyDescriptor propertyDescriptor : Introspector.getBeanInfo(CmisAllowableActionsType.class, Object.class).getPropertyDescriptors())
{
String label = propertyDescriptor.getName();
CMISAllowedActionEnum allowedActionEnum = CMISAllowedActionEnum.FACTORY.fromLabel(label);
if (allowedActionEnum != null)
{
ALLOWED_ACTION_ENUM_MAPPING.put(allowedActionEnum, propertyDescriptor);
}
}
}
catch (IntrospectionException e)
{
throw new ExceptionInInitializerError(e);
}
}
private Paging paging = new Paging();
protected ObjectFactory cmisObjectFactory = new ObjectFactory();
protected CMISDictionaryService cmisDictionaryService;
protected CMISQueryService cmisQueryService;
protected CMISServices cmisService;
protected CMISChangeLogService cmisChangeLogService;
@@ -107,11 +125,8 @@ public class DMAbstractServicePort
protected DescriptorService descriptorService;
protected NodeService nodeService;
protected VersionService versionService;
protected FileFolderService fileFolderService;
protected CheckOutCheckInService checkOutCheckInService;
protected SearchService searchService;
protected CmisObjectsUtils cmisObjectsUtils;
protected PropertyUtil propertiesUtil;
protected PermissionService permissionService;
@@ -120,11 +135,6 @@ public class DMAbstractServicePort
this.cmisService = cmisService;
}
public void setCmisDictionaryService(CMISDictionaryService cmisDictionaryService)
{
this.cmisDictionaryService = cmisDictionaryService;
}
public void setCmisQueryService(CMISQueryService cmisQueryService)
{
this.cmisQueryService = cmisQueryService;
@@ -155,27 +165,11 @@ public class DMAbstractServicePort
this.nodeService = nodeService;
}
public void setVersionService(VersionService versionService)
{
this.versionService = versionService;
}
public void setFileFolderService(FileFolderService fileFolderService)
{
this.fileFolderService = fileFolderService;
}
public void setCheckOutCheckInService(CheckOutCheckInService checkOutCheckInService)
{
this.checkOutCheckInService = checkOutCheckInService;
}
public void setCmisObjectsUtils(CmisObjectsUtils cmisObjectsUtils)
{
this.cmisObjectsUtils = cmisObjectsUtils;
}
public void setPropertiesUtil(PropertyUtil propertiesUtil)
{
this.propertiesUtil = propertiesUtil;
@@ -193,7 +187,7 @@ public class DMAbstractServicePort
protected PropertyFilter createPropertyFilter(String filter) throws CmisException
{
return (filter == null) ? (new PropertyFilter()) : (new PropertyFilter(filter, cmisObjectsUtils));
return (filter == null) ? (new PropertyFilter()) : (new PropertyFilter(filter));
}
protected PropertyFilter createPropertyFilter(JAXBElement<String> element) throws CmisException
@@ -239,7 +233,7 @@ public class DMAbstractServicePort
protected CmisObjectType createCmisObject(Object identifier, PropertyFilter filter, boolean includeAllowableActions, String renditionFilter) throws CmisException
{
CmisObjectType result = new CmisObjectType();
result.setProperties(propertiesUtil.getPropertiesType(identifier.toString(), filter));
result.setProperties(propertiesUtil.getProperties(identifier, filter));
if (includeAllowableActions)
{
result.setAllowableActions(determineObjectAllowableActions(identifier));
@@ -255,20 +249,6 @@ public class DMAbstractServicePort
return result;
}
/**
* Asserts "Folder with folderNodeRef exists"
*
* @param folderNodeRef node reference
* @throws FolderNotValidException folderNodeRef doesn't exist or folderNodeRef isn't for folder object
*/
protected void assertExistFolder(NodeRef folderNodeRef) throws CmisException
{
if (!this.cmisObjectsUtils.isFolder(folderNodeRef))
{
throw new CmisException(INVALID_FOLDER_OBJECT_ID_MESSAGE, cmisObjectsUtils.createCmisException(INVALID_FOLDER_OBJECT_ID_MESSAGE, EnumServiceException.INVALID_ARGUMENT));
}
}
/**
* Checks specified in CMIS request parameters repository Id.
*
@@ -279,54 +259,29 @@ public class DMAbstractServicePort
{
if (!this.descriptorService.getCurrentRepositoryDescriptor().getId().equals(repositoryId))
{
throw cmisObjectsUtils.createCmisException(INVALID_REPOSITORY_ID_MESSAGE, EnumServiceException.INVALID_ARGUMENT);
throw ExceptionUtil.createCmisException(INVALID_REPOSITORY_ID_MESSAGE, EnumServiceException.INVALID_ARGUMENT);
}
}
protected Map<String, Serializable> createVersionProperties(String versionDescription, VersionType versionType)
{
Map<String, Serializable> result = new HashMap<String, Serializable>();
result.put(Version.PROP_DESCRIPTION, versionDescription);
result.put(VersionModel.PROP_VERSION_TYPE, versionType);
return result;
}
protected NodeRef checkoutNode(NodeRef documentNodeReference)
{
if (!this.nodeService.hasAspect(documentNodeReference, ContentModel.ASPECT_VERSIONABLE))
{
this.versionService.createVersion(documentNodeReference, createVersionProperties(INITIAL_VERSION_DESCRIPTION, VersionType.MAJOR));
}
return checkOutCheckInService.checkout(documentNodeReference);
}
protected CMISTypeDefinition getCmisTypeDefinition(String typeId) throws CmisException
{
try
{
return cmisDictionaryService.findType(typeId);
}
catch (Exception e)
{
throw new CmisException(("Invalid typeId " + typeId), cmisObjectsUtils.createCmisException(("Invalid typeId " + typeId), EnumServiceException.INVALID_ARGUMENT));
}
}
protected List<CmisRenditionType> getRenditions(Object objectId, String renditionFilter) throws CmisException
protected List<CmisRenditionType> getRenditions(Object object, String renditionFilter) throws CmisException
{
List<CmisRenditionType> result = null;
if (NodeRef.isNodeRef(objectId.toString()))
if (object instanceof Version)
{
NodeRef document = new NodeRef(objectId.toString());
object = ((Version) object).getFrozenStateNodeRef();
}
if (object instanceof NodeRef)
{
NodeRef document = (NodeRef) object;
List<CMISRendition> renditions = null;
try
{
renditions = cmisRenditionService.getRenditions(document, renditionFilter);
}
catch (Exception e)
catch (CMISFilterNotValidException e)
{
throw cmisObjectsUtils.createCmisException("Invalid rendition filter", EnumServiceException.FILTER_NOT_VALID);
throw ExceptionUtil.createCmisException(e);
}
if (renditions != null && !renditions.isEmpty())
{
@@ -372,130 +327,44 @@ public class DMAbstractServicePort
{
return null;
}
String typeId = propertiesUtil.getProperty(object, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, null);
CMISTypeDefinition objectType = (null == typeId) ? (null) : (cmisDictionaryService.findType(typeId));
if (null == objectType)
{
throw cmisObjectsUtils.createCmisException("Type Definition for specified Object was not found", EnumServiceException.STORAGE);
}
if (!objectType.isControllableACL())
{
throw cmisObjectsUtils.createCmisException("Object that was specified is not ACL Controllable", EnumServiceException.CONSTRAINT);
}
CMISAclPropagationEnum propagation = (null == aclPropagation) ? (CMISAclPropagationEnum.PROPAGATE) : (ACL_PROPAGATION_ENUM_MAPPGIN.get(aclPropagation));
List<CMISAccessControlEntry> acesToAdd = (null == addACEs) ? (null) : (convertToAlfrescoAceEntriesList(addACEs.getPermission()));
List<CMISAccessControlEntry> acesToRemove = (null == removeACEs) ? (null) : (convertToAlfrescoAceEntriesList(removeACEs.getPermission()));
CMISAccessControlReport aclReport = null;
try
{
CMISAclPropagationEnum propagation = (null == aclPropagation) ? (CMISAclPropagationEnum.PROPAGATE) : (ACL_PROPAGATION_ENUM_MAPPGIN.get(aclPropagation));
List<CMISAccessControlEntry> acesToAdd = (null == addACEs) ? (null) : (convertToAlfrescoAceEntriesList(addACEs.getPermission()));
List<CMISAccessControlEntry> acesToRemove = (null == removeACEs) ? (null) : (convertToAlfrescoAceEntriesList(removeACEs.getPermission()));
CMISAccessControlReport aclReport = null;
aclReport = cmisAclService.applyAcl(object, acesToRemove, acesToAdd, propagation, CMISAccessControlFormatEnum.REPOSITORY_SPECIFIC_PERMISSIONS);
CmisACLType result = convertAclReportToCmisAclType(aclReport);
return result;
}
catch (Exception e)
catch (CMISConstraintException e)
{
throw cmisObjectsUtils.createCmisException(("Can't perform updating of Object Permissions. Error cause message: " + e.toString()), EnumServiceException.CONSTRAINT);
throw ExceptionUtil.createCmisException(e);
}
CmisACLType result = convertAclReportToCmisAclType(aclReport);
return result;
}
private List<CMISAccessControlEntry> convertToAlfrescoAceEntriesList(List<CmisAccessControlEntryType> source)
private List<CMISAccessControlEntry> convertToAlfrescoAceEntriesList(List<CmisAccessControlEntryType> source) throws CmisException
{
List<CMISAccessControlEntry> result = new LinkedList<CMISAccessControlEntry>();
for (CmisAccessControlEntryType cmisEntry : source)
{
result.add(convertToAlfrescoAceEntry(cmisEntry));
if (!cmisEntry.isDirect())
{
throw ExceptionUtil.createCmisException("Inherited Permissions can't be updated or deleted from Object", EnumServiceException.NOT_SUPPORTED);
}
String principalId = cmisEntry.getPrincipal().getPrincipalId();
if (CMIS_USER.equals(principalId))
{
principalId = AuthenticationUtil.getFullyAuthenticatedUser();
}
for (String permission : cmisEntry.getPermission())
{
result.add(new CMISAccessControlEntryImpl(principalId, permission));
}
}
return result;
}
private CMISAccessControlEntry convertToAlfrescoAceEntry(final CmisAccessControlEntryType entry)
{
final Holder<String> correctPrincipalId = new Holder<String>(entry.getPrincipal().getPrincipalId());
if ("cmis:user".equals(correctPrincipalId))
{
correctPrincipalId.value = AuthenticationUtil.getFullyAuthenticatedUser();
}
CMISAccessControlEntry result = new CMISAccessControlEntry() // FIXME: It is better to use already implemented class of this interface
{
private String principalId;
private String permission; // FIXME: [BUG] It MUST BE a List of permissions!!!
private boolean direct;
{
principalId = correctPrincipalId.value;
permission = entry.getPermission().iterator().next(); // FIXME: See line 66
direct = entry.isDirect();
}
public String getPrincipalId()
{
return principalId;
}
public String getPermission()
{
return permission;
}
public boolean getDirect()
{
return direct;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((permission == null) ? 0 : permission.hashCode());
result = prime * result + ((principalId == null) ? 0 : principalId.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final CMISAccessControlEntry other = (CMISAccessControlEntry) obj;
if (permission == null)
{
if (other.getPermission() != null)
{
return false;
}
}
else if (!permission.equals(other.getPermission()))
{
return false;
}
if (principalId == null)
{
if (other.getPrincipalId() != null)
{
return false;
}
}
else if (!principalId.equals(other.getPrincipalId()))
{
return false;
}
return true;
}
};
return result;
}
protected CmisACLType convertAclReportToCmisAclType(CMISAccessControlReport aclReport)
{
CmisACLType result = new CmisACLType();
@@ -515,90 +384,54 @@ public class DMAbstractServicePort
return result;
}
@SuppressWarnings("unchecked")
protected CmisAllowableActionsType determineObjectAllowableActions(Object objectIdentifier) throws CmisException
{
if (objectIdentifier instanceof String)
CMISTypeDefinition typeDef;
try
{
objectIdentifier = cmisObjectsUtils.getIdentifierInstance(objectIdentifier.toString(), AlfrescoObjectType.ANY_OBJECT);
if (objectIdentifier instanceof AssociationRef)
{
typeDef = cmisService.getTypeDefinition((AssociationRef) objectIdentifier);
}
else
{
if (objectIdentifier instanceof Version)
{
objectIdentifier = ((Version) objectIdentifier).getFrozenStateNodeRef();
}
typeDef = cmisService.getTypeDefinition((NodeRef) objectIdentifier);
}
}
if (objectIdentifier instanceof AssociationRef)
catch (CMISInvalidArgumentException e)
{
return determineRelationshipAllowableActions((AssociationRef) objectIdentifier);
throw ExceptionUtil.createCmisException(e);
}
switch (cmisObjectsUtils.determineObjectType(objectIdentifier.toString()))
{
case CMIS_DOCUMENT:
{
return determineDocumentAllowableActions((NodeRef) objectIdentifier);
}
case CMIS_FOLDER:
{
return determineFolderAllowableActions((NodeRef) objectIdentifier);
}
}
// TODO: determinePolicyAllowableActions() when Policy functionality is ready
throw cmisObjectsUtils.createCmisException("It is impossible to get Allowable actions for the specified Object", EnumServiceException.NOT_SUPPORTED);
}
private CmisAllowableActionsType determineBaseAllowableActions(NodeRef objectNodeReference)
{
CmisAllowableActionsType result = new CmisAllowableActionsType();
result.setCanGetProperties(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_PROPERTIES) == AccessStatus.ALLOWED);
result.setCanUpdateProperties(this.permissionService.hasPermission(objectNodeReference, PermissionService.WRITE_PROPERTIES) == AccessStatus.ALLOWED);
result.setCanDeleteObject(this.permissionService.hasPermission(objectNodeReference, PermissionService.DELETE) == AccessStatus.ALLOWED);
// TODO: response.setCanAddPolicy(value);
// TODO: response.setCanRemovePolicy(value);
// TODO: response.setCanGetAppliedPolicies(value);
return result;
}
private CmisAllowableActionsType determineDocumentAllowableActions(NodeRef objectNodeReference)
{
CmisAllowableActionsType result = determineBaseAllowableActions(objectNodeReference);
determineCommonFolderDocumentAllowableActions(objectNodeReference, result);
result.setCanGetObjectParents(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_ASSOCIATIONS) == AccessStatus.ALLOWED);
result.setCanGetContentStream(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_CONTENT) == AccessStatus.ALLOWED);
result.setCanSetContentStream(this.permissionService.hasPermission(objectNodeReference, PermissionService.WRITE_CONTENT) == AccessStatus.ALLOWED);
result.setCanCheckOut(this.permissionService.hasPermission(objectNodeReference, PermissionService.CHECK_OUT) == AccessStatus.ALLOWED);
result.setCanCheckIn(this.permissionService.hasPermission(objectNodeReference, PermissionService.CHECK_IN) == AccessStatus.ALLOWED);
result.setCanCancelCheckOut(this.permissionService.hasPermission(objectNodeReference, PermissionService.CANCEL_CHECK_OUT) == AccessStatus.ALLOWED);
result.setCanDeleteContentStream(result.isCanUpdateProperties() && result.isCanSetContentStream());
return result;
}
private CmisAllowableActionsType determineFolderAllowableActions(NodeRef objectNodeReference)
{
CmisAllowableActionsType result = determineBaseAllowableActions(objectNodeReference);
determineCommonFolderDocumentAllowableActions(objectNodeReference, result);
result.setCanGetChildren(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_CHILDREN) == AccessStatus.ALLOWED);
result.setCanCreateDocument(this.permissionService.hasPermission(objectNodeReference, PermissionService.ADD_CHILDREN) == AccessStatus.ALLOWED);
result.setCanGetDescendants(result.isCanGetChildren() && (this.permissionService.hasPermission(objectNodeReference, PermissionService.READ) == AccessStatus.ALLOWED));
result.setCanDeleteTree(this.permissionService.hasPermission(objectNodeReference, PermissionService.DELETE_CHILDREN) == AccessStatus.ALLOWED);
result.setCanGetFolderParent(result.isCanGetObjectRelationships());
result.setCanCreateFolder(result.isCanCreateDocument());
// TODO: response.setCanCreatePolicy(value);
return result;
}
private void determineCommonFolderDocumentAllowableActions(NodeRef objectNodeReference, CmisAllowableActionsType allowableActions)
{
allowableActions.setCanAddObjectToFolder(this.permissionService.hasPermission(objectNodeReference, PermissionService.CREATE_ASSOCIATIONS) == AccessStatus.ALLOWED);
allowableActions.setCanGetObjectRelationships(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_ASSOCIATIONS) == AccessStatus.ALLOWED);
allowableActions.setCanMoveObject(allowableActions.isCanUpdateProperties() && allowableActions.isCanAddObjectToFolder());
allowableActions.setCanRemoveObjectFromFolder(allowableActions.isCanUpdateProperties());
allowableActions.setCanCreateRelationship(allowableActions.isCanAddObjectToFolder());
}
private CmisAllowableActionsType determineRelationshipAllowableActions(AssociationRef association)
{
CmisAllowableActionsType result = new CmisAllowableActionsType();
result.setCanDeleteObject(this.permissionService.hasPermission(association.getSourceRef(), PermissionService.DELETE_ASSOCIATIONS) == AccessStatus.ALLOWED);
result.setCanGetObjectRelationships(this.permissionService.hasPermission(association.getSourceRef(), PermissionService.READ_ASSOCIATIONS) == AccessStatus.ALLOWED);
for (Entry<CMISAllowedActionEnum, CMISActionEvaluator<? extends Object>> entry : typeDef.getActionEvaluators().entrySet())
{
PropertyDescriptor propertyDescriptor = ALLOWED_ACTION_ENUM_MAPPING.get(entry.getKey());
if (propertyDescriptor != null)
{
// Let's assume that the evaluator will accept the object
try
{
propertyDescriptor.getWriteMethod().invoke(result, new Boolean(((CMISActionEvaluator) entry.getValue()).isAllowed(objectIdentifier)));
}
catch (IllegalArgumentException e)
{
throw new AlfrescoRuntimeException("Exception setting allowable actions", e);
}
catch (IllegalAccessException e)
{
throw new AlfrescoRuntimeException("Exception setting allowable actions", e);
}
catch (InvocationTargetException e)
{
throw new AlfrescoRuntimeException("Exception setting allowable actions", e.getTargetException());
}
}
}
return result;
}
}

View File

@@ -26,7 +26,8 @@ package org.alfresco.repo.cmis.ws;
import org.alfresco.cmis.CMISAccessControlFormatEnum;
import org.alfresco.cmis.CMISAccessControlReport;
import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType;
import org.alfresco.cmis.CMISServiceException;
import org.alfresco.repo.cmis.ws.utils.ExceptionUtil;
import org.alfresco.service.cmr.repository.NodeRef;
/**
@@ -42,7 +43,15 @@ public class DMAclServicePort extends DMAbstractServicePort implements ACLServic
CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef object = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.ANY_OBJECT);
NodeRef object;
try
{
object = cmisService.getObject(objectId, NodeRef.class, true, false, false);
}
catch (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
return applyAclCarefully(object, addACEs, removeACEs, aclPropagation);
}
@@ -52,10 +61,18 @@ public class DMAclServicePort extends DMAbstractServicePort implements ACLServic
public CmisACLType getACL(String repositoryId, String objectId, Boolean onlyBasicPermissions, CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef object = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.ANY_OBJECT);
NodeRef nodeRef;
try
{
nodeRef = cmisService.getReadableObject(objectId, NodeRef.class);
}
catch (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
CMISAccessControlFormatEnum permissionsKind = ((null == onlyBasicPermissions) || onlyBasicPermissions) ? (CMISAccessControlFormatEnum.CMIS_BASIC_PERMISSIONS)
: (CMISAccessControlFormatEnum.REPOSITORY_SPECIFIC_PERMISSIONS);
CMISAccessControlReport aclReport = cmisAclService.getAcl(object, permissionsKind);
CMISAccessControlReport aclReport = cmisAclService.getAcl(nodeRef, permissionsKind);
return convertAclReportToCmisAclType(aclReport);
}
}

View File

@@ -26,7 +26,6 @@ package org.alfresco.repo.cmis.ws;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -43,8 +42,9 @@ import org.alfresco.cmis.CMISQueryOptions;
import org.alfresco.cmis.CMISResultSet;
import org.alfresco.cmis.CMISResultSetColumn;
import org.alfresco.cmis.CMISResultSetRow;
import org.alfresco.cmis.CMISServiceException;
import org.alfresco.repo.cmis.PropertyFilter;
import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType;
import org.alfresco.repo.cmis.ws.utils.ExceptionUtil;
/**
* Port for Discovery service.
@@ -118,7 +118,15 @@ public class DMDiscoveryServicePort extends DMAbstractServicePort implements Dis
CmisObjectType object = new CmisObjectType();
object.setProperties(properties);
Object identifier = cmisObjectsUtils.getIdentifierInstance((String) values.get(CMISDictionaryModel.PROP_OBJECT_ID), AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT);
Object identifier;
try
{
identifier = cmisService.getReadableObject((String) values.get(CMISDictionaryModel.PROP_OBJECT_ID), Object.class);
}
catch (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
if (includeAllowableActions)
{
object.setAllowableActions(determineObjectAllowableActions(identifier));
@@ -175,26 +183,14 @@ public class DMDiscoveryServicePort extends DMAbstractServicePort implements Dis
filter = CMISDictionaryModel.PROP_OBJECT_ID;
}
if (changeToken != null)
{
try
{
Long.parseLong(changeToken);
}
catch (Exception e)
{
throw cmisObjectsUtils.createCmisException("Invalid changeLogToken was specified", EnumServiceException.INVALID_ARGUMENT);
}
}
CMISChangeLog changeLog = null;
try
{
changeLog = cmisChangeLogService.getChangeLogEvents(changeToken, maxAmount);
}
catch (Exception e)
catch (CMISServiceException e)
{
throw cmisObjectsUtils.createCmisException(e.getMessage(), EnumServiceException.STORAGE);
throw ExceptionUtil.createCmisException(e);
}
if (null == objects.value)
{
@@ -230,10 +226,10 @@ public class DMDiscoveryServicePort extends DMAbstractServicePort implements Dis
CmisObjectType object = new CmisObjectType();
CmisPropertiesType propertiesType = new CmisPropertiesType();
object.setProperties(propertiesType);
propertiesType.getProperty().add(propertiesUtil.createProperty(CMISDictionaryModel.PROP_OBJECT_ID, CMISDataTypeEnum.ID, event.getNode()));
if (nodeService.exists(event.getNode()) && includeAce)
propertiesType.getProperty().add(propertiesUtil.createProperty(CMISDictionaryModel.PROP_OBJECT_ID, CMISDataTypeEnum.ID, event.getObjectId()));
if (nodeService.exists(event.getChangedNode()) && includeAce)
{
appendWithAce(event.getNode(), object);
appendWithAce(event.getChangedNode(), object);
}
CmisChangeEventType changeInfo = new CmisChangeEventType();
XMLGregorianCalendar modificationDate = propertiesUtil.convert(event.getChangeTime());

View File

@@ -26,10 +26,8 @@ package org.alfresco.repo.cmis.ws;
import javax.xml.ws.Holder;
import org.alfresco.cmis.CMISDictionaryModel;
import org.alfresco.cmis.CMISTypeDefinition;
import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.cmis.CMISServiceException;
import org.alfresco.repo.cmis.ws.utils.ExceptionUtil;
/**
* Port for Multi-Filing service.
@@ -51,25 +49,13 @@ public class DMMultiFilingServicePort extends DMAbstractServicePort implements M
public void addObjectToFolder(String repositoryId, String objectId, String folderId, Boolean allVersions, Holder<CmisExtensionType> extension) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef objectNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT);
NodeRef parentFolderNodeRef = cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT);
CMISTypeDefinition objectType = cmisDictionaryService.findType(propertiesUtil.getProperty(objectNodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, (String) null));
CMISTypeDefinition folderType = cmisDictionaryService.findType(propertiesUtil.getProperty(parentFolderNodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, (String) null));
if (folderType == null)
try
{
throw cmisObjectsUtils.createCmisException("Type of the specified parent folder can't be resovled", EnumServiceException.RUNTIME);
cmisService.addObjectToFolder(objectId, folderId);
}
// FIXME [BUG]: folderType.getAllowedTargetTypes() MUST be changed on folderType.getAllowedChildObjectTypeIds()
if (!folderType.getAllowedTargetTypes().isEmpty() && !folderType.getAllowedTargetTypes().contains(objectType))
catch (CMISServiceException e)
{
throw cmisObjectsUtils.createCmisException(("The Object of '" + objectType.getTypeId() + "' Type can't be child of Folder of '" + folderType.getTypeId() + "' Type"),
EnumServiceException.CONSTRAINT);
}
if (!cmisObjectsUtils.addObjectToFolder(objectNodeRef, parentFolderNodeRef))
{
Throwable exception = cmisObjectsUtils.getLastOperationException();
throw cmisObjectsUtils.createCmisException(("Can't add specified Object to specified Folder. Cause exception message: " + exception.toString()),
EnumServiceException.STORAGE, exception);
throw ExceptionUtil.createCmisException(e);
}
}
@@ -84,43 +70,13 @@ public class DMMultiFilingServicePort extends DMAbstractServicePort implements M
public void removeObjectFromFolder(String repositoryId, String objectId, String folderId, Holder<CmisExtensionType> extension) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef objectNodeReference = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT);
NodeRef folderNodeReference = checkAndReceiveFolderIdentifier(folderId);
// FIXME [BUG]: if Document is Multi-Filled then removing this Object from Primary Parent Folder MUST treat to determine Primary Parent for Document from other Parent
// Folders
checkObjectChildParentRelationships(objectNodeReference, folderNodeReference);
if (!cmisObjectsUtils.removeObject(objectNodeReference, folderNodeReference))
{
Throwable exception = cmisObjectsUtils.getLastOperationException();
if (null != exception)
{
throw cmisObjectsUtils.createCmisException(("Can't remove specified Object from specified Folder. Cause exception message: " + exception.toString()),
EnumServiceException.STORAGE, exception);
}
else
{
throw cmisObjectsUtils.createCmisException("Can't remove specified Object from specified Folder", EnumServiceException.STORAGE, exception);
}
}
}
private NodeRef checkAndReceiveFolderIdentifier(String folderIdentifier) throws CmisException
{
try
{
return cmisObjectsUtils.getIdentifierInstance(folderIdentifier, AlfrescoObjectType.FOLDER_OBJECT);
cmisService.removeObjectFromFolder(objectId, folderId);
}
catch (Throwable e)
catch (CMISServiceException e)
{
throw cmisObjectsUtils.createCmisException("Unfiling is not supported. An Object can't be deleted from all Folders", EnumServiceException.NOT_SUPPORTED, e);
}
}
private void checkObjectChildParentRelationships(NodeRef objectNodeReference, NodeRef folderNodeReference) throws CmisException
{
if (cmisObjectsUtils.isPrimaryObjectParent(folderNodeReference, objectNodeReference))
{
throw cmisObjectsUtils.createCmisException("Unfiling is not supported. Use deleteObject() Service instead", EnumServiceException.NOT_SUPPORTED);
throw ExceptionUtil.createCmisException(e);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2008 Alfresco Software Limited.
* Copyright (C) 2005-2010 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
@@ -15,11 +15,11 @@
* 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 received 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;
@@ -29,17 +29,16 @@ import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
import java.util.regex.Pattern;
import org.alfresco.cmis.CMISDictionaryModel;
import org.alfresco.cmis.CMISServiceException;
import org.alfresco.cmis.CMISTypesFilterEnum;
import org.alfresco.repo.cmis.PropertyFilter;
import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType;
import org.alfresco.repo.cmis.ws.utils.ExceptionUtil;
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.NodeRef;
import org.springframework.extensions.surf.util.Pair;
/**
* Port for navigation service
@@ -55,9 +54,6 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
private static final String FILTER_TOKENS_DELIMETER = ", ";
private static final Pattern ORDER_BY_CLAUSE_MASK = Pattern.compile("^( )*([\\p{Alnum}_]+(( )+((ASC)|(DESC))){1}){1}((,){1}( )*[\\p{Alnum}_]+(( )+((ASC)|(DESC))){1})*( )*$",
Pattern.CASE_INSENSITIVE);
/**
* Gets the private working copies of checked-out objects that the user is allowed to update.
*
@@ -71,35 +67,36 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
checkRepositoryId(repositoryId);
PropertyFilter propertyFilter = createPropertyFilter(filter);
NodeRef folderRef = null;
if ((folderId != null) && !folderId.equals(""))
try
{
folderRef = cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT);
}
NodeRef folderRef = null;
if ((folderId != null) && !folderId.equals(""))
{
folderRef = cmisService.getFolder(folderId);
}
@SuppressWarnings("unused")
List<Pair<String, Boolean>> orderingFields = null;
if ((orderBy != null) && !orderBy.equals(""))
NodeRef[] nodeRefs = cmisService.getCheckedOut(AuthenticationUtil.getFullyAuthenticatedUser(), folderRef,
(folderRef == null), orderBy);
Cursor cursor = createCursor(nodeRefs.length, skipCount, maxItems);
CmisObjectListType result = new CmisObjectListType();
List<CmisObjectType> resultListing = result.getObjects();
for (int index = cursor.getStartRow(); index <= cursor.getEndRow(); index++)
{
resultListing.add(createCmisObject(nodeRefs[index], propertyFilter, includeAllowableActions,
renditionFilter));
}
result.setHasMoreItems(new Boolean(cursor.getEndRow() < (nodeRefs.length - 1)));
// TODO: includeAllowableActions, includeRelationships, renditions
return result;
}
catch (CMISServiceException e)
{
orderingFields = checkAndParseOrderByClause(orderBy);
throw ExceptionUtil.createCmisException(e);
}
// TODO: Ordering functionality SHOULD be moved to getChildren service method
NodeRef[] nodeRefs = cmisService.getCheckedOut(AuthenticationUtil.getFullyAuthenticatedUser(), folderRef, (folderRef == null));
Cursor cursor = createCursor(nodeRefs.length, skipCount, maxItems);
CmisObjectListType result = new CmisObjectListType();
List<CmisObjectType> resultListing = result.getObjects();
for (int index = cursor.getStartRow(); index <= cursor.getEndRow(); index++)
{
resultListing.add(createCmisObject(nodeRefs[index].toString(), propertyFilter, includeAllowableActions, renditionFilter));
}
result.setHasMoreItems(new Boolean(cursor.getEndRow() < (nodeRefs.length - 1)));
// TODO: includeAllowableActions, includeRelationships, renditions
return result;
}
/**
@@ -111,46 +108,48 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
* @return collection of CmisObjectType and boolean hasMoreItems
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, FILTER_NOT_VALID)
*/
public CmisObjectInFolderListType getChildren(String repositoryId, String folderId, String filter, String orderBy, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments, BigInteger maxItems, BigInteger skipCount,
CmisExtensionType extension) throws CmisException
public CmisObjectInFolderListType getChildren(String repositoryId, String folderId, String filter, String orderBy,
Boolean includeAllowableActions, EnumIncludeRelationships includeRelationships, String renditionFilter,
Boolean includePathSegments, BigInteger maxItems, BigInteger skipCount, CmisExtensionType extension)
throws CmisException
{
checkRepositoryId(repositoryId);
PropertyFilter propertyFilter = createPropertyFilter(filter);
NodeRef folderNodeRef = cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT);
@SuppressWarnings("unused")
List<Pair<String, Boolean>> orderingFields = null;
if ((orderBy != null) && !orderBy.equals(""))
try
{
orderingFields = checkAndParseOrderByClause(orderBy);
}
NodeRef folderNodeRef = cmisService.getFolder(folderId);
// TODO: Ordering functionality SHOULD be moved to getChildren service method
NodeRef[] listing = cmisService.getChildren(folderNodeRef, CMISTypesFilterEnum.ANY);
NodeRef[] listing = cmisService.getChildren(folderNodeRef, CMISTypesFilterEnum.ANY, orderBy);
CmisObjectInFolderListType result = new CmisObjectInFolderListType();
CmisObjectInFolderListType result = new CmisObjectInFolderListType();
Cursor cursor = createCursor(listing.length, skipCount, maxItems);
Cursor cursor = createCursor(listing.length, skipCount, maxItems);
for (int index = cursor.getStartRow(); index <= cursor.getEndRow(); index++)
{
CmisObjectType cmisObject = createCmisObject(listing[index].toString(), propertyFilter, includeAllowableActions, renditionFilter);
CmisObjectInFolderType cmisObjectInFolder = new CmisObjectInFolderType();
cmisObjectInFolder.setObject(cmisObject);
if (includePathSegments != null && includePathSegments)
for (int index = cursor.getStartRow(); index <= cursor.getEndRow(); index++)
{
cmisObjectInFolder.setPathSegment(propertiesUtil.getProperty(listing[index], CMISDictionaryModel.PROP_NAME, ""));
CmisObjectType cmisObject = createCmisObject(listing[index], propertyFilter, includeAllowableActions,
renditionFilter);
CmisObjectInFolderType cmisObjectInFolder = new CmisObjectInFolderType();
cmisObjectInFolder.setObject(cmisObject);
if (includePathSegments != null && includePathSegments)
{
cmisObjectInFolder.setPathSegment(propertiesUtil.getProperty(listing[index],
CMISDictionaryModel.PROP_NAME, ""));
}
result.getObjects().add(cmisObjectInFolder);
}
result.getObjects().add(cmisObjectInFolder);
result.setHasMoreItems(cursor.getEndRow() < (listing.length - 1));
result.setNumItems(BigInteger.valueOf(listing.length));
// TODO: Process includeRelationships, includeACL
return result;
}
catch (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
result.setHasMoreItems(cursor.getEndRow() < (listing.length - 1));
result.setNumItems(BigInteger.valueOf(listing.length));
// TODO: Process includeRelationships, includeACL
return result;
}
/**
@@ -165,7 +164,7 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
public List<CmisObjectInFolderContainerType> getDescendants(String repositoryId, String folderId, BigInteger depth, String filter, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments, CmisExtensionType extension) throws CmisException
{
CmisObjectInFolderContainerType objectInFolderContainerType = getDescedantsTree(repositoryId, folderId, depth, filter, includeAllowableActions, includeRelationships,
CmisObjectInFolderContainerType objectInFolderContainerType = getDescendantsTree(repositoryId, folderId, depth, filter, includeAllowableActions, includeRelationships,
renditionFilter, includePathSegments, CMISTypesFilterEnum.ANY);
return objectInFolderContainerType.getChildren();
}
@@ -182,7 +181,7 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
public List<CmisObjectInFolderContainerType> getFolderTree(String repositoryId, String folderId, BigInteger depth, String filter, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments, CmisExtensionType extension) throws CmisException
{
CmisObjectInFolderContainerType objectInFolderContainerType = getDescedantsTree(repositoryId, folderId, depth, filter, includeAllowableActions, includeRelationships,
CmisObjectInFolderContainerType objectInFolderContainerType = getDescendantsTree(repositoryId, folderId, depth, filter, includeAllowableActions, includeRelationships,
renditionFilter, includePathSegments, CMISTypesFilterEnum.FOLDERS);
return objectInFolderContainerType.getChildren();
}
@@ -211,9 +210,17 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
}
}
PropertyFilter propertyFilter = createPropertyFilter(filter);
NodeRef parentRef = receiveParent(folderId);
NodeRef parentRef;
try
{
parentRef = cmisService.getFolderParent(folderId);
}
catch (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
CmisObjectType result = createCmisObject(parentRef, propertyFilter, false, null);
// TODO: It is not clear whether ACL etc should be returned
return result;
}
@@ -231,7 +238,15 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
checkRepositoryId(repositoryId);
PropertyFilter propertyFilter = createPropertyFilter(filter);
NodeRef childNode = (NodeRef) cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT);
NodeRef childNode;
try
{
childNode = (NodeRef) cmisService.getReadableObject(objectId, NodeRef.class);
}
catch (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
List<NodeRef> parents = receiveObjectParents(childNode);
List<CmisObjectParentsType> result = new ArrayList<CmisObjectParentsType>();
@@ -252,7 +267,7 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
return result;
}
private CmisObjectInFolderContainerType getDescedantsTree(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
{
checkRepositoryId(repositoryId);
@@ -262,34 +277,43 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
long maxDepth = depth.longValue();
checkDepthParameter(depth);
NodeRef folderNodeRef = cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT);
Stack<RecursiveElement> descedantsStack = new Stack<RecursiveElement>();
CmisObjectInFolderContainerType objectInFolderContainer = createObjectInFolderContainer(folderNodeRef, propertyFilter, includeAllowableActions, includeRelationships,
renditionFilter, includePathSegments);
NodeRef[] children = cmisService.getChildren(folderNodeRef, types);
for (NodeRef childRef : children)
try
{
descedantsStack.push(new RecursiveElement(objectInFolderContainer, 1, childRef));
}
while (!descedantsStack.isEmpty())
{
RecursiveElement element = descedantsStack.pop();
CmisObjectInFolderContainerType currentContainer = createObjectInFolderContainer(element.getCurrentNodeRef(), propertyFilter, includeAllowableActions,
includeRelationships, renditionFilter, includePathSegments);
element.getParentContainerType().getChildren().add(currentContainer);
if (element.getDepth() <= maxDepth)
NodeRef folderNodeRef = cmisService.getFolder(folderId);
Stack<RecursiveElement> descedantsStack = new Stack<RecursiveElement>();
CmisObjectInFolderContainerType objectInFolderContainer = createObjectInFolderContainer(folderNodeRef,
propertyFilter, includeAllowableActions, includeRelationships, renditionFilter, includePathSegments);
NodeRef[] children = cmisService.getChildren(folderNodeRef, types, null);
for (NodeRef childRef : children)
{
children = cmisService.getChildren(element.getCurrentNodeRef(), types);
if (children != null)
descedantsStack.push(new RecursiveElement(objectInFolderContainer, 1, childRef));
}
while (!descedantsStack.isEmpty())
{
RecursiveElement element = descedantsStack.pop();
CmisObjectInFolderContainerType currentContainer = createObjectInFolderContainer(element
.getCurrentNodeRef(), propertyFilter, includeAllowableActions, includeRelationships,
renditionFilter, includePathSegments);
element.getParentContainerType().getChildren().add(currentContainer);
if (element.getDepth() <= maxDepth)
{
for (NodeRef childRef : children)
children = cmisService.getChildren(element.getCurrentNodeRef(), types, null);
if (children != null)
{
descedantsStack.push(new RecursiveElement(currentContainer, element.getDepth() + 1, childRef));
for (NodeRef childRef : children)
{
descedantsStack.push(new RecursiveElement(currentContainer, element.getDepth() + 1,
childRef));
}
}
}
}
return objectInFolderContainer;
}
catch (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
return objectInFolderContainer;
}
private CmisObjectInFolderContainerType createObjectInFolderContainer(NodeRef nodeRef, PropertyFilter filter, Boolean includeAllowableActions,
@@ -311,56 +335,15 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
return result;
}
private List<Pair<String, Boolean>> checkAndParseOrderByClause(String orderByClause) throws CmisException
{
List<Pair<String, Boolean>> result = new LinkedList<Pair<String, Boolean>>();
if (!ORDER_BY_CLAUSE_MASK.matcher(orderByClause).matches())
{
throw cmisObjectsUtils.createCmisException(("\"" + orderByClause + "\" Order By Clause is invalid!"), EnumServiceException.INVALID_ARGUMENT);
}
for (String token : orderByClause.split(","))
{
token = token.trim();
String[] direction = token.split(" ");
String fieldName = direction[0];
result.add(new Pair<String, Boolean>(fieldName, direction[direction.length - 1].toLowerCase().equals("asc")));
}
return result;
}
private NodeRef receiveParent(String targetChildIdentifier) throws CmisException
{
if (cmisService.getDefaultRootNodeRef().toString().equals(targetChildIdentifier))
{
throw cmisObjectsUtils.createCmisException("Root Folder has no parents", EnumServiceException.INVALID_ARGUMENT);
}
NodeRef identifierInstance = (NodeRef) cmisObjectsUtils.getIdentifierInstance(targetChildIdentifier, AlfrescoObjectType.FOLDER_OBJECT);
return receiveNextParentNodeReference(identifierInstance, new LinkedList<NodeRef>());
}
private void checkDepthParameter(BigInteger depth) throws CmisException
{
if (depth.equals(BigInteger.ZERO) || (depth.compareTo(FULL_DESCENDANTS_HIERARCHY_CONDITION) < EQUALS_CONDITION_VALUE))
{
throw cmisObjectsUtils.createCmisException("The specified descendants depth is not valid. Valid depth values are: -1 (full hierarchy), N > 0",
throw ExceptionUtil.createCmisException("The specified descendants depth is not valid. Valid depth values are: -1 (full hierarchy), N > 0",
EnumServiceException.INVALID_ARGUMENT);
}
}
private NodeRef receiveNextParentNodeReference(NodeRef currentParent, List<NodeRef> parents)
{
currentParent = nodeService.getPrimaryParent(currentParent).getParentRef();
if (currentParent != null)
{
parents.add(currentParent);
}
return currentParent;
}
private List<NodeRef> receiveObjectParents(NodeRef objectId) throws CmisException
{
List<NodeRef> parents = new LinkedList<NodeRef>();

View File

@@ -28,6 +28,8 @@ import java.util.List;
import javax.xml.ws.Holder;
import org.alfresco.repo.cmis.ws.utils.ExceptionUtil;
@javax.jws.WebService(name = "PolicyServicePort", serviceName = "PolicyServicePort", portName = "PolicyServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200908/", endpointInterface = "org.alfresco.repo.cmis.ws.PolicyServicePort")
public class DMPolicyServicePort extends DMAbstractServicePort implements PolicyServicePort
{
@@ -43,7 +45,7 @@ public class DMPolicyServicePort extends DMAbstractServicePort implements Policy
*/
public void applyPolicy(String repositoryId, String policyId, String objectId, Holder<CmisExtensionType> extension) throws CmisException
{
throw cmisObjectsUtils.createCmisException(POLICY_NOT_SUPPORTED_MESSAGE, EnumServiceException.RUNTIME);
throw ExceptionUtil.createCmisException(POLICY_NOT_SUPPORTED_MESSAGE, EnumServiceException.RUNTIME);
}
/**
@@ -54,7 +56,7 @@ public class DMPolicyServicePort extends DMAbstractServicePort implements Policy
*/
public List<CmisObjectType> getAppliedPolicies(String repositoryId, String objectId, String filter, CmisExtensionType extension) throws CmisException
{
throw cmisObjectsUtils.createCmisException(POLICY_NOT_SUPPORTED_MESSAGE, EnumServiceException.RUNTIME);
throw ExceptionUtil.createCmisException(POLICY_NOT_SUPPORTED_MESSAGE, EnumServiceException.RUNTIME);
}
/**
@@ -67,6 +69,6 @@ public class DMPolicyServicePort extends DMAbstractServicePort implements Policy
*/
public void removePolicy(String repositoryId, String policyId, String objectId, Holder<CmisExtensionType> extension) throws CmisException
{
throw cmisObjectsUtils.createCmisException(POLICY_NOT_SUPPORTED_MESSAGE, EnumServiceException.RUNTIME);
throw ExceptionUtil.createCmisException(POLICY_NOT_SUPPORTED_MESSAGE, EnumServiceException.RUNTIME);
}
}

View File

@@ -25,18 +25,17 @@
package org.alfresco.repo.cmis.ws;
import java.math.BigInteger;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.cmis.CMISScope;
import org.alfresco.cmis.CMISRelationshipDirectionEnum;
import org.alfresco.cmis.CMISServiceException;
import org.alfresco.cmis.CMISTypeDefinition;
import org.alfresco.repo.cmis.PropertyFilter;
import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType;
import org.alfresco.repo.cmis.ws.utils.ExceptionUtil;
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
@@ -46,11 +45,13 @@ import org.alfresco.service.namespace.QNamePattern;
@javax.jws.WebService(name = "RelationshipServicePort", serviceName = "RelationshipService", portName = "RelationshipServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200908/", endpointInterface = "org.alfresco.repo.cmis.ws.RelationshipServicePort")
public class DMRelationshipServicePort extends DMAbstractServicePort implements RelationshipServicePort
{
private DictionaryService dictionaryService;
public void setDictionaryService(DictionaryService dictionaryService)
private static final Map<EnumRelationshipDirection, CMISRelationshipDirectionEnum> RELATIONSHIP_DIRECTION_MAPPING;
static
{
this.dictionaryService = dictionaryService;
RELATIONSHIP_DIRECTION_MAPPING = new HashMap<EnumRelationshipDirection, CMISRelationshipDirectionEnum>(5);
RELATIONSHIP_DIRECTION_MAPPING.put(EnumRelationshipDirection.SOURCE, CMISRelationshipDirectionEnum.SOURCE);
RELATIONSHIP_DIRECTION_MAPPING.put(EnumRelationshipDirection.TARGET, CMISRelationshipDirectionEnum.TARGET);
RELATIONSHIP_DIRECTION_MAPPING.put(EnumRelationshipDirection.EITHER, CMISRelationshipDirectionEnum.BOTH);
}
/**
@@ -66,31 +67,25 @@ public class DMRelationshipServicePort extends DMAbstractServicePort implements
String typeId, String filter, Boolean includeAllowableActions, BigInteger maxItems, BigInteger skipCount, CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef objectNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT);
if (null == includeSubRelationshipTypes)
if ((null == objectId) || "".equals(objectId) || !NodeRef.isNodeRef(objectId))
{
throw cmisObjectsUtils.createCmisException("includeSubRelationshipTypes input parameter is required", EnumServiceException.INVALID_ARGUMENT);
throw ExceptionUtil.createCmisException(("Object with Id='" + objectId + "' is not exist!"), EnumServiceException.OBJECT_NOT_FOUND);
}
relationshipDirection = (null != relationshipDirection) ? relationshipDirection : EnumRelationshipDirection.SOURCE;
skipCount = (null != skipCount) ? skipCount : BigInteger.ZERO;
maxItems = (null != maxItems) ? maxItems : BigInteger.ZERO;
QName associationType = null;
if ((null != typeId) && !"".equals(typeId))
{
CMISTypeDefinition cmisTypeDef = cmisDictionaryService.findType(typeId);
associationType = cmisTypeDef.getTypeId().getQName();
}
PropertyFilter propertyFilter = createPropertyFilter(filter);
List<AssociationRef> assocs = null;
try
{
assocs = cmisObjectsUtils.receiveAssociations(objectNodeRef, new RelationshipTypeFilter(associationType, includeSubRelationshipTypes), relationshipDirection);
CMISTypeDefinition relDef = (null != typeId) ? (cmisService.getTypeDefinition(typeId)):(null);
NodeRef nodeRef = cmisService.getReadableObject(objectId, NodeRef.class);
AssociationRef[] assocs = cmisService.getRelationships(nodeRef, relDef, includeSubRelationshipTypes != null && includeSubRelationshipTypes,
relationshipDirection == null ? CMISRelationshipDirectionEnum.SOURCE : RELATIONSHIP_DIRECTION_MAPPING.get(relationshipDirection));
skipCount = (null != skipCount) ? skipCount : BigInteger.ZERO;
maxItems = (null != maxItems) ? maxItems : BigInteger.ZERO;
PropertyFilter propertyFilter = createPropertyFilter(filter);
return createResult(propertyFilter, includeAllowableActions, assocs, skipCount, maxItems);
}
catch (Exception e)
catch (CMISServiceException e)
{
throw cmisObjectsUtils.createCmisException("Can't receive associations", e);
throw ExceptionUtil.createCmisException(e);
}
return createResult(propertyFilter, includeAllowableActions, assocs.toArray(), skipCount, maxItems);
}
private CmisObjectListType createResult(PropertyFilter filter, boolean includeAllowableActions, Object[] sourceArray, BigInteger skipCount, BigInteger maxItems)
@@ -100,39 +95,10 @@ public class DMRelationshipServicePort extends DMAbstractServicePort implements
CmisObjectListType result = new CmisObjectListType();
for (int i = cursor.getStartRow(); i <= cursor.getEndRow(); i++)
{
result.getObjects().add(createCmisObject(sourceArray[i].toString(), filter, includeAllowableActions, null));
result.getObjects().add(createCmisObject(sourceArray[i], filter, includeAllowableActions, null));
}
result.setHasMoreItems(cursor.getEndRow() < sourceArray.length);
result.setNumItems(BigInteger.valueOf(cursor.getPageSize()));
return result;
}
private class RelationshipTypeFilter implements QNamePattern
{
private boolean includeSubtypes;
private QName relationshipType;
public RelationshipTypeFilter(QName ralationshipType, boolean includeSubtypes)
{
this.relationshipType = ralationshipType;
this.includeSubtypes = includeSubtypes;
}
public boolean isMatch(QName qname)
{
if (relationshipType == null)
{
return true;
}
else if (includeSubtypes)
{
return null != dictionaryService.getAssociation(qname);
}
else
{
CMISTypeDefinition typeDef = cmisDictionaryService.findTypeForClass(qname, CMISScope.RELATIONSHIP);
return typeDef != null && relationshipType.equals(qname);
}
}
}
}

View File

@@ -33,7 +33,6 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import org.alfresco.cmis.CMISAclCapabilityEnum;
import org.alfresco.cmis.CMISAclPropagationEnum;
@@ -50,8 +49,10 @@ import org.alfresco.cmis.CMISPermissionDefinition;
import org.alfresco.cmis.CMISPermissionMapping;
import org.alfresco.cmis.CMISPropertyDefinition;
import org.alfresco.cmis.CMISQueryEnum;
import org.alfresco.cmis.CMISServiceException;
import org.alfresco.cmis.CMISTypeDefinition;
import org.alfresco.cmis.CMISUpdatabilityEnum;
import org.alfresco.repo.cmis.ws.utils.ExceptionUtil;
import org.alfresco.repo.web.util.paging.Cursor;
import org.alfresco.service.descriptor.Descriptor;
@@ -324,7 +325,7 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re
}
default:
{
throw cmisObjectsUtils.createCmisException(type.getLabel(), EnumServiceException.OBJECT_NOT_FOUND);
throw ExceptionUtil.createCmisException(type.getLabel(), EnumServiceException.OBJECT_NOT_FOUND);
}
}
}
@@ -379,7 +380,7 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re
{
if (typeDef == null)
{
throw cmisObjectsUtils.createCmisException("Type not found", EnumServiceException.OBJECT_NOT_FOUND);
throw ExceptionUtil.createCmisException("Type not found", EnumServiceException.OBJECT_NOT_FOUND);
}
CmisTypeDefinitionType result = null;
@@ -439,7 +440,7 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re
result = relationshipDefinitionType;
break;
case UNKNOWN:
throw cmisObjectsUtils.createCmisException("Unknown CMIS Type", EnumServiceException.INVALID_ARGUMENT);
throw ExceptionUtil.createCmisException("Unknown CMIS Type", EnumServiceException.INVALID_ARGUMENT);
}
return result;
@@ -572,7 +573,15 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re
CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
Collection<CMISTypeDefinition> typeDefs = getBaseTypesCollection(typeId, true);
Collection<CMISTypeDefinition> typeDefs;
try
{
typeDefs = typeId == null ? cmisService.getBaseTypes() : cmisService.getTypeDefinition(typeId).getSubTypes(false);
}
catch (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
// skip
Cursor cursor = createCursor(typeDefs.size(), skipCount, maxItems);
Iterator<CMISTypeDefinition> iterTypeDefs = typeDefs.iterator();
@@ -593,7 +602,7 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re
}
else
{
throw cmisObjectsUtils.createCmisException(("Subtypes collection is corrupted. Type id: " + typeId), EnumServiceException.STORAGE);
throw ExceptionUtil.createCmisException(("Subtypes collection is corrupted. Type id: " + typeId), EnumServiceException.STORAGE);
}
}
result.setHasMoreItems(((maxItems == null) || (0 == maxItems.intValue())) ? (false) : ((cursor.getEndRow() < (typeDefs.size() - 1))));
@@ -614,11 +623,11 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re
CMISTypeDefinition typeDef;
try
{
typeDef = cmisDictionaryService.findType(typeId);
typeDef = cmisService.getTypeDefinition(typeId);
}
catch (Exception e)
catch (CMISServiceException e)
{
throw cmisObjectsUtils.createCmisException(e.toString(), EnumServiceException.INVALID_ARGUMENT);
throw ExceptionUtil.createCmisException(e);
}
return getCmisTypeDefinition(typeDef, true);
}
@@ -634,39 +643,39 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re
throws CmisException
{
checkRepositoryId(repositoryId);
long depthLong = (null == depth) ? (-1) : (depth.longValue());
long depthLong = (null == depth || null == typeId) ? (-1) : (depth.longValue());
if (0 == depthLong)
{
throw cmisObjectsUtils.createCmisException("Depth parameter equal to '0' have no sence", EnumServiceException.INVALID_ARGUMENT);
throw ExceptionUtil.createCmisException("Invalid depth '0'", EnumServiceException.INVALID_ARGUMENT);
}
boolean includePropertyDefsBool = (null == includePropertyDefinitions) ? (false) : (includePropertyDefinitions);
List<CmisTypeContainer> result = new LinkedList<CmisTypeContainer>();
Queue<TypeElement> typesQueue = new LinkedList<TypeElement>();
Collection<CMISTypeDefinition> typeDefs = getBaseTypesCollection(typeId, false);
for (CMISTypeDefinition typeDef : typeDefs)
CMISTypeDefinition typeDef;
try
{
typesQueue.add(new TypeElement(0L, typeDef, createTypeContainer(typeDef, includePropertyDefsBool)));
typeDef = typeId == null ? null : cmisService.getTypeDefinition(typeId);
}
for (TypeElement element = typesQueue.peek(); !typesQueue.isEmpty(); element = (typeDefs.isEmpty()) ? (null) : (typesQueue.peek()))
catch (CMISServiceException e)
{
typesQueue.poll();
result.add(element.getContainer());
long nextLevel = element.getLevel() + 1;
Collection<CMISTypeDefinition> subTypes = element.getTypeDefinition().getSubTypes(false);
if (null != subTypes)
throw ExceptionUtil.createCmisException(e);
}
getTypeDescendants(typeDef, result, includePropertyDefinitions != null && includePropertyDefinitions, 1, depthLong);
return result;
}
private void getTypeDescendants(CMISTypeDefinition parent, List<CmisTypeContainer> result, boolean includePropertyDefs, long depth, long maxDepth) throws CmisException
{
Collection<CMISTypeDefinition> subtypes = parent == null ? cmisService.getBaseTypes() : parent.getSubTypes(false);
for (CMISTypeDefinition typeDef : subtypes)
{
result.add(createTypeContainer(typeDef, includePropertyDefs));
}
if (maxDepth == -1 || depth + 1 <= maxDepth)
{
for (CMISTypeDefinition typeDef : subtypes)
{
for (CMISTypeDefinition typeDef : subTypes)
{
CmisTypeContainer childContainer = createTypeContainer(typeDef, includePropertyDefsBool);
if ((-1 == depthLong) || (nextLevel <= depthLong))
{
element.getContainer().getChildren().add(childContainer);
typesQueue.add(new TypeElement(nextLevel, typeDef, childContainer));
}
}
getTypeDescendants(typeDef, result, includePropertyDefs, depth + 1, maxDepth);
}
}
return result;
}
private CmisTypeContainer createTypeContainer(CMISTypeDefinition parentType, boolean includeProperties) throws CmisException
@@ -675,70 +684,4 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re
result.setType(getCmisTypeDefinition(parentType, includeProperties));
return result;
}
private class TypeElement
{
private long level;
private CMISTypeDefinition typeDefinition;
private CmisTypeContainer container;
public TypeElement(long level, CMISTypeDefinition typeDefinition, CmisTypeContainer container)
{
this.level = level;
this.typeDefinition = typeDefinition;
this.container = container;
}
public long getLevel()
{
return level;
}
public CMISTypeDefinition getTypeDefinition()
{
return typeDefinition;
}
public CmisTypeContainer getContainer()
{
return container;
}
}
private Collection<CMISTypeDefinition> getBaseTypesCollection(String typeId, boolean includeSubtypes) throws CmisException
{
Collection<CMISTypeDefinition> typeDefs = new LinkedList<CMISTypeDefinition>();
if ((null == typeId) || "".equals(typeId))
{
typeDefs = cmisDictionaryService.getBaseTypes();
}
else
{
CMISTypeDefinition typeDef = null;
try
{
typeDef = cmisDictionaryService.findType(typeId);
}
catch (Exception e)
{
throw cmisObjectsUtils.createCmisException(e.toString(), EnumServiceException.INVALID_ARGUMENT);
}
if (null == typeDef)
{
throw cmisObjectsUtils.createCmisException(("Invalid type id: \"" + typeId + "\""), EnumServiceException.INVALID_ARGUMENT);
}
typeDefs.add(typeDef);
if (includeSubtypes)
{
Collection<CMISTypeDefinition> subTypes = typeDef.getSubTypes(false);
if (null != subTypes)
{
typeDefs.addAll(subTypes);
}
}
}
return typeDefs;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2008 Alfresco Software Limited.
* Copyright (C) 2005-2010 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
@@ -15,16 +15,16 @@
* 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 received 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.CmisObjectsUtils;
import org.alfresco.repo.cmis.ws.utils.ExceptionUtil;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -40,13 +40,6 @@ public class DMServicePortThrowsAdvice implements ThrowsAdvice
{
private static final Log LOGGER = LogFactory.getLog("org.alfresco.repo.cmis.ws");
private CmisObjectsUtils cmisObjectsUtils;
public void setCmisObjectsUtils(CmisObjectsUtils cmisObjectsUtils)
{
this.cmisObjectsUtils = cmisObjectsUtils;
}
public void afterThrowing(AccessDeniedException e) throws CmisException
{
if (LOGGER.isInfoEnabled())
@@ -54,7 +47,7 @@ public class DMServicePortThrowsAdvice implements ThrowsAdvice
LOGGER.error(e.toString(), e);
}
throw cmisObjectsUtils.createCmisException(("Access denied. Message: " + e.toString()), e);
throw ExceptionUtil.createCmisException(("Access denied. Message: " + e.toString()), e);
}
public void afterThrowing(java.lang.RuntimeException e) throws CmisException
@@ -64,7 +57,7 @@ public class DMServicePortThrowsAdvice implements ThrowsAdvice
LOGGER.error(e.toString(), e);
}
throw cmisObjectsUtils.createCmisException(("Runtime error. Message: " + e.toString()), e);
throw ExceptionUtil.createCmisException(("Runtime error. Message: " + e.toString()), e);
}
public void afterThrowing(java.lang.Exception e) throws CmisException
@@ -76,7 +69,7 @@ public class DMServicePortThrowsAdvice implements ThrowsAdvice
if (!(e instanceof CmisException))
{
throw cmisObjectsUtils.createCmisException(("Some error occured during last service invokation. Message: " + e.toString()), e);
throw ExceptionUtil.createCmisException(("Some error occured during last service invokation. Message: " + e.toString()), e);
}
else
{

View File

@@ -31,18 +31,12 @@ import javax.xml.ws.Holder;
import org.alfresco.cmis.CMISContentStreamAllowedEnum;
import org.alfresco.cmis.CMISDictionaryModel;
import org.alfresco.cmis.CMISServiceException;
import org.alfresco.cmis.CMISTypeDefinition;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.cmis.PropertyFilter;
import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.lock.LockStatus;
import org.alfresco.repo.cmis.ws.utils.ExceptionUtil;
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.
@@ -53,13 +47,6 @@ import org.alfresco.service.cmr.version.VersionType;
@javax.jws.WebService(name = "VersioningServicePort", serviceName = "VersioningService", portName = "VersioningServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200908/", endpointInterface = "org.alfresco.repo.cmis.ws.VersioningServicePort")
public class DMVersioningServicePort extends DMAbstractServicePort implements VersioningServicePort
{
private LockService lockService;
public void setLockService(LockService lockService)
{
this.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.
@@ -73,31 +60,14 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve
public void cancelCheckOut(String repositoryId, String objectId, Holder<CmisExtensionType> extension) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT);
assertVersionableIsTrue(documentNodeRef);
boolean checkedOut = propertiesUtil.getProperty(documentNodeRef, CMISDictionaryModel.PROP_IS_VERSION_SERIES_CHECKED_OUT, false);
NodeRef workingCopyNodeRef = definitelyGetWorkingCopy(checkedOut, documentNodeRef);
checkOutCheckInService.cancelCheckout(workingCopyNodeRef);
}
private void assertVersionableIsTrue(NodeRef workingCopyNodeRef) throws CmisException
{
if (!getTypeDefinition(workingCopyNodeRef).isVersionable())
try
{
// FIXME: uncomment this when CMIS dictionary model will be corrected
// throw cmisObjectsUtils.createCmisException("Document that was specified is not versionable", EnumServiceException.CONSTRAINT);
cmisService.cancelCheckOut(objectId);
}
}
private CMISTypeDefinition getTypeDefinition(NodeRef nodeRef) throws CmisException
{
String typeId = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, null);
CMISTypeDefinition typeDefinition = (null != typeId) ? (cmisDictionaryService.findType(typeId)) : (null);
if (null == typeDefinition)
catch (CMISServiceException e)
{
throw cmisObjectsUtils.createCmisException(("Object type property is invalid"), EnumServiceException.RUNTIME);
throw ExceptionUtil.createCmisException(e);
}
return typeDefinition;
}
/**
@@ -117,46 +87,41 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve
List<String> policies, CmisAccessControlListType addACEs, CmisAccessControlListType removeACEs, Holder<CmisExtensionType> extension) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef workingCopyNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId.value, AlfrescoObjectType.DOCUMENT_OBJECT);
assertVersionableIsTrue(workingCopyNodeRef);
assertLatestVersion(workingCopyNodeRef, true);
String versionSeriesId = propertiesUtil.getProperty(workingCopyNodeRef, CMISDictionaryModel.PROP_VERSION_SERIES_ID, null);
CMISTypeDefinition seriesObjectTypeDefinition = getTypeDefinition((NodeRef) cmisObjectsUtils.getIdentifierInstance(versionSeriesId, AlfrescoObjectType.DOCUMENT_OBJECT));
if ((null != contentStream) && (CMISContentStreamAllowedEnum.NOT_ALLOWED == seriesObjectTypeDefinition.getContentStreamAllowed()))
{
throw cmisObjectsUtils.createCmisException("Content stream is not allowed", EnumServiceException.STREAM_NOT_SUPPORTED);
}
if (contentStream != null)
{
try
{
ContentWriter writer = fileFolderService.getWriter(workingCopyNodeRef);
writer.setMimetype(contentStream.getMimeType());
writer.putContent(contentStream.getStream().getInputStream());
}
catch (Exception e)
{
throw cmisObjectsUtils.createCmisException("Exception while updating content stream", EnumServiceException.UPDATE_CONFLICT, e);
}
}
NodeRef nodeRef;
try
{
nodeRef = checkOutCheckInService.checkin(workingCopyNodeRef, createVersionProperties(checkinComment, ((null == major) || major) ? (VersionType.MAJOR)
: (VersionType.MINOR)));
propertiesUtil.setProperties(nodeRef, properties, null);
NodeRef workingCopyNodeRef = cmisService.getObject(objectId.value, NodeRef.class, true, true, true);
CMISTypeDefinition seriesObjectTypeDefinition = cmisService.getTypeDefinition(workingCopyNodeRef);
if ((null != contentStream) && (CMISContentStreamAllowedEnum.NOT_ALLOWED == seriesObjectTypeDefinition.getContentStreamAllowed()))
{
throw ExceptionUtil.createCmisException("Content stream is not allowed", EnumServiceException.STREAM_NOT_SUPPORTED);
}
if (contentStream != null)
{
try
{
ContentWriter writer = fileFolderService.getWriter(workingCopyNodeRef);
writer.setMimetype(contentStream.getMimeType());
writer.putContent(contentStream.getStream().getInputStream());
}
catch (Exception e)
{
throw ExceptionUtil.createCmisException("Exception while updating content stream", EnumServiceException.RUNTIME, e);
}
}
propertiesUtil.setProperties(workingCopyNodeRef, properties, null);
NodeRef nodeRef = cmisService.checkIn(objectId.value, checkinComment, major == null || major);
// TODO: applyPolicies
applyAclCarefully(nodeRef, addACEs, removeACEs, EnumACLPropagation.PROPAGATE);
objectId.value = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_OBJECT_ID, objectId.value);
}
catch (Exception e)
catch (CMISServiceException e)
{
throw cmisObjectsUtils.createCmisException("Unable to check in Private Working Copy object that was specified", EnumServiceException.STORAGE, e);
throw ExceptionUtil.createCmisException(e);
}
// TODO: applyPolicies
applyAclCarefully(nodeRef, addACEs, removeACEs, EnumACLPropagation.PROPAGATE);
objectId.value = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_OBJECT_ID, objectId.value);
}
/**
@@ -172,48 +137,18 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve
public void checkOut(String repositoryId, Holder<String> objectId, Holder<CmisExtensionType> extension, Holder<Boolean> contentCopied) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId.value, AlfrescoObjectType.DOCUMENT_OBJECT);
assertVersionableIsTrue(documentNodeRef);
assertLatestVersion(documentNodeRef, false);
LockStatus lockStatus = lockService.getLockStatus(documentNodeRef);
if (lockStatus.equals(LockStatus.LOCKED) || lockStatus.equals(LockStatus.LOCK_OWNER) || nodeService.hasAspect(documentNodeRef, ContentModel.ASPECT_WORKING_COPY))
{
throw cmisObjectsUtils.createCmisException("Object is locked or already checked out", EnumServiceException.UPDATE_CONFLICT);
}
try
{
NodeRef pwcNodeRef = checkoutNode(documentNodeRef);
NodeRef pwcNodeRef = cmisService.checkOut(objectId.value);
objectId.value = propertiesUtil.getProperty(pwcNodeRef, CMISDictionaryModel.PROP_OBJECT_ID, objectId.value);
contentCopied.value = null != fileFolderService.getReader(pwcNodeRef);
}
catch (Exception e)
catch (CMISServiceException e)
{
throw cmisObjectsUtils.createCmisException(("Unable to execute Check Out services. Cause message: " + e.toString()), EnumServiceException.STORAGE);
throw ExceptionUtil.createCmisException(e);
}
}
/**
* Deletes all document versions in the specified version series.
*
* @param repositoryId repository Id
* @param versionSeriesId version series Id
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME)
*/
public void deleteAllVersions(String repositoryId, String versionSeriesId) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(versionSeriesId, AlfrescoObjectType.DOCUMENT_OBJECT);
NodeRef workingCopyRef = (cmisObjectsUtils.isWorkingCopy(documentNodeRef)) ? (documentNodeRef) : (checkOutCheckInService.getWorkingCopy(documentNodeRef));
if ((null != workingCopyRef) && cmisObjectsUtils.isWorkingCopy(workingCopyRef))
{
documentNodeRef = checkOutCheckInService.cancelCheckout(workingCopyRef);
}
versionService.deleteVersionHistory(documentNodeRef);
}
/**
* Gets the list of all document versions for the specified version series.
*
@@ -225,38 +160,23 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve
throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT);
documentNodeRef = cmisObjectsUtils.getLatestNode(documentNodeRef, false);
PropertyFilter propertyFilter = createPropertyFilter(filter);
List<CmisObjectType> objects = new LinkedList<CmisObjectType>();
includeAllowableActions = (null == includeAllowableActions) ? (false) : (includeAllowableActions);
if (includeAllowableActions == null)
{
includeAllowableActions = false;
}
try
{
NodeRef workingCopyNodeReference = cmisObjectsUtils.isWorkingCopy(documentNodeRef) ? documentNodeRef : checkOutCheckInService.getWorkingCopy(documentNodeRef);
if (null != workingCopyNodeReference)
for (NodeRef nodeRef : cmisService.getAllVersions(objectId))
{
objects.add(createCmisObject(workingCopyNodeReference, propertyFilter, includeAllowableActions, null));
objects.add(createCmisObject(nodeRef, propertyFilter, includeAllowableActions, null));
}
}
catch (Exception e)
catch (CMISServiceException e)
{
if (!(e instanceof AccessDeniedException))
{
throw cmisObjectsUtils.createCmisException(e.toString(), EnumServiceException.RUNTIME);
}
throw ExceptionUtil.createCmisException(e);
}
VersionHistory versionHistory = versionService.getVersionHistory(documentNodeRef);
if (null != versionHistory)
{
for (Version version = versionService.getCurrentVersion(documentNodeRef); null != version; version = versionHistory.getPredecessor(version))
{
objects.add(createCmisObject(version.getFrozenStateNodeRef(), propertyFilter, includeAllowableActions, null));
}
}
// TODO: includeRelationships
return objects;
}
@@ -271,43 +191,17 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve
public CmisPropertiesType getPropertiesOfLatestVersion(String repositoryId, String objectId, Boolean major, String filter, CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT);
NodeRef latestVersionNodeRef;
try
{
latestVersionNodeRef = cmisService.getLatestVersion(objectId, major != null && major);
}
catch (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
PropertyFilter propertyFilter = createPropertyFilter(filter);
major = (null == major) ? (false) : (major);
NodeRef latestVersionNodeRef = getAndCheckLatestNodeRef(documentNodeRef, major);
return propertiesUtil.getPropertiesType(latestVersionNodeRef.toString(), propertyFilter);
}
private void assertLatestVersion(NodeRef nodeRef, boolean mustBePwc) throws CmisException
{
if (mustBePwc)
{
boolean checkedOut = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_IS_VERSION_SERIES_CHECKED_OUT, false);
definitelyGetWorkingCopy(checkedOut, nodeRef);
}
else
{
Boolean latestVersion = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_IS_LATEST_VERSION, false);
if (!latestVersion && !cmisObjectsUtils.isWorkingCopy(nodeRef))
{
throw cmisObjectsUtils.createCmisException("Operation can be executed only on the latest document version", EnumServiceException.VERSIONING);
}
}
}
private NodeRef definitelyGetWorkingCopy(boolean checkedOut, NodeRef nodeRef) throws CmisException
{
NodeRef workingCopy = null;
String workingCopyId = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_VERSION_SERIES_CHECKED_OUT_ID, null);
if (checkedOut && (null != workingCopyId) && !"".equals(workingCopyId))
{
workingCopy = cmisObjectsUtils.getIdentifierInstance(workingCopyId, AlfrescoObjectType.DOCUMENT_OBJECT);
}
if ((null == workingCopy) || !cmisObjectsUtils.isWorkingCopy(workingCopy))
{
throw cmisObjectsUtils.createCmisException("Object isn't checked out", EnumServiceException.UPDATE_CONFLICT);
}
return workingCopy;
return propertiesUtil.getProperties(latestVersionNodeRef, propertyFilter);
}
/**
@@ -318,29 +212,23 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve
EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePolicyIds, Boolean includeACL, CmisExtensionType extension) throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT);
PropertyFilter propertyFilter = createPropertyFilter(filter);
includeAllowableActions = (null == includeAllowableActions) ? (false) : (includeAllowableActions);
major = (null == major) ? (false) : (major);
NodeRef latestVersionNodeRef = getAndCheckLatestNodeRef(documentNodeRef, major);
// TODO: includeRelationships
// TODO: includePolicyIds
CmisObjectType result = createCmisObject(latestVersionNodeRef.toString(), propertyFilter, includeAllowableActions, renditionFilter);
if (includeACL)
try
{
appendWithAce(documentNodeRef, result);
}
return result;
}
NodeRef latestVersionNodeRef = cmisService.getLatestVersion(objectId, major != null && major);
// TODO: includeRelationships
// TODO: includePolicyIds
PropertyFilter propertyFilter = createPropertyFilter(filter);
CmisObjectType result = createCmisObject(latestVersionNodeRef, propertyFilter, includeAllowableActions, renditionFilter);
if (includeACL)
{
appendWithAce(cmisService.getVersionSeries(objectId, NodeRef.class, false), result);
}
private NodeRef getAndCheckLatestNodeRef(NodeRef documentNodeRef, Boolean major) throws CmisException
{
NodeRef latestVersionNodeRef = cmisObjectsUtils.getLatestNode(documentNodeRef, major);
Boolean majorVersionProperty = propertiesUtil.getProperty(latestVersionNodeRef, CMISDictionaryModel.PROP_IS_MAJOR_VERSION, false);
if (major && !majorVersionProperty)
{
throw cmisObjectsUtils.createCmisException("Object that was specified has no latest major version", EnumServiceException.OBJECT_NOT_FOUND);
return result;
}
catch (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
return latestVersionNodeRef;
}
}

View File

@@ -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.utils;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.cmis.mapping.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<String, AlfrescoObjectType> VALUES;
static
{
VALUES = new HashMap<String, AlfrescoObjectType>();
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;
}
}

View File

@@ -1,364 +0,0 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* 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.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.cmis.ws.EnumUnfileObject;
import org.alfresco.repo.model.filefolder.FileInfoImpl;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.namespace.QName;
/**
* This class enumerates Documents and Folders hierarchy that begins from specified folder. Iterator returns Document or Empty Folder Objects those may be removed or deleted from
* repository according to {@link EnumUnfileObject} <b>unfileObject</b> and {@link Boolean} <b>continueOnFailure</b> parameters. After hierarchy enumerating completion iterator may
* introduce Object Id(s) {@link List} those were not deleted due to {@link Exception}(s)
*
* @author Dmitry Velichkevich
*/
public class CmisObjectIterator implements Iterator<FileInfo>
{
private EnumUnfileObject unfillingStrategy;
private boolean continueOnFailure;
private NodeService nodeService;
private FileFolderService fileFolderService;
private VersionService versionService;
private CheckOutCheckInService checkOutCheckInService;
private CmisObjectsUtils objectsUtils;
private Map<FileInfo, List<FileInfo>> hierarchy = new HashMap<FileInfo, List<FileInfo>>();
private LinkedList<FileInfo> objects = new LinkedList<FileInfo>();
private List<String> failToDelete = new LinkedList<String>();
private FileInfo next;
private boolean lastDeleted;
private boolean nextFound;
private boolean deleteAllVersions;
/**
* Mandatory constructor
*
* @param rootObject - {@link NodeRef} instance that represents Root folder for hierarchy
* @param unfillingStrategy - {@link EnumUnfileObject} value that determines File-able Objects deletion or removing strategy
* @param continueOnFailure - {@link Boolean} value that determines whether it is necessary continue deletion after some {@link Exception} occurred
* @param nodeService - A {@link NodeService} implementation instance for manipulating with Object Properties
* @param fileFolderService - A {@link FileFolderService} implementation instance for manipulating with Objects
* @param objectsUtils - {@link CmisObjectsUtils} service instance for simplifying manipulations with Objects and Object Properties
*/
public CmisObjectIterator(NodeRef rootObject, EnumUnfileObject unfillingStrategy, boolean continueOnFailure, boolean deleteAllVersions, NodeService nodeService,
FileFolderService fileFolderService, VersionService versionService, CheckOutCheckInService checkOutCheckInService, CmisObjectsUtils objectsUtils)
{
this.unfillingStrategy = unfillingStrategy;
this.deleteAllVersions = deleteAllVersions;
this.continueOnFailure = continueOnFailure;
this.nodeService = nodeService;
this.fileFolderService = fileFolderService;
this.versionService = versionService;
this.checkOutCheckInService = checkOutCheckInService;
this.objectsUtils = objectsUtils;
objects.add(new ParentedFileInfo(fileFolderService.getFileInfo(rootObject), null));
}
/**
* This method performs searching for next Object (see {@link CmisObjectIterator})
*/
public boolean hasNext()
{
if (nextFound)
{
return true;
}
if (objects.isEmpty() || (!failToDelete.isEmpty() && !continueOnFailure))
{
return false;
}
for (next = objects.removeFirst(); processFolder() && !objects.isEmpty(); next = objects.removeFirst())
{
}
nextFound = (null != next) && (!next.isFolder() || (null == receiveChildren(next.getNodeRef())));
return nextFound;
}
private boolean processFolder()
{
if (next.isFolder())
{
List<ChildAssociationRef> children = receiveChildren(next.getNodeRef());
if (null != children)
{
objects.addFirst(next);
for (ChildAssociationRef child : children)
{
FileInfo info = fileFolderService.getFileInfo(child.getChildRef());
ParentedFileInfo childInfo = new ParentedFileInfo(info, next);
objects.addFirst(childInfo);
addChildToParent(next, childInfo);
}
return true;
}
}
return false;
}
private void addChildToParent(FileInfo parent, FileInfo child)
{
if (null != parent)
{
List<FileInfo> children;
if (hierarchy.containsKey(parent))
{
children = hierarchy.get(parent);
}
else
{
children = new LinkedList<FileInfo>();
hierarchy.put(parent, children);
}
children.add(child);
}
}
private List<ChildAssociationRef> receiveChildren(NodeRef folderRef)
{
if (null != folderRef)
{
List<ChildAssociationRef> result = nodeService.getChildAssocs(folderRef);
if ((null != result) && !result.isEmpty())
{
return result;
}
}
return null;
}
/**
* This method returns currently enumerated Object and changes flag to enumerate next Object
*
* @see CmisObjectIterator
* @see CmisObjectIterator#hasNext()
* @see CmisObjectIterator#remove()
*/
public FileInfo next()
{
nextFound = false;
return next;
}
/**
* This method removes currently enumerated Object (see {@link CmisObjectIterator}). If Object deletion or removing fails due to {@link Exception} then according to
* <b>continueOnFailure</b> parameter current Object Id and (if <b>continueOnFailure</b>="<b>true</b>") current Object Parent(s)' Id(s) will be stored in <b>failedToDelete</b>
* {@link List}. Not deleted Object and its Parent(s) never will be enumerated again
*
* @see CmisObjectIterator
* @see CmisObjectIterator#hasNext()
* @see CmisObjectIterator#next()
*/
public void remove()
{
lastDeleted = false;
NodeRef parentRef = null;
ParentedFileInfo info = null;
if (null != next)
{
info = (ParentedFileInfo) next;
EnumUnfileObject howToDelete = null;
parentRef = (null != info.getExactParent()) ? (info.getExactParent().getNodeRef()) : (null);
if ((null != parentRef) && ((EnumUnfileObject.DELETESINGLEFILED == unfillingStrategy) || !objectsUtils.isPrimaryObjectParent(parentRef, info.getNodeRef())))
{
howToDelete = EnumUnfileObject.DELETESINGLEFILED;
}
else
{
howToDelete = EnumUnfileObject.DELETE;
}
if (EnumUnfileObject.DELETESINGLEFILED == howToDelete)
{
lastDeleted = objectsUtils.removeObject(info.getNodeRef(), parentRef);
}
else
{
if (deleteAllVersions)
{
NodeRef workingCopyRef = (objectsUtils.isWorkingCopy(info.getNodeRef())) ? (info.getNodeRef()) : (checkOutCheckInService.getWorkingCopy(info.getNodeRef()));
if (null == workingCopyRef)
{
versionService.deleteVersionHistory(info.getNodeRef());
}
}
lastDeleted = (objectsUtils.deleteObject(info.getNodeRef()));
}
}
if (!lastDeleted && (null != info))
{
failToDelete.add(generateId(info));
if ((null == info.getExactParent()) && info.isFolder())
{
removeFolderFromCollections(info);
}
if (continueOnFailure)
{
for (; null != info.getExactParent(); info = (ParentedFileInfo) info.getExactParent())
{
failToDelete.add(generateId(info.getExactParent()));
removeFolderFromCollections(info.getExactParent());
}
}
}
}
private void removeFolderFromCollections(FileInfo object)
{
if (hierarchy.containsKey(object))
{
hierarchy.remove(object);
objects.remove(object);
}
}
private String generateId(FileInfo object)
{
StringBuilder generator = new StringBuilder(object.getNodeRef().toString());
Map<QName, Serializable> properties = object.getProperties();
String versionLabel = (null != properties) ? ((String) properties.get(ContentModel.PROP_VERSION_LABEL)) : (null);
if (null != versionLabel)
{
generator.append(CmisObjectsUtils.NODE_REFERENCE_ID_DELIMITER).append(versionLabel);
}
return generator.toString();
}
public boolean wasLastRemoved()
{
return lastDeleted;
}
public List<String> getFailToDelete()
{
return failToDelete;
}
/**
* This class is {@link org.alfresco.jlan.server.filesys.FileInfo} implementation that uses {@link FileInfoImpl} instances to delegate core functionality. The main target of
* this class is extended standard {@link FileInfo} Objects with Parent Object
*
* @author Dmitry Velichkevich
*/
private class ParentedFileInfo implements FileInfo, Serializable
{
private static final long serialVersionUID = -3024276223816623074L;
private FileInfo delegator;
private FileInfo exactParent;
public ParentedFileInfo(FileInfo delegator, FileInfo exactParent)
{
this.delegator = delegator;
this.exactParent = exactParent;
}
public ContentData getContentData()
{
return delegator.getContentData();
}
public Date getCreatedDate()
{
return delegator.getCreatedDate();
}
public NodeRef getLinkNodeRef()
{
return delegator.getLinkNodeRef();
}
public Date getModifiedDate()
{
return delegator.getModifiedDate();
}
public String getName()
{
return delegator.getName();
}
public NodeRef getNodeRef()
{
return delegator.getNodeRef();
}
public Map<QName, Serializable> getProperties()
{
return delegator.getProperties();
}
public boolean isFolder()
{
return delegator.isFolder();
}
public boolean isLink()
{
return delegator.isLink();
}
public FileInfo getExactParent()
{
return exactParent;
}
@Override
public boolean equals(Object obj)
{
return delegator.equals(obj);
}
@Override
public int hashCode()
{
return delegator.hashCode();
}
@Override
public String toString()
{
return delegator.toString();
}
}
}

View File

@@ -1,566 +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.utils;
import java.math.BigInteger;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.alfresco.cmis.CMISDictionaryService;
import org.alfresco.cmis.CMISQueryException;
import org.alfresco.cmis.CMISScope;
import org.alfresco.cmis.CMISTypeDefinition;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.cmis.ws.CmisException;
import org.alfresco.repo.cmis.ws.CmisFaultType;
import org.alfresco.repo.cmis.ws.EnumBaseObjectTypeIds;
import org.alfresco.repo.cmis.ws.EnumRelationshipDirection;
import org.alfresco.repo.cmis.ws.EnumServiceException;
import org.alfresco.repo.cmis.ws.EnumUnfileObject;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.permissions.AccessDeniedException;
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.ContentIOException;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
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.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory;
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;
import org.alfresco.service.namespace.QNamePattern;
import org.springframework.extensions.surf.util.Pair;
/**
* @author Dmitry Velichkevich
*/
public class CmisObjectsUtils
{
public static final String NODE_REFERENCE_ID_DELIMITER = ";";
private static final Pattern VERSION_LABEL_MATCHING_COMPILED_PATTERN = Pattern.compile("([\\p{Graph}])+([\\p{Digit}]*)\\.([\\p{Digit}]*)$");
private static final String INVALID_OBJECT_IDENTIFIER_MESSAGE = "Invalid Object Identifier was specified: Identifier is incorrect or Object with the specified Identifier does not exist";
private static final List<QName> DOCUMENT_AND_FOLDER_TYPES;
static
{
DOCUMENT_AND_FOLDER_TYPES = new LinkedList<QName>();
DOCUMENT_AND_FOLDER_TYPES.add(ContentModel.TYPE_CONTENT);
DOCUMENT_AND_FOLDER_TYPES.add(ContentModel.TYPE_FOLDER);
}
private static final Map<String, EnumServiceException> CLASS_TO_ENUM_EXCEPTION_MAPPING;
static
{
CLASS_TO_ENUM_EXCEPTION_MAPPING = new HashMap<String, EnumServiceException>();
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(AccessDeniedException.class.getName(), EnumServiceException.PERMISSION_DENIED);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(java.lang.RuntimeException.class.getName(), EnumServiceException.RUNTIME);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(UnsupportedOperationException.class.getName(), EnumServiceException.NOT_SUPPORTED);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(InvalidNodeRefException.class.getName(), EnumServiceException.INVALID_ARGUMENT);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(ContentIOException.class.getName(), EnumServiceException.NOT_SUPPORTED);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(CMISQueryException.class.getName(), EnumServiceException.INVALID_ARGUMENT);
// TODO: insert CLASS_TO_ENUM_EXCEPTION_MAPPING.put(<Concreate_Exception_Type>.class.getName(), EnumServiceException.<Appropriate_Enum_value>);
}
private CheckOutCheckInService checkOutCheckInService;
private CMISDictionaryService cmisDictionaryService;
private FileFolderService fileFolderService;
private AuthorityService authorityService;
private VersionService versionService;
private NodeService nodeService;
private LockService lockService;
private Throwable lastException;
public void setCmisDictionaryService(CMISDictionaryService cmisDictionaryService)
{
this.cmisDictionaryService = cmisDictionaryService;
}
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 void setVersionService(VersionService versionService)
{
this.versionService = versionService;
}
public CmisException createCmisException(String message, EnumServiceException exceptionType)
{
return createCmisException(message, exceptionType, null, 0);
}
public CmisException createCmisException(String message, Throwable cause)
{
EnumServiceException exceptionType = null;
if (CLASS_TO_ENUM_EXCEPTION_MAPPING.containsKey(cause.getClass().getName()))
{
exceptionType = CLASS_TO_ENUM_EXCEPTION_MAPPING.get(cause.getClass().getName());
}
exceptionType = (exceptionType == null) ? (EnumServiceException.RUNTIME) : (exceptionType);
return createCmisException(message, exceptionType, cause, 0);
}
public CmisException createCmisException(String message, EnumServiceException exceptionType, Throwable cause)
{
return createCmisException(message, exceptionType, cause, 0);
}
public CmisException createCmisException(String message, EnumServiceException exceptionType, Throwable cause, int errorCode)
{
CmisFaultType fault = new CmisFaultType();
fault.setMessage(message);
fault.setType(exceptionType);
fault.setCode(BigInteger.valueOf(errorCode));
return new CmisException(message, fault, cause);
}
@SuppressWarnings("unchecked")
public <IdentifierType> IdentifierType getIdentifierInstance(String identifier, AlfrescoObjectType expectedType) throws CmisException
{
if (!(identifier instanceof String))
{
throw createCmisException("Invalid Object Identifier was specified", EnumServiceException.INVALID_ARGUMENT);
}
IdentifierType result;
AlfrescoObjectType actualObjectType;
if (isRelationship(identifier))
{
result = (IdentifierType) safeGetAssociationRef(identifier);
actualObjectType = AlfrescoObjectType.RELATIONSHIP_OBJECT;
}
else
{
NodeRef nodeReference = safeGetNodeRef(identifier);
result = (IdentifierType) nodeReference;
actualObjectType = determineActualObjectType(expectedType, this.nodeService.getType(nodeReference));
}
if ((AlfrescoObjectType.ANY_OBJECT == expectedType) || (actualObjectType == expectedType))
{
return result;
}
throw createCmisException(("Unexpected object type of the specified Object with \"" + identifier + "\" identifier"), EnumServiceException.INVALID_ARGUMENT);
}
public List<String> deleteFolder(NodeRef folderNodeReference, boolean continueOnFailure, EnumUnfileObject unfillingStrategy, boolean deleteAllVersions) throws CmisException
{
CmisObjectIterator iterator = new CmisObjectIterator(folderNodeReference, unfillingStrategy, continueOnFailure, deleteAllVersions, nodeService, fileFolderService,
versionService, checkOutCheckInService, this);
if (iterator.hasNext())
{
for (; iterator.hasNext(); iterator.next())
{
iterator.remove();
}
}
return iterator.getFailToDelete();
}
public boolean deleteObject(NodeRef objectNodeReference)
{
if (null == objectNodeReference)
{
return false;
}
if (versionService.getVersionStoreReference().getIdentifier().equals(objectNodeReference.getStoreRef().getIdentifier()))
{
String versionLabel = (String) nodeService.getProperty(objectNodeReference, ContentModel.PROP_VERSION_LABEL);
if ((null != versionLabel) && !versionLabel.equals(""))
{
Version currentVersion = versionService.getCurrentVersion(objectNodeReference);
if ((null != currentVersion) && nodeService.exists(currentVersion.getVersionedNodeRef()))
{
versionService.deleteVersion(currentVersion.getVersionedNodeRef(), currentVersion);
return true;
}
}
return false;
}
return canLock(objectNodeReference) && performNodeDeletion(objectNodeReference);
}
public boolean removeObject(NodeRef objectNodeReference, NodeRef folderNodeReference)
{
if (isChildOfThisFolder(objectNodeReference, folderNodeReference))
{
try
{
this.nodeService.removeChild(folderNodeReference, objectNodeReference);
}
catch (Throwable e)
{
lastException = e;
return false;
}
return true;
}
return false;
}
public boolean addObjectToFolder(NodeRef objectNodeRef, NodeRef parentFolderNodeRef)
{
try
{
QName name = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName((String) nodeService.getProperty(objectNodeRef,
ContentModel.PROP_NAME)));
nodeService.addChild(parentFolderNodeRef, objectNodeRef, ContentModel.ASSOC_CONTAINS, name);
return true;
}
catch (Throwable e)
{
lastException = e;
return false;
}
}
public boolean isFolder(NodeRef folderNodeRef)
{
if (folderNodeRef == null)
{
return false;
}
QName typeQName = nodeService.getType(folderNodeRef);
CMISTypeDefinition typeDef = cmisDictionaryService.findTypeForClass(typeQName, CMISScope.FOLDER);
return typeDef != null;
}
public boolean isDocument(NodeRef documentNodeRef)
{
if (documentNodeRef == null)
{
return false;
}
QName typeQName = nodeService.getType(documentNodeRef);
CMISTypeDefinition typeDef = cmisDictionaryService.findTypeForClass(typeQName, CMISScope.DOCUMENT);
return typeDef != null;
}
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 EnumBaseObjectTypeIds determineObjectType(String identifier)
{
if (isRelationship(identifier))
{
return EnumBaseObjectTypeIds.CMIS_RELATIONSHIP;
}
NodeRef objectNodeReference = new NodeRef(identifier);
if (isFolder(objectNodeReference))
{
return EnumBaseObjectTypeIds.CMIS_FOLDER;
}
if (isDocument(objectNodeReference))
{
return EnumBaseObjectTypeIds.CMIS_DOCUMENT;
}
return EnumBaseObjectTypeIds.CMIS_POLICY;
}
public boolean isChildOfThisFolder(NodeRef objectNodeReference, NodeRef folderNodeReference)
{
NodeRef searchedObjectNodeReference = fileFolderService.searchSimple(folderNodeReference, (String) nodeService.getProperty(objectNodeReference, ContentModel.PROP_NAME));
return (searchedObjectNodeReference != null) && searchedObjectNodeReference.equals(objectNodeReference);
}
public boolean isPrimaryObjectParent(NodeRef folderNodeReference, NodeRef objectNodeReference)
{
NodeRef searchedParentObject = nodeService.getPrimaryParent(objectNodeReference).getParentRef();
return (searchedParentObject != null) && searchedParentObject.equals(folderNodeReference);
}
public boolean isWorkingCopy(NodeRef objectIdentifier)
{
return nodeService.hasAspect(objectIdentifier, ContentModel.ASPECT_WORKING_COPY);
}
public List<AssociationRef> receiveAssociations(NodeRef objectNodeReference, QNamePattern qnameFilter, EnumRelationshipDirection direction)
{
List<AssociationRef> result = new LinkedList<AssociationRef>();
if ((direction == EnumRelationshipDirection.EITHER) || (direction == EnumRelationshipDirection.TARGET))
{
result.addAll(nodeService.getSourceAssocs(objectNodeReference, qnameFilter));
}
if ((direction == EnumRelationshipDirection.EITHER) || (direction == EnumRelationshipDirection.SOURCE))
{
result.addAll(nodeService.getTargetAssocs(objectNodeReference, qnameFilter));
}
return result;
}
/**
* Returns latest minor or major version of document
*
* @param documentNodeRef document node reference
* @param major need latest major version
* @return latest version node reference
*/
public NodeRef getLatestNode(NodeRef documentNodeRef, boolean major)
{
NodeRef latestVersionNodeRef = documentNodeRef;
VersionHistory versionHistory = versionService.getVersionHistory(documentNodeRef);
if (null != versionHistory)
{
Collection<Version> allVersions = versionHistory.getAllVersions();
Iterator<Version> versionsIterator = ((null != allVersions) && !allVersions.isEmpty()) ? (allVersions.iterator()) : (null);
Version latestVersion = (null == versionsIterator) ? (null) : (versionsIterator.next());
String currentVersionLabel = (null != latestVersion) ? (latestVersion.getVersionLabel()) : (null);
if (major && (null != latestVersion))
{
for (; (VersionType.MAJOR != latestVersion.getVersionType()) && versionsIterator.hasNext(); latestVersion = versionsIterator.next())
{
}
latestVersion = (VersionType.MAJOR != latestVersion.getVersionType()) ? (null) : (latestVersion);
}
if ((null != latestVersion) && (null != latestVersion.getVersionLabel()))
{
latestVersionNodeRef = (!latestVersion.getVersionLabel().equals(currentVersionLabel) || (null == latestVersion.getVersionedNodeRef()) || !nodeService
.exists(latestVersion.getVersionedNodeRef())) ? (latestVersion.getFrozenStateNodeRef()) : (latestVersion.getVersionedNodeRef());
}
}
return latestVersionNodeRef;
}
private boolean performNodeDeletion(NodeRef objectNodeReference)
{
if (nodeService.hasAspect(objectNodeReference, ContentModel.ASPECT_WORKING_COPY))
{
checkOutCheckInService.cancelCheckout(objectNodeReference);
return true;
}
try
{
List<AssociationRef> associations = receiveAssociations(objectNodeReference, new MatcheAllQNames(), EnumRelationshipDirection.EITHER);
for (AssociationRef association : associations)
{
if ((null != association) && (null != association.getSourceRef()) && (null != association.getTargetRef()) && (null != association.getTypeQName()))
{
nodeService.removeAssociation(association.getSourceRef(), association.getTargetRef(), association.getTypeQName());
}
}
for (ChildAssociationRef parentAssociation : nodeService.getParentAssocs(objectNodeReference))
{
if (!parentAssociation.isPrimary())
{
nodeService.removeChildAssociation(parentAssociation);
}
}
nodeService.deleteNode(objectNodeReference);
}
catch (Throwable e)
{
lastException = e;
return false;
}
return true;
}
private boolean canLock(NodeRef objectNodeReference)
{
String currentUserName = AuthenticationUtil.getFullyAuthenticatedUser();
return (this.lockService.getLockStatus(objectNodeReference, currentUserName) != LockStatus.LOCKED) || authorityService.isAdminAuthority(currentUserName);
}
private AssociationRef safeGetAssociationRef(String identifier) throws CmisException
{
AssociationRef result = new AssociationRef(identifier);
if (!nodeService.exists(result.getSourceRef()) || !nodeService.exists(result.getTargetRef()))
{
throw createCmisException(INVALID_OBJECT_IDENTIFIER_MESSAGE, EnumServiceException.INVALID_ARGUMENT);
}
return result;
}
private NodeRef safeGetNodeRef(String nodeIdentifier) throws CmisException
{
Pair<String, String> nodeRefAndVersionLabel = (null != nodeIdentifier) ? (splitOnNodeRefAndVersionLabel(nodeIdentifier)) : (null);
if ((null != nodeRefAndVersionLabel) && (null != nodeRefAndVersionLabel.getFirst()) && NodeRef.isNodeRef(nodeRefAndVersionLabel.getFirst()))
{
NodeRef result = new NodeRef(nodeRefAndVersionLabel.getFirst());
if (nodeService.exists(result))
{
result = getNodeRefFromVersion(result, nodeRefAndVersionLabel.getSecond());
if ((null != result) && nodeService.exists(result))
{
return result;
}
}
}
throw createCmisException(INVALID_OBJECT_IDENTIFIER_MESSAGE, EnumServiceException.OBJECT_NOT_FOUND);
}
private Pair<String, String> splitOnNodeRefAndVersionLabel(String nodeIdentifier)
{
String versionLabel = null;
int versionDelimeterIndex = nodeIdentifier.lastIndexOf(NODE_REFERENCE_ID_DELIMITER);
if (versionDelimeterIndex > 0)
{
versionLabel = nodeIdentifier.substring(versionDelimeterIndex + 1);
if ((null != versionLabel) && !versionLabel.equals("") && VERSION_LABEL_MATCHING_COMPILED_PATTERN.matcher(versionLabel).matches())
{
nodeIdentifier = nodeIdentifier.substring(0, versionDelimeterIndex);
}
else
{
versionLabel = null;
}
}
return new Pair<String, String>(nodeIdentifier, versionLabel);
}
private NodeRef getNodeRefFromVersion(NodeRef nodeRef, String versionLabel) throws CmisException
{
NodeRef result = nodeRef;
NodeRef latestNodeRef = ((null != versionLabel) && (null != nodeRef)) ? (getLatestNode(nodeRef, false)) : (null);
if ((null != latestNodeRef) && nodeService.exists(latestNodeRef) && !versionLabel.equals(nodeService.getProperty(latestNodeRef, ContentModel.PROP_VERSION_LABEL)))
{
VersionHistory versionHistory = versionService.getVersionHistory(latestNodeRef);
if (null != versionHistory)
{
Version version = versionHistory.getVersion(versionLabel);
if ((null == version) || (null == version.getFrozenStateNodeRef()))
{
throw createCmisException(("Specified object has no " + versionLabel + " version"), EnumServiceException.INVALID_ARGUMENT);
}
result = version.getFrozenStateNodeRef();
}
}
return result;
}
private AlfrescoObjectType determineActualObjectType(AlfrescoObjectType expectedType, QName objectType)
{
CMISTypeDefinition typeDef = cmisDictionaryService.findTypeForClass(objectType);
if ((expectedType == AlfrescoObjectType.DOCUMENT_OBJECT || expectedType == AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT)
&& typeDef.getTypeId().getScope() == CMISScope.DOCUMENT)
{
return expectedType;
}
if ((expectedType == AlfrescoObjectType.FOLDER_OBJECT || expectedType == AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT)
&& typeDef.getTypeId().getScope() == CMISScope.FOLDER)
{
return expectedType;
}
return AlfrescoObjectType.ANY_OBJECT;
}
private class MatcheAllQNames implements QNamePattern
{
public boolean isMatch(QName qname)
{
return true;
}
}
public Throwable getLastOperationException()
{
Throwable result = lastException;
lastException = null;
return result;
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2005-2010 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 received 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.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.cmis.CMISQueryException;
import org.alfresco.cmis.CMISServiceException;
import org.alfresco.repo.cmis.ws.CmisException;
import org.alfresco.repo.cmis.ws.CmisFaultType;
import org.alfresco.repo.cmis.ws.EnumServiceException;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
/**
* @author Dmitry Velichkevich
*/
public abstract class ExceptionUtil
{
private static final Map<String, EnumServiceException> CLASS_TO_ENUM_EXCEPTION_MAPPING;
static
{
CLASS_TO_ENUM_EXCEPTION_MAPPING = new HashMap<String, EnumServiceException>();
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(AccessDeniedException.class.getName(), EnumServiceException.PERMISSION_DENIED);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(java.lang.RuntimeException.class.getName(), EnumServiceException.RUNTIME);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(UnsupportedOperationException.class.getName(), EnumServiceException.NOT_SUPPORTED);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(InvalidNodeRefException.class.getName(), EnumServiceException.INVALID_ARGUMENT);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(ContentIOException.class.getName(), EnumServiceException.NOT_SUPPORTED);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(CMISQueryException.class.getName(), EnumServiceException.INVALID_ARGUMENT);
}
public static CmisException createCmisException(String message, EnumServiceException exceptionType)
{
return createCmisException(message, exceptionType, null, 0);
}
public static CmisException createCmisException(String message, Throwable cause)
{
EnumServiceException exceptionType = null;
if (cause instanceof CMISServiceException)
{
return createCmisException((CMISServiceException)cause);
}
if (CLASS_TO_ENUM_EXCEPTION_MAPPING.containsKey(cause.getClass().getName()))
{
exceptionType = CLASS_TO_ENUM_EXCEPTION_MAPPING.get(cause.getClass().getName());
}
exceptionType = (exceptionType == null) ? (EnumServiceException.RUNTIME) : (exceptionType);
return createCmisException(message, exceptionType, cause, 0);
}
public static CmisException createCmisException(String message, EnumServiceException exceptionType, Throwable cause)
{
return createCmisException(message, exceptionType, cause, 0);
}
public static CmisException createCmisException(CMISServiceException exception)
{
return createCmisException(exception.getMessage(), EnumServiceException.fromValue(exception.getFaultName()), exception, exception.getStatusCode());
}
public static CmisException createCmisException(String message, EnumServiceException exceptionType, Throwable cause, int errorCode)
{
CmisFaultType fault = new CmisFaultType();
fault.setMessage(message);
fault.setType(exceptionType);
fault.setCode(BigInteger.valueOf(errorCode));
return new CmisException(message, fault, cause);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
* Copyright (C) 2005-2010 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
@@ -15,11 +15,11 @@
* 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 received 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;
@@ -40,6 +40,7 @@ import javax.xml.datatype.XMLGregorianCalendar;
import org.alfresco.cmis.CMISDataTypeEnum;
import org.alfresco.cmis.CMISDictionaryModel;
import org.alfresco.cmis.CMISDictionaryService;
import org.alfresco.cmis.CMISInvalidArgumentException;
import org.alfresco.cmis.CMISPropertyDefinition;
import org.alfresco.cmis.CMISScope;
import org.alfresco.cmis.CMISServices;
@@ -65,6 +66,7 @@ import org.alfresco.service.cmr.dictionary.TypeDefinition;
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.version.Version;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
@@ -98,7 +100,6 @@ public class PropertyUtil
private NamespaceService namespaceService;
private CMISServices cmisService;
private CMISDictionaryService cmisDictionaryService;
private CmisObjectsUtils cmisObjectsUtils;
public PropertyUtil()
{
@@ -129,11 +130,6 @@ public class PropertyUtil
this.cmisDictionaryService = cmisDictionaryService;
}
public void setCmisObjectsUtils(CmisObjectsUtils cmisObjectsUtils)
{
this.cmisObjectsUtils = cmisObjectsUtils;
}
/**
* Gets property value by its name from Node Reference object
*
@@ -275,7 +271,7 @@ public class PropertyUtil
if ((PropertyMultiValueStateEnum.PROPERTY_NOT_MULTIVALUED == state) && (values.size() > 1))
{
throw cmisObjectsUtils.createCmisException("\"" + propertyName + "\" property is not Multi Valued", EnumServiceException.INVALID_ARGUMENT);
throw ExceptionUtil.createCmisException("\"" + propertyName + "\" property is not Multi Valued", EnumServiceException.INVALID_ARGUMENT);
}
return PropertyMultiValueStateEnum.PROPERTY_MULTIVALUED == state;
@@ -379,7 +375,7 @@ public class PropertyUtil
if ((null == cmisObjectType) && (null == nativeObjectType))
{
throw cmisObjectsUtils.createCmisException(("Can't find type definition for current object with \"" + typeId + "\" type Id"), EnumServiceException.INVALID_ARGUMENT);
throw ExceptionUtil.createCmisException(("Can't find type definition for current object with \"" + typeId + "\" type Id"), EnumServiceException.INVALID_ARGUMENT);
}
for (CmisProperty property : properties.getProperty())
@@ -406,7 +402,7 @@ public class PropertyUtil
}
case PROPERTY_NOT_UPDATABLE:
{
throw cmisObjectsUtils.createCmisException(("\"" + propertyName + "\" property is not updatable by repository for specified Object id"),
throw ExceptionUtil.createCmisException(("\"" + propertyName + "\" property is not updatable by repository for specified Object id"),
EnumServiceException.CONSTRAINT);
}
}
@@ -479,7 +475,7 @@ public class PropertyUtil
if (propertyDefinition.isRequired() && (null == value))
{
throw cmisObjectsUtils.createCmisException((propertyName + " property required"), EnumServiceException.CONSTRAINT);
throw ExceptionUtil.createCmisException((propertyName + " property required"), EnumServiceException.CONSTRAINT);
}
switch (propertyDefinition.getDataType())
@@ -514,7 +510,7 @@ public class PropertyUtil
{
if (value != null && (propertyDefinition.getMaximumLength() > 0) && (value.length() > propertyDefinition.getMaximumLength()))
{
throw cmisObjectsUtils.createCmisException((propertyName + " property value is too long"), EnumServiceException.CONSTRAINT);
throw ExceptionUtil.createCmisException((propertyName + " property value is too long"), EnumServiceException.CONSTRAINT);
}
}
@@ -525,21 +521,32 @@ public class PropertyUtil
* @param filter property filter
* @return properties
*/
public CmisPropertiesType getPropertiesType(String identifier, PropertyFilter filter) throws CmisException
public CmisPropertiesType getProperties(Object object, PropertyFilter filter) throws CmisException
{
Map<String, Serializable> properties;
if (!identifier.contains("|"))
try
{
properties = cmisService.getProperties(new NodeRef(identifier));
}
else
{
properties = createBaseRelationshipProperties(new AssociationRef(identifier));
}
Map<String, Serializable> properties;
if (object instanceof NodeRef)
{
properties = cmisService.getProperties((NodeRef) object);
}
else if (object instanceof Version)
{
properties = cmisService.getProperties(((Version) object).getFrozenStateNodeRef());
}
else
{
properties = createBaseRelationshipProperties((AssociationRef) object);
}
CmisPropertiesType result = new CmisPropertiesType();
convertToCmisProperties(properties, filter, result);
return result;
CmisPropertiesType result = new CmisPropertiesType();
convertToCmisProperties(properties, filter, result);
return result;
}
catch (CMISInvalidArgumentException e)
{
throw ExceptionUtil.createCmisException(e.getMessage(), EnumServiceException.INVALID_ARGUMENT, e);
}
}
private Map<String, Serializable> createBaseRelationshipProperties(AssociationRef association)
@@ -562,7 +569,7 @@ public class PropertyUtil
if (null == type)
{
throw cmisObjectsUtils.createCmisException(("Type with " + typeId + " typeId was not found"), EnumServiceException.RUNTIME);
throw ExceptionUtil.createCmisException(("Type with " + typeId + " typeId was not found"), EnumServiceException.RUNTIME);
}
for (String propertyName : properties.keySet())