From fbd7aab3b1cd0c9434644d86ecf0776b6a2fdbf3 Mon Sep 17 00:00:00 2001 From: David Caruana Date: Thu, 25 Feb 2010 15:02:44 +0000 Subject: [PATCH] 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 --- config/alfresco/audit/alfresco-audit-cmis.xml | 2 +- config/alfresco/cmis-api-context.xml | 9 +- .../cmis/CMISAccessControlReport.java | 4 +- .../cmis/CMISAccessControlService.java | 7 +- .../alfresco/cmis/CMISActionEvaluator.java | 9 +- .../org/alfresco/cmis/CMISChangeEvent.java | 40 +- .../alfresco/cmis/CMISChangeLogService.java | 3 +- .../cmis/CMISConstraintException.java | 53 +- .../CMISContentAlreadyExistsException.java | 40 + .../cmis/CMISFilterNotValidException.java | 40 + ...java => CMISInvalidArgumentException.java} | 101 +- ...ce.java => CMISNotSupportedException.java} | 107 +- .../cmis/CMISObjectNotFoundException.java | 35 + .../cmis/CMISPermissionDeniedException.java | 45 + .../org/alfresco/cmis/CMISQueryException.java | 4 +- .../alfresco/cmis/CMISRenditionService.java | 3 +- .../alfresco/cmis/CMISRuntimeException.java | 56 +- .../alfresco/cmis/CMISServiceException.java | 113 ++ .../java/org/alfresco/cmis/CMISServices.java | 584 +++++++- .../cmis/CMISStreamNotSupportedException.java | 41 + .../org/alfresco/cmis/CMISTypeDefinition.java | 2 +- .../cmis/CMISVersioningException.java | 45 + ...ence.java => CMISVersioningStateEnum.java} | 116 +- .../UnsupportedCMISAclPropagationMode.java | 80 -- ...ontrolEntriesGroupedByPrincipalIdImpl.java | 2 +- .../cmis/acl/CMISAccessControlReportImpl.java | 3 +- .../acl/CMISAccessControlServiceImpl.java | 4 +- .../acl/CMISAccessControlServiceTest.java | 10 +- .../cmis/changelog/CMISChangeEventImpl.java | 63 +- .../changelog/CMISChangeLogDataExtractor.java | 14 +- .../changelog/CMISChangeLogServiceImpl.java | 23 +- .../changelog/CMISChangeLogServiceTest.java | 19 +- .../CMISAbstractTypeDefinition.java | 6 +- .../CMISDocumentTypeDefinition.java | 19 +- .../cmis/mapping/AbstractActionEvaluator.java | 2 +- .../mapping/AbstractVersioningProperty.java | 85 ++ .../alfresco/cmis/mapping/CMISMapping.java | 76 +- .../cmis/mapping/CMISPropertyServiceTest.java | 14 +- .../cmis/mapping/CMISServicesImpl.java | 1211 +++++++++++++++-- .../cmis/mapping/CheckinCommentProperty.java | 31 +- .../mapping/FixedValueActionEvaluator.java | 5 +- .../cmis/mapping/IsImmutableProperty.java | 27 +- .../mapping/IsLatestMajorVersionProperty.java | 35 +- .../cmis/mapping/IsLatestVersionProperty.java | 11 +- .../cmis/mapping/IsMajorVersionProperty.java | 34 +- .../IsVersionSeriesCheckedOutProperty.java | 28 +- .../cmis/mapping/ObjectIdProperty.java | 36 +- .../cmis/mapping/ParentActionEvaluator.java | 6 +- .../mapping/PermissionActionEvaluator.java | 2 +- .../VersionLabelProperty.java} | 134 +- .../VersionSeriesCheckedOutByProperty.java | 33 +- .../VersionSeriesCheckedOutIdProperty.java | 27 +- .../cmis/mapping/VersionSeriesIdProperty.java | 20 +- .../cmis/reference/NodeRefReference.java | 110 -- .../cmis/reference/ObjectIdReference.java | 98 -- .../cmis/reference/ObjectPathReference.java | 88 -- .../cmis/reference/ReferenceFactory.java | 180 --- ...SourceTypeTargetRelationshipReference.java | 93 -- .../reference/StoreRepositoryReference.java | 86 -- .../renditions/CMISRenditionServiceImpl.java | 17 +- .../renditions/CMISRenditionServiceTest.java | 18 +- .../org/alfresco/cmis/search/QueryTest.java | 123 +- .../org/alfresco/repo/avm/AVMNodeService.java | 12 + .../repo/domain/hibernate/NodeAssocImpl.java | 1 + .../repo/node/db/DbNodeServiceImpl.java | 9 +- .../alfresco/repo/node/db/NodeDaoService.java | 12 +- .../HibernateNodeDaoServiceImpl.java | 10 + .../repo/tenant/MultiTServiceImpl.java | 4 +- .../repo/version/NodeServiceImpl.java | 14 +- .../cmr/repository/AssociationRef.java | 30 +- .../service/cmr/repository/NodeService.java | 11 +- 71 files changed, 2811 insertions(+), 1624 deletions(-) create mode 100644 source/java/org/alfresco/cmis/CMISContentAlreadyExistsException.java create mode 100644 source/java/org/alfresco/cmis/CMISFilterNotValidException.java rename source/java/org/alfresco/cmis/{reference/AbstractRepositoryReference.java => CMISInvalidArgumentException.java} (61%) rename source/java/org/alfresco/cmis/{reference/AbstractObjectReference.java => CMISNotSupportedException.java} (53%) create mode 100644 source/java/org/alfresco/cmis/CMISObjectNotFoundException.java create mode 100644 source/java/org/alfresco/cmis/CMISPermissionDeniedException.java create mode 100644 source/java/org/alfresco/cmis/CMISServiceException.java create mode 100644 source/java/org/alfresco/cmis/CMISStreamNotSupportedException.java create mode 100644 source/java/org/alfresco/cmis/CMISVersioningException.java rename source/java/org/alfresco/cmis/{reference/DefaultRepositoryReference.java => CMISVersioningStateEnum.java} (59%) delete mode 100644 source/java/org/alfresco/cmis/UnsupportedCMISAclPropagationMode.java create mode 100644 source/java/org/alfresco/cmis/mapping/AbstractVersioningProperty.java rename source/java/org/alfresco/cmis/{reference/AVMPathReference.java => mapping/VersionLabelProperty.java} (55%) delete mode 100644 source/java/org/alfresco/cmis/reference/NodeRefReference.java delete mode 100644 source/java/org/alfresco/cmis/reference/ObjectIdReference.java delete mode 100644 source/java/org/alfresco/cmis/reference/ObjectPathReference.java delete mode 100644 source/java/org/alfresco/cmis/reference/ReferenceFactory.java delete mode 100644 source/java/org/alfresco/cmis/reference/SourceTypeTargetRelationshipReference.java delete mode 100644 source/java/org/alfresco/cmis/reference/StoreRepositoryReference.java diff --git a/config/alfresco/audit/alfresco-audit-cmis.xml b/config/alfresco/audit/alfresco-audit-cmis.xml index 305c07023d..56b487e013 100755 --- a/config/alfresco/audit/alfresco-audit-cmis.xml +++ b/config/alfresco/audit/alfresco-audit-cmis.xml @@ -54,7 +54,7 @@ - + diff --git a/config/alfresco/cmis-api-context.xml b/config/alfresco/cmis-api-context.xml index 13714efe63..e6484a8f82 100644 --- a/config/alfresco/cmis-api-context.xml +++ b/config/alfresco/cmis-api-context.xml @@ -24,7 +24,11 @@ + + + + @@ -122,11 +126,6 @@ - - - - - diff --git a/source/java/org/alfresco/cmis/CMISAccessControlReport.java b/source/java/org/alfresco/cmis/CMISAccessControlReport.java index 07d631bbd3..cec4c3fc09 100644 --- a/source/java/org/alfresco/cmis/CMISAccessControlReport.java +++ b/source/java/org/alfresco/cmis/CMISAccessControlReport.java @@ -26,6 +26,7 @@ package org.alfresco.cmis; import java.util.List; + /** * An Access control report. * This is an ACL. @@ -53,8 +54,9 @@ public interface CMISAccessControlReport /** * Get ACEs grouped by principal id * @return + * @throws CMISConstraintException */ - public List getAccessControlEntriesGroupedByPrincipalId(); + public List getAccessControlEntriesGroupedByPrincipalId() throws CMISConstraintException; } diff --git a/source/java/org/alfresco/cmis/CMISAccessControlService.java b/source/java/org/alfresco/cmis/CMISAccessControlService.java index cdb7cc6919..035b2a3446 100644 --- a/source/java/org/alfresco/cmis/CMISAccessControlService.java +++ b/source/java/org/alfresco/cmis/CMISAccessControlService.java @@ -111,8 +111,9 @@ public interface CMISAccessControlService * @param nodeRef * @param acesToApply * @return an access control report of the final state + * @throws CMISConstraintException */ - public CMISAccessControlReport applyAcl(NodeRef nodeRef, List acesToApply); + public CMISAccessControlReport applyAcl(NodeRef nodeRef, List acesToApply) throws CMISConstraintException; /** * Update the ACEs on a node. @@ -125,7 +126,7 @@ public interface CMISAccessControlService * @param propagation * @param format * @return an access control report of the final state - * @exception UnsupportedCMISAclPropagationMode will be thrown for unsupported propagation modes. + * @throws CMISConstraintException */ - public CMISAccessControlReport applyAcl(NodeRef nodeRef, List acesToRemove, List acesToAdd, CMISAclPropagationEnum propagation, CMISAccessControlFormatEnum format); + public CMISAccessControlReport applyAcl(NodeRef nodeRef, List acesToRemove, List acesToAdd, CMISAclPropagationEnum propagation, CMISAccessControlFormatEnum format) throws CMISConstraintException; } diff --git a/source/java/org/alfresco/cmis/CMISActionEvaluator.java b/source/java/org/alfresco/cmis/CMISActionEvaluator.java index c692aa0a1b..92b4d89bd8 100644 --- a/source/java/org/alfresco/cmis/CMISActionEvaluator.java +++ b/source/java/org/alfresco/cmis/CMISActionEvaluator.java @@ -24,9 +24,8 @@ */ package org.alfresco.cmis; -import org.alfresco.service.cmr.repository.NodeRef; -public interface CMISActionEvaluator +public interface CMISActionEvaluator { /** * Gets the CMIS Allowed Action @@ -36,10 +35,10 @@ public interface CMISActionEvaluator public CMISAllowedActionEnum getAction(); /** - * Determines if Action is allowed + * Determines if an action is allowed on an object * - * @param nodeRef + * @param object * @return */ - public boolean isAllowed(NodeRef nodeRef); + public boolean isAllowed(T object); } diff --git a/source/java/org/alfresco/cmis/CMISChangeEvent.java b/source/java/org/alfresco/cmis/CMISChangeEvent.java index 9fb84ee154..82be3888e4 100755 --- a/source/java/org/alfresco/cmis/CMISChangeEvent.java +++ b/source/java/org/alfresco/cmis/CMISChangeEvent.java @@ -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.cmis; @@ -29,24 +29,38 @@ import java.util.Date; import org.alfresco.service.cmr.repository.NodeRef; /** - * This class describes entry record for some Change Log descriptor + * This class describes entry record for some Change Log descriptor. * * @author Dmitry Velichkevich */ public interface CMISChangeEvent -{ - /** - * @return {@link NodeRef} instance that represents Id of one of the Change Event objects for some Change Log Token - */ - public NodeRef getNode(); - +{ /** + * Gets the change type. + * * @return {@link CMISChangeType} enum value that determines the type of current Change Event */ public CMISChangeType getChangeType(); /** + * Gets the change time. + * * @return {@link Date} value that represents time of current Change Event */ public Date getChangeTime(); + + /** + * Gets the changed node (may no longer exist). + * + * @return the changed node + */ + public NodeRef getChangedNode(); + + /** + * Gets the object id. + * + * @return the object id + */ + public String getObjectId(); + } diff --git a/source/java/org/alfresco/cmis/CMISChangeLogService.java b/source/java/org/alfresco/cmis/CMISChangeLogService.java index 2b475e7ac8..5daa2406a6 100755 --- a/source/java/org/alfresco/cmis/CMISChangeLogService.java +++ b/source/java/org/alfresco/cmis/CMISChangeLogService.java @@ -37,8 +37,9 @@ public interface CMISChangeLogService * @param changeLogToken - {@link String} value that represents some Change Log Token * @param maxItems - {@link Integer} value that determines required amount of entries * @return {@link CMISChangeLog} instance that describes entry mapped to specified Change Log Token + * @throws CMISInvalidArgumentException */ - public CMISChangeLog getChangeLogEvents(String changeLogToken, Integer maxItems); + public CMISChangeLog getChangeLogEvents(String changeLogToken, Integer maxItems) throws CMISInvalidArgumentException; /** * @return {@link String} value that represents Change Log Token which is currently actual diff --git a/source/java/org/alfresco/cmis/CMISConstraintException.java b/source/java/org/alfresco/cmis/CMISConstraintException.java index 8e68c3d1dd..83c11e6228 100644 --- a/source/java/org/alfresco/cmis/CMISConstraintException.java +++ b/source/java/org/alfresco/cmis/CMISConstraintException.java @@ -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 @@ -18,62 +18,29 @@ * 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 + * 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.cmis; -/** - * @author andyh - * - */ -public class CMISConstraintException extends CMISRuntimeException +public class CMISConstraintException extends CMISServiceException { + private static final long serialVersionUID = -6416548401387587007L; - /** - * - */ - private static final long serialVersionUID = 575343231113393902L; - - /** - * @param msgId - */ - public CMISConstraintException(String msgId) + public CMISConstraintException(String message) { - super(msgId); - // TODO Auto-generated constructor stub + super(message, "constraint", 409); } - /** - * @param msgId - * @param msgParams - */ - public CMISConstraintException(String msgId, Object[] msgParams) + public CMISConstraintException(Throwable cause) { - super(msgId, msgParams); - // TODO Auto-generated constructor stub + super(cause, "constraint", 409); } - /** - * @param msgId - * @param cause - */ - public CMISConstraintException(String msgId, Throwable cause) + public CMISConstraintException(String message, Throwable cause) { - super(msgId, cause); - // TODO Auto-generated constructor stub - } - - /** - * @param msgId - * @param msgParams - * @param cause - */ - public CMISConstraintException(String msgId, Object[] msgParams, Throwable cause) - { - super(msgId, msgParams, cause); - // TODO Auto-generated constructor stub + super(message, cause, "constraint", 409); } } diff --git a/source/java/org/alfresco/cmis/CMISContentAlreadyExistsException.java b/source/java/org/alfresco/cmis/CMISContentAlreadyExistsException.java new file mode 100644 index 0000000000..3ffd2a40be --- /dev/null +++ b/source/java/org/alfresco/cmis/CMISContentAlreadyExistsException.java @@ -0,0 +1,40 @@ +/* + * 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.cmis; + +public class CMISContentAlreadyExistsException extends CMISServiceException +{ + private static final long serialVersionUID = -3036139369370574358L; + + public CMISContentAlreadyExistsException() + { + super("Content already exists", "contentAlreadyExists", 409); + } + + public CMISContentAlreadyExistsException(Throwable cause) + { + super("Content already exists", cause, "contentAlreadyExists", 409); + } +} diff --git a/source/java/org/alfresco/cmis/CMISFilterNotValidException.java b/source/java/org/alfresco/cmis/CMISFilterNotValidException.java new file mode 100644 index 0000000000..59c94dd1d3 --- /dev/null +++ b/source/java/org/alfresco/cmis/CMISFilterNotValidException.java @@ -0,0 +1,40 @@ +/* + * 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.cmis; + +public class CMISFilterNotValidException extends CMISServiceException +{ + private static final long serialVersionUID = -1947056142715192667L; + + public CMISFilterNotValidException(String filter) + { + super("Filter not valid: " + filter, "filterNotValid", 400); + } + + public CMISFilterNotValidException(String filter, Throwable cause) + { + super("Filter not valid: " + filter, cause, "filterNotValid", 400); + } +} diff --git a/source/java/org/alfresco/cmis/reference/AbstractRepositoryReference.java b/source/java/org/alfresco/cmis/CMISInvalidArgumentException.java similarity index 61% rename from source/java/org/alfresco/cmis/reference/AbstractRepositoryReference.java rename to source/java/org/alfresco/cmis/CMISInvalidArgumentException.java index 389fa6d519..0a6ad1c07e 100644 --- a/source/java/org/alfresco/cmis/reference/AbstractRepositoryReference.java +++ b/source/java/org/alfresco/cmis/CMISInvalidArgumentException.java @@ -1,56 +1,45 @@ -/* - * Copyright (C) 2005-2007 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.cmis.reference; - -import org.alfresco.cmis.CMISRepositoryReference; -import org.alfresco.cmis.CMISServices; - - -/** - * Abstract Repository Reference - * - * @author davidc - */ -public abstract class AbstractRepositoryReference implements CMISRepositoryReference -{ - protected CMISServices cmisServices; - - /** - * Construct - * - * @param cmisServices - */ - public AbstractRepositoryReference(CMISServices cmisServices) - { - this.cmisServices = cmisServices; - } - - @Override - public String toString() - { - return getStoreRef().toString(); - } - -} +/* + * 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.cmis; + +public class CMISInvalidArgumentException extends CMISServiceException +{ + private static final long serialVersionUID = -3036139369370574358L; + + public CMISInvalidArgumentException(String message) + { + super(message, "invalidArgument", 400); + } + + public CMISInvalidArgumentException(Throwable cause) + { + super(cause, "invalidArgument", 400); + } + + public CMISInvalidArgumentException(String message, Throwable cause) + { + super(message, cause, "invalidArgument", 400); + } +} diff --git a/source/java/org/alfresco/cmis/reference/AbstractObjectReference.java b/source/java/org/alfresco/cmis/CMISNotSupportedException.java similarity index 53% rename from source/java/org/alfresco/cmis/reference/AbstractObjectReference.java rename to source/java/org/alfresco/cmis/CMISNotSupportedException.java index 8c59e2494a..5b1d175a67 100644 --- a/source/java/org/alfresco/cmis/reference/AbstractObjectReference.java +++ b/source/java/org/alfresco/cmis/CMISNotSupportedException.java @@ -1,62 +1,45 @@ -/* - * Copyright (C) 2005-2007 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.cmis.reference; - -import org.alfresco.cmis.CMISObjectReference; -import org.alfresco.cmis.CMISRepositoryReference; -import org.alfresco.cmis.CMISServices; - - -/** - * Abstract Object Reference - * - * @author davidc - */ -public abstract class AbstractObjectReference implements CMISObjectReference -{ - protected CMISServices cmisServices; - protected CMISRepositoryReference repo; - - /** - * Construct - * - * @param cmisServices - * @param repo - */ - public AbstractObjectReference(CMISServices cmisServices, CMISRepositoryReference repo) - { - this.cmisServices = cmisServices; - this.repo = repo; - } - - /* - * (non-Javadoc) - * @see org.alfresco.cmis.CMISObjectReference#getRepositoryReference() - */ - public CMISRepositoryReference getRepositoryReference() - { - return repo; - } -} +/* + * 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.cmis; + +public class CMISNotSupportedException extends CMISServiceException +{ + private static final long serialVersionUID = 3550854898281486115L; + + public CMISNotSupportedException(String message) + { + super(message, "notSupported", 405); + } + + public CMISNotSupportedException(Throwable cause) + { + super(cause, "notSupported", 405); + } + + public CMISNotSupportedException(String message, Throwable cause) + { + super(message, cause, "notSupported", 405); + } +} diff --git a/source/java/org/alfresco/cmis/CMISObjectNotFoundException.java b/source/java/org/alfresco/cmis/CMISObjectNotFoundException.java new file mode 100644 index 0000000000..92ae86e2a4 --- /dev/null +++ b/source/java/org/alfresco/cmis/CMISObjectNotFoundException.java @@ -0,0 +1,35 @@ +/* + * 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.cmis; + +public class CMISObjectNotFoundException extends CMISServiceException +{ + private static final long serialVersionUID = 1726826685938651586L; + + public CMISObjectNotFoundException(String objectId) + { + super("Unable to find Object " + objectId, "objectNotFound", 404); + } +} diff --git a/source/java/org/alfresco/cmis/CMISPermissionDeniedException.java b/source/java/org/alfresco/cmis/CMISPermissionDeniedException.java new file mode 100644 index 0000000000..e849d70f63 --- /dev/null +++ b/source/java/org/alfresco/cmis/CMISPermissionDeniedException.java @@ -0,0 +1,45 @@ +/* + * 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.cmis; + +public class CMISPermissionDeniedException extends CMISServiceException +{ + private static final long serialVersionUID = 5483026490801996479L; + + public CMISPermissionDeniedException(String message) + { + super(message, "permissionDenied", 403); + } + + public CMISPermissionDeniedException(Throwable cause) + { + super(cause, "permissionDenied", 403); + } + + public CMISPermissionDeniedException(String message, Throwable cause) + { + super(message, cause, "permissionDenied", 403); + } +} diff --git a/source/java/org/alfresco/cmis/CMISQueryException.java b/source/java/org/alfresco/cmis/CMISQueryException.java index d7c9f6ca8b..240e8e3f76 100644 --- a/source/java/org/alfresco/cmis/CMISQueryException.java +++ b/source/java/org/alfresco/cmis/CMISQueryException.java @@ -24,12 +24,14 @@ */ package org.alfresco.cmis; +import org.alfresco.error.AlfrescoRuntimeException; + /** * @author andyh * */ -public class CMISQueryException extends CMISRuntimeException +public class CMISQueryException extends AlfrescoRuntimeException { /** diff --git a/source/java/org/alfresco/cmis/CMISRenditionService.java b/source/java/org/alfresco/cmis/CMISRenditionService.java index c5e94d8a32..48b765a5ef 100755 --- a/source/java/org/alfresco/cmis/CMISRenditionService.java +++ b/source/java/org/alfresco/cmis/CMISRenditionService.java @@ -41,7 +41,8 @@ public interface CMISRenditionService * @param node node reference of document * @param renditionFilter renditions filter * @return list of renditions + * @throws CMISFilterNotValidException */ - public List getRenditions(NodeRef node, String renditionFilter); + public List getRenditions(NodeRef node, String renditionFilter) throws CMISFilterNotValidException; } diff --git a/source/java/org/alfresco/cmis/CMISRuntimeException.java b/source/java/org/alfresco/cmis/CMISRuntimeException.java index 7fbbb25ecb..ade9da9c9f 100644 --- a/source/java/org/alfresco/cmis/CMISRuntimeException.java +++ b/source/java/org/alfresco/cmis/CMISRuntimeException.java @@ -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 @@ -18,64 +18,28 @@ * 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 + * 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.cmis; -import org.alfresco.error.AlfrescoRuntimeException; - -/** - * @author andyh - * - */ -public class CMISRuntimeException extends AlfrescoRuntimeException +public class CMISRuntimeException extends CMISServiceException { + private static final long serialVersionUID = 18549812596930942L; - /** - * - */ - private static final long serialVersionUID = 121670154804835474L; - - /** - * @param msgId - */ - public CMISRuntimeException(String msgId) + public CMISRuntimeException(String message) { - super(msgId); - // TODO Auto-generated constructor stub + super(message, "runtime", 500); } - /** - * @param msgId - * @param msgParams - */ - public CMISRuntimeException(String msgId, Object[] msgParams) + public CMISRuntimeException(Throwable cause) { - super(msgId, msgParams); - // TODO Auto-generated constructor stub + super(cause, "runtime", 500); } - /** - * @param msgId - * @param cause - */ - public CMISRuntimeException(String msgId, Throwable cause) + public CMISRuntimeException(String message, Throwable cause) { - super(msgId, cause); - // TODO Auto-generated constructor stub + super(message, cause, "runtime", 500); } - - /** - * @param msgId - * @param msgParams - * @param cause - */ - public CMISRuntimeException(String msgId, Object[] msgParams, Throwable cause) - { - super(msgId, msgParams, cause); - // TODO Auto-generated constructor stub - } - } diff --git a/source/java/org/alfresco/cmis/CMISServiceException.java b/source/java/org/alfresco/cmis/CMISServiceException.java new file mode 100644 index 0000000000..0ecbd38045 --- /dev/null +++ b/source/java/org/alfresco/cmis/CMISServiceException.java @@ -0,0 +1,113 @@ +/* + * 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.cmis; + +/** + * A base class for all exceptions that map to CMIS SOAP faults / HTTP error codes. Intentionally a checked + * non-RuntimeException so that the faults codes are propagated and signalled correctly. + * + * @author dward + */ +public abstract class CMISServiceException extends Exception +{ + private static final long serialVersionUID = 8220732267294509499L; + + /** The fault name, as per the CMIS spec. */ + private final String faultName; + + /** The status code, as per the CMIS REST binding. */ + private final int statusCode; + + /** + * Instantiates a new CMIS Service exception. + * + * @param message + * the message + * @param faultName + * the fault name, as per the CMIS spec + * @param statusCode + * the status code, as per the CMIS REST binding + */ + public CMISServiceException(String message, String faultName, int statusCode) + { + super(message); + this.faultName = faultName; + this.statusCode = statusCode; + } + + /** + * Instantiates a new CMIS Service exception. + * + * @param cause + * the cause + * @param faultName + * the fault name, as per the CMIS spec + * @param statusCode + * the status code, as per the CMIS REST binding + */ + public CMISServiceException(Throwable cause, String faultName, int errorCode) + { + this(cause.getMessage(), cause, faultName, errorCode); + } + + /** + * Instantiates a new CMIS Service exception. + * + * @param message + * the message + * @param cause + * the cause + * @param faultName + * the fault name, as per the CMIS spec + * @param statusCode + * the status code, as per the CMIS REST binding + */ + public CMISServiceException(String message, Throwable cause, String faultName, int errorCode) + { + super(message, cause); + this.faultName = faultName; + this.statusCode = errorCode; + } + + /** + * Gets the fault name. + * + * @return the fault name + */ + public String getFaultName() + { + return faultName; + } + + /** + * Gets the status code. + * + * @return the status code + */ + public int getStatusCode() + { + return this.statusCode; + } +} diff --git a/source/java/org/alfresco/cmis/CMISServices.java b/source/java/org/alfresco/cmis/CMISServices.java index e0cfafaa1d..9561bd72d5 100644 --- a/source/java/org/alfresco/cmis/CMISServices.java +++ b/source/java/org/alfresco/cmis/CMISServices.java @@ -24,21 +24,31 @@ */ package org.alfresco.cmis; +import java.io.InputStream; import java.io.Serializable; +import java.util.Collection; +import java.util.List; import java.util.Map; import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.namespace.QName; /** - * CMIS Services + * CMIS Services. * * @author davidc + * @author dward */ public interface CMISServices { + /** + * The prefix we give to association object IDs. + */ + public static final String ASSOC_ID_PREFIX = "assoc:"; + /** * Gets the supported CMIS Version * @@ -91,81 +101,583 @@ public interface CMISServices * @param renditionFilter * the rendition filter * @return the attribute map + * @throws CMISFilterNotValidException + * if the rendition filter is invalid */ - public Map getRenditions(NodeRef nodeRef, String renditionFilter); + public Map getRenditions(NodeRef nodeRef, String renditionFilter) + throws CMISFilterNotValidException; /** * Query for node children * - * @param parent node to query children for - * @param typesFilter types filter - * @return children of node + * @param parent + * node to query children for + * @param typesFilter + * types filter + * @param orderBy + * comma-separated list of query names and the ascending modifier "ASC" or the descending modifier "DESC" + * for each query name + * @return children of node */ - public NodeRef[] getChildren(NodeRef parent, CMISTypesFilterEnum typesFilter); + public NodeRef[] getChildren(NodeRef parent, CMISTypesFilterEnum typesFilter, String orderBy) + throws CMISInvalidArgumentException; /** * Query for checked out items - * - * @param username for user - * @param folder (optional) within folder - * @param includeDescendants true => include descendants of folder, false => only children of folder - * @return checked out items + * + * @param username + * for user + * @param folder + * (optional) within folder + * @param includeDescendants + * true => include descendants of folder, false => only children of folder + * @param orderBy + * comma-separated list of query names and the ascending modifier "ASC" or the descending modifier "DESC" + * for each query name + * @return checked out items */ - public NodeRef[] getCheckedOut(String username, NodeRef folder, boolean includeDescendants); + public NodeRef[] getCheckedOut(String username, NodeRef folder, boolean includeDescendants, String orderBy) + throws CMISInvalidArgumentException; /** - * Query for relationship + * Query for relationships. * * @param relDef - * @param source - * @param target - * @return relationship + * type of relationship to query (or null, for all relationships) + * @param includeSubTypes + * the include sub types + * @param direction + * limit direction of relationships to query (or null, for both directions) + * @param node + * the node + * @return relationships + * @throws CMISInvalidArgumentException + * if an argument is invalid */ - public AssociationRef getRelationship(CMISTypeDefinition relDef, NodeRef source, NodeRef target); + public AssociationRef[] getRelationships(NodeRef node, CMISTypeDefinition relDef, boolean includeSubTypes, CMISRelationshipDirectionEnum direction) throws CMISInvalidArgumentException; /** - * Query for relationships - * - * @param item node to query relationships for - * @param relDef type of relationship to query (or null, for all relationships) - * @param includeSubTypes - * @param direction limit direction of relationships to query (or null, for both directions) - * @return relationships - */ - public AssociationRef[] getRelationships(NodeRef node, CMISTypeDefinition relDef, boolean includeSubTypes, CMISRelationshipDirectionEnum direction); - - /** - * Get a single property for a node + * Get a single property for a node. * * @param nodeRef + * the node * @param propertyName + * the property name * @return value + * @throws CMISInvalidArgumentException + * if an argument is invalid */ - public Serializable getProperty(NodeRef nodeRef, String propertyName); + public Serializable getProperty(NodeRef nodeRef, String propertyName) throws CMISInvalidArgumentException; /** - * Get a single property for an association + * Get a single property for an association. * * @param assocRef + * the association * @param propertyName + * the property name * @return value */ public Serializable getProperty(AssociationRef assocRef, String propertyName); /** - * Get all properties + * Get all properties. * * @param nodeRef - * @return + * the node ref + * @return the properties + * @throws CMISInvalidArgumentException + * if an argument is invalid */ - public Map getProperties(NodeRef nodeRef); + public Map getProperties(NodeRef nodeRef) throws CMISInvalidArgumentException; /** - * Set a single property + * Set a single property. * * @param nodeRef + * the node ref * @param propertyName + * the property name * @param value + * the value + * @throws CMISInvalidArgumentException + * if an argument is invalid */ - public void setProperty(NodeRef nodeRef, String propertyName, Serializable value); + public void setProperty(NodeRef nodeRef, String propertyName, Serializable value) throws CMISInvalidArgumentException; + + /** + * Applies a versioning state to a new node, potentially resulting in a new node. + * + * @param source + * the node + * @param versioningState + * the versioning state + * @return the node to write changes to + * @throws CMISConstraintException + * if it's not possible to apply the state + * @throws CMISInvalidArgumentException + * if an argument is invalid + */ + public NodeRef applyVersioningState(NodeRef source, CMISVersioningStateEnum versioningState) + throws CMISConstraintException, CMISInvalidArgumentException; + + /** + * Gets a readable object of a required type from an object ID. The object may be immutable. Note that version + * history nodes can be returned as Versions or Nodes. + * + * @param objectId + * the object id + * @param requiredType + * the required type (NodeRef.class, Version.class, AssociationRef.class or Object.class) + * @return the readable object + * @throws CMISConstraintException + * if the object can't be returned as the right type + * @throws CMISVersioningException + * if the object's versioning state isn't as expected + * @throws CMISObjectNotFoundException + * if the object does not exist + * @throws CMISInvalidArgumentException + * if an argument is invalid + * @throws CMISPermissionDeniedException + * if access to the object is denied + */ + public T getReadableObject(String objectId, Class requiredType) throws CMISConstraintException, + CMISVersioningException, CMISObjectNotFoundException, CMISInvalidArgumentException, + CMISPermissionDeniedException; + + /** + * Gets an object or a required type from an object ID. The object's mutability and versioning state will be + * validated as required. + * + * @param objectId + * the object id + * @param requiredType + * the required type (NodeRef.class, Version.class, AssociationRef.class or Object.class) + * @param forUpdate + * Do we require to write to this object? If true then the object must not be checked out + * and must not be a version history node unless the required type is assignable from Version.class. + * @param isVersionable + * Should the object be versionable? + * @param isPwc + * If isVersionable is true then the object should either be or not be a private working + * copy, as indicated by this flag + * @return the object + * @throws CMISConstraintException + * if the object can't be returned as the right type + * @throws CMISVersioningException + * if the object's versioning state isn't as expected + * @throws CMISObjectNotFoundException + * if the object does not exist + * @throws CMISInvalidArgumentException + * if an argument is invalid + * @throws CMISPermissionDeniedException + * if access to the object is denied + */ + public T getObject(String objectId, Class requiredType, boolean forUpdate, boolean isVersionable, + boolean isPwc) throws CMISConstraintException, CMISVersioningException, CMISObjectNotFoundException, + CMISInvalidArgumentException, CMISPermissionDeniedException; + + /** + * Gets the version series of an object. + * + * @param objectId + * the object id + * @param requiredType + * the required type (NodeRef.class, Version.class or AssociationRef.class) + * @param isVersionable + * Should the object be versionable? + * @return the version series + * @throws CMISConstraintException + * if the object can't be returned as the right type + * @throws CMISVersioningException + * if the object's versioning state isn't as expected + * @throws CMISObjectNotFoundException + * if the object does not exist + * @throws CMISInvalidArgumentException + * if an argument is invalid + * @throws CMISPermissionDeniedException + * if access to the object is denied + */ + public T getVersionSeries(String objectId, Class requiredType, boolean isVersionable) + throws CMISConstraintException, CMISVersioningException, CMISObjectNotFoundException, + CMISInvalidArgumentException, CMISPermissionDeniedException; + + /** + * Gets a folder from an object ID. + * + * @param objectId + * the object id + * @return the folder + * @throws CMISConstraintException + * if the object can't be returned as the right type + * @throws CMISVersioningException + * if the object's versioning state isn't as expected + * @throws CMISObjectNotFoundException + * if the object does not exist + * @throws CMISInvalidArgumentException + * if an argument is invalid + * @throws CMISPermissionDeniedException + * if access to the object is denied + */ + public NodeRef getFolder(String objectId) throws CMISConstraintException, CMISVersioningException, + CMISObjectNotFoundException, CMISInvalidArgumentException, CMISPermissionDeniedException; + + /** + * Gets parent of a folder. + * + * @param folderId + * the folder id + * @return the folder parent + * @throws CMISConstraintException + * if the object can't be returned as the right type + * @throws CMISVersioningException + * if the object's versioning state isn't as expected + * @throws CMISObjectNotFoundException + * if the object does not exist + * @throws CMISInvalidArgumentException + * if an argument is invalid + * @throws CMISPermissionDeniedException + * if access to the object is denied + */ + public NodeRef getFolderParent(String folderId) throws CMISConstraintException, CMISVersioningException, + CMISObjectNotFoundException, CMISInvalidArgumentException, CMISPermissionDeniedException; + + /** + * Gets the type definition for a node. + * + * @param nodeRef + * the node + * @return the type definition + * @throws CMISInvalidArgumentException + * if an argument is invalid + */ + public CMISTypeDefinition getTypeDefinition(NodeRef nodeRef) throws CMISInvalidArgumentException; + + /** + * Gets the type definition for an association. + * + * @param associationRef + * the association + * @return the type definition + * @throws CMISInvalidArgumentException + * if an argument is invalid + */ + public CMISTypeDefinition getTypeDefinition(AssociationRef associationRef) throws CMISInvalidArgumentException; + + /** + * Gets the type definition for a given type ID. + * + * @param typeId + * the type id + * @return the type definition + * @throws CMISInvalidArgumentException + * if an argument is invalid + */ + public CMISTypeDefinition getTypeDefinition(String typeId) throws CMISInvalidArgumentException; + + /** + * Gets the CMIS base types. + * + * @return the base types + */ + public Collection getBaseTypes(); + + /** + * Checks out an object. + * + * @param objectId + * the object id + * @return the resulting private working copy node + * @throws CMISConstraintException + * if the object isn't of the right type + * @throws CMISVersioningException + * if the object's versioning state isn't as expected + * @throws CMISObjectNotFoundException + * if the object does not exist + * @throws CMISInvalidArgumentException + * if an argument is invalid + * @throws CMISPermissionDeniedException + * if access to the object is denied + */ + public NodeRef checkOut(String objectId) throws CMISConstraintException, CMISVersioningException, + CMISObjectNotFoundException, CMISInvalidArgumentException, CMISPermissionDeniedException; + + /** + * Checks in a private working copy. + * + * @param objectId + * the object id of the private working copy + * @param checkinComment + * the checkin comment + * @param isMajor + * Is this a major version? + * @return the checked in node + * @throws CMISConstraintException + * if the object isn't of the right type + * @throws CMISVersioningException + * if the object's versioning state isn't as expected + * @throws CMISObjectNotFoundException + * if the object does not exist + * @throws CMISInvalidArgumentException + * if an argument is invalid + * @throws CMISPermissionDeniedException + * if access to the object is denied + */ + public NodeRef checkIn(String objectId, String checkinComment, boolean isMajor) throws CMISConstraintException, + CMISVersioningException, CMISObjectNotFoundException, CMISInvalidArgumentException, + CMISPermissionDeniedException; + + /** + * Cancels check out of a private working copy. + * + * @param objectId + * the object id of the private working copy + * @throws CMISConstraintException + * if the object isn't of the right type + * @throws CMISVersioningException + * if the object's versioning state isn't as expected + * @throws CMISObjectNotFoundException + * if the object does not exist + * @throws CMISInvalidArgumentException + * if an argument is invalid + * @throws CMISPermissionDeniedException + * if access to the object is denied + */ + public void cancelCheckOut(String objectId) throws CMISConstraintException, CMISVersioningException, + CMISObjectNotFoundException, CMISInvalidArgumentException, CMISPermissionDeniedException; + + /** + * Gets all versions of an object. + * + * @param objectId + * the object id + * @return the all versions + * @throws CMISConstraintException + * if the object isn't of the right type + * @throws CMISVersioningException + * if the object's versioning state isn't as expected + * @throws CMISObjectNotFoundException + * if the object does not exist + * @throws CMISInvalidArgumentException + * if an argument is invalid + * @throws CMISPermissionDeniedException + * if access to the object is denied + */ + public List getAllVersions(String objectId) throws CMISConstraintException, CMISVersioningException, + CMISObjectNotFoundException, CMISInvalidArgumentException, CMISPermissionDeniedException; + + /** + * Gets the latest version of an object and optionally the latest major version. + * + * @param objectId + * the object id + * @param major + * Should we return the latest major version? + * @return the latest version + * @throws CMISConstraintException + * if the object isn't of the right type + * @throws CMISVersioningException + * if the object's versioning state isn't as expected + * @throws CMISObjectNotFoundException + * if the object does not exist + * @throws CMISInvalidArgumentException + * if an argument is invalid + * @throws CMISPermissionDeniedException + * if access to the object is denied + */ + public NodeRef getLatestVersion(String objectId, boolean major) throws CMISConstraintException, + CMISVersioningException, CMISObjectNotFoundException, CMISInvalidArgumentException, + CMISPermissionDeniedException; + + /** + * Deletes a folder and its children, without raising any exceptions. + * + * @param objectId + * the folder's object id + * @param continueOnFailure + * should we continue if an error occurs with one of the children? + * @param unfile + * should we remove non-primary associations to nodes rather than delete them? + * @param deleteAllVersions + * should we delete all the versions of the documents we delete? + * @return list of object IDs of the children we failed to delete + * @throws CMISConstraintException + * if the object isn't of the right type + * @throws CMISVersioningException + * if the object's versioning state isn't as expected + * @throws CMISObjectNotFoundException + * if the object does not exist + * @throws CMISInvalidArgumentException + * if an argument is invalid + * @throws CMISPermissionDeniedException + * if access to the object is denied + */ + public List deleteTree(String objectId, boolean continueOnFailure, boolean unfile, boolean deleteAllVersions) + throws CMISConstraintException, CMISVersioningException, CMISObjectNotFoundException, + CMISInvalidArgumentException, CMISPermissionDeniedException; + + /** + * Deletes a folder and its children, raising an exception for the last error encountered. + * + * @param objectId + * the folder's object id + * @param continueOnFailure + * should we continue if an error occurs with one of the children? + * @param unfile + * should we remove non-primary associations to nodes rather than delete them? + * @param deleteAllVersions + * should we delete all the versions of the nodes we delete? + * @return list of object IDs of the children we failed to delete + * @throws CMISServiceException + * the last error encountered + */ + public void deleteTreeReportLastError(String objectId, boolean continueOnFailure, boolean unfile, + boolean deleteAllVersions) throws CMISServiceException; + + /** + * Deletes a document's content stream. + * + * @param objectId + * the object id of the document + * @throws CMISConstraintException + * if the object isn't of the right type + * @throws CMISVersioningException + * if the object's versioning state isn't as expected + * @throws CMISObjectNotFoundException + * if the object does not exist + * @throws CMISInvalidArgumentException + * if an argument is invalid + * @throws CMISPermissionDeniedException + * if access to the object is denied + */ + public void deleteContentStream(String objectId) throws CMISConstraintException, CMISVersioningException, + CMISObjectNotFoundException, CMISInvalidArgumentException, CMISPermissionDeniedException; + + /** + * Deletes an object. + * + * @param objectId + * the object id + * @param allVersions + * if the object is a document, should we delete all versions? + * @throws CMISConstraintException + * if the object isn't of the right type + * @throws CMISVersioningException + * if the object's versioning state isn't as expected + * @throws CMISObjectNotFoundException + * if the object does not exist + * @throws CMISInvalidArgumentException + * if an argument is invalid + * @throws CMISPermissionDeniedException + * if access to the object is denied + * @throws CMISRuntimeException + * on other exceptions + */ + public void deleteObject(String objectId, boolean allVersions) throws CMISConstraintException, + CMISVersioningException, CMISObjectNotFoundException, CMISInvalidArgumentException, + CMISPermissionDeniedException, CMISRuntimeException; + + /** + * Adds a secondary child association to an object from a folder. + * + * @param objectId + * the object id + * @param folderId + * the folder id + * @throws CMISConstraintException + * if an object isn't of the right type + * @throws CMISVersioningException + * if an object's versioning state isn't as expected + * @throws CMISObjectNotFoundException + * if an object does not exist + * @throws CMISInvalidArgumentException + * if an argument is invalid + * @throws CMISPermissionDeniedException + * if access to an object is denied + */ + public void addObjectToFolder(String objectId, String folderId) throws CMISConstraintException, + CMISVersioningException, CMISObjectNotFoundException, CMISInvalidArgumentException, + CMISPermissionDeniedException; + + /** + * Removes a secondary child association to an object from a folder. + * + * @param objectId + * the object id + * @param folderId + * the folder id + * @throws CMISNotSupportedException + * if the child association is primary + * @throws CMISConstraintException + * if an object isn't of the right type + * @throws CMISVersioningException + * if an object's versioning state isn't as expected + * @throws CMISObjectNotFoundException + * if an object does not exist + * @throws CMISInvalidArgumentException + * if an argument is invalid + * @throws CMISPermissionDeniedException + * if access to an object is denied + */ + public void removeObjectFromFolder(String objectId, String folderId) throws CMISNotSupportedException, + CMISConstraintException, CMISVersioningException, CMISObjectNotFoundException, + CMISInvalidArgumentException, CMISPermissionDeniedException; + + /** + * Moves an object from one folder to another. + * + * @param objectId + * the object id + * @param targetFolderId + * the target folder id + * @param sourceFolderId + * the source folder id + * @throws CMISConstraintException + * if an object isn't of the right type + * @throws CMISVersioningException + * if an object's versioning state isn't as expected + * @throws CMISObjectNotFoundException + * if an object does not exist + * @throws CMISInvalidArgumentException + * if an argument is invalid + * @throws CMISPermissionDeniedException + * if access to an object is denied + */ + public void moveObject(String objectId, String targetFolderId, String sourceFolderId) + throws CMISConstraintException, CMISVersioningException, CMISObjectNotFoundException, + CMISInvalidArgumentException, CMISPermissionDeniedException; + + /** + * Sets the content stream on an object. + * + * @param objectId + * the object id + * @param propertyQName + * the property q name + * @param overwriteFlag + * the overwrite flag + * @param contentStream + * the content stream + * @param mimeType + * the mime type + * @return true if content was overwritten + * @throws CMISContentAlreadyExistsException + * if overwrite was false and content already existed + * @throws CMISStreamNotSupportedException + * if the object's type definition does not allow a content stream + * @throws CMISConstraintException + * if an object isn't of the right type + * @throws CMISVersioningException + * if an object's versioning state isn't as expected + * @throws CMISObjectNotFoundException + * if an object does not exist + * @throws CMISInvalidArgumentException + * if an argument is invalid + * @throws CMISPermissionDeniedException + * if access to an object is denied + */ + public boolean setContentStream(String objectId, QName propertyQName, boolean overwriteFlag, + InputStream contentStream, String mimeType) throws CMISConstraintException, CMISVersioningException, + CMISObjectNotFoundException, CMISContentAlreadyExistsException, CMISStreamNotSupportedException, + CMISInvalidArgumentException, CMISPermissionDeniedException; } diff --git a/source/java/org/alfresco/cmis/CMISStreamNotSupportedException.java b/source/java/org/alfresco/cmis/CMISStreamNotSupportedException.java new file mode 100644 index 0000000000..2c70f427b8 --- /dev/null +++ b/source/java/org/alfresco/cmis/CMISStreamNotSupportedException.java @@ -0,0 +1,41 @@ +/* + * 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.cmis; + + +public class CMISStreamNotSupportedException extends CMISServiceException +{ + private static final long serialVersionUID = -3036139369370574358L; + + public CMISStreamNotSupportedException(CMISTypeDefinition typeDefinition) + { + super("Stream not supported by type " + typeDefinition.getTypeId(), "streamNotSupported", 403); + } + + public CMISStreamNotSupportedException(CMISTypeDefinition typeDefinition, Throwable cause) + { + super("Stream not supported by type " + typeDefinition.getTypeId(), cause, "streamNotSupported", 403); + } +} diff --git a/source/java/org/alfresco/cmis/CMISTypeDefinition.java b/source/java/org/alfresco/cmis/CMISTypeDefinition.java index 1ec084e74b..067fbe1a15 100644 --- a/source/java/org/alfresco/cmis/CMISTypeDefinition.java +++ b/source/java/org/alfresco/cmis/CMISTypeDefinition.java @@ -188,5 +188,5 @@ public interface CMISTypeDefinition * * @return */ - public Map getActionEvaluators(); + public Map> getActionEvaluators(); } diff --git a/source/java/org/alfresco/cmis/CMISVersioningException.java b/source/java/org/alfresco/cmis/CMISVersioningException.java new file mode 100644 index 0000000000..f297f77c59 --- /dev/null +++ b/source/java/org/alfresco/cmis/CMISVersioningException.java @@ -0,0 +1,45 @@ +/* + * 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.cmis; + +public class CMISVersioningException extends CMISServiceException +{ + private static final long serialVersionUID = 6876828094374256016L; + + public CMISVersioningException(String message) + { + super(message, "versioning", 409); + } + + public CMISVersioningException(Throwable cause) + { + super(cause, "versioning", 409); + } + + public CMISVersioningException(String message, Throwable cause) + { + super(message, cause, "versioning", 409); + } +} diff --git a/source/java/org/alfresco/cmis/reference/DefaultRepositoryReference.java b/source/java/org/alfresco/cmis/CMISVersioningStateEnum.java similarity index 59% rename from source/java/org/alfresco/cmis/reference/DefaultRepositoryReference.java rename to source/java/org/alfresco/cmis/CMISVersioningStateEnum.java index fdeb04bbca..527fab814c 100644 --- a/source/java/org/alfresco/cmis/reference/DefaultRepositoryReference.java +++ b/source/java/org/alfresco/cmis/CMISVersioningStateEnum.java @@ -1,57 +1,59 @@ -/* - * Copyright (C) 2005-2007 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.cmis.reference; - -import org.alfresco.cmis.CMISServices; -import org.alfresco.service.cmr.repository.StoreRef; - - -/** - * Default Repository Reference - * - * @author davidc - */ -public class DefaultRepositoryReference extends AbstractRepositoryReference -{ - /** - * Construct - * - * @param cmisServices - */ - public DefaultRepositoryReference(CMISServices cmisServices) - { - super(cmisServices); - } - - /* - * (non-Javadoc) - * @see org.alfresco.cmis.CMISRepositoryReference#getStoreRef() - */ - public StoreRef getStoreRef() - { - return cmisServices.getDefaultRootStoreRef(); - } - -} +/* + * 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.cmis; + +/** + * CMIS Versioning State Enumeration. + * + * @author dward + */ +public enum CMISVersioningStateEnum implements EnumLabel +{ + NONE("none"), CHECKED_OUT("checkedout"), MAJOR("major"), MINOR("minor"); + + private String label; + + /** + * Construct. + * + * @param label + */ + CMISVersioningStateEnum(String label) + { + this.label = label; + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.EnumLabel#label() + */ + public String getLabel() + { + return label; + } + + public static EnumFactory FACTORY = new EnumFactory( + CMISVersioningStateEnum.class, null, true); +} diff --git a/source/java/org/alfresco/cmis/UnsupportedCMISAclPropagationMode.java b/source/java/org/alfresco/cmis/UnsupportedCMISAclPropagationMode.java deleted file mode 100644 index f8cf415957..0000000000 --- a/source/java/org/alfresco/cmis/UnsupportedCMISAclPropagationMode.java +++ /dev/null @@ -1,80 +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.cmis; - -import org.alfresco.error.AlfrescoRuntimeException; - -/** - * Thrown when an unsupported CMISAclPropagationModeEnum is specified. - * @author andyh - * - */ -public class UnsupportedCMISAclPropagationMode extends AlfrescoRuntimeException -{ - - /** - * - */ - private static final long serialVersionUID = 3844368557738616296L; - - /** - * @param msgId - * @param msgParams - * @param cause - */ - public UnsupportedCMISAclPropagationMode(String msgId, Object[] msgParams, Throwable cause) - { - super(msgId, msgParams, cause); - } - - /** - * @param msgId - * @param msgParams - */ - public UnsupportedCMISAclPropagationMode(String msgId, Object[] msgParams) - { - super(msgId, msgParams); - } - - /** - * @param msgId - * @param cause - */ - public UnsupportedCMISAclPropagationMode(String msgId, Throwable cause) - { - super(msgId, cause); - } - - /** - * @param msgId - */ - public UnsupportedCMISAclPropagationMode(String msgId) - { - super(msgId); - } - - - -} diff --git a/source/java/org/alfresco/cmis/acl/CMISAccessControlEntriesGroupedByPrincipalIdImpl.java b/source/java/org/alfresco/cmis/acl/CMISAccessControlEntriesGroupedByPrincipalIdImpl.java index a34b525ef0..a7c117bf81 100644 --- a/source/java/org/alfresco/cmis/acl/CMISAccessControlEntriesGroupedByPrincipalIdImpl.java +++ b/source/java/org/alfresco/cmis/acl/CMISAccessControlEntriesGroupedByPrincipalIdImpl.java @@ -72,7 +72,7 @@ public class CMISAccessControlEntriesGroupedByPrincipalIdImpl implements CMISAcc return principalId; } - /* package */ void addEntry(CMISAccessControlEntry entry) + /* package */ void addEntry(CMISAccessControlEntry entry) throws CMISConstraintException { if(!principalId.equals(entry.getPrincipalId())) { diff --git a/source/java/org/alfresco/cmis/acl/CMISAccessControlReportImpl.java b/source/java/org/alfresco/cmis/acl/CMISAccessControlReportImpl.java index 14c0c40702..d7fc5b985a 100644 --- a/source/java/org/alfresco/cmis/acl/CMISAccessControlReportImpl.java +++ b/source/java/org/alfresco/cmis/acl/CMISAccessControlReportImpl.java @@ -31,6 +31,7 @@ import java.util.List; import org.alfresco.cmis.CMISAccessControlEntriesGroupedByPrincipalId; import org.alfresco.cmis.CMISAccessControlEntry; import org.alfresco.cmis.CMISAccessControlReport; +import org.alfresco.cmis.CMISConstraintException; /** * A simple CMIS access control report @@ -92,7 +93,7 @@ public class CMISAccessControlReportImpl implements CMISAccessControlReport /* (non-Javadoc) * @see org.alfresco.cmis.CMISAccessControlReport#getAccessControlEntriesGroupedByPrincipalId() */ - public List getAccessControlEntriesGroupedByPrincipalId() + public List getAccessControlEntriesGroupedByPrincipalId() throws CMISConstraintException { HashMap grouped = new HashMap(); for(CMISAccessControlEntry entry : getAccessControlEntries()) diff --git a/source/java/org/alfresco/cmis/acl/CMISAccessControlServiceImpl.java b/source/java/org/alfresco/cmis/acl/CMISAccessControlServiceImpl.java index 9b324f0aa8..9cc3e0b939 100644 --- a/source/java/org/alfresco/cmis/acl/CMISAccessControlServiceImpl.java +++ b/source/java/org/alfresco/cmis/acl/CMISAccessControlServiceImpl.java @@ -160,7 +160,7 @@ public class CMISAccessControlServiceImpl implements CMISAccessControlService * @see org.alfresco.cmis.CMISAccessControlService#applyAcl(org.alfresco.service.cmr.repository.NodeRef, * java.util.List) */ - public CMISAccessControlReport applyAcl(NodeRef nodeRef, List acesToApply) + public CMISAccessControlReport applyAcl(NodeRef nodeRef, List acesToApply) throws CMISConstraintException { Set acesToAdd = new LinkedHashSet(acesToApply); List acesExisting = getAcl(nodeRef, @@ -186,7 +186,7 @@ public class CMISAccessControlServiceImpl implements CMISAccessControlService * java.util.List, java.util.List, org.alfresco.cmis.CMISAclPropagationEnum) */ public CMISAccessControlReport applyAcl(NodeRef nodeRef, List acesToRemove, List acesToAdd, CMISAclPropagationEnum propagation, - CMISAccessControlFormatEnum format) + CMISAccessControlFormatEnum format) throws CMISConstraintException { if (propagation != CMISAclPropagationEnum.PROPAGATE) { diff --git a/source/java/org/alfresco/cmis/acl/CMISAccessControlServiceTest.java b/source/java/org/alfresco/cmis/acl/CMISAccessControlServiceTest.java index 0209876d02..8b434543ee 100644 --- a/source/java/org/alfresco/cmis/acl/CMISAccessControlServiceTest.java +++ b/source/java/org/alfresco/cmis/acl/CMISAccessControlServiceTest.java @@ -81,7 +81,7 @@ public class CMISAccessControlServiceTest extends BaseCMISTest } - public void testAclReportingCmisPermissionsOnly() + public void testAclReportingCmisPermissionsOnly() throws Exception { createTestAcls(); @@ -144,7 +144,7 @@ public class CMISAccessControlServiceTest extends BaseCMISTest return answer; } - private boolean checkCounts(CMISAccessControlReport report, String key, int direct, int indirect) + private boolean checkCounts(CMISAccessControlReport report, String key, int direct, int indirect) throws Exception { // check all permissions are valid @@ -178,7 +178,7 @@ public class CMISAccessControlServiceTest extends BaseCMISTest return false; } - private boolean checkAbsent(CMISAccessControlReport report, String key) + private boolean checkAbsent(CMISAccessControlReport report, String key) throws Exception { for (CMISAccessControlEntriesGroupedByPrincipalId group : report.getAccessControlEntriesGroupedByPrincipalId()) { @@ -190,7 +190,7 @@ public class CMISAccessControlServiceTest extends BaseCMISTest return true; } - public void testAclReportingAllPermissions() + public void testAclReportingAllPermissions() throws Exception { createTestAcls(); @@ -381,7 +381,7 @@ public class CMISAccessControlServiceTest extends BaseCMISTest assertEquals("Writer2", ordered.get(i).getAuthority()); } - public void testApplyAcl() + public void testApplyAcl() throws Exception { grandParent = nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, QName.createQName("cm", "Parent", namespaceService), ContentModel.TYPE_FOLDER).getChildRef(); nodeService.setProperty(grandParent, ContentModel.PROP_NAME, "GrandParent"); diff --git a/source/java/org/alfresco/cmis/changelog/CMISChangeEventImpl.java b/source/java/org/alfresco/cmis/changelog/CMISChangeEventImpl.java index 3ea8b61356..410f5eec95 100755 --- a/source/java/org/alfresco/cmis/changelog/CMISChangeEventImpl.java +++ b/source/java/org/alfresco/cmis/changelog/CMISChangeEventImpl.java @@ -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.cmis.changelog; @@ -37,22 +37,30 @@ import org.alfresco.service.cmr.repository.NodeRef; */ public class CMISChangeEventImpl implements CMISChangeEvent { - private NodeRef node; private CMISChangeType changeType; private Date changeTime; + private NodeRef changedNode; + private String objectId; + /** - * Construct a CMISChangeEvent using fields + * Instantiates a new CMIS change event. * - * @param changeType change type - * @param node node reference - * @param changeTime change time + * @param changeType + * the change type + * @param changeTime + * the change time + * @param changedNode + * the changed node + * @param objectId + * the object id */ - public CMISChangeEventImpl(CMISChangeType changeType, NodeRef node, Date changeTime) + public CMISChangeEventImpl(CMISChangeType changeType, Date changeTime, NodeRef changedNode, String objectId) { this.changeType = changeType; - this.node = node; this.changeTime = changeTime; + this.changedNode = changedNode; + this.objectId = objectId; } /** @@ -63,14 +71,6 @@ public class CMISChangeEventImpl implements CMISChangeEvent return changeType; } - /** - * @see org.alfresco.cmis.CMISChangeEvent#getNode() - */ - public NodeRef getNode() - { - return node; - } - /** * @see org.alfresco.cmis.CMISChangeEvent#getChangeTime() */ @@ -79,6 +79,23 @@ public class CMISChangeEventImpl implements CMISChangeEvent return changeTime; } + + /** + * @see org.alfresco.cmis.CMISChangeEvent#getChangedNode() + */ + public NodeRef getChangedNode() + { + return changedNode; + } + + /** + * @see org.alfresco.cmis.CMISChangeEvent#getObjectId() + */ + public String getObjectId() + { + return objectId; + } + /** * @see java.lang.Object#equals(java.lang.Object) */ @@ -90,7 +107,7 @@ public class CMISChangeEventImpl implements CMISChangeEvent return false; } CMISChangeEvent converted = (CMISChangeEvent) obj; - return same(node, converted.getNode()) && same(changeType, converted.getChangeType()) && same(changeTime, converted.getChangeTime()); + return same(changedNode, converted.getChangedNode()) && same(changeType, converted.getChangeType()) && same(changeTime, converted.getChangeTime()); } private boolean same(Object left, Object right) @@ -104,7 +121,7 @@ public class CMISChangeEventImpl implements CMISChangeEvent @Override public int hashCode() { - int result = (null != node) ? (node.hashCode()) : (31); + int result = (null != changedNode) ? (changedNode.hashCode()) : (31); return result * 37 + (null != changeType ? changeType.hashCode() : 31) + (null != changeTime ? changeTime.hashCode() : 31); } diff --git a/source/java/org/alfresco/cmis/changelog/CMISChangeLogDataExtractor.java b/source/java/org/alfresco/cmis/changelog/CMISChangeLogDataExtractor.java index 02beb9d5a8..d16ea265ea 100755 --- a/source/java/org/alfresco/cmis/changelog/CMISChangeLogDataExtractor.java +++ b/source/java/org/alfresco/cmis/changelog/CMISChangeLogDataExtractor.java @@ -25,7 +25,9 @@ package org.alfresco.cmis.changelog; import java.io.Serializable; +import java.util.HashMap; +import org.alfresco.cmis.CMISDictionaryModel; import org.alfresco.cmis.CMISServices; import org.alfresco.repo.audit.extractor.AbstractDataExtractor; import org.alfresco.service.cmr.model.FileFolderService; @@ -42,15 +44,23 @@ public class CMISChangeLogDataExtractor extends AbstractDataExtractor { private CMISServices cmisService; private FileFolderService fileFolderService; + + public static final String KEY_NODE_REF = "nodeRef"; + public static final String KEY_OBJECT_ID = "objectId"; /** - * Extracts the NodeRef from auditing data + * Extracts relevant node refs and Ids from auditing data * * @see org.alfresco.repo.audit.extractor.DataExtractor.extractData(java.io.Serializable) */ public Serializable extractData(Serializable value) throws Throwable { - return getNodeRef(value); + NodeRef nodeRef = getNodeRef(value); + HashMap result = new HashMap(5); + result.put(KEY_NODE_REF, nodeRef); + // Support version nodes by recording the object ID + result.put(KEY_OBJECT_ID, cmisService.getProperty(nodeRef, CMISDictionaryModel.PROP_OBJECT_ID)); + return result; } /** diff --git a/source/java/org/alfresco/cmis/changelog/CMISChangeLogServiceImpl.java b/source/java/org/alfresco/cmis/changelog/CMISChangeLogServiceImpl.java index b158b53242..cb963ccc71 100755 --- a/source/java/org/alfresco/cmis/changelog/CMISChangeLogServiceImpl.java +++ b/source/java/org/alfresco/cmis/changelog/CMISChangeLogServiceImpl.java @@ -38,6 +38,7 @@ import org.alfresco.cmis.CMISChangeEvent; import org.alfresco.cmis.CMISChangeLog; import org.alfresco.cmis.CMISChangeLogService; import org.alfresco.cmis.CMISChangeType; +import org.alfresco.cmis.CMISInvalidArgumentException; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.service.cmr.audit.AuditQueryParameters; import org.alfresco.service.cmr.audit.AuditService; @@ -68,9 +69,10 @@ public class CMISChangeLogServiceImpl implements CMISChangeLogService } /** + * @throws CMISInvalidArgumentException * @see org.alfresco.cmis.CMISChangeLogService#getChangeLogEvents(java.lang.String, java.lang.Integer) */ - public CMISChangeLog getChangeLogEvents(String changeLogToken, Integer maxItems) + public CMISChangeLog getChangeLogEvents(String changeLogToken, Integer maxItems) throws CMISInvalidArgumentException { if (!auditService.isAuditEnabled(cmisAuditApplicationName, ("/" + cmisAuditApplicationName))) { @@ -88,7 +90,15 @@ public class CMISChangeLogServiceImpl implements CMISChangeLogService return super.handleAuditEntry(entryId, user, time, values); } }; - Long from = changeLogToken != null ? Long.parseLong(changeLogToken) : null; + Long from; + try + { + from = changeLogToken != null ? Long.parseLong(changeLogToken) : null; + } + catch (NumberFormatException e) + { + throw new CMISInvalidArgumentException("Invalid change log token " + changeLogToken); + } AuditQueryParameters params = new AuditQueryParameters(); params.setApplicationName(cmisAuditApplicationName); params.setForward(true); @@ -213,6 +223,7 @@ public class CMISChangeLogServiceImpl implements CMISChangeLogService * @param time audit event time * @return list of CMISChangeEvent */ + @SuppressWarnings("unchecked") private List convertValuesMapToChangeLogEvents(Map values, long time) { List result = new ArrayList(); @@ -224,10 +235,12 @@ public class CMISChangeLogServiceImpl implements CMISChangeLogService { String path = entry.getKey(); CMISChangeType changeType = getCMISChangeType(path); - NodeRef nodeRef = entry.getValue() instanceof NodeRef ? (NodeRef) entry.getValue() : null; - if (changeType != null && nodeRef != null) + if (changeType != null && entry.getValue() instanceof Map) { - result.add(new CMISChangeEventImpl(changeType, nodeRef, new Date(time))); + Map valueMap = (Map)entry.getValue(); + result.add(new CMISChangeEventImpl(changeType, new Date(time), (NodeRef) valueMap + .get(CMISChangeLogDataExtractor.KEY_NODE_REF), (String) valueMap + .get(CMISChangeLogDataExtractor.KEY_OBJECT_ID))); } } } diff --git a/source/java/org/alfresco/cmis/changelog/CMISChangeLogServiceTest.java b/source/java/org/alfresco/cmis/changelog/CMISChangeLogServiceTest.java index e5b31d52e9..4c7f4f20f7 100755 --- a/source/java/org/alfresco/cmis/changelog/CMISChangeLogServiceTest.java +++ b/source/java/org/alfresco/cmis/changelog/CMISChangeLogServiceTest.java @@ -36,6 +36,7 @@ import org.alfresco.cmis.CMISChangeEvent; import org.alfresco.cmis.CMISChangeLog; import org.alfresco.cmis.CMISChangeLogService; import org.alfresco.cmis.CMISChangeType; +import org.alfresco.cmis.CMISInvalidArgumentException; import org.alfresco.cmis.mapping.BaseCMISTest; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; @@ -252,22 +253,22 @@ public class CMISChangeLogServiceTest extends BaseCMISTest for (CMISChangeEvent event : changeLog.getChangeEvents()) { assertNotNull(("One of the Change Log Event Enries is undefined for '" + logToken + "' Change Log Token"), event); - assertNotNull(("Change Event Entry Id of one of the Change Entries is undefined for '" + logToken + "' Change Log Token"), event.getNode()); + assertNotNull(("Change Event Entry Id of one of the Change Entries is undefined for '" + logToken + "' Change Log Token"), event.getChangedNode()); assertNotNull(("Change Event Change Type of one of the Change Entries is undefined for '" + logToken + "' Change Log Token"), event.getChangeType()); - assertTrue("Unexpected Object Id='" + event.getNode().toString() + "' from Change Log Token Entries list for '" + logToken + "' Change Log Token", created - .contains(event.getNode())); - if (!deleted.contains(event.getNode())) + assertTrue("Unexpected Object Id='" + event.getChangedNode().toString() + "' from Change Log Token Entries list for '" + logToken + "' Change Log Token", created + .contains(event.getChangedNode())); + if (!deleted.contains(event.getChangedNode())) { - folderWasFound = folderWasFound || fileFolderService.getFileInfo(event.getNode()).isFolder(); + folderWasFound = folderWasFound || fileFolderService.getFileInfo(event.getChangedNode()).isFolder(); assertTrue( ("Object from Change Event Entries list is marked as '" + event.getChangeType().toString() + "' but does not exist for '" + logToken + "' Change Log Token"), - nodeService.exists(event.getNode())); + nodeService.exists(event.getChangedNode())); } else { - assertTrue("Object has been deleted", deleted.contains(event.getNode())); + assertTrue("Object has been deleted", deleted.contains(event.getChangedNode())); assertFalse(("Object from Change Event Entries list is marked as 'DELETED' but it still exist for '" + logToken + "' Change Log Token"), nodeService.exists(event - .getNode())); + .getChangedNode())); } addOneToAmount(logAmounts, event.getChangeType()); } @@ -348,7 +349,7 @@ public class CMISChangeLogServiceTest extends BaseCMISTest } catch (Exception e) { - assertTrue("Invalid exception type from Change Log Service method call with enabled Changes Logging", e instanceof java.lang.NumberFormatException); + assertTrue("Invalid exception type from Change Log Service method call with enabled Changes Logging", e instanceof CMISInvalidArgumentException); } disableAudit(); try diff --git a/source/java/org/alfresco/cmis/dictionary/CMISAbstractTypeDefinition.java b/source/java/org/alfresco/cmis/dictionary/CMISAbstractTypeDefinition.java index b6efd55840..d7177cbe22 100644 --- a/source/java/org/alfresco/cmis/dictionary/CMISAbstractTypeDefinition.java +++ b/source/java/org/alfresco/cmis/dictionary/CMISAbstractTypeDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-20079 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 @@ -84,7 +84,7 @@ public abstract class CMISAbstractTypeDefinition implements CMISTypeDefinition, protected Map properties = null; protected Map inheritedProperties = null; protected Map ownedProperties = null; - protected Map actionEvaluators = null; + protected Map> actionEvaluators = null; /*package*/ void assertComplete() @@ -442,7 +442,7 @@ public abstract class CMISAbstractTypeDefinition implements CMISTypeDefinition, * (non-Javadoc) * @see org.alfresco.cmis.CMISTypeDefinition#getActionEvaluators() */ - public Map getActionEvaluators() + public Map> getActionEvaluators() { return actionEvaluators; } diff --git a/source/java/org/alfresco/cmis/dictionary/CMISDocumentTypeDefinition.java b/source/java/org/alfresco/cmis/dictionary/CMISDocumentTypeDefinition.java index 11ee364a2c..22f749628a 100644 --- a/source/java/org/alfresco/cmis/dictionary/CMISDocumentTypeDefinition.java +++ b/source/java/org/alfresco/cmis/dictionary/CMISDocumentTypeDefinition.java @@ -24,15 +24,11 @@ */ package org.alfresco.cmis.dictionary; -import java.util.List; - import org.alfresco.cmis.CMISContentStreamAllowedEnum; import org.alfresco.cmis.CMISDictionaryModel; import org.alfresco.cmis.CMISScope; import org.alfresco.cmis.CMISTypeId; import org.alfresco.cmis.mapping.CMISMapping; -import org.alfresco.model.ContentModel; -import org.alfresco.service.cmr.dictionary.AspectDefinition; import org.alfresco.service.cmr.dictionary.ClassDefinition; import org.alfresco.service.namespace.QName; @@ -48,7 +44,6 @@ public class CMISDocumentTypeDefinition extends CMISAbstractTypeDefinition // document specific properties protected boolean fileable; - protected boolean versionable; protected CMISContentStreamAllowedEnum contentStreamAllowed; @@ -96,17 +91,6 @@ public class CMISDocumentTypeDefinition extends CMISAbstractTypeDefinition actionEvaluators = cmisMapping.getActionEvaluators(objectTypeId.getScope()); - // Document type properties - versionable = false; - List defaultAspects = cmisClassDef.getDefaultAspects(); - for (AspectDefinition aspectDefinition : defaultAspects) - { - if (aspectDefinition.getName().equals(ContentModel.ASPECT_VERSIONABLE)) - { - versionable = true; - break; - } - } fileable = true; contentStreamAllowed = CMISContentStreamAllowedEnum.ALLOWED; } @@ -128,7 +112,8 @@ public class CMISDocumentTypeDefinition extends CMISAbstractTypeDefinition */ public boolean isVersionable() { - return versionable; + // Documents and their subtypes are versionable + return true; } /** diff --git a/source/java/org/alfresco/cmis/mapping/AbstractActionEvaluator.java b/source/java/org/alfresco/cmis/mapping/AbstractActionEvaluator.java index 20256abb7b..fe0a6d9b67 100644 --- a/source/java/org/alfresco/cmis/mapping/AbstractActionEvaluator.java +++ b/source/java/org/alfresco/cmis/mapping/AbstractActionEvaluator.java @@ -34,7 +34,7 @@ import org.alfresco.service.ServiceRegistry; * @author davidc * */ -public abstract class AbstractActionEvaluator implements CMISActionEvaluator +public abstract class AbstractActionEvaluator implements CMISActionEvaluator { private ServiceRegistry serviceRegistry; private CMISAllowedActionEnum action; diff --git a/source/java/org/alfresco/cmis/mapping/AbstractVersioningProperty.java b/source/java/org/alfresco/cmis/mapping/AbstractVersioningProperty.java new file mode 100644 index 0000000000..521fa8b9fa --- /dev/null +++ b/source/java/org/alfresco/cmis/mapping/AbstractVersioningProperty.java @@ -0,0 +1,85 @@ +/* + * 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.cmis.mapping; + +import java.io.Serializable; +import java.util.Map; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.version.VersionBaseModel; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.lock.LockType; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; + +/** + * Base class for versioning property accessors. + * + * @author dward + * + */ +public abstract class AbstractVersioningProperty extends AbstractProperty +{ + + /** + * Construct + * + * @param serviceRegistry + * @param propertyName + */ + protected AbstractVersioningProperty(ServiceRegistry serviceRegistry, String propertyName) + { + super(serviceRegistry, propertyName); + } + + + public NodeRef getVersionSeries(NodeRef nodeRef) + { + if (nodeRef.getStoreRef().getProtocol().equals(VersionBaseModel.STORE_PROTOCOL)) + { + // Due to the remapping done for us by the versioned node services, we can simply look up the properties + // containing the component parts of the node ref to map back to the original node + Map properties = getServiceRegistry().getNodeService().getProperties(nodeRef); + return new NodeRef((String) properties.get(ContentModel.PROP_STORE_PROTOCOL), + (String) properties.get(ContentModel.PROP_STORE_IDENTIFIER), (String) properties + .get(ContentModel.PROP_NODE_UUID)); + } + else if (isWorkingCopy(nodeRef)) + { + return (NodeRef) getServiceRegistry().getNodeService().getProperty(nodeRef, ContentModel.PROP_COPY_REFERENCE); + } + return nodeRef; + } + + public boolean isWorkingCopy(NodeRef nodeRef) + { + return getServiceRegistry().getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY); + } + + public boolean hasWorkingCopy(NodeRef nodeRef) + { + return getServiceRegistry().getLockService().getLockType(nodeRef) == LockType.READ_ONLY_LOCK; + } +} diff --git a/source/java/org/alfresco/cmis/mapping/CMISMapping.java b/source/java/org/alfresco/cmis/mapping/CMISMapping.java index a1e8a672d5..77da72d562 100644 --- a/source/java/org/alfresco/cmis/mapping/CMISMapping.java +++ b/source/java/org/alfresco/cmis/mapping/CMISMapping.java @@ -47,6 +47,8 @@ import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.dictionary.AspectDefinition; import org.alfresco.service.cmr.dictionary.AssociationDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; @@ -109,7 +111,7 @@ public class CMISMapping implements InitializingBean private Map mapAlfrescoQNameToCmisQName = new HashMap(); private Map mapAlfrescoToCmisDataType = new HashMap(); private Map propertyAccessors = new HashMap(); - private Map> actionEvaluators = new HashMap>(); + private Map>> actionEvaluators = new HashMap>>(); private Set cmisRead = new HashSet(); @@ -185,7 +187,7 @@ public class CMISMapping implements InitializingBean registerPropertyAccessor(new IsLatestVersionProperty(serviceRegistry)); registerPropertyAccessor(new IsMajorVersionProperty(serviceRegistry)); registerPropertyAccessor(new IsLatestMajorVersionProperty(serviceRegistry)); - registerPropertyAccessor(new DirectProperty(serviceRegistry, CMISDictionaryModel.PROP_VERSION_LABEL, ContentModel.PROP_VERSION_LABEL)); + registerPropertyAccessor(new VersionLabelProperty(serviceRegistry)); registerPropertyAccessor(new VersionSeriesIdProperty(serviceRegistry)); registerPropertyAccessor(new IsVersionSeriesCheckedOutProperty(serviceRegistry)); registerPropertyAccessor(new VersionSeriesCheckedOutByProperty(serviceRegistry)); @@ -211,8 +213,8 @@ public class CMISMapping implements InitializingBean registerEvaluator(CMISScope.DOCUMENT, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_DELETE_OBJECT, PermissionService.DELETE_NODE)); registerEvaluator(CMISScope.DOCUMENT, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_UPDATE_PROPERTIES, PermissionService.WRITE_PROPERTIES)); registerEvaluator(CMISScope.DOCUMENT, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_PROPERTIES, PermissionService.READ_PROPERTIES)); - registerEvaluator(CMISScope.DOCUMENT, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_OBJECT_RELATIONSHIPS, true)); - registerEvaluator(CMISScope.DOCUMENT, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_OBJECT_PARENTS, true)); + registerEvaluator(CMISScope.DOCUMENT, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_OBJECT_RELATIONSHIPS, true)); + registerEvaluator(CMISScope.DOCUMENT, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_OBJECT_PARENTS, true)); // Is CAN_MOVE correct mapping? registerEvaluator(CMISScope.DOCUMENT, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_MOVE_OBJECT, PermissionService.DELETE_NODE)); registerEvaluator(CMISScope.DOCUMENT, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_DELETE_CONTENT_STREAM, PermissionService.WRITE_PROPERTIES, PermissionService.WRITE_CONTENT)); @@ -220,16 +222,16 @@ public class CMISMapping implements InitializingBean registerEvaluator(CMISScope.DOCUMENT, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_CANCEL_CHECKOUT, PermissionService.CANCEL_CHECK_OUT)); registerEvaluator(CMISScope.DOCUMENT, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_CHECKIN, PermissionService.CHECK_IN)); registerEvaluator(CMISScope.DOCUMENT, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_SET_CONTENT_STREAM, PermissionService.WRITE_CONTENT)); - registerEvaluator(CMISScope.DOCUMENT, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_ALL_VERSIONS, true)); + registerEvaluator(CMISScope.DOCUMENT, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_ALL_VERSIONS, true)); registerEvaluator(CMISScope.DOCUMENT, new ParentActionEvaluator(new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_ADD_OBJECT_TO_FOLDER, PermissionService.LINK_CHILDREN))); // Is CAN_REMOVE_FROM_FOLDER correct mapping? - registerEvaluator(CMISScope.DOCUMENT, new ParentActionEvaluator(new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_REMOVE_OBJECT_FROM_FOLDER, true))); + registerEvaluator(CMISScope.DOCUMENT, new ParentActionEvaluator(new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_REMOVE_OBJECT_FROM_FOLDER, true))); registerEvaluator(CMISScope.DOCUMENT, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_CONTENT_STREAM, PermissionService.READ_CONTENT)); - registerEvaluator(CMISScope.DOCUMENT, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_APPLY_POLICY, false)); - registerEvaluator(CMISScope.DOCUMENT, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_APPLIED_POLICIES, false)); - registerEvaluator(CMISScope.DOCUMENT, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_REMOVE_POLICY, false)); - registerEvaluator(CMISScope.DOCUMENT, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_CREATE_RELATIONSHIP, true)); - registerEvaluator(CMISScope.DOCUMENT, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_RENDITIONS, true)); + registerEvaluator(CMISScope.DOCUMENT, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_APPLY_POLICY, false)); + registerEvaluator(CMISScope.DOCUMENT, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_APPLIED_POLICIES, false)); + registerEvaluator(CMISScope.DOCUMENT, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_REMOVE_POLICY, false)); + registerEvaluator(CMISScope.DOCUMENT, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_CREATE_RELATIONSHIP, true)); + registerEvaluator(CMISScope.DOCUMENT, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_RENDITIONS, true)); registerEvaluator(CMISScope.DOCUMENT, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_ACL, PermissionService.READ_PERMISSIONS)); registerEvaluator(CMISScope.DOCUMENT, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_APPLY_ACL, PermissionService.CHANGE_PERMISSIONS)); @@ -237,15 +239,15 @@ public class CMISMapping implements InitializingBean registerEvaluator(CMISScope.FOLDER, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_UPDATE_PROPERTIES, PermissionService.WRITE_PROPERTIES)); registerEvaluator(CMISScope.FOLDER, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_FOLDER_TREE, PermissionService.READ_CHILDREN)); registerEvaluator(CMISScope.FOLDER, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_PROPERTIES, PermissionService.READ_PROPERTIES)); - registerEvaluator(CMISScope.FOLDER, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_OBJECT_RELATIONSHIPS, true)); - registerEvaluator(CMISScope.FOLDER, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_OBJECT_PARENTS, true)); - registerEvaluator(CMISScope.FOLDER, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_FOLDER_PARENT, true)); + registerEvaluator(CMISScope.FOLDER, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_OBJECT_RELATIONSHIPS, true)); + registerEvaluator(CMISScope.FOLDER, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_OBJECT_PARENTS, true)); + registerEvaluator(CMISScope.FOLDER, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_FOLDER_PARENT, true)); registerEvaluator(CMISScope.FOLDER, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_DESCENDANTS, PermissionService.READ_CHILDREN)); // Is CAN_MOVE_OBJECT correct mapping? registerEvaluator(CMISScope.FOLDER, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_MOVE_OBJECT, PermissionService.DELETE_NODE)); - registerEvaluator(CMISScope.FOLDER, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_APPLY_POLICY, false)); - registerEvaluator(CMISScope.FOLDER, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_APPLIED_POLICIES, false)); - registerEvaluator(CMISScope.FOLDER, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_REMOVE_POLICY, false)); + registerEvaluator(CMISScope.FOLDER, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_APPLY_POLICY, false)); + registerEvaluator(CMISScope.FOLDER, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_APPLIED_POLICIES, false)); + registerEvaluator(CMISScope.FOLDER, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_REMOVE_POLICY, false)); registerEvaluator(CMISScope.FOLDER, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_CHILDREN, PermissionService.READ_CHILDREN)); registerEvaluator(CMISScope.FOLDER, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_CREATE_DOCUMENT, PermissionService.CREATE_CHILDREN)); registerEvaluator(CMISScope.FOLDER, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_CREATE_FOLDER, PermissionService.CREATE_CHILDREN)); @@ -254,22 +256,22 @@ public class CMISMapping implements InitializingBean registerEvaluator(CMISScope.FOLDER, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_ACL, PermissionService.READ_PERMISSIONS)); registerEvaluator(CMISScope.FOLDER, new PermissionActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_APPLY_ACL, PermissionService.CHANGE_PERMISSIONS)); - registerEvaluator(CMISScope.RELATIONSHIP, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_DELETE_OBJECT, true)); - registerEvaluator(CMISScope.RELATIONSHIP, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_UPDATE_PROPERTIES, false)); - registerEvaluator(CMISScope.RELATIONSHIP, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_PROPERTIES, true)); - registerEvaluator(CMISScope.RELATIONSHIP, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_ACL, false)); - registerEvaluator(CMISScope.RELATIONSHIP, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_APPLY_ACL, false)); + registerEvaluator(CMISScope.RELATIONSHIP, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_DELETE_OBJECT, true)); + registerEvaluator(CMISScope.RELATIONSHIP, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_UPDATE_PROPERTIES, false)); + registerEvaluator(CMISScope.RELATIONSHIP, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_PROPERTIES, true)); + registerEvaluator(CMISScope.RELATIONSHIP, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_ACL, false)); + registerEvaluator(CMISScope.RELATIONSHIP, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_APPLY_ACL, false)); - registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_DELETE_OBJECT, false)); - registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_UPDATE_PROPERTIES, false)); - registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_PROPERTIES, false)); - registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_OBJECT_PARENTS, false)); - registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_MOVE_OBJECT, false)); - registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_ADD_OBJECT_TO_FOLDER, false)); - registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_REMOVE_OBJECT_FROM_FOLDER, false)); - registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_OBJECT_RELATIONSHIPS, false)); - registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_ACL, false)); - registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_APPLY_ACL, false)); + registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_DELETE_OBJECT, false)); + registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_UPDATE_PROPERTIES, false)); + registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_PROPERTIES, false)); + registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_OBJECT_PARENTS, false)); + registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_MOVE_OBJECT, false)); + registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_ADD_OBJECT_TO_FOLDER, false)); + registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_REMOVE_OBJECT_FROM_FOLDER, false)); + registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_OBJECT_RELATIONSHIPS, false)); + registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_GET_ACL, false)); + registerEvaluator(CMISScope.POLICY, new FixedValueActionEvaluator(serviceRegistry, CMISAllowedActionEnum.CAN_APPLY_ACL, false)); cmisRead.add(PermissionService.READ_PROPERTIES); cmisRead.add(PermissionService.READ_CONTENT); @@ -756,9 +758,9 @@ public class CMISMapping implements InitializingBean * @param cmisScope * @return */ - public Map getActionEvaluators(CMISScope scope) + public Map> getActionEvaluators(CMISScope scope) { - Map evaluators = actionEvaluators.get(scope); + Map> evaluators = actionEvaluators.get(scope); if (evaluators == null) { evaluators = Collections.emptyMap(); @@ -772,12 +774,12 @@ public class CMISMapping implements InitializingBean * @param scope * @param evaluator */ - private void registerEvaluator(CMISScope scope, CMISActionEvaluator evaluator) + private void registerEvaluator(CMISScope scope, CMISActionEvaluator evaluator) { - Map evaluators = actionEvaluators.get(scope); + Map> evaluators = actionEvaluators.get(scope); if (evaluators == null) { - evaluators = new LinkedHashMap(); + evaluators = new LinkedHashMap>(); actionEvaluators.put(scope, evaluators); } if (evaluators.get(evaluator.getAction()) != null) diff --git a/source/java/org/alfresco/cmis/mapping/CMISPropertyServiceTest.java b/source/java/org/alfresco/cmis/mapping/CMISPropertyServiceTest.java index 3294ac5e78..b156bb9870 100644 --- a/source/java/org/alfresco/cmis/mapping/CMISPropertyServiceTest.java +++ b/source/java/org/alfresco/cmis/mapping/CMISPropertyServiceTest.java @@ -42,7 +42,7 @@ import org.alfresco.service.cmr.version.VersionType; public class CMISPropertyServiceTest extends BaseCMISTest { - public void testBasicFolder() + public void testBasicFolder() throws Exception { NodeRef folder = fileFolderService.create(cmisService.getDefaultRootNodeRef(), "BaseFolder", ContentModel.TYPE_FOLDER).getNodeRef(); Map properties = cmisService.getProperties(folder); @@ -76,7 +76,7 @@ public class CMISPropertyServiceTest extends BaseCMISTest assertNull(properties.get(CMISDictionaryModel.PROP_ALLOWED_CHILD_OBJECT_TYPE_IDS)); } - public void testBasicDocument() + public void testBasicDocument() throws Exception { NodeRef content = fileFolderService.create(rootNodeRef, "BaseContent", ContentModel.TYPE_CONTENT).getNodeRef(); @@ -109,7 +109,7 @@ public class CMISPropertyServiceTest extends BaseCMISTest assertNull(properties.get(CMISDictionaryModel.PROP_ALLOWED_CHILD_OBJECT_TYPE_IDS)); } - public void testContentProperties() + public void testContentProperties() throws Exception { NodeRef content = fileFolderService.create(rootNodeRef, "BaseContent", ContentModel.TYPE_CONTENT).getNodeRef(); @@ -160,7 +160,7 @@ public class CMISPropertyServiceTest extends BaseCMISTest assertNotNull(properties.get(CMISDictionaryModel.PROP_CONTENT_STREAM_ID)); } - public void testLock() + public void testLock() throws Exception { NodeRef content = fileFolderService.create(rootNodeRef, "BaseContent", ContentModel.TYPE_CONTENT).getNodeRef(); @@ -239,7 +239,7 @@ public class CMISPropertyServiceTest extends BaseCMISTest assertNull(properties.get(CMISDictionaryModel.PROP_ALLOWED_CHILD_OBJECT_TYPE_IDS)); } - public void testCheckOut() + public void testCheckOut() throws Exception { NodeRef content = fileFolderService.create(rootNodeRef, "BaseContent", ContentModel.TYPE_CONTENT).getNodeRef(); @@ -423,7 +423,7 @@ public class CMISPropertyServiceTest extends BaseCMISTest assertNull(properties.get(CMISDictionaryModel.PROP_ALLOWED_CHILD_OBJECT_TYPE_IDS)); } - public void testVersioning() + public void testVersioning() throws Exception { NodeRef content = fileFolderService.create(rootNodeRef, "BaseContent", ContentModel.TYPE_CONTENT).getNodeRef(); @@ -719,7 +719,7 @@ public class CMISPropertyServiceTest extends BaseCMISTest assertNull(properties.get(CMISDictionaryModel.PROP_ALLOWED_CHILD_OBJECT_TYPE_IDS)); } - public void testSinglePropertyFolderAccess() + public void testSinglePropertyFolderAccess() throws Exception { NodeRef folder = fileFolderService.create(rootNodeRef, "BaseFolder", ContentModel.TYPE_FOLDER).getNodeRef(); assertEquals(cmisService.getProperty(folder, CMISDictionaryModel.PROP_OBJECT_ID), folder.toString()); diff --git a/source/java/org/alfresco/cmis/mapping/CMISServicesImpl.java b/source/java/org/alfresco/cmis/mapping/CMISServicesImpl.java index 5fa66d5cc0..22f2ac8b6b 100644 --- a/source/java/org/alfresco/cmis/mapping/CMISServicesImpl.java +++ b/source/java/org/alfresco/cmis/mapping/CMISServicesImpl.java @@ -24,38 +24,67 @@ */ package org.alfresco.cmis.mapping; +import java.io.BufferedInputStream; +import java.io.InputStream; import java.io.Serializable; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.alfresco.cmis.CMISConstraintException; +import org.alfresco.cmis.CMISContentAlreadyExistsException; +import org.alfresco.cmis.CMISContentStreamAllowedEnum; import org.alfresco.cmis.CMISDictionaryModel; import org.alfresco.cmis.CMISDictionaryService; +import org.alfresco.cmis.CMISFilterNotValidException; +import org.alfresco.cmis.CMISInvalidArgumentException; +import org.alfresco.cmis.CMISNotSupportedException; +import org.alfresco.cmis.CMISObjectNotFoundException; +import org.alfresco.cmis.CMISPermissionDeniedException; import org.alfresco.cmis.CMISPropertyDefinition; import org.alfresco.cmis.CMISRelationshipDirectionEnum; import org.alfresco.cmis.CMISRendition; import org.alfresco.cmis.CMISRenditionService; +import org.alfresco.cmis.CMISRuntimeException; import org.alfresco.cmis.CMISScope; +import org.alfresco.cmis.CMISServiceException; import org.alfresco.cmis.CMISServices; +import org.alfresco.cmis.CMISStreamNotSupportedException; import org.alfresco.cmis.CMISTypeDefinition; import org.alfresco.cmis.CMISTypesFilterEnum; +import org.alfresco.cmis.CMISVersioningException; +import org.alfresco.cmis.CMISVersioningStateEnum; +import org.alfresco.cmis.dictionary.CMISFolderTypeDefinition; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; +import org.alfresco.repo.content.encoding.ContentCharsetFinder; import org.alfresco.repo.model.Repository; import org.alfresco.repo.search.QueryParameterDefImpl; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.repo.tenant.TenantAdminService; import org.alfresco.repo.tenant.TenantDeployer; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.repo.version.VersionModel; +import org.alfresco.service.cmr.coci.CheckOutCheckInService; +import org.alfresco.service.cmr.coci.CheckOutCheckInServiceException; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.MimetypeService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; @@ -63,48 +92,44 @@ import org.alfresco.service.cmr.search.QueryParameterDefinition; import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.cmr.version.Version; +import org.alfresco.service.cmr.version.VersionDoesNotExistException; +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.RegexQNamePattern; -import org.springframework.extensions.surf.util.AbstractLifecycleBean; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; - +import org.springframework.context.event.ApplicationContextEvent; +import org.springframework.extensions.surf.util.AbstractLifecycleBean; /** - * CMIS Services Implementation + * CMIS Services Implementation. * * @author davidc + * @author dward */ -public class CMISServicesImpl implements CMISServices, ApplicationContextAware, ApplicationListener, TenantDeployer +public class CMISServicesImpl implements CMISServices, ApplicationContextAware, ApplicationListener, TenantDeployer { /** Query Parameters */ private static final QName PARAM_PARENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "parent"); private static final QName PARAM_USERNAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "username"); - /** Shallow search for all files and folders */ - private static final String LUCENE_QUERY_SHALLOW_FOLDERS = - "+PARENT:\"${cm:parent}\" " + - "-TYPE:\"" + ContentModel.TYPE_SYSTEM_FOLDER + "\" " + - "+TYPE:\"" + ContentModel.TYPE_FOLDER + "\""; - - /** Shallow search for all files and folders */ - private static final String LUCENE_QUERY_SHALLOW_FILES = - "+PARENT:\"${cm:parent}\" " + - "-TYPE:\"" + ContentModel.TYPE_SYSTEM_FOLDER + "\" " + - "+TYPE:\"" + ContentModel.TYPE_CONTENT + "\" " + - "-ASPECT:\"" + ContentModel.ASPECT_WORKING_COPY + "\""; - private static final String LUCENE_QUERY_CHECKEDOUT = "+@cm\\:workingCopyOwner:${cm:username}"; private static final String LUCENE_QUERY_CHECKEDOUT_IN_FOLDER = "+@cm\\:workingCopyOwner:${cm:username} " + "+PARENT:\"${cm:parent}\""; - + + private static final int ASSOC_ID_PREFIX_LENGTH = ASSOC_ID_PREFIX.length(); + + private static final Pattern ORDER_BY_PATTERN = Pattern.compile("^([^\\s,\"'\\\\\\.\\(\\)]+)\\s+(ASC|DESC)$"); // dependencies private Repository repository; @@ -113,9 +138,13 @@ public class CMISServicesImpl implements CMISServices, ApplicationContextAware, private CMISDictionaryService cmisDictionaryService; private SearchService searchService; private NodeService nodeService; + private ContentService contentService; private TenantAdminService tenantAdminService; - private ProcessorLifecycle lifecycle = new ProcessorLifecycle(); private CMISRenditionService cmisRenditionService; + private CheckOutCheckInService checkOutCheckInService; + private VersionService versionService; + private MimetypeService mimetypeService; + private ProcessorLifecycle lifecycle = new ProcessorLifecycle(); // CMIS supported version private String cmisVersion = "[undefined]"; @@ -220,7 +249,21 @@ public class CMISServicesImpl implements CMISServices, ApplicationContextAware, } /** + * Sets the content service. + * + * @param contentService + * the content service + */ + public void setContentService(ContentService contentService) + { + this.contentService = contentService; + } + + /** + * Sets the repository. + * * @param repository + * the repository */ public void setRepository(Repository repository) { @@ -238,6 +281,39 @@ public class CMISServicesImpl implements CMISServices, ApplicationContextAware, this.cmisRenditionService = cmisRenditionService; } + /** + * Sets the check out check in service. + * + * @param checkOutCheckInService + * the check out check in service + */ + public void setCheckOutCheckInService(CheckOutCheckInService checkOutCheckInService) + { + this.checkOutCheckInService = checkOutCheckInService; + } + + /** + * Sets the version service. + * + * @param versionService + * the version service + */ + public void setVersionService(VersionService versionService) + { + this.versionService = versionService; + } + + /** + * Sets the mimetype service. + * + * @param mimetypeService + * the mimetype service + */ + public void setMimetypeService(MimetypeService mimetypeService) + { + this.mimetypeService = mimetypeService; + } + /* (non-Javadoc) * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) */ @@ -249,22 +325,29 @@ public class CMISServicesImpl implements CMISServices, ApplicationContextAware, /* (non-Javadoc) * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent) */ - public void onApplicationEvent(ApplicationEvent event) + public void onApplicationEvent(ApplicationContextEvent event) { lifecycle.onApplicationEvent(event); } /** - * Hooks into Spring Application Lifecycle + * Hooks into Spring Application Lifecycle. */ private class ProcessorLifecycle extends AbstractLifecycleBean { + + /* (non-Javadoc) + * @see org.alfresco.util.AbstractLifecycleBean#onBootstrap(org.springframework.context.ApplicationEvent) + */ @Override protected void onBootstrap(ApplicationEvent event) { init(); } + /* (non-Javadoc) + * @see org.alfresco.util.AbstractLifecycleBean#onShutdown(org.springframework.context.ApplicationEvent) + */ @Override protected void onShutdown(ApplicationEvent event) { @@ -397,7 +480,7 @@ public class CMISServicesImpl implements CMISServices, ApplicationContextAware, * (non-Javadoc) * @see org.alfresco.cmis.CMISServices#getRenditions(org.alfresco.service.cmr.repository.NodeRef, java.lang.String) */ - public Map getRenditions(NodeRef nodeRef, String renditionFilter) + public Map getRenditions(NodeRef nodeRef, String renditionFilter) throws CMISFilterNotValidException { Map result = new TreeMap(); List renditions = cmisRenditionService.getRenditions(nodeRef, renditionFilter); @@ -419,38 +502,65 @@ public class CMISServicesImpl implements CMISServices, ApplicationContextAware, /* * (non-Javadoc) - * @see org.alfresco.cmis.CMISServices#getChildren(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.cmis.CMISTypesFilterEnum) + * @see org.alfresco.cmis.CMISServices#getChildren(org.alfresco.service.cmr.repository.NodeRef, + * org.alfresco.cmis.CMISTypesFilterEnum, java.lang.String) */ - public NodeRef[] getChildren(NodeRef parent, CMISTypesFilterEnum typesFilter) + public NodeRef[] getChildren(NodeRef parent, CMISTypesFilterEnum typesFilter, String orderBy) + throws CMISInvalidArgumentException { - if (typesFilter == CMISTypesFilterEnum.ANY) + if (typesFilter == CMISTypesFilterEnum.POLICIES) { - NodeRef[] folders = queryChildren(parent, CMISTypesFilterEnum.FOLDERS); - NodeRef[] docs = queryChildren(parent, CMISTypesFilterEnum.DOCUMENTS); - NodeRef[] foldersAndDocs = new NodeRef[folders.length + docs.length]; - System.arraycopy(folders, 0, foldersAndDocs, 0, folders.length); - System.arraycopy(docs, 0, foldersAndDocs, folders.length, docs.length); - return foldersAndDocs; + return new NodeRef[0]; } - else if (typesFilter == CMISTypesFilterEnum.FOLDERS) + SearchParameters params = new SearchParameters(); + params.setLanguage(SearchService.LANGUAGE_LUCENE); + params.addStore(parent.getStoreRef()); + QueryParameterDefinition parentDef = new QueryParameterDefImpl(PARAM_PARENT, nodeRefDataType, true, parent.toString()); + params.addQueryParameterDefinition(parentDef); + + // Build a query for the appropriate types + StringBuilder query = new StringBuilder(1024).append("+PARENT:\"${cm:parent}\" -ASPECT:\"").append( + ContentModel.ASPECT_WORKING_COPY).append("\" +TYPE:("); + + // Include doc type if necessary + if (typesFilter != CMISTypesFilterEnum.FOLDERS) { - NodeRef[] folders = queryChildren(parent, CMISTypesFilterEnum.FOLDERS); - return folders; + query.append('"').append(ContentModel.TYPE_CONTENT).append('"'); } - else if (typesFilter == CMISTypesFilterEnum.DOCUMENTS) + // Include folder type if necessary + if (typesFilter != CMISTypesFilterEnum.DOCUMENTS) { - NodeRef[] docs = queryChildren(parent, CMISTypesFilterEnum.DOCUMENTS); - return docs; + if (typesFilter == CMISTypesFilterEnum.ANY) + { + query.append(" "); + } + query.append('"').append(ContentModel.TYPE_FOLDER).append('"'); + } + // Always exclude system folders + query.append(") -TYPE:\"").append(ContentModel.TYPE_SYSTEM_FOLDER).append("\""); + params.setQuery(query.toString()); + parseOrderBy(orderBy, params); + ResultSet resultSet = null; + try + { + resultSet = searchService.query(params); + List results = resultSet.getNodeRefs(); + NodeRef[] nodeRefs = new NodeRef[results.size()]; + return results.toArray(nodeRefs); + } + finally + { + if (resultSet != null) resultSet.close(); } - - return new NodeRef[0]; } /* * (non-Javadoc) - * @see org.alfresco.cmis.CMISServices#getCheckedOut(java.lang.String, org.alfresco.service.cmr.repository.NodeRef, boolean) + * @see org.alfresco.cmis.CMISServices#getCheckedOut(java.lang.String, org.alfresco.service.cmr.repository.NodeRef, + * boolean, java.lang.String) */ - public NodeRef[] getCheckedOut(String username, NodeRef folder, boolean includeDescendants) + public NodeRef[] getCheckedOut(String username, NodeRef folder, boolean includeDescendants, String orderBy) + throws CMISInvalidArgumentException { SearchParameters params = new SearchParameters(); params.setLanguage(SearchService.LANGUAGE_LUCENE); @@ -482,6 +592,7 @@ public class CMISServicesImpl implements CMISServices, ApplicationContextAware, params.addQueryParameterDefinition(parentDef); } } + parseOrderBy(orderBy, params); ResultSet resultSet = null; try @@ -498,86 +609,54 @@ public class CMISServicesImpl implements CMISServices, ApplicationContextAware, } /** - * Query children helper + * Parses an order by clause and adds its orderings to the given search parameters. * - * NOTE: Queries for folders only or documents only - * - * @param parent node to query children for - * @param typesFilter folders or documents - * @return node children + * @param orderBy + * the order by clause + * @param params + * the search parameters + * @throws CMISInvalidArgumentException + * if the order by clause is invalid */ - private NodeRef[] queryChildren(NodeRef parent, CMISTypesFilterEnum typesFilter) + private void parseOrderBy(String orderBy, SearchParameters params) throws CMISInvalidArgumentException { - SearchParameters params = new SearchParameters(); - params.setLanguage(SearchService.LANGUAGE_LUCENE); - params.addStore(parent.getStoreRef()); - QueryParameterDefinition parentDef = new QueryParameterDefImpl(PARAM_PARENT, nodeRefDataType, true, parent.toString()); - params.addQueryParameterDefinition(parentDef); - - if (typesFilter == CMISTypesFilterEnum.FOLDERS) + if (orderBy == null) { - params.setQuery(LUCENE_QUERY_SHALLOW_FOLDERS); + return; } - else if (typesFilter == CMISTypesFilterEnum.DOCUMENTS) + for (String token : orderBy.split(",")) { - params.setQuery(LUCENE_QUERY_SHALLOW_FILES); - } - - ResultSet resultSet = null; - try - { - resultSet = searchService.query(params); - List results = resultSet.getNodeRefs(); - NodeRef[] nodeRefs = new NodeRef[results.size()]; - return results.toArray(nodeRefs); - } - finally - { - if (resultSet != null) resultSet.close(); - } - } - - /* - * (non-Javadoc) - * @see org.alfresco.cmis.CMISServices#getRelationship(org.alfresco.cmis.CMISTypeDefinition, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef) - */ - public AssociationRef getRelationship(CMISTypeDefinition relDef, NodeRef source, NodeRef target) - { - if (relDef == null) - { - relDef = cmisDictionaryService.findType(CMISDictionaryModel.RELATIONSHIP_TYPE_ID); - } - if (!relDef.getBaseType().getTypeId().equals(CMISDictionaryModel.RELATIONSHIP_TYPE_ID)) - { - throw new AlfrescoRuntimeException("Type Id " + relDef.getTypeId() + " is not a relationship type"); - } - - QName relDefQName = relDef.getTypeId().getQName(); - List assocs = nodeService.getTargetAssocs(source, new RegexQNamePattern(relDefQName.getNamespaceURI(), relDefQName.getLocalName())); - for (AssociationRef assoc : assocs) - { - if (assoc.getTargetRef().equals(target)) + Matcher matcher = ORDER_BY_PATTERN.matcher(token); + if (!matcher.matches()) { - return assoc; + throw new CMISInvalidArgumentException("Invalid order by clause: \"" + orderBy + '"'); + } + String queryName = matcher.group(1); + CMISPropertyDefinition propDef = cmisDictionaryService.findPropertyByQueryName(queryName); + if (propDef == null) + { + throw new CMISInvalidArgumentException("No such property: \"" + queryName + '"'); + } + // We can only order by orderable properties + if (propDef.isOrderable()) + { + params.addSort(propDef.getPropertyLuceneBuilder().getLuceneFieldName(), matcher.group(2).equals("ASC")); } } - return null; } - + /* * (non-Javadoc) * @see org.alfresco.cmis.CMISServices#getRelationships(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.cmis.CMISTypeId, boolean, org.alfresco.cmis.CMISRelationshipDirectionEnum) */ public AssociationRef[] getRelationships(NodeRef node, CMISTypeDefinition relDef, boolean includeSubTypes, CMISRelationshipDirectionEnum direction) + throws CMISInvalidArgumentException { + // by the spec. if typeId=null then it is necessary return ALL associated Relationship objects! // establish relationship type to filter on - if (relDef == null) + if ((relDef != null) && !relDef.getBaseType().getTypeId().equals(CMISDictionaryModel.RELATIONSHIP_TYPE_ID)) { - relDef = cmisDictionaryService.findType(CMISDictionaryModel.RELATIONSHIP_TYPE_ID); - } - if (!relDef.getBaseType().getTypeId().equals(CMISDictionaryModel.RELATIONSHIP_TYPE_ID)) - { - throw new AlfrescoRuntimeException("Type Id " + relDef.getTypeId() + " is not a relationship type"); + throw new CMISInvalidArgumentException("Type Id " + relDef.getTypeId() + " is not a relationship type"); } // retrieve associations @@ -591,22 +670,29 @@ public class CMISServicesImpl implements CMISServices, ApplicationContextAware, assocs.addAll(nodeService.getSourceAssocs(node, RegexQNamePattern.MATCH_ALL)); } - // filter association by type - Collection subRelDefs = (includeSubTypes ? relDef.getSubTypes(true) : null); List filteredAssocs = new ArrayList(assocs.size()); - for (AssociationRef assoc : assocs) + if (null != relDef) { - CMISTypeDefinition assocTypeDef = cmisDictionaryService.findTypeForClass(assoc.getTypeQName(), CMISScope.RELATIONSHIP); - if (assocTypeDef == null) + // filter association by type + Collection subRelDefs = (includeSubTypes ? relDef.getSubTypes(true) : null); + for (AssociationRef assoc : assocs) { - throw new AlfrescoRuntimeException("Association Type QName " + assoc.getTypeQName() + " does not map to a CMIS Relationship Type"); - } - - if (assocTypeDef.equals(relDef) || (subRelDefs != null && subRelDefs.contains(assocTypeDef))) - { - filteredAssocs.add(assoc); + CMISTypeDefinition assocTypeDef = cmisDictionaryService.findTypeForClass(assoc.getTypeQName(), CMISScope.RELATIONSHIP); + if (assocTypeDef == null) + { + throw new CMISInvalidArgumentException("Association Type QName " + assoc.getTypeQName() + " does not map to a CMIS Relationship Type"); + } + + if (assocTypeDef.equals(relDef) || (subRelDefs != null && subRelDefs.contains(assocTypeDef))) + { + filteredAssocs.add(assoc); + } } } + else + { + filteredAssocs = assocs; + } AssociationRef[] assocArray = new AssociationRef[filteredAssocs.size()]; filteredAssocs.toArray(assocArray); @@ -617,20 +703,76 @@ public class CMISServicesImpl implements CMISServices, ApplicationContextAware, * (non-Javadoc) * @see org.alfresco.cmis.CMISServices#getProperty(org.alfresco.service.cmr.repository.NodeRef, java.lang.String) */ - public Serializable getProperty(NodeRef nodeRef, String propertyName) + public Serializable getProperty(NodeRef nodeRef, String propertyName) throws CMISInvalidArgumentException + { + CMISTypeDefinition typeDef = getTypeDefinition(nodeRef); + CMISPropertyDefinition propDef = cmisDictionaryService.findProperty(propertyName, typeDef); + if (propDef == null) + { + throw new CMISInvalidArgumentException("Property " + propertyName + " not found for type " + + typeDef.getTypeId() + " in CMIS Dictionary"); + } + return propDef.getPropertyAccessor().getValue(nodeRef); + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#getTypeDefinition(org.alfresco.service.cmr.repository.NodeRef) + */ + public CMISTypeDefinition getTypeDefinition(NodeRef nodeRef) throws CMISInvalidArgumentException { QName typeQName = nodeService.getType(nodeRef); CMISTypeDefinition typeDef = cmisDictionaryService.findTypeForClass(typeQName); if (typeDef == null) { - throw new AlfrescoRuntimeException("Type " + typeQName + " not found in CMIS Dictionary"); + throw new CMISInvalidArgumentException("Type " + typeQName + " not found in CMIS Dictionary"); } - CMISPropertyDefinition propDef = cmisDictionaryService.findProperty(propertyName, typeDef); - if (propDef == null) + return typeDef; + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#getTypeDefinition(org.alfresco.service.cmr.repository.AssociationRef) + */ + public CMISTypeDefinition getTypeDefinition(AssociationRef associationRef) throws CMISInvalidArgumentException + { + QName typeQName = associationRef.getTypeQName(); + CMISTypeDefinition typeDef = cmisDictionaryService.findTypeForClass(typeQName, CMISScope.RELATIONSHIP); + if (typeDef == null) { - throw new AlfrescoRuntimeException("Property " + propertyName + " not found for type " + typeDef.getTypeId() + " in CMIS Dictionary"); + throw new CMISInvalidArgumentException("Association Type " + typeQName + " not found in CMIS Dictionary"); } - return propDef.getPropertyAccessor().getValue(nodeRef); + return typeDef; + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#getTypeDefinition(java.lang.String) + */ + public CMISTypeDefinition getTypeDefinition(String typeId) throws CMISInvalidArgumentException + { + CMISTypeDefinition typeDef = null; + try + { + typeDef = cmisDictionaryService.findType(typeId); + } + catch (Exception e) + { + } + if (typeDef == null) + { + throw new CMISInvalidArgumentException("Invalid typeId " + typeId); + } + return typeDef; + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#getBaseTypes() + */ + public Collection getBaseTypes() + { + return cmisDictionaryService.getBaseTypes(); } /* @@ -648,7 +790,8 @@ public class CMISServicesImpl implements CMISServices, ApplicationContextAware, CMISPropertyDefinition propDef = cmisDictionaryService.findProperty(propertyName, typeDef); if (propDef == null) { - throw new AlfrescoRuntimeException("Property " + propertyName + " not found for relationship type " + typeDef.getTypeId() + " in CMIS Dictionary"); + throw new AlfrescoRuntimeException("Property " + propertyName + " not found for relationship type " + + typeDef.getTypeId() + " in CMIS Dictionary"); } return propDef.getPropertyAccessor().getValue(assocRef); } @@ -657,14 +800,9 @@ public class CMISServicesImpl implements CMISServices, ApplicationContextAware, * (non-Javadoc) * @see org.alfresco.cmis.CMISServices#getProperties(org.alfresco.service.cmr.repository.NodeRef) */ - public Map getProperties(NodeRef nodeRef) + public Map getProperties(NodeRef nodeRef) throws CMISInvalidArgumentException { - QName typeQName = nodeService.getType(nodeRef); - CMISTypeDefinition typeDef = cmisDictionaryService.findTypeForClass(typeQName); - if (typeDef == null) - { - throw new AlfrescoRuntimeException("Type " + typeQName + " not found in CMIS Dictionary"); - } + CMISTypeDefinition typeDef = getTypeDefinition(nodeRef); Map propDefs = typeDef.getPropertyDefinitions(); Map values = new HashMap(propDefs.size()); for (CMISPropertyDefinition propDef : propDefs.values()) @@ -679,18 +817,821 @@ public class CMISServicesImpl implements CMISServices, ApplicationContextAware, * @see org.alfresco.cmis.CMISServices#setProperty(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, java.io.Serializable) */ public void setProperty(NodeRef nodeRef, String propertyName, Serializable value) + throws CMISInvalidArgumentException { - QName typeQName = nodeService.getType(nodeRef); - CMISTypeDefinition typeDef = cmisDictionaryService.findTypeForClass(typeQName); - if (typeDef == null) - { - throw new AlfrescoRuntimeException("Type " + typeQName + " not found in CMIS Dictionary"); - } + CMISTypeDefinition typeDef = getTypeDefinition(nodeRef); CMISPropertyDefinition propDef = cmisDictionaryService.findProperty(propertyName, typeDef); if (propDef == null) { - throw new AlfrescoRuntimeException("Property " + propertyName + " not found for type " + typeDef.getTypeId() + " in CMIS Dictionary"); + throw new AlfrescoRuntimeException("Property " + propertyName + " not found for type " + + typeDef.getTypeId() + " in CMIS Dictionary"); } propDef.getPropertyAccessor().setValue(nodeRef, value); } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#applyVersioningState(org.alfresco.service.cmr.repository.NodeRef, + * org.alfresco.cmis.CMISVersioningStateEnum) + */ + public NodeRef applyVersioningState(NodeRef source, CMISVersioningStateEnum versioningState) + throws CMISConstraintException, CMISInvalidArgumentException + { + switch (versioningState) + { + case NONE: + return source; + case CHECKED_OUT: + validateVersionable(source); + return this.checkOutCheckInService.checkout(source); + default: + validateVersionable(source); + this.versionService.createVersion(source, createVersionProperties("Initial Version", + versioningState != CMISVersioningStateEnum.MINOR)); + break; + } + return source; + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#checkOut(java.lang.String) + */ + public NodeRef checkOut(String objectId) throws CMISConstraintException, CMISVersioningException, + CMISObjectNotFoundException, CMISInvalidArgumentException, CMISPermissionDeniedException + { + NodeRef nodeRef = getObject(objectId, NodeRef.class, true, true, false); + try + { + return this.checkOutCheckInService.checkout(nodeRef); + } + catch (CheckOutCheckInServiceException e) + { + throw new CMISVersioningException(e.getMessage(), e); + } + catch (AccessDeniedException e) + { + throw new CMISPermissionDeniedException(e.getMessage(), e); + } + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#checkIn(java.lang.String, java.lang.String, boolean) + */ + public NodeRef checkIn(String objectId, String checkinComment, boolean isMajor) throws CMISConstraintException, + CMISVersioningException, CMISObjectNotFoundException, CMISInvalidArgumentException, + CMISPermissionDeniedException + { + NodeRef nodeRef = getObject(objectId, NodeRef.class, true, true, true); + try + { + return checkOutCheckInService.checkin(nodeRef, createVersionProperties(checkinComment, isMajor)); + } + catch (CheckOutCheckInServiceException e) + { + throw new CMISVersioningException(e.getMessage(), e); + } + catch (AccessDeniedException e) + { + throw new CMISPermissionDeniedException(e.getMessage(), e); + } + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#cancelCheckOut(java.lang.String) + */ + public void cancelCheckOut(String objectId) throws CMISConstraintException, CMISVersioningException, + CMISObjectNotFoundException, CMISInvalidArgumentException, CMISPermissionDeniedException + { + NodeRef nodeRef = getObject(objectId, NodeRef.class, true, true, true); + try + { + checkOutCheckInService.cancelCheckout(nodeRef); + } + catch (CheckOutCheckInServiceException e) + { + throw new CMISVersioningException(e.getMessage(), e); + } + catch (AccessDeniedException e) + { + throw new CMISPermissionDeniedException(e.getMessage(), e); + } + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#getAllVersions(java.lang.String) + */ + public List getAllVersions(String objectId) throws CMISConstraintException, CMISVersioningException, + CMISObjectNotFoundException, CMISInvalidArgumentException, CMISPermissionDeniedException + { + NodeRef nodeRef = getVersionSeries(objectId, NodeRef.class, true); + + List objects = new LinkedList(); + NodeRef pwc = checkOutCheckInService.getWorkingCopy(nodeRef); + if (pwc != null) + { + objects.add(pwc); + } + objects.add(nodeRef); + VersionHistory versionHistory = versionService.getVersionHistory(nodeRef); + if (versionHistory != null) + { + Version current = versionService.getCurrentVersion(nodeRef); + while (current != null) + { + objects.add(current.getFrozenStateNodeRef()); + current = versionHistory.getPredecessor(current); + } + } + return objects; + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#getObject(java.lang.String, java.lang.Class, boolean, boolean, boolean) + */ + @SuppressWarnings("unchecked") + public T getObject(String objectId, Class requiredType, boolean forUpdate, boolean isVersionable, + boolean isPwc) throws CMISConstraintException, CMISVersioningException, CMISObjectNotFoundException, + CMISInvalidArgumentException, CMISPermissionDeniedException + { + try + { + int sepIndex = objectId.lastIndexOf(';'); + String nodeRefString; + // Handle version format IDs + if (sepIndex != -1 && NodeRef.isNodeRef(nodeRefString = objectId.substring(0, sepIndex))) + { + if (isPwc) + { + throw new CMISVersioningException(objectId + " is not a working copy"); + } + + // Allow returning of non-updateable version nodes as noderefs + if (requiredType.isAssignableFrom(Version.class) || !forUpdate + && requiredType.isAssignableFrom(NodeRef.class)) + { + NodeRef nodeRef = new NodeRef(nodeRefString); + if (!nodeService.exists(nodeRef)) + { + throw new CMISObjectNotFoundException(objectId); + } + VersionHistory versionHistory = versionService.getVersionHistory(nodeRef); + if (versionHistory == null) + { + throw new CMISObjectNotFoundException(objectId); + } + try + { + Version version = versionHistory.getVersion(objectId.substring(sepIndex + 1)); + + // Return as noderef if required + return requiredType.isAssignableFrom(Version.class) ? (T) version : (T) version + .getFrozenStateNodeRef(); + } + catch (VersionDoesNotExistException e) + { + throw new CMISObjectNotFoundException(objectId); + } + } + else if (requiredType.isAssignableFrom(NodeRef.class)) + { + // We wanted an updateable node but got a history node + throw new CMISVersioningException(objectId + " is not a current node"); + } + } + // Handle node format IDs + else if (NodeRef.isNodeRef(objectId)) + { + if (requiredType.isAssignableFrom(NodeRef.class)) + { + NodeRef nodeRef = new NodeRef(objectId); + if (!nodeService.exists(nodeRef)) + { + throw new CMISObjectNotFoundException(objectId); + } + if (isVersionable) + { + validateVersionable(nodeRef); + + // Check that the PWC status is as we require + if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY)) + { + // This is a PWC so make sure we wanted one + if (!isPwc) + { + throw new CMISVersioningException(objectId + " is a working copy"); + } + } + else + { + // This is not a PWC so make sure we didn't want one + if (isPwc) + { + throw new CMISVersioningException(objectId + " is not a working copy"); + } + + // If it should be updateable, make sure it's not currently checked out + if (forUpdate) + { + if (checkOutCheckInService.getWorkingCopy(nodeRef) != null) + { + throw new CMISVersioningException("Can't update " + objectId + " while checked out"); + } + } + } + } + return (T) new NodeRef(objectId); + } + } + // Handle Assoc IDs + else if (objectId.startsWith(ASSOC_ID_PREFIX)) + { + if (isPwc) + { + throw new CMISVersioningException(objectId + " is not a working copy"); + } + if (isVersionable) + { + throw new CMISConstraintException("Type " + CMISDictionaryModel.RELATIONSHIP_TYPE_ID + + " is not versionable"); + } + if (requiredType.isAssignableFrom(AssociationRef.class)) + { + AssociationRef associationRef = nodeService.getAssoc(new Long(objectId.substring(ASSOC_ID_PREFIX_LENGTH))); + if (associationRef == null) + { + throw new CMISObjectNotFoundException("Unable to find object " + objectId); + } + return (T) associationRef; + } + } + } + catch (AccessDeniedException e) + { + throw new CMISPermissionDeniedException(e); + } + throw new CMISConstraintException("Object " + objectId + " is not of required type"); + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#getReadableObject(java.lang.String, java.lang.Class) + */ + public T getReadableObject(String objectId, Class requiredType) throws CMISConstraintException, + CMISVersioningException, CMISObjectNotFoundException, CMISInvalidArgumentException, + CMISPermissionDeniedException + { + return getObject(objectId, requiredType, false, false, false); + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#getFolder(java.lang.String) + */ + public NodeRef getFolder(String objectId) throws CMISConstraintException, CMISVersioningException, + CMISObjectNotFoundException, CMISInvalidArgumentException, CMISPermissionDeniedException + { + NodeRef folderRef = getReadableObject(objectId, NodeRef.class); + CMISTypeDefinition typeDef = getTypeDefinition(folderRef); + if (typeDef.getTypeId().getBaseTypeId() != CMISDictionaryModel.FOLDER_TYPE_ID) + { + throw new CMISInvalidArgumentException("Object " + objectId + " is not a folder"); + } + return folderRef; + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#getFolderParent(java.lang.String) + */ + public NodeRef getFolderParent(String folderId) throws CMISConstraintException, CMISVersioningException, + CMISObjectNotFoundException, CMISInvalidArgumentException, CMISPermissionDeniedException + { + NodeRef folderRef = getFolder(folderId); + if (getDefaultRootNodeRef().equals(folderRef)) + { + throw new CMISInvalidArgumentException("Root Folder has no parents"); + } + return nodeService.getPrimaryParent(folderRef).getParentRef(); + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#getVersionSeries(java.lang.String, java.lang.Class, boolean) + */ + @SuppressWarnings("unchecked") + public T getVersionSeries(String objectId, Class requiredType, boolean isVersionable) + throws CMISConstraintException, CMISVersioningException, CMISObjectNotFoundException, + CMISInvalidArgumentException, CMISPermissionDeniedException + { + // Preserve non-node objects + if (!requiredType.isAssignableFrom(NodeRef.class)) + { + return getObject(objectId, requiredType, false, isVersionable, false); + } + + Object object = getReadableObject(objectId, Object.class); + NodeRef result; + // Map version nodes back to their source node + if (object instanceof Version) + { + result = ((Version) object).getVersionedNodeRef(); + } + else if (object instanceof NodeRef) + { + NodeRef nodeRef = (NodeRef) object; + // Map working copy nodes back to where they were checked out from + if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY)) + { + result = (NodeRef) nodeService.getProperty(nodeRef, ContentModel.PROP_COPY_REFERENCE); + } + // Preserve all other nodes + else + { + result = nodeRef; + } + } + else + { + throw new CMISConstraintException("Object " + objectId + " is not of required type"); + } + if (isVersionable) + { + validateVersionable(result); + } + return (T)result; + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#getLatestVersion(java.lang.String, boolean) + */ + public NodeRef getLatestVersion(String objectId, boolean major) throws CMISConstraintException, + CMISVersioningException, CMISObjectNotFoundException, CMISInvalidArgumentException, + CMISPermissionDeniedException + { + NodeRef versionSeries = getVersionSeries(objectId, NodeRef.class, false); + // If we don't care whether the latest version is major or minor, the latest version is either the working copy + // or the live node + if (!major) + { + NodeRef nodeRef = checkOutCheckInService.getWorkingCopy(versionSeries); + if (nodeRef != null) + { + return nodeRef; + } + + return versionSeries; + } + + // Now check the version history + VersionHistory versionHistory = versionService.getVersionHistory(versionSeries); + if (versionHistory == null) + { + throw new CMISObjectNotFoundException(objectId); + } + Version current = versionService.getCurrentVersion(versionSeries); + while (current != null && current.getVersionType() != VersionType.MAJOR) + { + current = versionHistory.getPredecessor(current); + } + if (current == null) + { + throw new CMISObjectNotFoundException(objectId); + } + return current.getFrozenStateNodeRef(); + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#deleteContentStream(java.lang.String) + */ + public void deleteContentStream(String objectId) throws CMISConstraintException, CMISVersioningException, + CMISObjectNotFoundException, CMISInvalidArgumentException, CMISPermissionDeniedException + { + NodeRef currentNode = getObject(objectId, NodeRef.class, true, false, false); + CMISTypeDefinition typeDef = getTypeDefinition(currentNode); + if (CMISContentStreamAllowedEnum.REQUIRED.equals(typeDef.getContentStreamAllowed())) + { + throw new CMISConstraintException( + "The 'contentStreamAllowed' attribute of the specified Object-Type definition is set to 'required'."); + } + + try + { + nodeService.setProperty(currentNode, ContentModel.PROP_CONTENT, null); + } + catch (AccessDeniedException e) + { + throw new CMISPermissionDeniedException(e); + } + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#deleteObject(java.lang.String, boolean) + */ + public void deleteObject(String objectId, boolean allVersions) throws CMISConstraintException, + CMISVersioningException, CMISObjectNotFoundException, CMISInvalidArgumentException, + CMISPermissionDeniedException, CMISRuntimeException + { + try + { + Object object = allVersions ? getVersionSeries(objectId, Object.class, false) : getObject(objectId, Object.class, true, false, + false); + + // Handle associations + if (object instanceof AssociationRef) + { + AssociationRef assocRef = (AssociationRef) object; + nodeService + .removeAssociation(assocRef.getSourceRef(), assocRef.getTargetRef(), assocRef.getTypeQName()); + return; + } + + // Handle individual versions + if (object instanceof Version) + { + Version version = (Version) object; + versionService.deleteVersion(version.getVersionedNodeRef(), version); + return; + } + NodeRef nodeRef = (NodeRef) object; + + // Handle a working copy + if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY)) + { + checkOutCheckInService.cancelCheckout(nodeRef); + return; + } + + // Handle 'real' nodes + CMISTypeDefinition typeDef = getTypeDefinition(nodeRef); + if (typeDef.getTypeId().getBaseTypeId() == CMISDictionaryModel.FOLDER_TYPE_ID) + { + if (nodeService.getChildAssocs(nodeRef).size() > 0) + { + throw new CMISConstraintException("Could not delete folder with at least one Child"); + } + } + // Only honour the allVersions flag for non-folder versionable objects + else if (typeDef.isVersionable() && allVersions) + { + NodeRef workingCopy = checkOutCheckInService.getWorkingCopy(nodeRef); + if (workingCopy != null) + { + checkOutCheckInService.cancelCheckout(workingCopy); + } + versionService.deleteVersionHistory(nodeRef); + } + + // Attempt to delete the node + nodeService.deleteNode(nodeRef); + } + catch (AccessDeniedException e) + { + throw new CMISPermissionDeniedException(e); + } + catch (Exception e) + { + throw new CMISRuntimeException(e); + } + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#deleteTree(java.lang.String, boolean, boolean, boolean) + */ + public List deleteTree(String objectId, boolean continueOnFailure, boolean unfile, boolean deleteAllVersions) + throws CMISConstraintException, CMISVersioningException, CMISObjectNotFoundException, + CMISInvalidArgumentException, CMISPermissionDeniedException + { + NodeRef folderRef = getFolder(objectId); + List failedToDelete = new LinkedList(); + deleteTree(nodeService.getPrimaryParent(folderRef), continueOnFailure, unfile, deleteAllVersions, + failedToDelete); + return failedToDelete; + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#deleteTreeReportLastError(java.lang.String, boolean, boolean, boolean) + */ + public void deleteTreeReportLastError(String objectId, boolean continueOnFailure, boolean unfile, + boolean deleteAllVersions) throws CMISServiceException + { + NodeRef folderRef = getFolder(objectId); + List failedToDelete = new LinkedList(); + CMISServiceException lastError = deleteTree(nodeService.getPrimaryParent(folderRef), continueOnFailure, unfile, + deleteAllVersions, failedToDelete); + if (lastError != null) + { + throw lastError; + } + } + + /** + * Internal recursive helper method for tree deletion. Returns the last error encountered, rather than throwing it, + * to avoid transaction rollback. + * + * @param parentRef + * the parent folder + * @param continueOnFailure + * should we continue if an error occurs with one of the children? + * @param unfile + * should we remove non-primary associations to nodes rather than delete them? + * @param deleteAllVersions + * should we delete all the versions of the documents we delete? + * @param failedToDelete + * list of object IDs of the children we failed to delete + * @return the last error encountered. + * @throws CMISInvalidArgumentException + * the CMIS invalid argument exception + */ + private CMISServiceException deleteTree(ChildAssociationRef parentRef, boolean continueOnFailure, boolean unfile, + boolean deleteAllVersions, List failedToDelete) throws CMISInvalidArgumentException + { + CMISServiceException lastError = null; + NodeRef child = parentRef.getChildRef(); + + // Due to multi-filing, it could be that a sub-tree has already been deleted + if (!nodeService.exists(child)) + { + return lastError; + } + + String objectId = (String) getProperty(child, CMISDictionaryModel.PROP_OBJECT_ID); + + // First Delete children + for (ChildAssociationRef childRef : nodeService.getChildAssocs(child)) + { + CMISServiceException thisError = deleteTree(childRef, continueOnFailure, unfile, deleteAllVersions, + failedToDelete); + if (thisError != null) + { + lastError = thisError; + if (!continueOnFailure) + { + return lastError; + } + } + } + + // Don't try deleting the parent if we couldn't delete one or more of its children + if (lastError != null) + { + failedToDelete.add(objectId); + return lastError; + } + + // Now delete the parent + try + { + if (unfile && !parentRef.isPrimary()) + { + this.nodeService.removeChildAssociation(parentRef); + } + else + { + deleteObject(objectId, deleteAllVersions); + } + } + catch (AccessDeniedException t) + { + failedToDelete.add(objectId); + lastError = new CMISPermissionDeniedException(t); + } + catch (Throwable t) + { + // Before absorbing an exception, check whether it is a transactional one that should be retried further up + // the stack + if (RetryingTransactionHelper.extractRetryCause(t) != null) + { + throw new AlfrescoRuntimeException("Transactional Error", t); + } + failedToDelete.add(objectId); + lastError = t instanceof CMISServiceException ? (CMISServiceException) t : new CMISRuntimeException(t); + } + + return lastError; + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#addObjectToFolder(java.lang.String, java.lang.String) + */ + public void addObjectToFolder(String objectId, String folderId) throws CMISConstraintException, + CMISVersioningException, CMISObjectNotFoundException, CMISInvalidArgumentException, + CMISPermissionDeniedException + { + try + { + NodeRef objectNodeRef = getObject(objectId, NodeRef.class, true, false, false); + NodeRef parentFolderNodeRef = getFolder(folderId); + CMISTypeDefinition objectType = getTypeDefinition(objectNodeRef); + CMISTypeDefinition folderType = getTypeDefinition(parentFolderNodeRef); + if (!folderType.getAllowedTargetTypes().isEmpty() + && !folderType.getAllowedTargetTypes().contains(objectType)) + { + throw new CMISConstraintException("An object of type '" + objectType.getTypeId() + + "' can't be a child of a folder of type '" + folderType.getTypeId() + "'"); + } + 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); + } + catch (AccessDeniedException e) + { + throw new CMISPermissionDeniedException(e.getMessage(), e); + } + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#removeObjectFromFolder(java.lang.String, java.lang.String) + */ + public void removeObjectFromFolder(String objectId, String folderId) throws CMISNotSupportedException, + CMISConstraintException, CMISVersioningException, CMISObjectNotFoundException, + CMISInvalidArgumentException, CMISPermissionDeniedException + { + try + { + if (folderId == null || folderId.length() == 0) + { + throw new CMISNotSupportedException( + "Unfiling from primary parent folder is not supported. Use deleteObject() instead"); + } + NodeRef objectNodeRef = getObject(objectId, NodeRef.class, true, false, false); + NodeRef parentFolderNodeRef = getFolder(folderId); + if (nodeService.getPrimaryParent(objectNodeRef).getParentRef().equals(parentFolderNodeRef)) + { + throw new CMISNotSupportedException( + "Unfiling from primary parent folder is not supported. Use deleteObject() instead"); + } + nodeService.removeChild(parentFolderNodeRef, objectNodeRef); + } + catch (AccessDeniedException e) + { + throw new CMISPermissionDeniedException(e.getMessage(), e); + } + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#moveObject(java.lang.String, java.lang.String, java.lang.String) + */ + public void moveObject(String objectId, String targetFolderId, String sourceFolderId) + throws CMISConstraintException, CMISVersioningException, CMISObjectNotFoundException, + CMISInvalidArgumentException, CMISPermissionDeniedException + { + try + { + NodeRef objectNodeRef = getObject(objectId, NodeRef.class, true, false, false); + + NodeRef sourceFolderNodeRef; + // We have a specific requirement in the spec to throw invalidArgument for missing source folders, rather + // than objectNotFound + try + { + sourceFolderNodeRef = getFolder(sourceFolderId); + } + catch (CMISObjectNotFoundException e) + { + throw new CMISInvalidArgumentException(e.getMessage(), e); + } + NodeRef targetFolderNodeRef = getFolder(targetFolderId); + CMISFolderTypeDefinition targetTypeDef = (CMISFolderTypeDefinition) getTypeDefinition(targetFolderNodeRef); + + CMISTypeDefinition objectTypeDef = getTypeDefinition(objectNodeRef); + if (!targetTypeDef.getAllowedTargetTypes().isEmpty() + && !targetTypeDef.getAllowedTargetTypes().contains(objectTypeDef)) + { + throw new CMISConstraintException("Object with '" + objectTypeDef.getTypeId() + + "' Type can't be moved to Folder with '" + targetTypeDef.getTypeId() + "' Type"); + } + + // If this is a primary child node, move it + ChildAssociationRef primaryParentRef = nodeService.getPrimaryParent(objectNodeRef); + if (primaryParentRef.getParentRef().equals(sourceFolderNodeRef)) + { + nodeService.moveNode(objectNodeRef, targetFolderNodeRef, primaryParentRef.getTypeQName(), + primaryParentRef.getQName()); + } + else + { + // Otherwise, reparent it + for (ChildAssociationRef parent : nodeService.getParentAssocs(objectNodeRef, + ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL)) + { + if (parent.getParentRef().equals(sourceFolderNodeRef)) + { + nodeService.removeChildAssociation(parent); + nodeService.addChild(targetFolderNodeRef, objectNodeRef, ContentModel.ASSOC_CONTAINS, parent + .getQName()); + return; + } + } + throw new CMISInvalidArgumentException( + "The Document is not a Child of the Source Folder that was specified"); + } + } + catch (AccessDeniedException e) + { + throw new CMISPermissionDeniedException(e.getMessage(), e); + } + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISServices#setContentStream(java.lang.String, org.alfresco.service.namespace.QName, + * boolean, java.io.InputStream, java.lang.String) + */ + public boolean setContentStream(String objectId, QName propertyQName, boolean overwriteFlag, + InputStream contentStream, String mimeType) throws CMISConstraintException, CMISVersioningException, + CMISObjectNotFoundException, CMISContentAlreadyExistsException, CMISStreamNotSupportedException, + CMISInvalidArgumentException, CMISPermissionDeniedException + { + try + { + NodeRef nodeRef = getObject(objectId, NodeRef.class, true, false, false); + + CMISTypeDefinition typeDef = getTypeDefinition(nodeRef); + if (CMISContentStreamAllowedEnum.NOT_ALLOWED.equals(typeDef.getContentStreamAllowed())) + { + throw new CMISStreamNotSupportedException(typeDef); + } + // Alfresco extension for setting the content property + if (propertyQName == null) + { + propertyQName = ContentModel.PROP_CONTENT; + } + + // Determine whether content already exists + boolean existed = contentService.getReader(nodeRef, propertyQName) != null; + if (existed && !overwriteFlag) + { + throw new CMISContentAlreadyExistsException(); + } + + contentStream = contentStream.markSupported() ? contentStream : new BufferedInputStream(contentStream); + + // establish content encoding + ContentCharsetFinder charsetFinder = mimetypeService.getContentCharsetFinder(); + Charset encoding = charsetFinder.getCharset(contentStream, mimeType); + + ContentWriter writer = contentService.getWriter(nodeRef, propertyQName, true); + writer.setMimetype(mimeType); + writer.setEncoding(encoding.name()); + writer.putContent(contentStream); + + return existed; + } + catch (AccessDeniedException e) + { + throw new CMISPermissionDeniedException(e.getMessage(), e); + } + } + + /** + * Validates that a node is versionable. + * + * @param source + * the node + * @throws CMISConstraintException + * if the node is not versionable + * @throws CMISInvalidArgumentException + * if an argument is invalid + */ + private void validateVersionable(NodeRef source) throws CMISConstraintException, CMISInvalidArgumentException + { + CMISTypeDefinition typeDef = getTypeDefinition(source); + if (!typeDef.isVersionable()) + { + throw new CMISConstraintException("Type " + typeDef.getTypeId() + " is not versionable"); + } + } + + /** + * Creates a property map for the version service. + * + * @param versionDescription + * a version description + * @param isMajor + * is this a major version? + * @return the property map + */ + private Map createVersionProperties(String versionDescription, boolean isMajor) + { + Map versionProperties = new HashMap(5); + versionProperties.put(VersionModel.PROP_VERSION_TYPE, isMajor ? VersionType.MAJOR : VersionType.MINOR); + if (versionDescription != null) + { + versionProperties.put(VersionModel.PROP_DESCRIPTION, versionDescription); + } + return versionProperties; + } } diff --git a/source/java/org/alfresco/cmis/mapping/CheckinCommentProperty.java b/source/java/org/alfresco/cmis/mapping/CheckinCommentProperty.java index 3a9bf116c8..866bfdc708 100644 --- a/source/java/org/alfresco/cmis/mapping/CheckinCommentProperty.java +++ b/source/java/org/alfresco/cmis/mapping/CheckinCommentProperty.java @@ -27,16 +27,18 @@ package org.alfresco.cmis.mapping; import java.io.Serializable; import org.alfresco.cmis.CMISDictionaryModel; +import org.alfresco.model.ContentModel; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.version.Version; +import org.alfresco.service.cmr.version.VersionHistory; /** * Accessor for the CMIS Checkin Comment * - * @author andyh + * @author dward */ -public class CheckinCommentProperty extends AbstractProperty +public class CheckinCommentProperty extends AbstractVersioningProperty { /** * Construct @@ -54,14 +56,27 @@ public class CheckinCommentProperty extends AbstractProperty */ public Serializable getValue(NodeRef nodeRef) { - Version version = getServiceRegistry().getVersionService().getCurrentVersion(nodeRef); - if (version != null) - { - return version.getDescription(); - } - else + NodeRef versionSeries; + if (isWorkingCopy(nodeRef) || (versionSeries = getVersionSeries(nodeRef)).equals(nodeRef)) { return null; } + ServiceRegistry serviceRegistry = getServiceRegistry(); + String versionLabel = (String)serviceRegistry.getNodeService().getProperty(nodeRef, ContentModel.PROP_VERSION_LABEL); + if (versionLabel == null) + { + return null; + } + VersionHistory versionHistory = serviceRegistry.getVersionService().getVersionHistory(versionSeries); + if (versionHistory == null) + { + return null; + } + Version version = versionHistory.getVersion(versionLabel); + if (version == null) + { + return null; + } + return version.getDescription(); } } diff --git a/source/java/org/alfresco/cmis/mapping/FixedValueActionEvaluator.java b/source/java/org/alfresco/cmis/mapping/FixedValueActionEvaluator.java index 67509cc0c4..652f6d6e29 100644 --- a/source/java/org/alfresco/cmis/mapping/FixedValueActionEvaluator.java +++ b/source/java/org/alfresco/cmis/mapping/FixedValueActionEvaluator.java @@ -26,7 +26,6 @@ package org.alfresco.cmis.mapping; import org.alfresco.cmis.CMISAllowedActionEnum; import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.repository.NodeRef; /** * Action Evaluator whose evaluation is fixed @@ -34,7 +33,7 @@ import org.alfresco.service.cmr.repository.NodeRef; * @author davidc * */ -public class FixedValueActionEvaluator extends AbstractActionEvaluator +public class FixedValueActionEvaluator extends AbstractActionEvaluator { private boolean allowed; @@ -54,7 +53,7 @@ public class FixedValueActionEvaluator extends AbstractActionEvaluator * (non-Javadoc) * @see org.alfresco.cmis.CMISActionEvaluator#isAllowed(org.alfresco.service.cmr.repository.NodeRef) */ - public boolean isAllowed(NodeRef nodeRef) + public boolean isAllowed(T object) { return allowed; } diff --git a/source/java/org/alfresco/cmis/mapping/IsImmutableProperty.java b/source/java/org/alfresco/cmis/mapping/IsImmutableProperty.java index 033d76e58d..9229d398a2 100644 --- a/source/java/org/alfresco/cmis/mapping/IsImmutableProperty.java +++ b/source/java/org/alfresco/cmis/mapping/IsImmutableProperty.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 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 @@ -18,7 +18,7 @@ * 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 + * 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" */ @@ -27,18 +27,15 @@ package org.alfresco.cmis.mapping; import java.io.Serializable; import org.alfresco.cmis.CMISDictionaryModel; -import org.alfresco.model.ContentModel; import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.lock.LockType; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; /** * Property accessor for CMIS is immutable property * - * @author andyh + * @author dward */ -public class IsImmutableProperty extends AbstractProperty +public class IsImmutableProperty extends AbstractVersioningProperty { /** * Construct @@ -56,20 +53,14 @@ public class IsImmutableProperty extends AbstractProperty */ public Serializable getValue(NodeRef nodeRef) { - LockType type = getServiceRegistry().getLockService().getLockType(nodeRef); - if (type == LockType.READ_ONLY_LOCK) + if (isWorkingCopy(nodeRef)) { - return Boolean.valueOf(true); + return false; } - Serializable value = getServiceRegistry().getNodeService().getProperty(nodeRef, ContentModel.PROP_AUTO_VERSION); - if (value != null) + if (getVersionSeries(nodeRef).equals(nodeRef)) { - Boolean autoVersion = DefaultTypeConverter.INSTANCE.convert(Boolean.class, value); - if (false == autoVersion.booleanValue()) - { - return Boolean.valueOf(true); - } + return hasWorkingCopy(nodeRef); } - return Boolean.valueOf(false); + return true; } } diff --git a/source/java/org/alfresco/cmis/mapping/IsLatestMajorVersionProperty.java b/source/java/org/alfresco/cmis/mapping/IsLatestMajorVersionProperty.java index c90f888828..958140745c 100644 --- a/source/java/org/alfresco/cmis/mapping/IsLatestMajorVersionProperty.java +++ b/source/java/org/alfresco/cmis/mapping/IsLatestMajorVersionProperty.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 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 @@ -18,7 +18,7 @@ * 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 + * 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" */ @@ -27,18 +27,19 @@ package org.alfresco.cmis.mapping; import java.io.Serializable; import org.alfresco.cmis.CMISDictionaryModel; -import org.alfresco.model.ContentModel; import org.alfresco.service.ServiceRegistry; 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.VersionService; import org.alfresco.service.cmr.version.VersionType; /** * Accessor for CMIS is latest major version property * - * @author andyh + * @author dward */ -public class IsLatestMajorVersionProperty extends AbstractProperty +public class IsLatestMajorVersionProperty extends AbstractVersioningProperty { /** * Construct @@ -57,21 +58,33 @@ public class IsLatestMajorVersionProperty extends AbstractProperty */ public Serializable getValue(NodeRef nodeRef) { - if (getServiceRegistry().getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY)) + NodeRef versionSeries; + if (isWorkingCopy(nodeRef) || (versionSeries = getVersionSeries(nodeRef)).equals(nodeRef)) { return false; } - else + ServiceRegistry serviceRegistry = getServiceRegistry(); + VersionService versionService = serviceRegistry.getVersionService(); + VersionHistory versionHistory = versionService.getVersionHistory(versionSeries); + if (versionHistory == null) { - Version version = getServiceRegistry().getVersionService().getCurrentVersion(nodeRef); - if (version != null) + return false; + } + // Go back in time to the last major version + Version currentVersion = versionService.getCurrentVersion(versionSeries); + while (currentVersion != null) + { + if (currentVersion.getVersionType() == VersionType.MAJOR) { - return (version.getVersionType() == VersionType.MAJOR); + return currentVersion.getFrozenStateNodeRef().equals(nodeRef); } - else + // We got to the current node and its not major. We failed! + else if (currentVersion.getFrozenStateNodeRef().equals(nodeRef)) { return false; } + currentVersion = versionHistory.getPredecessor(currentVersion); } + return false; } } diff --git a/source/java/org/alfresco/cmis/mapping/IsLatestVersionProperty.java b/source/java/org/alfresco/cmis/mapping/IsLatestVersionProperty.java index 92fd5de954..877994964d 100644 --- a/source/java/org/alfresco/cmis/mapping/IsLatestVersionProperty.java +++ b/source/java/org/alfresco/cmis/mapping/IsLatestVersionProperty.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 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 @@ -18,7 +18,7 @@ * 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 + * 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" */ @@ -27,16 +27,15 @@ package org.alfresco.cmis.mapping; import java.io.Serializable; import org.alfresco.cmis.CMISDictionaryModel; -import org.alfresco.model.ContentModel; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; /** * Accesser for CMIS is latest version property * - * @author andyh + * @author dward */ -public class IsLatestVersionProperty extends AbstractProperty +public class IsLatestVersionProperty extends AbstractVersioningProperty { /** * Construct @@ -54,6 +53,6 @@ public class IsLatestVersionProperty extends AbstractProperty */ public Serializable getValue(NodeRef nodeRef) { - return !getServiceRegistry().getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY); + return isWorkingCopy(nodeRef) || getVersionSeries(nodeRef).equals(nodeRef) && !hasWorkingCopy(nodeRef); } } diff --git a/source/java/org/alfresco/cmis/mapping/IsMajorVersionProperty.java b/source/java/org/alfresco/cmis/mapping/IsMajorVersionProperty.java index 4b0e1903ae..c4084bd84b 100644 --- a/source/java/org/alfresco/cmis/mapping/IsMajorVersionProperty.java +++ b/source/java/org/alfresco/cmis/mapping/IsMajorVersionProperty.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 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 @@ -18,7 +18,7 @@ * 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 + * 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" */ @@ -30,15 +30,15 @@ import org.alfresco.cmis.CMISDictionaryModel; import org.alfresco.model.ContentModel; import org.alfresco.service.ServiceRegistry; 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; /** * Accessor for CMIS is major version property * - * @author andyh + * @author dward */ -public class IsMajorVersionProperty extends AbstractProperty +public class IsMajorVersionProperty extends AbstractVersioningProperty { /** * Construct @@ -56,21 +56,23 @@ public class IsMajorVersionProperty extends AbstractProperty */ public Serializable getValue(NodeRef nodeRef) { - if (getServiceRegistry().getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY)) + NodeRef versionSeries; + if (isWorkingCopy(nodeRef) || (versionSeries = getVersionSeries(nodeRef)).equals(nodeRef)) { return false; } - else + ServiceRegistry serviceRegistry = getServiceRegistry(); + String versionLabel = (String) serviceRegistry.getNodeService().getProperty(nodeRef, + ContentModel.PROP_VERSION_LABEL); + if (versionLabel == null) { - Version version = getServiceRegistry().getVersionService().getCurrentVersion(nodeRef); - if (version != null) - { - return (version.getVersionType() == VersionType.MAJOR); - } - else - { - return false; - } + return false; } + VersionHistory versionHistory = serviceRegistry.getVersionService().getVersionHistory(versionSeries); + if (versionHistory == null) + { + return false; + } + return versionHistory.getVersion(versionLabel).getVersionType() == VersionType.MAJOR; } } diff --git a/source/java/org/alfresco/cmis/mapping/IsVersionSeriesCheckedOutProperty.java b/source/java/org/alfresco/cmis/mapping/IsVersionSeriesCheckedOutProperty.java index 5989c9a4b0..e39fe18414 100644 --- a/source/java/org/alfresco/cmis/mapping/IsVersionSeriesCheckedOutProperty.java +++ b/source/java/org/alfresco/cmis/mapping/IsVersionSeriesCheckedOutProperty.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 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 @@ -18,7 +18,7 @@ * 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 + * 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" */ @@ -27,17 +27,15 @@ package org.alfresco.cmis.mapping; import java.io.Serializable; import org.alfresco.cmis.CMISDictionaryModel; -import org.alfresco.model.ContentModel; import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.lock.LockType; import org.alfresco.service.cmr.repository.NodeRef; /** * Get the CMIS version series checked out property * - * @author andyh + * @author dward */ -public class IsVersionSeriesCheckedOutProperty extends AbstractProperty +public class IsVersionSeriesCheckedOutProperty extends AbstractVersioningProperty { /** * Construct @@ -55,22 +53,6 @@ public class IsVersionSeriesCheckedOutProperty extends AbstractProperty */ public Serializable getValue(NodeRef nodeRef) { - if (getServiceRegistry().getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY)) - { - return true; - } - else - { - LockType type = getServiceRegistry().getLockService().getLockType(nodeRef); - if (type == LockType.READ_ONLY_LOCK) - { - NodeRef wc = getServiceRegistry().getCheckOutCheckInService().getWorkingCopy(nodeRef); - return (wc != null); - } - else - { - return false; - } - } + return isWorkingCopy(nodeRef) || hasWorkingCopy(getVersionSeries(nodeRef)); } } diff --git a/source/java/org/alfresco/cmis/mapping/ObjectIdProperty.java b/source/java/org/alfresco/cmis/mapping/ObjectIdProperty.java index 0c7c1b2b2c..35d8f4d59a 100644 --- a/source/java/org/alfresco/cmis/mapping/ObjectIdProperty.java +++ b/source/java/org/alfresco/cmis/mapping/ObjectIdProperty.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 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 @@ -18,7 +18,7 @@ * 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 + * 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" */ @@ -29,6 +29,7 @@ import java.util.Collection; import org.alfresco.cmis.CMISDictionaryModel; import org.alfresco.cmis.CMISQueryException; +import org.alfresco.cmis.CMISServices; import org.alfresco.model.ContentModel; import org.alfresco.repo.search.impl.lucene.AnalysisMode; import org.alfresco.repo.search.impl.lucene.LuceneFunction; @@ -51,8 +52,9 @@ import org.apache.lucene.search.BooleanClause.Occur; * Get the CMIS object id property. * * @author andyh + * @author dward */ -public class ObjectIdProperty extends AbstractProperty +public class ObjectIdProperty extends AbstractVersioningProperty { /** * Construct @@ -70,24 +72,17 @@ public class ObjectIdProperty extends AbstractProperty */ public Serializable getValue(NodeRef nodeRef) { - if (!getServiceRegistry().getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY)) + NodeRef versionSeries; + if (isWorkingCopy(nodeRef) || (versionSeries = getVersionSeries(nodeRef)).equals(nodeRef)) { - if (getServiceRegistry().getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE)) - { - Serializable value = getServiceRegistry().getNodeService().getProperty(nodeRef, ContentModel.PROP_VERSION_LABEL); - if (value != null) - { - String versionLabel = DefaultTypeConverter.INSTANCE.convert(String.class, value); - StringBuilder builder = new StringBuilder(128); - builder.append(nodeRef.toString()); - builder.append(";"); - builder.append(versionLabel); - return builder.toString(); - } - } + return nodeRef.toString(); + } + else + { + return new StringBuilder(1024).append(versionSeries.toString()).append(';').append( + getServiceRegistry().getNodeService().getProperty(nodeRef, ContentModel.PROP_VERSION_LABEL)) + .toString(); } - - return nodeRef.toString(); } /* @@ -96,8 +91,7 @@ public class ObjectIdProperty extends AbstractProperty */ public Serializable getValue(AssociationRef assocRef) { - // TODO: determine appropriate id for associations - return assocRef.getSourceRef().toString(); + return CMISServices.ASSOC_ID_PREFIX + assocRef.getId(); } public String getLuceneFieldName() diff --git a/source/java/org/alfresco/cmis/mapping/ParentActionEvaluator.java b/source/java/org/alfresco/cmis/mapping/ParentActionEvaluator.java index d73d44ff67..0c7a48709a 100644 --- a/source/java/org/alfresco/cmis/mapping/ParentActionEvaluator.java +++ b/source/java/org/alfresco/cmis/mapping/ParentActionEvaluator.java @@ -32,9 +32,9 @@ import org.alfresco.service.cmr.repository.NodeRef; * * @author davidc */ -public class ParentActionEvaluator extends AbstractActionEvaluator +public class ParentActionEvaluator extends AbstractActionEvaluator { - private AbstractActionEvaluator evaluator; + private AbstractActionEvaluator evaluator; /** * Construct @@ -42,7 +42,7 @@ public class ParentActionEvaluator extends AbstractActionEvaluator * @param serviceRegistry * @param action */ - protected ParentActionEvaluator(AbstractActionEvaluator evaluator) + protected ParentActionEvaluator(AbstractActionEvaluator evaluator) { super(evaluator.getServiceRegistry(), evaluator.getAction()); this.evaluator = evaluator; diff --git a/source/java/org/alfresco/cmis/mapping/PermissionActionEvaluator.java b/source/java/org/alfresco/cmis/mapping/PermissionActionEvaluator.java index dd68cd418c..ed14528fdc 100644 --- a/source/java/org/alfresco/cmis/mapping/PermissionActionEvaluator.java +++ b/source/java/org/alfresco/cmis/mapping/PermissionActionEvaluator.java @@ -35,7 +35,7 @@ import org.alfresco.service.cmr.security.PermissionService; * * @author davidc */ -public class PermissionActionEvaluator extends AbstractActionEvaluator +public class PermissionActionEvaluator extends AbstractActionEvaluator { private String[] permissions; private PermissionService permissionService; diff --git a/source/java/org/alfresco/cmis/reference/AVMPathReference.java b/source/java/org/alfresco/cmis/mapping/VersionLabelProperty.java similarity index 55% rename from source/java/org/alfresco/cmis/reference/AVMPathReference.java rename to source/java/org/alfresco/cmis/mapping/VersionLabelProperty.java index 6327bcf87a..4bf3fb3c7b 100644 --- a/source/java/org/alfresco/cmis/reference/AVMPathReference.java +++ b/source/java/org/alfresco/cmis/mapping/VersionLabelProperty.java @@ -1,66 +1,68 @@ -/* - * Copyright (C) 2005-2007 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.cmis.reference; - -import org.alfresco.cmis.CMISRepositoryReference; -import org.alfresco.cmis.CMISServices; -import org.alfresco.service.cmr.repository.NodeRef; - - -/** - * AVM Path Reference - * - * @author davidc - */ -public class AVMPathReference extends ObjectPathReference -{ - /** - * Construct - * - * @param cmisServices - * @param repo - * @param path - */ - public AVMPathReference(CMISServices cmisServices, CMISRepositoryReference repo, String path) - { - super(cmisServices, repo, path); - } - - /* - * (non-Javadoc) - * @see org.alfresco.cmis.reference.ObjectPathReference#getNodeRef() - */ - public NodeRef getNodeRef() - { - return cmisServices.getNode("avmpath", reference); - } - - @Override - public String toString() - { - return "AVMPathReference[storeRef=" + repo.getStoreRef() + ",path=" + path + "]"; - } - -} +/* + * 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 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.cmis.mapping; + +import java.io.Serializable; + +import org.alfresco.cmis.CMISDictionaryModel; +import org.alfresco.model.ContentModel; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * @author dward + */ +public class VersionLabelProperty extends AbstractVersioningProperty +{ + /** + * Construct + * + * @param serviceRegistry + */ + public VersionLabelProperty(ServiceRegistry serviceRegistry) + { + super(serviceRegistry, CMISDictionaryModel.PROP_VERSION_LABEL); + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.property.PropertyAccessor#getValue(org.alfresco.service.cmr.repository.NodeRef) + */ + public Serializable getValue(NodeRef nodeRef) + { + if (isWorkingCopy(nodeRef)) + { + return "pwc"; + } + if (getVersionSeries(nodeRef).equals(nodeRef)) + { + return "current"; + } + else + { + return getServiceRegistry().getNodeService().getProperty(nodeRef, ContentModel.PROP_VERSION_LABEL); + } + } +} diff --git a/source/java/org/alfresco/cmis/mapping/VersionSeriesCheckedOutByProperty.java b/source/java/org/alfresco/cmis/mapping/VersionSeriesCheckedOutByProperty.java index a1218770ee..2be20843f3 100644 --- a/source/java/org/alfresco/cmis/mapping/VersionSeriesCheckedOutByProperty.java +++ b/source/java/org/alfresco/cmis/mapping/VersionSeriesCheckedOutByProperty.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 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 @@ -18,7 +18,7 @@ * 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 + * 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" */ @@ -29,15 +29,14 @@ import java.io.Serializable; import org.alfresco.cmis.CMISDictionaryModel; import org.alfresco.model.ContentModel; import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.lock.LockType; import org.alfresco.service.cmr.repository.NodeRef; /** * Get the CMIS version series checked out by property * - * @author andyh + * @author dward */ -public class VersionSeriesCheckedOutByProperty extends AbstractProperty +public class VersionSeriesCheckedOutByProperty extends AbstractVersioningProperty { /** * Construct @@ -55,29 +54,15 @@ public class VersionSeriesCheckedOutByProperty extends AbstractProperty */ public Serializable getValue(NodeRef nodeRef) { - if (getServiceRegistry().getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY)) + NodeRef versionSeries; + if (isWorkingCopy(nodeRef)) { return getServiceRegistry().getNodeService().getProperty(nodeRef, ContentModel.PROP_WORKING_COPY_OWNER); } - else + else if (hasWorkingCopy((versionSeries = getVersionSeries(nodeRef)))) { - LockType type = getServiceRegistry().getLockService().getLockType(nodeRef); - if (type == LockType.READ_ONLY_LOCK) - { - NodeRef wc = getServiceRegistry().getCheckOutCheckInService().getWorkingCopy(nodeRef); - if (wc != null) - { - return getServiceRegistry().getNodeService().getProperty(nodeRef, ContentModel.PROP_LOCK_OWNER); - } - else - { - return null; - } - } - else - { - return null; - } + return getServiceRegistry().getNodeService().getProperty(versionSeries, ContentModel.PROP_LOCK_OWNER); } + return null; } } diff --git a/source/java/org/alfresco/cmis/mapping/VersionSeriesCheckedOutIdProperty.java b/source/java/org/alfresco/cmis/mapping/VersionSeriesCheckedOutIdProperty.java index a298afb6e4..baf90bad99 100644 --- a/source/java/org/alfresco/cmis/mapping/VersionSeriesCheckedOutIdProperty.java +++ b/source/java/org/alfresco/cmis/mapping/VersionSeriesCheckedOutIdProperty.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 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 @@ -18,7 +18,7 @@ * 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 + * 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" */ @@ -27,17 +27,15 @@ package org.alfresco.cmis.mapping; import java.io.Serializable; import org.alfresco.cmis.CMISDictionaryModel; -import org.alfresco.model.ContentModel; import org.alfresco.service.ServiceRegistry; -import org.alfresco.service.cmr.lock.LockType; import org.alfresco.service.cmr.repository.NodeRef; /** * Get the CMIS version series checked out id property * - * @author andyh + * @author dward */ -public class VersionSeriesCheckedOutIdProperty extends AbstractProperty +public class VersionSeriesCheckedOutIdProperty extends AbstractVersioningProperty { /** * Construct @@ -55,22 +53,19 @@ public class VersionSeriesCheckedOutIdProperty extends AbstractProperty */ public Serializable getValue(NodeRef nodeRef) { - if (getServiceRegistry().getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY)) + NodeRef versionSeries; + if (isWorkingCopy(nodeRef)) { return nodeRef.toString(); } - else + else if (hasWorkingCopy((versionSeries = getVersionSeries(nodeRef)))) { - LockType type = getServiceRegistry().getLockService().getLockType(nodeRef); - if (type == LockType.READ_ONLY_LOCK) + NodeRef pwc = getServiceRegistry().getCheckOutCheckInService().getWorkingCopy(versionSeries); + if (pwc != null) { - NodeRef pwc = getServiceRegistry().getCheckOutCheckInService().getWorkingCopy(nodeRef); - return (pwc == null) ? null : pwc.toString(); - } - else - { - return null; + return pwc.toString(); } } + return null; } } diff --git a/source/java/org/alfresco/cmis/mapping/VersionSeriesIdProperty.java b/source/java/org/alfresco/cmis/mapping/VersionSeriesIdProperty.java index 2b17db7ecd..37ede68a82 100644 --- a/source/java/org/alfresco/cmis/mapping/VersionSeriesIdProperty.java +++ b/source/java/org/alfresco/cmis/mapping/VersionSeriesIdProperty.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2007 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 @@ -18,7 +18,7 @@ * 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 + * 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" */ @@ -30,11 +30,12 @@ import org.alfresco.cmis.CMISDictionaryModel; import org.alfresco.model.ContentModel; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; /** - * @author andyh + * @author dward */ -public class VersionSeriesIdProperty extends AbstractProperty +public class VersionSeriesIdProperty extends AbstractVersioningProperty { /** * Construct @@ -52,11 +53,14 @@ public class VersionSeriesIdProperty extends AbstractProperty */ public Serializable getValue(NodeRef nodeRef) { - if (getServiceRegistry().getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY)) + NodeService nodeService = getServiceRegistry().getNodeService(); + if (isWorkingCopy(nodeRef)) { - Serializable seriesId = getServiceRegistry().getNodeService().getProperty(nodeRef, ContentModel.PROP_COPY_REFERENCE); - return (seriesId != null) ? seriesId.toString() : null; + return nodeService.getProperty(nodeRef, ContentModel.PROP_COPY_REFERENCE).toString(); + } + else + { + return getVersionSeries(nodeRef).toString(); } - return nodeRef.toString(); } } diff --git a/source/java/org/alfresco/cmis/reference/NodeRefReference.java b/source/java/org/alfresco/cmis/reference/NodeRefReference.java deleted file mode 100644 index 03f524754e..0000000000 --- a/source/java/org/alfresco/cmis/reference/NodeRefReference.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2005-2007 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.cmis.reference; - -import java.util.regex.Pattern; - -import org.alfresco.cmis.CMISObjectReference; -import org.alfresco.cmis.CMISRepositoryReference; -import org.alfresco.cmis.CMISServices; -import org.alfresco.service.cmr.repository.NodeRef; - -/** - * NodeRef Object Reference - * - * NOTE: Also takes into account versioned NodeRefs - protocol://store/id;version - * - * @author davidc - */ -public class NodeRefReference implements CMISObjectReference -{ - // versioned objectId pattern - // TODO: encapsulate elsewhere - private static final Pattern versionedNodeRefPattern = Pattern.compile(".+://.+/.+;.+"); - private ObjectIdReference reference; - - /** - * Construct - * - * @param cmisServices - * @param nodeRef - * @param version - */ - public NodeRefReference(CMISServices cmisServices, NodeRef nodeRef, String version) - { - CMISRepositoryReference repo = new StoreRepositoryReference(cmisServices, nodeRef.getStoreRef()); - reference = new ObjectIdReference(cmisServices, repo, nodeRef.getId() + ";" + version); - } - - /** - * Construct - * - * @param cmisServices - * @param nodeRefStr - */ - public NodeRefReference(CMISServices cmisServices, String nodeRefStr) - { - NodeRef nodeRef; - String version = null; - if (versionedNodeRefPattern.matcher(nodeRefStr).matches()) - { - int vIdx = nodeRefStr.lastIndexOf(";"); - nodeRef = new NodeRef(nodeRefStr.substring(0, vIdx)); - version = nodeRefStr.substring(vIdx +1); - } - else - { - nodeRef = new NodeRef(nodeRefStr); - } - - CMISRepositoryReference repo = new StoreRepositoryReference(cmisServices, nodeRef.getStoreRef()); - reference = new ObjectIdReference(cmisServices, repo, nodeRef.getId() + ";" + version); - } - - /* - * (non-Javadoc) - * @see org.alfresco.cmis.CMISObjectReference#getRepositoryReference() - */ - public CMISRepositoryReference getRepositoryReference() - { - return reference.getRepositoryReference(); - } - - /* - * (non-Javadoc) - * @see org.alfresco.cmis.CMISObjectReference#getNodeRef() - */ - public NodeRef getNodeRef() - { - return reference.getNodeRef(); - } - - @Override - public String toString() - { - return reference.toString(); - } - -} diff --git a/source/java/org/alfresco/cmis/reference/ObjectIdReference.java b/source/java/org/alfresco/cmis/reference/ObjectIdReference.java deleted file mode 100644 index d3e1ba066d..0000000000 --- a/source/java/org/alfresco/cmis/reference/ObjectIdReference.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2005-2007 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.cmis.reference; - -import org.alfresco.cmis.CMISRepositoryReference; -import org.alfresco.cmis.CMISServices; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.StoreRef; - - -/** - * GUID Object Reference - * - * @author davidc - */ -public class ObjectIdReference extends AbstractObjectReference -{ - private String id; - private String version; - private String[] reference; - - /** - * Construct - * - * @param cmisServices - * @param repo - * @param id - */ - public ObjectIdReference(CMISServices cmisServices, CMISRepositoryReference repo, String id) - { - super(cmisServices, repo); - - int vIdx = id.lastIndexOf(";"); - if (vIdx != -1) - { - this.id = id.substring(0, vIdx); - this.version = id.substring(vIdx +1); - } - else - { - this.id = id; - this.version = null; - } - - StoreRef storeRef = repo.getStoreRef(); - String[] idParts = this.id.split("/"); - reference = new String[2 + idParts.length]; - reference[0] = storeRef.getProtocol(); - reference[1] = storeRef.getIdentifier(); - System.arraycopy(idParts, 0, reference, 2, idParts.length); - } - - /* - * (non-Javadoc) - * @see org.alfresco.cmis.CMISObjectReference#getNodeRef() - */ - public NodeRef getNodeRef() - { - return cmisServices.getNode("node", reference); - } - - /** - * @return id - */ - public String getId() - { - return id; - } - - @Override - public String toString() - { - return "ObjectIdReference[storeRef=" + repo.getStoreRef() + ",id=" + id + ",v=" + (version == null ? "" : version) + "]"; - } - -} diff --git a/source/java/org/alfresco/cmis/reference/ObjectPathReference.java b/source/java/org/alfresco/cmis/reference/ObjectPathReference.java deleted file mode 100644 index c8002f540a..0000000000 --- a/source/java/org/alfresco/cmis/reference/ObjectPathReference.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2005-2007 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.cmis.reference; - -import org.alfresco.cmis.CMISRepositoryReference; -import org.alfresco.cmis.CMISServices; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.StoreRef; - - -/** - * Path Object Reference - * - * @author davidc - */ -public class ObjectPathReference extends AbstractObjectReference -{ - protected String path; - protected String[] reference; - - /** - * Construct - * - * @param cmisServices - * @param repo - * @param path - */ - public ObjectPathReference(CMISServices cmisServices, CMISRepositoryReference repo, String path) - { - super(cmisServices, repo); - this.path = path.startsWith("/") ? path : "/" + path; - this.path = (!cmisServices.getDefaultRootPath().equals("/")) ? cmisServices.getDefaultRootPath() + this.path : this.path; - String[] splitPath = this.path.split("/"); - String[] pathSegments = new String[splitPath.length -1]; - System.arraycopy(splitPath, 1, pathSegments, 0, splitPath.length -1); - this.reference = new String[2 + pathSegments.length]; - StoreRef storeRef = repo.getStoreRef(); - reference[0] = storeRef.getProtocol(); - reference[1] = storeRef.getIdentifier(); - System.arraycopy(pathSegments, 0, reference, 2, pathSegments.length); - } - - /* - * (non-Javadoc) - * @see org.alfresco.cmis.CMISObjectReference#getNodeRef() - */ - public NodeRef getNodeRef() - { - return cmisServices.getNode("path", reference); - } - - /** - * @return path - */ - public String getPath() - { - return path; - } - - @Override - public String toString() - { - return "ObjectPathReference[storeRef=" + repo.getStoreRef() + ",path=" + path + "]"; - } - -} diff --git a/source/java/org/alfresco/cmis/reference/ReferenceFactory.java b/source/java/org/alfresco/cmis/reference/ReferenceFactory.java deleted file mode 100644 index 95976d3746..0000000000 --- a/source/java/org/alfresco/cmis/reference/ReferenceFactory.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2005-2007 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.cmis.reference; - -import java.util.Map; - -import org.alfresco.cmis.CMISDictionaryModel; -import org.alfresco.cmis.CMISDictionaryService; -import org.alfresco.cmis.CMISObjectReference; -import org.alfresco.cmis.CMISRelationshipReference; -import org.alfresco.cmis.CMISRepositoryReference; -import org.alfresco.cmis.CMISServices; -import org.alfresco.cmis.CMISTypeDefinition; -import org.alfresco.error.AlfrescoRuntimeException; - - -/** - * Reference Factory - * - * @author davidc - */ -public class ReferenceFactory -{ - private CMISServices cmisService; - private CMISDictionaryService cmisDictionary; - - /** - * @param cmisService - */ - public void setCMISService(CMISServices cmisService) - { - this.cmisService = cmisService; - } - - /** - * @param cmisDictionary - */ - public void setCMISDictionaryService(CMISDictionaryService cmisDictionary) - { - this.cmisDictionary = cmisDictionary; - } - - /** - * Create CMIS Repository Reference from URL segments - * - * @param args url arguments - * @param templateArgs url template arguments - * @return Repository Reference (or null, in case of bad url) - */ - public CMISRepositoryReference createRepoReferenceFromUrl(Map args, Map templateArgs) - { - String store_type = templateArgs.get("store_type"); - String store_id = templateArgs.get("store_id"); - if (store_type != null && store_id != null) - { - return new StoreRepositoryReference(cmisService, store_type + ":" + store_id); - } - - String store = templateArgs.get("store"); - if (store != null) - { - return new StoreRepositoryReference(cmisService, store); - } - - // TODO: repository id -// String repoId = templateArgs.get("repo"); -// else if (repoId != null) -// { -// } - - return new DefaultRepositoryReference(cmisService); - } - - /** - * Create CMIS Object Reference from URL segments - * - * @param args url arguments - * @param templateArgs url template arguments - * @return Repository Reference (or null, in case of bad url) - */ - public CMISObjectReference createObjectReferenceFromUrl(Map args, Map templateArgs) - { - String nodeRef = args.get("noderef"); - if (nodeRef != null) - { - return new NodeRefReference(cmisService, nodeRef); - } - - CMISRepositoryReference repo = createRepoReferenceFromUrl(args, templateArgs); - String id = templateArgs.get("id"); - if (id != null) - { - return new ObjectIdReference(cmisService, repo, id); - } - - String path = templateArgs.get("path"); - if (path == null) - { - path = args.get("path"); - } - if (path != null) - { - return new ObjectPathReference(cmisService, repo, path); - } - - String avmPath = templateArgs.get("avmpath"); - if (avmPath != null) - { - return new AVMPathReference(cmisService, repo, avmPath); - } - - return null; - } - - /** - * Create CMIS Relationship Reference from URL segments - * - * @param args url arguments - * @param templateArgs url template arguments - * @return Repository Reference (or null, in case of bad url) - */ - public CMISRelationshipReference createRelationshipReferenceFromUrl(Map args, Map templateArgs) - { - // retrieve relationship type definition - CMISTypeDefinition typeDefinition = null; - String relType = templateArgs.get("rel_type"); - if (relType != null) - { - try - { - typeDefinition = cmisDictionary.findType(relType); - } - catch(AlfrescoRuntimeException e) {} - } - if (typeDefinition == null) - { - return null; - } - if (!typeDefinition.getBaseType().getTypeId().equals(CMISDictionaryModel.RELATIONSHIP_TYPE_ID)) - { - return null; - } - - // retrieve source / target nodes - String srcStore = templateArgs.get("store"); - String srcId = templateArgs.get("id"); - String tgtStore = templateArgs.get("target_store"); - String tgtId = templateArgs.get("target_id"); - - if (srcStore != null && srcId != null && tgtStore != null && tgtId != null) - { - return new SourceTypeTargetRelationshipReference(cmisService, typeDefinition, srcStore, srcId, tgtStore, tgtId); - } - - return null; - } - -} diff --git a/source/java/org/alfresco/cmis/reference/SourceTypeTargetRelationshipReference.java b/source/java/org/alfresco/cmis/reference/SourceTypeTargetRelationshipReference.java deleted file mode 100644 index 950311c016..0000000000 --- a/source/java/org/alfresco/cmis/reference/SourceTypeTargetRelationshipReference.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2005-2007 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.cmis.reference; - -import org.alfresco.cmis.CMISRelationshipReference; -import org.alfresco.cmis.CMISRepositoryReference; -import org.alfresco.cmis.CMISServices; -import org.alfresco.cmis.CMISTypeDefinition; -import org.alfresco.service.cmr.repository.AssociationRef; -import org.alfresco.service.cmr.repository.NodeRef; - - -/** - * Source Node / Rel Type / Target Node Relationship Reference - * - * @author davidc - */ -public class SourceTypeTargetRelationshipReference implements CMISRelationshipReference -{ - protected CMISServices cmisServices; - protected StoreRepositoryReference repo; - protected CMISTypeDefinition type; - protected NodeRef source; - protected NodeRef target; - - - /** - * Construct - * - * @param cmisServices - * @param type - * @param srcStore - * @param srcId - * @param tgtStore - * @param tgtId - */ - public SourceTypeTargetRelationshipReference(CMISServices cmisServices, CMISTypeDefinition type, String srcStore, String srcId, String tgtStore, String tgtId) - { - this.cmisServices = cmisServices; - this.repo = new StoreRepositoryReference(cmisServices, srcStore); - this.type = type; - this.source = new NodeRef(repo.getStoreRef(), srcId); - StoreRepositoryReference tgtStoreRef = new StoreRepositoryReference(cmisServices, tgtStore); - this.target = new NodeRef(tgtStoreRef.getStoreRef(), tgtId); - } - - /* - * (non-Javadoc) - * @see org.alfresco.cmis.CMISRelationshipReference#getRepositoryReference() - */ - public CMISRepositoryReference getRepositoryReference() - { - return repo; - } - - /* - * (non-Javadoc) - * @see org.alfresco.cmis.CMISRelationshipReference#getAssocRef() - */ - public AssociationRef getAssocRef() - { - return cmisServices.getRelationship(type, source, target); - } - - @Override - public String toString() - { - return "SourceTypeTargetRelationshipReference[type=" + type.getTypeId().getId() + ",source=" + source.toString() + ",target=" + target.toString() + "]"; - } - -} diff --git a/source/java/org/alfresco/cmis/reference/StoreRepositoryReference.java b/source/java/org/alfresco/cmis/reference/StoreRepositoryReference.java deleted file mode 100644 index 4fa3bc8eef..0000000000 --- a/source/java/org/alfresco/cmis/reference/StoreRepositoryReference.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2005-2007 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.cmis.reference; - -import org.alfresco.cmis.CMISServices; -import org.alfresco.service.cmr.repository.StoreRef; - - -/** - * Store Ref Repository Reference - * - * @author davidc - */ -public class StoreRepositoryReference extends AbstractRepositoryReference -{ - private StoreRef storeRef; - - /** - * Construct - * - * @param cmisServices - * @param storeRef - */ - public StoreRepositoryReference(CMISServices cmisServices, StoreRef storeRef) - { - super(cmisServices); - this.storeRef = storeRef; - } - - /** - * Construct - * - * @param cmisServices - * @param store accept storeType://storeId, storeType:storeId, storeId - */ - public StoreRepositoryReference(CMISServices cmisServices, String store) - { - super(cmisServices); - - if (store.indexOf(StoreRef.URI_FILLER) != -1) - { - storeRef = new StoreRef(store); - } - else if (store.indexOf(':') != -1) - { - String[] storeParts = store.split(":"); - storeRef = new StoreRef(storeParts[0], storeParts[1]); - } - else - { - storeRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, store); - } - } - - /* - * (non-Javadoc) - * @see org.alfresco.cmis.CMISRepositoryReference#getStoreRef() - */ - public StoreRef getStoreRef() - { - return storeRef; - } - -} diff --git a/source/java/org/alfresco/cmis/renditions/CMISRenditionServiceImpl.java b/source/java/org/alfresco/cmis/renditions/CMISRenditionServiceImpl.java index 089a6322e2..fca5b5a672 100755 --- a/source/java/org/alfresco/cmis/renditions/CMISRenditionServiceImpl.java +++ b/source/java/org/alfresco/cmis/renditions/CMISRenditionServiceImpl.java @@ -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 @@ -33,6 +33,7 @@ import java.util.Map; import java.util.Set; import java.util.Map.Entry; +import org.alfresco.cmis.CMISFilterNotValidException; import org.alfresco.cmis.CMISRendition; import org.alfresco.cmis.CMISRenditionKind; import org.alfresco.cmis.CMISRenditionService; @@ -73,9 +74,10 @@ public class CMISRenditionServiceImpl implements CMISRenditionService private CustomRenditionsCache customRenditionsCache; /** + * @throws CMISFilterNotValidException * @see org.alfresco.cmis.CMISRenditionService#getRenditions(org.alfresco.service.cmr.repository.NodeRef, java.lang.String) */ - public List getRenditions(NodeRef node, String renditionFilter) + public List getRenditions(NodeRef node, String renditionFilter) throws CMISFilterNotValidException { Collection result = null; ThumbnailFilter thumbnailFilter = getThumbnailFilter(renditionFilter); @@ -171,12 +173,21 @@ public class CMISRenditionServiceImpl implements CMISRenditionService * * @param renditionFilter rendition filter * @return thumbnail filter + * @throws CMISFilterNotValidException */ - private ThumbnailFilter getThumbnailFilter(String renditionFilter) + private ThumbnailFilter getThumbnailFilter(String renditionFilter) throws CMISFilterNotValidException { ThumbnailFilter result = null; if (renditionFilter != null && !renditionFilter.equals(FILTER_NONE)) { + // Scan the filter for whitespace, which is disallowed by the spec + for (int i=0; i < renditionFilter.length(); i = renditionFilter.offsetByCodePoints(i, 1)) + { + if (Character.isWhitespace(renditionFilter.codePointAt(i))) + { + throw new CMISFilterNotValidException(renditionFilter); + } + } result = new ThumbnailFilter(); if (renditionFilter.equals(FILTER_WILDCARD)) { diff --git a/source/java/org/alfresco/cmis/renditions/CMISRenditionServiceTest.java b/source/java/org/alfresco/cmis/renditions/CMISRenditionServiceTest.java index 5475713c97..a7aba94b3a 100755 --- a/source/java/org/alfresco/cmis/renditions/CMISRenditionServiceTest.java +++ b/source/java/org/alfresco/cmis/renditions/CMISRenditionServiceTest.java @@ -70,7 +70,7 @@ public class CMISRenditionServiceTest extends BaseCMISTest } } - public void testGetAllRenditions() + public void testGetAllRenditions() throws Exception { List receivedRenditions = cmisRenditionService.getRenditions(document, "*"); @@ -82,7 +82,7 @@ public class CMISRenditionServiceTest extends BaseCMISTest assertRendiions(receivedRenditions, expectedRenditions); } - public void testGetRenditionsByKind() + public void testGetRenditionsByKind() throws Exception { testGetRenditionsByKind(CMISRenditionKind.THUMBNAIL); testGetRenditionsByKind(CMISRenditionKind.WEB_PREVIEW); @@ -93,7 +93,7 @@ public class CMISRenditionServiceTest extends BaseCMISTest testGetRenditionsByKind(CMISRenditionKind.THUMBNAIL, CMISRenditionKind.WEB_PREVIEW, CMISRenditionKind.ICON16, CMISRenditionKind.ICON32); } - public void testGetRenditionsByMimetype() + public void testGetRenditionsByMimetype() throws Exception { for (CMISRendition rendition : documentRenditions) { @@ -106,7 +106,7 @@ public class CMISRenditionServiceTest extends BaseCMISTest testGetRenditionsByMimetype(mimetypes); } - public void testEmptyFilter() + public void testEmptyFilter() throws Exception { List receivedRenditions = cmisRenditionService.getRenditions(document, null); assertTrue(receivedRenditions == null || receivedRenditions.size() == 0); @@ -115,7 +115,7 @@ public class CMISRenditionServiceTest extends BaseCMISTest assertTrue(receivedRenditions == null || receivedRenditions.size() == 0); } - public void testRenditionsByBaseMimetype() + public void testRenditionsByBaseMimetype() throws Exception { String[] mimetypes = getDifferentMimetypes(); List baseMimetypeFilters = new ArrayList(); @@ -131,23 +131,23 @@ public class CMISRenditionServiceTest extends BaseCMISTest testGetRenditionsByMimetype(baseMimetypeFilters.toArray(new String[0])); } - public void testMixedFilter() + public void testMixedFilter() throws Exception { String[] mimetypes = getDifferentMimetypes(); testGetRenditions(THUMBNAIL_KINDS, mimetypes); } - private void testGetRenditionsByMimetype(String... mimetypes) + private void testGetRenditionsByMimetype(String... mimetypes) throws Exception { testGetRenditions(null, mimetypes); } - private void testGetRenditionsByKind(CMISRenditionKind... kinds) + private void testGetRenditionsByKind(CMISRenditionKind... kinds) throws Exception { testGetRenditions(kinds, null); } - private void testGetRenditions(CMISRenditionKind[] kinds, String[] mimetypes) + private void testGetRenditions(CMISRenditionKind[] kinds, String[] mimetypes) throws Exception { String filter = createFilter(kinds, mimetypes); List receivedRenditions = cmisRenditionService.getRenditions(document, filter); diff --git a/source/java/org/alfresco/cmis/search/QueryTest.java b/source/java/org/alfresco/cmis/search/QueryTest.java index 55ff920104..403ec5ff59 100644 --- a/source/java/org/alfresco/cmis/search/QueryTest.java +++ b/source/java/org/alfresco/cmis/search/QueryTest.java @@ -425,18 +425,18 @@ public class QueryTest extends BaseCMISTest nodeService.setProperty(c9, ContentModel.PROP_VERSION_LABEL, "label"); } - private T testQuery(String query, int size, boolean dump, String returnPropertyName, T returnType, boolean shouldThrow) + private T testQuery(String query, int size, boolean dump, String returnPropertyName, T returnType, boolean shouldThrow) throws Exception { return testQuery(query, size, dump, returnPropertyName, returnType, shouldThrow, CMISQueryMode.CMS_STRICT); } - private T testExtendedQuery(String query, int size, boolean dump, String returnPropertyName, T returnType, boolean shouldThrow) + private T testExtendedQuery(String query, int size, boolean dump, String returnPropertyName, T returnType, boolean shouldThrow) throws Exception { return testQuery(query, size, dump, returnPropertyName, returnType, shouldThrow, CMISQueryMode.CMS_WITH_ALFRESCO_EXTENSIONS); } @SuppressWarnings("unchecked") - private T testQuery(String query, int size, boolean dump, String returnPropertyName, T returnType, boolean shouldThrow, CMISQueryMode mode) + private T testQuery(String query, int size, boolean dump, String returnPropertyName, T returnType, boolean shouldThrow, CMISQueryMode mode) throws Exception { CMISResultSet rs = null; try @@ -535,7 +535,7 @@ public class QueryTest extends BaseCMISTest } - public void test_ALLOWED_CHILD_OBJECT_TYPES() + public void test_ALLOWED_CHILD_OBJECT_TYPES() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:Folder", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -603,7 +603,7 @@ public class QueryTest extends BaseCMISTest new String(), true); } - public void test_PARENT() + public void test_PARENT() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:Folder", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -668,7 +668,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT cmis:parentId FROM cmis:folder WHERE ANY cmis:parentId NOT IN ('" + rootNodeRef.toString() + "')", 6, false, "cmis:parentId", new String(), true); } - public void test_PATH() + public void test_PATH() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:folder", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -693,7 +693,7 @@ public class QueryTest extends BaseCMISTest } - public void test_CONTENT_STREAM_ID() + public void test_CONTENT_STREAM_ID() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:Document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -740,7 +740,7 @@ public class QueryTest extends BaseCMISTest } - public void test_CONTENT_STREAM_FILENAME() + public void test_CONTENT_STREAM_FILENAME() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:Document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -835,7 +835,7 @@ public class QueryTest extends BaseCMISTest new String(), true); } - public void test_CONTENT_STREAM_MIME_TYPE() + public void test_CONTENT_STREAM_MIME_TYPE() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:Document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -918,7 +918,7 @@ public class QueryTest extends BaseCMISTest new String(), true); } - public void test_CONTENT_STREAM_LENGTH() + public void test_CONTENT_STREAM_LENGTH() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:Document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -983,7 +983,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT cmis:contentStreamLength FROM cmis:document WHERE ANY cmis:contentStreamLength NOT IN (750)", 10, false, "cmis:contentStreamLength", new String(), true); } - public void test_CHECKIN_COMMENT() + public void test_CHECKIN_COMMENT() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:Document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -1032,7 +1032,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT cmis:checkinComment FROM cmis:document WHERE ANY cmis:checkinComment NOT IN ('admin')", 10, false, "cmis:objectId", new String(), true); } - public void test_VERSION_SERIES_CHECKED_OUT_ID() + public void test_VERSION_SERIES_CHECKED_OUT_ID() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:Document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -1083,7 +1083,7 @@ public class QueryTest extends BaseCMISTest true); } - public void test_VERSION_SERIES_CHECKED_OUT_BY() + public void test_VERSION_SERIES_CHECKED_OUT_BY() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:Document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -1134,7 +1134,7 @@ public class QueryTest extends BaseCMISTest true); } - public void test_IS_VERSION_SERIES_CHECKED_OUT() + public void test_IS_VERSION_SERIES_CHECKED_OUT() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:Document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -1183,7 +1183,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT cmis:isVeriesSeriesCheckedOut FROM cmis:document WHERE ANY cmis:isVeriesSeriesCheckedOut NOT IN ('TRUE')", 10, false, "cmis:objectId", new String(), true); } - public void test_VERSION_SERIES_ID() + public void test_VERSION_SERIES_ID() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:Document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -1231,7 +1231,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT cmis:versionSeriesId FROM cmis:document WHERE ANY cmis:versionSeriesId NOT IN ('company')", 10, false, "cmis:objectId", new String(), true); } - public void test_VERSION_LABEL() + public void test_VERSION_LABEL() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:Document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -1298,7 +1298,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT cmis:versionLabel FROM cmis:document WHERE ANY cmis:versionLabel NOT IN ('company')", 10, false, "cmis:objectId", new String(), true); } - public void test_IS_LATEST_MAJOR_VERSION() + public void test_IS_LATEST_MAJOR_VERSION() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:Document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -1347,7 +1347,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT cmis:isLatestMajorVersion FROM cmis:document WHERE ANY cmis:isLatestMajorVersion NOT IN ('TRUE')", 0, false, "cmis:objectId", new String(), true); } - public void test_IS_MAJOR_VERSION() + public void test_IS_MAJOR_VERSION() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:Document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -1399,7 +1399,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT cmis:isMajorVersion FROM cmis:document WHERE ANY cmis:isMajorVersion NOT IN ('TRUE')", 0, false, "cmis:objectId", new String(), true); } - public void test_IS_LATEST_VERSION() + public void test_IS_LATEST_VERSION() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:Document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -1448,7 +1448,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT cmis:isLatestVersion FROM cmis:document WHERE ANY cmis:isLatestVersion NOT IN ('TRUE')", 0, false, "cmis:objectId", new String(), true); } - public void test_IS_IMMUTABLE() + public void test_IS_IMMUTABLE() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:Document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -1497,7 +1497,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT cmis:isImmutable FROM cmis:document WHERE ANY cmis:isImmutable NOT IN ('TRUE')", 0, false, "cmis:objectId", new String(), true); } - public void test_folder_NAME() + public void test_folder_NAME() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:folder", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -1563,7 +1563,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT cmis:name FROM cmis:folder WHERE ANY cmis:name NOT IN ('Folder 1')", 9, false, "cmis:objectId", new String(), true); } - public void test_document_Name() + public void test_document_Name() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -1629,7 +1629,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT cmis:name FROM cmis:document WHERE ANY cmis:name NOT IN ('Alfresco Tutorial')", 9, false, "cmis:name", new String(), true); } - public void test_CHANGE_TOKEN() + public void test_CHANGE_TOKEN() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -1678,7 +1678,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT cmis:changeToken FROM cmis:folder WHERE ANY cmis:changeToken NOT IN ('test')", 10, false, "cmis:objectId", new String(), true); } - public void test_LAST_MODIFICATION_DATE() + public void test_LAST_MODIFICATION_DATE() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -1851,7 +1851,7 @@ public class QueryTest extends BaseCMISTest } - public void test_LAST_MODIFIED_BY() + public void test_LAST_MODIFIED_BY() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -1920,7 +1920,7 @@ public class QueryTest extends BaseCMISTest new String(), true); } - public void test_CREATION_DATE() + public void test_CREATION_DATE() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -2085,7 +2085,7 @@ public class QueryTest extends BaseCMISTest } - public void test_CREATED_BY() + public void test_CREATED_BY() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -2154,7 +2154,7 @@ public class QueryTest extends BaseCMISTest } - public void test_OBJECT_TYPE_ID() + public void test_OBJECT_TYPE_ID() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -2256,7 +2256,7 @@ public class QueryTest extends BaseCMISTest } - public void test_BASE_TYPE_ID() + public void test_BASE_TYPE_ID() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -2305,7 +2305,7 @@ public class QueryTest extends BaseCMISTest } - public void test_ObjectId() + public void test_ObjectId() throws Exception { CMISQueryOptions options = new CMISQueryOptions("SELECT * FROM cmis:document", rootNodeRef.getStoreRef()); options.setDefaultFTSConnective(Connective.OR); @@ -2400,7 +2400,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT cmis:objectId FROM cmis:folder WHERE ANY cmis:objectId NOT IN ('" + companyHomeId + "')", 9, false, "cmis:objectId", new String(), true); } - public void testOrderBy() + public void testOrderBy() throws Exception { testOrderBy("SELECT cmis:objectId FROM cmis:folder ORDER BY cmis:objectId", folder_count, false, Order.ASCENDING, CMISQueryMode.CMS_STRICT, "cmis:objectId"); testOrderBy("SELECT cmis:objectId FROM cmis:folder ORDER BY cmis:objectTypeId", folder_count, true, Order.ASCENDING, CMISQueryMode.CMS_STRICT, "cmis:objectTypeId"); @@ -2790,7 +2790,7 @@ public class QueryTest extends BaseCMISTest } - public void testUpperAndLower() + public void testUpperAndLower() throws Exception { testExtendedQuery("SELECT * FROM cmis:folder WHERE cmis:name = 'Folder 1'", 1, false, "cmis:objectId", new String(), false); testExtendedQuery("SELECT * FROM cmis:folder WHERE cmis:name = 'FOLDER 1'", 0, false, "cmis:objectId", new String(), false); @@ -2812,7 +2812,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT * FROM cmis:folder WHERE Upper(cmis:name) > 'FOLDER 1'", 8, false, "cmis:objectId", new String(), true); } - public void testAllSimpleTextPredicates() + public void testAllSimpleTextPredicates() throws Exception { testQuery("SELECT * FROM cmis:folder WHERE cmis:name IS NOT NULL AND cmis:name = 'Folder 1'", 1, false, "cmis:objectId", new String(), false); testQuery("SELECT * FROM cmis:folder WHERE cmis:name IS NOT NULL AND cmis:name = 'Folder 9'", 0, false, "cmis:objectId", new String(), false); @@ -2840,13 +2840,13 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT * FROM cmis:folder WHERE cmis:name IS NOT NULL AND cmis:name NOT LIKE 'F_l_e_ _'", 1, false, "cmis:objectId", new String(), false); } - public void testSimpleConjunction() + public void testSimpleConjunction() throws Exception { testQuery("SELECT * FROM cmis:folder WHERE cmis:name IS NOT NULL AND cmis:name = 'Folder 1'", 1, false, "cmis:objectId", new String(), false); testQuery("SELECT * FROM cmis:folder WHERE cmis:name IS NOT NULL AND cmis:name = 'Folder'", 0, false, "cmis:objectId", new String(), false); } - public void testSimpleDisjunction() + public void testSimpleDisjunction() throws Exception { testQuery("SELECT * FROM cmis:folder WHERE cmis:name = 'Folder 1'", 1, false, "cmis:objectId", new String(), false); testQuery("SELECT * FROM cmis:folder WHERE cmis:name = 'Folder 2'", 1, false, "cmis:objectId", new String(), false); @@ -2855,8 +2855,9 @@ public class QueryTest extends BaseCMISTest /** * In strict mode you should not be able to refer to aspect properties direct from the type + * @throws Exception */ - public void testPropertyToSelectorBinding() + public void testPropertyToSelectorBinding() throws Exception { testQuery("SELECT cmis:parentId FROM cmis:document", 10, false, "cmis:objectId", new String(), true, CMISQueryMode.CMS_STRICT); testQuery("SELECT * FROM cmis:document where cmis:parentId <> 'woof://woof/woof'", 10, false, "cmis:objectId", new String(), true, CMISQueryMode.CMS_STRICT); @@ -2866,7 +2867,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT * FROM cmis:document where CONTAINS('cmis:parentId:*')", 10, false, "cmis:objectId", new String(), true, CMISQueryMode.CMS_STRICT); } - public void testExists() + public void testExists() throws Exception { testQuery("SELECT * FROM cmis:folder WHERE cmis:name IS NOT NULL", 10, false, "cmis:objectId", new String(), false); testQuery("SELECT * FROM cmis:folder WHERE cmis:name IS NULL", 0, false, "cmis:objectId", new String(), false); @@ -2884,7 +2885,7 @@ public class QueryTest extends BaseCMISTest } - public void testFolderEquals() + public void testFolderEquals() throws Exception { Serializable ser = cmisService.getProperty(f0, CMISDictionaryModel.PROP_NAME); String Name = DefaultTypeConverter.INSTANCE.convert(String.class, ser); @@ -2895,7 +2896,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT * FROM cmis:folder WHERE cmis:allowedChildObjectTypeIds = 'meep'", 0, false, "cmis:objectId", new String(), true); } - public void test_IN_TREE() + public void test_IN_TREE() throws Exception { Serializable ser = cmisService.getProperty(f0, CMISDictionaryModel.PROP_OBJECT_ID); String id = DefaultTypeConverter.INSTANCE.convert(String.class, ser); @@ -2912,7 +2913,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT * FROM cmis:folder WHERE IN_TREE('woof://woof/woof')", 6, false, "cmis:objectId", new String(), true); } - public void test_IN_FOLDER() + public void test_IN_FOLDER() throws Exception { Serializable ser = cmisService.getProperty(f0, CMISDictionaryModel.PROP_OBJECT_ID); String id = DefaultTypeConverter.INSTANCE.convert(String.class, ser); @@ -2932,7 +2933,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT * FROM cmis:folder WHERE IN_FOLDER('woof://woof/woof')", 2, false, "cmis:objectId", new String(), true); } - public void testFTS() + public void testFTS() throws Exception { testQuery("SELECT SCORE(), D.* FROM cmis:document D WHERE D.cmis:contentStreamFileName = 'zebra'", 9, false, "cmis:objectId", new String(), true); testQuery("SELECT * FROM cmis:document WHERE CONTAINS('\\'zebra\\'') AND CONTAINS('\\'quick\\'')", 9, false, "cmis:objectId", new String(), true); @@ -2981,21 +2982,21 @@ public class QueryTest extends BaseCMISTest rs = null; } - public void testBasicSelectAsGuest() + public void testBasicSelectAsGuest() throws Exception { runAs("guest"); testQuery("SELECT * FROM cmis:document", 0, false, "cmis:objectId", new String(), false); } - public void testBasicSelectAsCmis() + public void testBasicSelectAsCmis() throws Exception { runAs("cmis"); testQuery("SELECT * FROM cmis:document", 7, false, "cmis:objectId", new String(), false); } - public void testBasicSelect() + public void testBasicSelect() throws Exception { testQuery("SELECT * FROM cmis:document", 10, false, "cmis:objectId", new String(), false); } @@ -3193,7 +3194,7 @@ public class QueryTest extends BaseCMISTest parse(query); } - public void testDateFormattingErrors() + public void testDateFormattingErrors() throws Exception { testQuery("SELECT * FROM cm:lockable L WHERE L.cm:expiryDate = TIMESTAMP '2012-12-12T12:12:12.012Z'", 1, false, "cmis:objectId", new String(), false, CMISQueryMode.CMS_WITH_ALFRESCO_EXTENSIONS); @@ -3227,7 +3228,7 @@ public class QueryTest extends BaseCMISTest rs.close(); } - public void testAspectJoin() + public void testAspectJoin() throws Exception { testQuery( "select o.*, t.* from ( cm:ownable o join cm:titled t on o.cmis:objectId = t.cmis:objectId JOIN CMIS:DOCUMENT AS D ON D.cmis:objectId = o.cmis:objectId ) where o.cm:owner = 'andy' and t.cm:title = 'Alfresco tutorial' and CONTAINS(D, '\\'jumped\\'') and D.cmis:contentStreamLength <> 2", @@ -3291,7 +3292,7 @@ public class QueryTest extends BaseCMISTest } - public void testFTSConnectives() + public void testFTSConnectives() throws Exception { testQuery("SELECT * FROM cmis:document where contains('\\'one\\' or \\'zebra\\'')", 9, false, "cmis:objectId", new String(), false, CMISQueryMode.CMS_STRICT); testQuery("SELECT * FROM cmis:document where contains('\\'one\\' \\'zebra\\'')", 1, false, "cmis:objectId", new String(), false, CMISQueryMode.CMS_STRICT); @@ -3320,7 +3321,7 @@ public class QueryTest extends BaseCMISTest rs.close(); } - public void testLikeEscaping() + public void testLikeEscaping() throws Exception { // TODO: testQuery("SELECT cmis:name FROM cmis:document WHERE cmis:name LIKE 'Alfresco Tutorial'", 1, false, "cmis:name", new String(), false); @@ -3353,7 +3354,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT cmis:name FROM cmis:document WHERE cmis:name LIKE 'DD\\''", 1, false, "cmis:name", new String(), false); } - public void testColumnAliasUse() + public void testColumnAliasUse() throws Exception { testQuery("SELECT cmis:name as myname FROM cmis:document WHERE myname LIKE 'Alfresco Tutorial'", 1, false, "myname", new String(), false); testQuery("SELECT cmis:name as myname FROM cmis:document WHERE myname LIKE 'A%' order by myname", 2, false, "cmis:name", new String(), false); @@ -3393,7 +3394,7 @@ public class QueryTest extends BaseCMISTest return queryNode; } - public void test_d_text() + public void test_d_text() throws Exception { addTypeTestData(); assertNotNull(dictionaryService.getType(extendedContent)); @@ -3598,7 +3599,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT T.test:multipleTextTokenised alias FROM test:extendedContent T WHERE ANY alias NOT IN ('tokenized')", 1, false, "cmis:name", new String(), false); } - public void test_locale() + public void test_locale() throws Exception { addTypeTestData(); assertNotNull(dictionaryService.getType(extendedContent)); @@ -3702,7 +3703,7 @@ public class QueryTest extends BaseCMISTest rs.close(); } - public void test_d_mltext() + public void test_d_mltext() throws Exception { addTypeTestData(); assertNotNull(dictionaryService.getType(extendedContent)); @@ -4021,7 +4022,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT test:multipleMLTextTokenised alias FROM test:extendedContent WHERE ANY alias NOT IN ('EEEE')", 1, false, "cmis:name", new String(), false); } - public void test_d_float() + public void test_d_float() throws Exception { addTypeTestData(); assertNotNull(dictionaryService.getType(extendedContent)); @@ -4154,7 +4155,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT test:multipleFloat as alias FROM test:extendedContent WHERE ANY alias NOT IN (1.3, 2.3)", 1, false, "cmis:name", new String(), false); } - public void test_d_double() + public void test_d_double() throws Exception { addTypeTestData(); assertNotNull(dictionaryService.getType(extendedContent)); @@ -4287,7 +4288,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT test:multipleDouble alias FROM test:extendedContent WHERE ANY alias NOT IN (1.3, 2.3)", 1, false, "cmis:name", new String(), false); } - public void test_d_int() + public void test_d_int() throws Exception { addTypeTestData(); assertNotNull(dictionaryService.getType(extendedContent)); @@ -4422,7 +4423,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT test:multipleInteger as alias FROM test:extendedContent WHERE ANY alias NOT IN (3, 4)", 1, false, "cmis:name", new String(), false); } - public void test_d_long() + public void test_d_long() throws Exception { addTypeTestData(); assertNotNull(dictionaryService.getType(extendedContent)); @@ -4557,7 +4558,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT test:multipleLong alias FROM test:extendedContent WHERE ANY alias NOT IN (3, 4)", 1, false, "cmis:name", new String(), false); } - public void test_d_date() + public void test_d_date() throws Exception { addTypeTestData(); assertNotNull(dictionaryService.getType(extendedContent)); @@ -4723,7 +4724,7 @@ public class QueryTest extends BaseCMISTest } - public void test_d_datetime() + public void test_d_datetime() throws Exception { addTypeTestData(); assertNotNull(dictionaryService.getType(extendedContent)); @@ -4892,7 +4893,7 @@ public class QueryTest extends BaseCMISTest } - public void test_d_boolean() + public void test_d_boolean() throws Exception { addTypeTestData(); assertNotNull(dictionaryService.getType(extendedContent)); @@ -5035,7 +5036,7 @@ public class QueryTest extends BaseCMISTest testQuery("SELECT test:multipleBoolean as alias FROM test:extendedContent WHERE ANY alias NOT IN (3, 4)", 1, false, "cmis:name", new String(), true); } - public void testBasicContainsSyntax() + public void testBasicContainsSyntax() throws Exception { testQuery("SELECT * FROM cmis:document WHERE CONTAINS('quick')", 1, false, "cmis:name", new String(), false); testQuery("SELECT * FROM cmis:document WHERE CONTAINS('one')", 1, false, "cmis:name", new String(), false); @@ -5151,7 +5152,7 @@ public class QueryTest extends BaseCMISTest testOrderablePropertyFail("test:multipleBoolean"); } - public void testNonQueryableTypes() + public void testNonQueryableTypes() throws Exception { testQuery("SELECT * FROM cmis:policy", 0, false, "cmis:name", new String(), true); testQuery("SELECT * FROM cmis:relationship ", 0, false, "cmis:name", new String(), true); diff --git a/source/java/org/alfresco/repo/avm/AVMNodeService.java b/source/java/org/alfresco/repo/avm/AVMNodeService.java index 479f3127e4..d73fe0debb 100644 --- a/source/java/org/alfresco/repo/avm/AVMNodeService.java +++ b/source/java/org/alfresco/repo/avm/AVMNodeService.java @@ -1797,6 +1797,18 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi throw new UnsupportedOperationException("AVM does not support arbitrary associations."); } + /** + * Gets an association by ID. + * + * @param assocId + * the association id + * @return the association, or null if it does not exist + */ + public AssociationRef getAssoc(Long id) + { + return null; + } + /** * Fetches all associations from the given source where the associations' * qualified names match the pattern provided. diff --git a/source/java/org/alfresco/repo/domain/hibernate/NodeAssocImpl.java b/source/java/org/alfresco/repo/domain/hibernate/NodeAssocImpl.java index 62b2423340..54b703d5bf 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/NodeAssocImpl.java +++ b/source/java/org/alfresco/repo/domain/hibernate/NodeAssocImpl.java @@ -108,6 +108,7 @@ public class NodeAssocImpl implements NodeAssoc, Serializable if (nodeAssocRef == null || trashReference) { nodeAssocRef = new AssociationRef( + this.id, getSource().getNodeRef(), this.typeQName, getTarget().getNodeRef()); diff --git a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java index 3aafb0e740..6cd29e0b6d 100644 --- a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java +++ b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java @@ -73,11 +73,11 @@ import org.alfresco.service.namespace.QNamePattern; import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.util.EqualsHelper; import org.alfresco.util.GUID; -import org.springframework.extensions.surf.util.Pair; -import org.springframework.extensions.surf.util.ParameterCheck; import org.alfresco.util.PropertyMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.surf.util.Pair; +import org.springframework.extensions.surf.util.ParameterCheck; import org.springframework.util.Assert; /** @@ -2007,6 +2007,11 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl // Invoke policy behaviours invokeOnDeleteAssociation(assocRef); } + + public AssociationRef getAssoc(Long id) + { + return nodeDaoService.getNodeAssocOrNull(id); + } public List getTargetAssocs(NodeRef sourceRef, QNamePattern qnamePattern) { diff --git a/source/java/org/alfresco/repo/node/db/NodeDaoService.java b/source/java/org/alfresco/repo/node/db/NodeDaoService.java index a158706155..8ac7b0ca52 100644 --- a/source/java/org/alfresco/repo/node/db/NodeDaoService.java +++ b/source/java/org/alfresco/repo/node/db/NodeDaoService.java @@ -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 @@ -456,6 +456,16 @@ public interface NodeDaoService @DirtySessionAnnotation(markDirty=false) public Pair getNodeAssoc(Long sourceNodeId, Long targetNodeId, QName assocTypeQName); + /** + * Gets a node association by ID. + * + * @param assocId + * the association id + * @return the node association, or null if it does not exist + */ + @DirtySessionAnnotation(markDirty = false) + public AssociationRef getNodeAssocOrNull(Long assocId); + /** * @return Returns all the node associations where the node is the source */ diff --git a/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java b/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java index c62ccdfc96..6760e4fa9f 100644 --- a/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java +++ b/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java @@ -3858,6 +3858,16 @@ public class HibernateNodeDaoServiceImpl return ret; } + public AssociationRef getNodeAssocOrNull(Long assocId) + { + NodeAssoc result = (NodeAssoc) getHibernateTemplate().get(NodeAssocImpl.class, assocId); + if (result == null) + { + return null; + } + return result.getNodeAssocRef(qnameDAO); + } + @SuppressWarnings("unchecked") public Collection> getTargetNodeAssocs(final Long sourceNodeId) { diff --git a/source/java/org/alfresco/repo/tenant/MultiTServiceImpl.java b/source/java/org/alfresco/repo/tenant/MultiTServiceImpl.java index c3848b1b71..8aeca7e074 100755 --- a/source/java/org/alfresco/repo/tenant/MultiTServiceImpl.java +++ b/source/java/org/alfresco/repo/tenant/MultiTServiceImpl.java @@ -121,7 +121,7 @@ public class MultiTServiceImpl implements TenantService { if (assocRef == null) { return null; } - return new AssociationRef( + return new AssociationRef(assocRef.getId(), getName(assocRef.getSourceRef()), assocRef.getTypeQName(), getName(assocRef.getTargetRef())); @@ -321,7 +321,7 @@ public class MultiTServiceImpl implements TenantService { if (assocRef == null) { return null; } - return new AssociationRef( + return new AssociationRef(assocRef.getId(), getBaseName(assocRef.getSourceRef()), assocRef.getTypeQName(), getBaseName(assocRef.getTargetRef())); diff --git a/source/java/org/alfresco/repo/version/NodeServiceImpl.java b/source/java/org/alfresco/repo/version/NodeServiceImpl.java index 824774e44d..40c3f8ad73 100644 --- a/source/java/org/alfresco/repo/version/NodeServiceImpl.java +++ b/source/java/org/alfresco/repo/version/NodeServiceImpl.java @@ -601,6 +601,18 @@ public class NodeServiceImpl implements NodeService, VersionModel throw new UnsupportedOperationException(MSG_UNSUPPORTED); } + /** + * Gets an association by ID. + * + * @param assocId + * the association id + * @return the association, or null if it does not exist + */ + public AssociationRef getAssoc(Long id) + { + return null; + } + /** * @throws UnsupportedOperationException always */ @@ -624,7 +636,7 @@ public class NodeServiceImpl implements NodeService, VersionModel if (qnamePattern.isMatch(qName) == true) { - AssociationRef newAssocRef = new AssociationRef(sourceRef, qName, referencedNode); + AssociationRef newAssocRef = new AssociationRef(null, sourceRef, qName, referencedNode); result.add(newAssocRef); } } diff --git a/source/java/org/alfresco/service/cmr/repository/AssociationRef.java b/source/java/org/alfresco/service/cmr/repository/AssociationRef.java index 2bf4491557..06e2774df7 100644 --- a/source/java/org/alfresco/service/cmr/repository/AssociationRef.java +++ b/source/java/org/alfresco/service/cmr/repository/AssociationRef.java @@ -42,6 +42,7 @@ public class AssociationRef implements EntityRef, Serializable private static final String FILLER = "|"; + private Long id; private NodeRef sourceRef; private QName assocTypeQName; private NodeRef targetRef; @@ -49,7 +50,9 @@ public class AssociationRef implements EntityRef, Serializable /** * Construct a representation of a source --- name ----> target * relationship. - * + * + * @param id + * unique identifier * @param sourceRef * the source reference - never null * @param assocTypeQName @@ -57,8 +60,9 @@ public class AssociationRef implements EntityRef, Serializable * @param targetRef * the target node reference - never null. */ - public AssociationRef(NodeRef sourceRef, QName assocTypeQName, NodeRef targetRef) + public AssociationRef(Long id, NodeRef sourceRef, QName assocTypeQName, NodeRef targetRef) { + this.id = id; this.sourceRef = sourceRef; this.assocTypeQName = assocTypeQName; this.targetRef = targetRef; @@ -88,10 +92,12 @@ public class AssociationRef implements EntityRef, Serializable { throw new AlfrescoRuntimeException("Unable to parse association string: " + assocRefStr); } + String idStr = tokenizer.nextToken(); String sourceNodeRefStr = tokenizer.nextToken(); String targetNodeRefStr = tokenizer.nextToken(); String assocTypeQNameStr = tokenizer.nextToken(); + this.id = new Long(idStr); this.sourceRef = new NodeRef(sourceNodeRefStr); this.targetRef = new NodeRef(targetNodeRefStr); this.assocTypeQName = QName.createQName(assocTypeQNameStr); @@ -103,7 +109,8 @@ public class AssociationRef implements EntityRef, Serializable public String toString() { StringBuilder sb = new StringBuilder(180); - sb.append(sourceRef).append(FILLER) + sb.append(id).append(FILLER) + .append(sourceRef).append(FILLER) .append(targetRef).append(FILLER) .append(assocTypeQName); return sb.toString(); @@ -112,6 +119,7 @@ public class AssociationRef implements EntityRef, Serializable /** * Compares: *
    + *
  • {@link #id}
  • *
  • {@link #sourceRef}
  • *
  • {@link #targetRef}
  • *
  • {@link #assocTypeQName}
  • @@ -129,19 +137,31 @@ public class AssociationRef implements EntityRef, Serializable } AssociationRef other = (AssociationRef) o; - return (EqualsHelper.nullSafeEquals(this.sourceRef, other.sourceRef) + return (EqualsHelper.nullSafeEquals(this.id, other.id) + && EqualsHelper.nullSafeEquals(this.sourceRef, other.sourceRef) && EqualsHelper.nullSafeEquals(this.assocTypeQName, other.assocTypeQName) && EqualsHelper.nullSafeEquals(this.targetRef, other.targetRef)); } public int hashCode() { - int hashCode = (getSourceRef() == null) ? 0 : getSourceRef().hashCode(); + int hashCode = (getId() == null) ? 0 : getId().hashCode(); + hashCode = 37 * hashCode + ((getSourceRef() == null) ? 0 : getSourceRef().hashCode()); hashCode = 37 * hashCode + ((getTypeQName() == null) ? 0 : getTypeQName().hashCode()); hashCode = 37 * hashCode + getTargetRef().hashCode(); return hashCode; } + /** + * Gets the unique identifier for this association. + * + * @return the unique identifier for this association + */ + public Long getId() + { + return this.id; + } + /** * Get the qualified name of the source-target association * diff --git a/source/java/org/alfresco/service/cmr/repository/NodeService.java b/source/java/org/alfresco/service/cmr/repository/NodeService.java index 6791b90371..cb1f0f4f27 100644 --- a/source/java/org/alfresco/service/cmr/repository/NodeService.java +++ b/source/java/org/alfresco/service/cmr/repository/NodeService.java @@ -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 @@ -643,6 +643,15 @@ public interface NodeService public void removeAssociation(NodeRef sourceRef, NodeRef targetRef, QName assocTypeQName) throws InvalidNodeRefException; + /** + * Gets an association by ID. + * + * @param assocId + * the association id + * @return the association, or null if it does not exist + */ + public AssociationRef getAssoc(Long id); + /** * Fetches all associations from the given source where the associations' * qualified names match the pattern provided.