From bd2f2441fd9f0f4a3868532bf32bc5a51ad88c9c 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/cmis-ws-context.xml | 30 +- .../cmis/checkedout.post.atomentry.js | 27 +- .../org/alfresco/cmis/children.get.desc.xml | 12 +- .../org/alfresco/cmis/children.get.js | 7 +- .../org/alfresco/cmis/children.post.atom.js | 64 +- .../org/alfresco/cmis/children.post.desc.xml | 12 +- .../org/alfresco/cmis/content.delete.js | 33 +- .../org/alfresco/cmis/item.delete.js | 32 +- .../org/alfresco/cmis/item.get.desc.xml | 1 - .../webscripts/org/alfresco/cmis/item.get.js | 8 +- .../alfresco/cmis/lib/atomentry.lib.atom.ftl | 68 +- .../org/alfresco/cmis/lib/links.lib.atom.ftl | 2 +- .../org/alfresco/cmis/lib/modify.lib.js | 7 +- .../org/alfresco/cmis/pwc.delete.js | 10 +- .../org/alfresco/cmis/pwc.patch.atom.js | 14 +- .../org/alfresco/cmis/pwc.put.atom.js | 14 +- .../cmis/relationship.delete.desc.xml | 2 +- .../org/alfresco/cmis/relationship.delete.js | 10 +- .../alfresco/cmis/relationship.get.desc.xml | 2 +- .../org/alfresco/cmis/tree.delete.desc.xml | 12 +- .../org/alfresco/cmis/tree.delete.js | 37 +- .../alfresco/cmis/versions.get.atomfeed.ftl | 2 +- .../org/alfresco/cmis/versions.get.js | 9 +- .../web-scripts-application-context.xml | 6 +- .../cmis/ws/CmisAllowableActionsType.java | 29 +- .../alfresco/repo/cmis/PropertyFilter.java | 6 +- .../repo/cmis/PropertyFilterTest.java | 21 +- .../repo/cmis/reference/AVMPathReference.java | 66 ++ .../reference/AbstractObjectReference.java | 62 ++ .../AbstractRepositoryReference.java | 56 ++ .../AssociationIdRelationshipReference.java | 93 +++ .../reference/DefaultRepositoryReference.java | 57 ++ .../repo/cmis/reference/NodeIdReference.java | 87 ++ .../cmis/reference/ObjectIdReference.java | 94 +++ .../cmis/reference/ObjectPathReference.java | 88 +++ .../repo/cmis/reference/ReferenceFactory.java | 145 ++++ ...SourceTypeTargetRelationshipReference.java | 93 +++ .../reference/StoreRepositoryReference.java | 86 ++ .../repo/cmis/rest/CMISChildrenMethod.java | 12 +- .../cmis/rest/CMISPropertyValueMethod.java | 11 +- .../repo/cmis/rest/CMISRenditionsMethod.java | 12 +- .../alfresco/repo/cmis/rest/CMISScript.java | 482 ++++++++++-- .../repo/cmis/rest/CMISTemplateResultSet.java | 13 + .../repo/cmis/ws/DMAbstractServicePort.java | 395 +++------- .../repo/cmis/ws/DMAclServicePort.java | 25 +- .../repo/cmis/ws/DMDiscoveryServicePort.java | 36 +- .../cmis/ws/DMMultiFilingServicePort.java | 62 +- .../repo/cmis/ws/DMNavigationServicePort.java | 249 +++--- .../repo/cmis/ws/DMObjectServicePort.java | 744 ++++++++---------- .../repo/cmis/ws/DMPolicyServicePort.java | 8 +- .../cmis/ws/DMRelationshipServicePort.java | 82 +- .../repo/cmis/ws/DMRepositoryServicePort.java | 139 +--- .../cmis/ws/DMServicePortThrowsAdvice.java | 27 +- .../repo/cmis/ws/DMVersioningServicePort.java | 256 ++---- .../cmis/ws/utils/AlfrescoObjectType.java | 73 -- .../cmis/ws/utils/CmisObjectIterator.java | 364 --------- .../repo/cmis/ws/utils/CmisObjectsUtils.java | 566 ------------- .../repo/cmis/ws/utils/ExceptionUtil.java | 100 +++ .../repo/cmis/ws/utils/PropertyUtil.java | 67 +- .../web/scripts/content/ContentDelete.java | 2 +- .../repo/web/scripts/content/ContentGet.java | 2 +- .../repo/web/scripts/content/ContentSet.java | 68 +- .../repo/cmis/ws/DMNavigationServiceTest.java | 24 +- .../repo/cmis/ws/DMVersioningServiceTest.java | 30 +- source/wsdl/CMIS-Core.xsd | 6 +- 65 files changed, 2477 insertions(+), 2782 deletions(-) create mode 100644 source/java/org/alfresco/repo/cmis/reference/AVMPathReference.java create mode 100644 source/java/org/alfresco/repo/cmis/reference/AbstractObjectReference.java create mode 100644 source/java/org/alfresco/repo/cmis/reference/AbstractRepositoryReference.java create mode 100644 source/java/org/alfresco/repo/cmis/reference/AssociationIdRelationshipReference.java create mode 100644 source/java/org/alfresco/repo/cmis/reference/DefaultRepositoryReference.java create mode 100644 source/java/org/alfresco/repo/cmis/reference/NodeIdReference.java create mode 100644 source/java/org/alfresco/repo/cmis/reference/ObjectIdReference.java create mode 100644 source/java/org/alfresco/repo/cmis/reference/ObjectPathReference.java create mode 100644 source/java/org/alfresco/repo/cmis/reference/ReferenceFactory.java create mode 100644 source/java/org/alfresco/repo/cmis/reference/SourceTypeTargetRelationshipReference.java create mode 100644 source/java/org/alfresco/repo/cmis/reference/StoreRepositoryReference.java delete mode 100755 source/java/org/alfresco/repo/cmis/ws/utils/AlfrescoObjectType.java delete mode 100755 source/java/org/alfresco/repo/cmis/ws/utils/CmisObjectIterator.java delete mode 100755 source/java/org/alfresco/repo/cmis/ws/utils/CmisObjectsUtils.java create mode 100755 source/java/org/alfresco/repo/cmis/ws/utils/ExceptionUtil.java diff --git a/config/alfresco/cmis-ws-context.xml b/config/alfresco/cmis-ws-context.xml index 63a7b7157c..5e104bdf8d 100644 --- a/config/alfresco/cmis-ws-context.xml +++ b/config/alfresco/cmis-ws-context.xml @@ -280,6 +280,7 @@ dmDiscoveryService dmRelationshipService dmPolicyService + dmAclService @@ -305,25 +306,12 @@ - - - + - - - - - - - - - - - @@ -341,15 +329,11 @@ - - - + - - - + @@ -358,20 +342,16 @@ - - - - - + diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/checkedout.post.atomentry.js b/config/alfresco/templates/webscripts/org/alfresco/cmis/checkedout.post.atomentry.js index 34d5971918..17d5e2309e 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/checkedout.post.atomentry.js +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/checkedout.post.atomentry.js @@ -30,33 +30,8 @@ script: } model.node = object.node; - // ensure node can be checked-out - if (!model.node.isDocument) - { - status.code = 400; - status.message = "Cannot checkout node " + object.ref + " as it is not a document"; - status.redirect = true; - break script; - } - - // TODO: need to test for isCheckedOut not isLocked - if (model.node.isLocked || model.node.hasAspect("cm:workingCopy")) - { - status.code = 400; - status.message = "Cannot checkout node " + object.ref + " as it is already checked-out"; - status.redirect = true; - break script; - } - - // switch on versioning - if (!model.node.hasAspect("cm:versionable")) - { - // create an initial version of the current document - model.node.createVersion("Initial Version", true); - } - // checkout - model.pwc = model.node.checkout(); + model.pwc = cmis.checkOut(objectId); // setup for 201 Created response // TODO: set Content-Location diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/children.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/cmis/children.get.desc.xml index 9349d90678..04efb35a97 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/children.get.desc.xml +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/children.get.desc.xml @@ -36,14 +36,14 @@ If no “maxItems” value is provided, then the Repository will determine an ap - /cmis/i/{id}/children?types={types}&filter={filter?}&skipCount={skipCount?}&maxItems={maxItems?}&includeAllowableActions={includeAllowableActions?}&renditionFilter={renditionFilter?} - /cmis/s/{store}/i/{id}/children?types={types}&filter={filter?}&skipCount={skipCount?}&maxItems={maxItems?}&includeAllowableActions={includeAllowableActions?}&renditionFilter={renditionFilter?} + /cmis/i/{id}/children?types={types}&filter={filter?}&skipCount={skipCount?}&maxItems={maxItems?}&includeAllowableActions={includeAllowableActions?}&renditionFilter={renditionFilter?}&orderBy={orderBy?} + /cmis/s/{store}/i/{id}/children?types={types}&filter={filter?}&skipCount={skipCount?}&maxItems={maxItems?}&includeAllowableActions={includeAllowableActions?}&renditionFilter={renditionFilter?}&orderBy={orderBy?} - /cmis/p{path}/children?types={types}&filter={filter?}&skipCount={skipCount?}&maxItems={maxItems?}&includeAllowableActions={includeAllowableActions?}&renditionFilter={renditionFilter?} - /cmis/s/{store}/p{path}/children?types={types}&filter={filter?}&skipCount={skipCount?}&maxItems={maxItems?}&includeAllowableActions={includeAllowableActions?}&renditionFilter={renditionFilter?} + /cmis/p{path}/children?types={types}&filter={filter?}&skipCount={skipCount?}&maxItems={maxItems?}&includeAllowableActions={includeAllowableActions?}&renditionFilter={renditionFilter?}&orderBy={orderBy?} + /cmis/s/{store}/p{path}/children?types={types}&filter={filter?}&skipCount={skipCount?}&maxItems={maxItems?}&includeAllowableActions={includeAllowableActions?}&renditionFilter={renditionFilter?}&orderBy={orderBy?} - /api/node/{store_type}/{store_id}/{id}/children?types={types}&filter={filter?}&skipCount={skipCount?}&maxItems={maxItems?}&includeAllowableActions={includeAllowableActions?}&renditionFilter={renditionFilter?} - /api/path/{store_type}/{store_id}/{path}/children?types={types}&filter={filter?}&skipCount={skipCount?}&maxItems={maxItems?}&includeAllowableActions={includeAllowableActions?}&renditionFilter={renditionFilter?} + /api/node/{store_type}/{store_id}/{id}/children?types={types}&filter={filter?}&skipCount={skipCount?}&maxItems={maxItems?}&includeAllowableActions={includeAllowableActions?}&renditionFilter={renditionFilter?}&orderBy={orderBy?} + /api/path/{store_type}/{store_id}/{path}/children?types={types}&filter={filter?}&skipCount={skipCount?}&maxItems={maxItems?}&includeAllowableActions={includeAllowableActions?}&renditionFilter={renditionFilter?}&orderBy={orderBy?} guest diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/children.get.js b/config/alfresco/templates/webscripts/org/alfresco/cmis/children.get.js index b4e886a7b5..9bb3e45beb 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/children.get.js +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/children.get.js @@ -33,14 +33,17 @@ script: { model.renditionFilter = "cmis:none"; } - + + // order by + var orderBy = args[cmis.ARG_ORDER_BY]; + // include allowable actions var includeAllowableActions = args[cmis.ARG_INCLUDE_ALLOWABLE_ACTIONS]; model.includeAllowableActions = (includeAllowableActions == "true" ? true : false); // retrieve children var page = paging.createPageOrWindow(args); - var paged = cmis.queryChildren(model.node, model.types, page); + var paged = cmis.queryChildren(model.node, model.types, orderBy, page); model.results = paged.results; model.cursor = paged.cursor; } diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/children.post.atom.js b/config/alfresco/templates/webscripts/org/alfresco/cmis/children.post.atom.js index 0317617eeb..76fe0121a3 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/children.post.atom.js +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/children.post.atom.js @@ -20,25 +20,48 @@ script: break script; } model.parent = parent.node; - + + // versioning state + var versioningState = args[cmis.ARG_VERSIONING_STATE]; + if (versioningState === null || versioningState.length == 0) + { + versioningState = "major"; + } + // is this a create or move? var object = entry.getExtension(atom.names.cmisra_object); var objectIdProp = (object !== null) ? object.objectId : null; var objectId = (objectIdProp !== null) ? objectIdProp.nativeValue : null; + var sourceFolderId = args[cmis.ARG_SOURCE_FOLDER_ID]; var node = null; if (objectId == null) { // create node - node = createNode(model.parent, entry, slug); + node = createNode(model.parent, entry, slug, versioningState); if (node == null) { break script; } + node.save(); + } + else if (sourceFolderId == null || sourceFolderId.length == 0) + { + // Add node + var object = getObjectFromObjectId(objectId); + if (object.node == null) + { + break script; + } + node = object.node; + + cmis.addObjectToFolder(node, model.parent); } else { - // locate node and its source folder + // move node + + // locate node var object = getObjectFromObjectId(objectId); if (object.node == null) { @@ -46,44 +69,11 @@ script: } node = object.node; - // move node - var sourceFolderId = args[cmis.ARG_SOURCE_FOLDER_ID]; - if (sourceFolderId == null) - { - status.code = 400; - status.message = "Move of object " + object.ref + " requires sourceFolderId argument"; - status.redirect = true; - break script; - } - - var sourceFolderObject = getObjectFromObjectId(sourceFolderId); - if (sourceFolderObject.node == null) - { - status.code = 400; - break script; - } - if (!sourceFolderObject.node.nodeRef.equals(node.parent.nodeRef)) - { - status.code = 400; - status.message = "Source Folder " + sourceFolderObject.ref + " is not parent of object " + object.ref; - status.redirect = true; - break script; - } - var sourceFolder = sourceFolderObject.node; - // perform move - var success = node.move(model.parent); - if (!success) - { - status.code = 500; - status.message = "Failed to move object " + object.ref + " from folder " + sourceFolderObject.ref + " to folder " + parent.ref; - status.redirect = true; - break script; - } + cmis.moveObject(node, model.parent, sourceFolderId); } // success - node.save(); model.node = node; // TODO: set Content-Location status.code = 201; diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/children.post.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/cmis/children.post.desc.xml index a3974c64db..0cc045dba6 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/children.post.desc.xml +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/children.post.desc.xml @@ -42,14 +42,14 @@ Root folder can not be created using this service.
]]> - /cmis/i/{id}/children?sourceFolderId={sourceFolderId} - /cmis/s/{store}/i/{id}/children?sourceFolderId={sourceFolderId} + /cmis/i/{id}/children?sourceFolderId={sourceFolderId}&versioningState={versioningState?} + /cmis/s/{store}/i/{id}/children?sourceFolderId={sourceFolderId}&versioningState={versioningState?} - /cmis/p{path}/children?sourceFolderId={sourceFolderId} - /cmis/s/{store}/p{path}/children?sourceFolderId={sourceFolderId} + /cmis/p{path}/children?sourceFolderId={sourceFolderId}&versioningState={versioningState?} + /cmis/s/{store}/p{path}/children?sourceFolderId={sourceFolderId}&versioningState={versioningState?} - /api/node/{store_type}/{store_id}/{id}/children?sourceFolderId={sourceFolderId} - /api/path/{store_type}/{store_id}/{path}/children?sourceFolderId={sourceFolderId} + /api/node/{store_type}/{store_id}/{id}/children?sourceFolderId={sourceFolderId}&versioningState={versioningState?} + /api/path/{store_type}/{store_id}/{path}/children?sourceFolderId={sourceFolderId}&versioningState={versioningState?} user diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/content.delete.js b/config/alfresco/templates/webscripts/org/alfresco/cmis/content.delete.js index 511c32e497..dc291f2517 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/content.delete.js +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/content.delete.js @@ -8,39 +8,10 @@ script: { break script; } - node = object.node; + var node = object.node; - if (!node.hasPermission("Delete")) - { - status.code = 403; - status.message = "Permission to delete is denied"; - status.redirect = true; - break script; - } + cmis.deleteContentStream(node); - // if deleting a folder, only delete when the folder is empty or - // a force delete has been specified - // NOTE: force delete is not part of CMIS specification - if (node.isFolder) - { - if (node.children.length > 0 && !args.includeChildren) - { - status.code = 403; - status.message = "Cannot delete folder " + pathSegments[2] + " " + reference.join("/") + " as it's not empty"; - status.redirect = true; - break script; - } - } - - // Note: checked-out documents are automatically unlocked if a private working copy is deleted - if (!node.remove()) - { - status.code = 500; - status.message = "Failed to delete node " + pathSegments[2] + " " + reference.join("/"); - status.redirect = true; - break script; - } - status.code = 204; // Success, but no response content status.redirect = true; } diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/item.delete.js b/config/alfresco/templates/webscripts/org/alfresco/cmis/item.delete.js index 8db081f016..3d535c101c 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/item.delete.js +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/item.delete.js @@ -10,36 +10,8 @@ script: } var node = object.node; - if (!node.hasPermission("Delete")) - { - status.code = 403; - status.message = "Permission to delete object " + object.ref + " is denied"; - status.redirect = true; - break script; - } - - // if deleting a folder, only delete when the folder is empty or - // a force delete has been specified - // NOTE: force delete is not part of CMIS specification - if (node.isFolder) - { - if (node.children.length > 0 && !args.includeChildren) - { - status.code = 403; - status.message = "Cannot delete folder " + object.ref + " as it's not empty"; - status.redirect = true; - break script; - } - } - - // Note: checked-out documents are automatically unlocked if a private working copy is deleted - if (!node.remove()) - { - status.code = 500; - status.message = "Failed to delete object " + object.ref; - status.redirect = true; - break script; - } + // Intentionally pass false as allVersions flag for now. There is no binding. + cmis.deleteObject(node, false); status.code = 204; // Success, but no response content status.redirect = true; diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/item.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/cmis/item.get.desc.xml index 3341c378da..34b16c87a4 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/item.get.desc.xml +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/item.get.desc.xml @@ -25,7 +25,6 @@ Does not return the content-stream of a document
PropertyCollection includes changeToken (if applicable to repository)
]]> - /cmis/i/{id}?filter={filter?}&returnVersion={returnVersion?}&includeAllowableActions={includeAllowableActions?}&includeACL={includeACL?}&renditionFilter={renditionFilter?} diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/item.get.js b/config/alfresco/templates/webscripts/org/alfresco/cmis/item.get.js index f548eedf82..8054613ab9 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/item.get.js +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/item.get.js @@ -9,7 +9,13 @@ script: } model.node = object.node; - // TODO: handle version?? + // return version + var returnVersion = args[cmis.ARG_RETURN_VERSION]; + if (returnVersion === null || returnVersion.length == 0) + { + returnVersion = "this"; + } + model.node = cmis.getReturnVersion(model.node, returnVersion); // property filter model.filter = args[cmis.ARG_FILTER]; diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/lib/atomentry.lib.atom.ftl b/config/alfresco/templates/webscripts/org/alfresco/cmis/lib/atomentry.lib.atom.ftl index 8d41093833..9cd98ab443 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/lib/atomentry.lib.atom.ftl +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/lib/atomentry.lib.atom.ftl @@ -15,7 +15,7 @@ [#assign typedef = cmistype(object)] [#list typedef.propertyDefinitions?values as propdef] - [@filter propfilter propdef.queryName][@prop propdef.propertyId.id object propdef.dataType.label/][/@filter] + [@filter propfilter propdef.queryName][@prop object propdef/][/@filter] [/#list] [/#macro] @@ -69,7 +69,7 @@ [#-- ATOM Entry for Version --] [#-- --] -[#macro version node version propfilter="*" ns=""] +[#macro version node propfilter="*" ns=""] [@entry ns] ${node.properties.creator!""} [@contentstream node/] @@ -263,10 +263,19 @@ [#assign rowvalues = row.values] [#list rowvalues?keys as colname] [#assign coltype = row.getColumnType(colname)] + [#assign propdef = row.getPropertyDefinition(colname)] [#if rowvalues[colname]??] - [@propvalue colname rowvalues[colname] coltype/] + [#if propdef??] + [@propvalue rowvalues[colname] coltype colname propdef.displayName propdef.queryName propdef.propertyId.localName/] [#else] - [@propnull colname coltype/] + [@propvalue rowvalues[colname] coltype colname/] + [/#if] + [#else] + [#if propdef??] + [@propnull coltype colname propdef.displayName propdef.queryName propdef.propertyId.localName/] + [#else] + [@propnull coltype colname/] + [/#if] [/#if] [/#list] @@ -289,7 +298,7 @@ ${xmldate(event.changeTime)} - [@propvalue "cmis:objectId" node.nodeRef?string cmisconstants.DATATYPE_ID/] + [@propvalue event.objectId cmisconstants.DATATYPE_ID "cmis:objectId"/] ${event.changeType.label} @@ -309,54 +318,63 @@ [#if filter == "*" || filter?index_of(value) != -1 || filter?matches(value,'i')][#nested][/#if] [/#macro] -[#macro prop name object type] -[#assign value=cmisproperty(object, name)/] +[#macro prop object propdef] +[#assign value=cmisproperty(object, propdef.propertyId.id)/] [#if value?is_string || value?is_number || value?is_boolean || value?is_date || value?is_enumerable] -[@propvalue name value type/] +[@propvaluedef value propdef/] [#elseif value.class.canonicalName?ends_with("NULL")] -[@propnull name type/] +[@propnulldef propdef/] [/#if] [/#macro] -[#macro propvalue name value type] +[#macro propvaluedef value propdef] + [@propvalue value propdef.dataType.label propdef.propertyId.id propdef.displayName propdef.queryName propdef.propertyId.localName/] +[/#macro] + +[#macro propvalue value type name displayname="" queryname="" localname=""] [#if type == cmisconstants.DATATYPE_STRING] -[@values value;v][@stringvalue v/][/@values] +[@values value;v][@stringvalue v/][/@values] [#elseif type == cmisconstants.DATATYPE_INTEGER] -[@values value;v][@integervalue v/][/@values] +[@values value;v][@integervalue v/][/@values] [#elseif type == cmisconstants.DATATYPE_DECIMAL] -[@values value;v][@decimalvalue v/][/@values] +[@values value;v][@decimalvalue v/][/@values] [#elseif type == cmisconstants.DATATYPE_BOOLEAN] -[@values value;v][@booleanvalue v/][/@values] +[@values value;v][@booleanvalue v/][/@values] [#elseif type == cmisconstants.DATATYPE_DATETIME] -[@values value;v][@datetimevalue v/][/@values] +[@values value;v][@datetimevalue v/][/@values] [#elseif type == cmisconstants.DATATYPE_URI] [#-- TODO: check validity of abs url prefix --] -[@values value;v][@urivalue absurl(url.serviceContext) + v/][/@values] +[@values value;v][@urivalue absurl(url.serviceContext) + v/][/@values] [#elseif type == cmisconstants.DATATYPE_ID] -[@values value;v][@idvalue v/][/@values] +[@values value;v][@idvalue v/][/@values] [#-- TODO: remaining property types --] [/#if] [/#macro] -[#macro propnull name type] +[#macro propnulldef propdef] + [@propnull propdef.dataType.label propdef.propertyId.id propdef.displayName propdef.queryName propdef.propertyId.localName/] +[/#macro] + +[#macro propnull type name displayname="" queryname="" localname=""] [#if type == cmisconstants.DATATYPE_STRING] - + [#elseif type == cmisconstants.DATATYPE_INTEGER] - + [#elseif type == cmisconstants.DATATYPE_DECIMAL] - + [#elseif type == cmisconstants.DATATYPE_BOOLEAN] - + [#elseif type == cmisconstants.DATATYPE_DATETIME] - + [#elseif type == cmisconstants.DATATYPE_URI] - + [#elseif type == cmisconstants.DATATYPE_ID] - + [#-- TODO: remaining property types --] [/#if] [/#macro] +[#macro propargs name displayname="" queryname="" localname=""]propertyDefinitionId="${name}"[#if displayname != ""] displayName="${displayname}"[/#if][#if queryname != ""] queryName="${queryname}"[/#if][/#macro] [#-- --] [#-- CMIS Values --] diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/lib/links.lib.atom.ftl b/config/alfresco/templates/webscripts/org/alfresco/cmis/lib/links.lib.atom.ftl index 2d43130f1f..57e3f68bc9 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/lib/links.lib.atom.ftl +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/lib/links.lib.atom.ftl @@ -158,7 +158,7 @@ [#macro nodeuri node]/cmis/[@noderef node/][/#macro] [#-- Helper to render Alfresco Assoc uri --] -[#macro assocuri assoc]/cmis/rel/[@noderef assoc.source/]/type/${cmistype(assoc).typeId.id!"undefined"}/target/[@noderef assoc.target/][/#macro] +[#macro assocuri assoc]/cmis/rel/${assoc.associationRef.id}[/#macro] [#-- Helper to render Alfresco Type uri --] [#macro typeuri typedef]/cmis/type/${typedef.typeId.id}[/#macro] diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/lib/modify.lib.js b/config/alfresco/templates/webscripts/org/alfresco/cmis/lib/modify.lib.js index c279058591..4008739c25 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/lib/modify.lib.js +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/lib/modify.lib.js @@ -6,7 +6,7 @@ // @param slug (optional) node name // @return created node (or null, in case of error) // -function createNode(parent, entry, slug) +function createNode(parent, entry, slug, versioningState) { var object = entry.getExtension(atom.names.cmisra_object); var typeId = (object !== null) ? object.objectTypeId.nativeValue : null; @@ -29,7 +29,10 @@ function createNode(parent, entry, slug) if (baseType == DOCUMENT_TYPE_ID) { node = parent.createFile(name); - // TODO: versioningState argument (CheckedOut/CheckedInMinor/CheckedInMajor) + if (versioningState != null) + { + node = cmis.applyVersioningState(node, versioningState); + } } else if (baseType == FOLDER_TYPE_ID) { diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/pwc.delete.js b/config/alfresco/templates/webscripts/org/alfresco/cmis/pwc.delete.js index 25440530fa..855969fcc8 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/pwc.delete.js +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/pwc.delete.js @@ -9,15 +9,7 @@ script: } var node = object.node; - if (!node.hasPermission("CancelCheckOut")) - { - status.code = 403; - status.message = "Permission to cancel checkout of " + object.ref + " is denied"; - status.redirect = true; - break script; - } - - node.cancelCheckout(); + cmis.cancelCheckOut(node); status.code = 204; // Success, but no response content status.redirect = true; diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/pwc.patch.atom.js b/config/alfresco/templates/webscripts/org/alfresco/cmis/pwc.patch.atom.js index 0ffe1854df..605e786a1d 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/pwc.patch.atom.js +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/pwc.patch.atom.js @@ -6,21 +6,9 @@ script: { // locate node var object = getObjectFromUrl(); - if (object.node == null) - { - break script; - } model.node = object.node; - // check permissions model.checkin = args[cmis.ARG_CHECKIN] == "true" ? true : false; - if (model.checkin && !model.node.hasPermission("CheckIn")) - { - status.code = 403; - status.message = "Permission to checkin " + object.ref + " is denied"; - status.redirect = true; - break script; - } if (entry !== null) { @@ -42,6 +30,6 @@ script: var comment = args[cmis.ARG_CHECKIN_COMMENT]; var major = args[cmis.ARG_MAJOR]; major = (major === null || major == "true") ? true : false; - model.node = model.node.checkin(comment === null ? "" : comment, major); + model.node = cmis.checkIn(model.node, comment, major); } } diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/pwc.put.atom.js b/config/alfresco/templates/webscripts/org/alfresco/cmis/pwc.put.atom.js index 8e3a653154..72f22858ea 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/pwc.put.atom.js +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/pwc.put.atom.js @@ -6,21 +6,9 @@ script: { // locate node var object = getObjectFromUrl(); - if (object.node === null || !object.node.hasAspect("cm:workingcopy")) - { - break script; - } model.node = object.node; - // check permissions model.checkin = args[cmis.ARG_CHECKIN] == "true" ? true : false; - if (model.checkin && !model.node.hasPermission("CheckIn")) - { - status.code = 403; - status.message = "Permission to checkin is denied"; - status.redirect = true; - break script; - } if (entry !== null) { @@ -42,6 +30,6 @@ script: var comment = args[cmis.ARG_CHECKIN_COMMENT]; var major = args[cmis.ARG_MAJOR]; major = (major === null || major == "true") ? true : false; - model.node = model.node.checkin(comment === null ? "" : comment, major); + model.node = cmis.checkIn(model.node, comment, major); } } diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/relationship.delete.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/cmis/relationship.delete.desc.xml index 9e134b11a5..4656786121 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/relationship.delete.desc.xml +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/relationship.delete.desc.xml @@ -3,7 +3,7 @@ - /cmis/rel/s/{store}/i/{id}/type/{rel_type}/target/s/{target_store}/i/{target_id} + /cmis/rel/{assoc_id} user diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/relationship.delete.js b/config/alfresco/templates/webscripts/org/alfresco/cmis/relationship.delete.js index e57d3936f1..5acf246a28 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/relationship.delete.js +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/relationship.delete.js @@ -10,15 +10,7 @@ script: } var assoc = rel.assoc; - // TODO: check permission -// if (!assoc.source.hasPermission("DeleteAssociations")) -// { -// status.setCode(403, "Permission to delete is denied"); -// break script; -// } - - // delete - assoc.source.removeAssociation(assoc.target, assoc.type); + cmis.deleteObject(assoc); status.code = 204; // Success, but no response content status.redirect = true; diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/relationship.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/cmis/relationship.get.desc.xml index d4501f728b..b0a6dbb98a 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/relationship.get.desc.xml +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/relationship.get.desc.xml @@ -3,7 +3,7 @@ - /cmis/rel/s/{store}/i/{id}/type/{rel_type}/target/s/{target_store}/i/{target_id}?filter={filter?}&includeAllowableActions={includeAllowableActions?} + /cmis/rel/{assoc_id}?filter={filter?}&includeAllowableActions={includeAllowableActions?} guest diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/tree.delete.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/cmis/tree.delete.desc.xml index 1d23eb01ea..51982a9d87 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/tree.delete.desc.xml +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/tree.delete.desc.xml @@ -4,14 +4,14 @@ - /cmis/i/{id}/tree?continueOnFailure={continueOnFailure?}&unfileMultiFiledDocuments={unfileMultiFiledDocuments} - /cmis/s/{store}/i/{id}/tree?continueOnFailure={continueOnFailure?}&unfileMultiFiledDocuments={unfileMultiFiledDocuments} + /cmis/i/{id}/tree?continueOnFailure={continueOnFailure?}&unfileObjects={unfileObjects} + /cmis/s/{store}/i/{id}/tree?continueOnFailure={continueOnFailure?}&unfileObjects={unfileObjects} - /cmis/p{path}/tree?continueOnFailure={continueOnFailure?}&unfileMultiFiledDocuments={unfileMultiFiledDocuments} - /cmis/s/{store}/p{path}/tree?continueOnFailure={continueOnFailure?}&unfileMultiFiledDocuments={unfileMultiFiledDocuments} + /cmis/p{path}/tree?continueOnFailure={continueOnFailure?}&unfileObjects={unfileObjects} + /cmis/s/{store}/p{path}/tree?continueOnFailure={continueOnFailure?}&unfileObjects={unfileObjects} - /api/node/{store_type}/{store_id}/{id}/tree?continueOnFailure={continueOnFailure?}&unfileMultiFiledDocuments={unfileMultiFiledDocuments} - /api/path/{store_type}/{store_id}/{path}/tree?continueOnFailure={continueOnFailure?}&unfileMultiFiledDocuments={unfileMultiFiledDocuments} + /api/node/{store_type}/{store_id}/{id}/tree?continueOnFailure={continueOnFailure?}&unfileObjects={unfileObjects} + /api/path/{store_type}/{store_id}/{path}/tree?continueOnFailure={continueOnFailure?}&unfileObjects={unfileObjects} user diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/tree.delete.js b/config/alfresco/templates/webscripts/org/alfresco/cmis/tree.delete.js index a05dc78d59..6421ca416a 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/tree.delete.js +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/tree.delete.js @@ -10,27 +10,24 @@ script: } var node = object.node; - // NOTE: Ignore continueOnDelete as complete tree is deleted in single transaction - // TODO: Throw error on invalid unfileMultiFiledDocuments error - - if (!node.hasPermission("Delete")) + // unfileObjects + var unfileObjects = args[cmis.ARG_UNFILE_OBJECTS]; + if (unfileObjects === null || unfileObjects.length == 0) { - status.code = 403; - status.message = "Permission to delete is denied"; - status.redirect = true; - break script; - } - - // TODO: Checked-out documents - are they automatically cancelled? - - if (!node.remove()) - { - status.code = 500; - status.message = "Failed to delete object " + object.ref; - status.redirect = true; - break script; + unfileObjects = "delete"; } - status.code = 204; // Success, but no response content - status.redirect = true; + // We only support delete and deletesinglefiled + if (unfileObjects == "unfile") + { + status.code = 405; + status.message = "Unfiling is not supported"; + status.redirect = true; + break script; + } + + var continueOnFailure = (args[cmis.ARG_CONTINUE_ON_FAILURE] == "true"); + + // Intentionally pass allVersions=false, even though this isn't the default! + cmis.deleteTree(node, status, continueOnFailure, unfileObjects != "delete", false); } diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/versions.get.atomfeed.ftl b/config/alfresco/templates/webscripts/org/alfresco/cmis/versions.get.atomfeed.ftl index 425ee9f3d8..b52b507550 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/versions.get.atomfeed.ftl +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/versions.get.atomfeed.ftl @@ -17,7 +17,7 @@ [/@feedLib.generic] [#list nodes as version] - [@entryLib.version version versions[version_index]/] + [@entryLib.version version/] [/#list] diff --git a/config/alfresco/templates/webscripts/org/alfresco/cmis/versions.get.js b/config/alfresco/templates/webscripts/org/alfresco/cmis/versions.get.js index 739822cfe8..e1b58935d3 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/cmis/versions.get.js +++ b/config/alfresco/templates/webscripts/org/alfresco/cmis/versions.get.js @@ -4,7 +4,7 @@ script: { // NOTE: version series is identified by noderef (as this is constant during lifetime of node) var object = getObjectFromUrl(); - if (object.node == null || !object.node.isVersioned) + if (object.node == null) { status.message = "Versions series " + object.ref + " not found"; break script; @@ -19,10 +19,5 @@ script: } // retrieve versions - model.versions = model.node.versionHistory; - model.nodes = new Array(model.versions.length); - for (i = 0; i < model.versions.length; i++) - { - model.nodes[i] = model.versions[i].node; - } + model.nodes = cmis.getAllVersions(model.node); } diff --git a/config/alfresco/web-scripts-application-context.xml b/config/alfresco/web-scripts-application-context.xml index c754e17eaf..8cdb8197ea 100644 --- a/config/alfresco/web-scripts-application-context.xml +++ b/config/alfresco/web-scripts-application-context.xml @@ -269,6 +269,10 @@
+ + + + cmis @@ -299,7 +303,7 @@ - + diff --git a/source/generated/org/alfresco/repo/cmis/ws/CmisAllowableActionsType.java b/source/generated/org/alfresco/repo/cmis/ws/CmisAllowableActionsType.java index c0141f9351..c4751404f0 100755 --- a/source/generated/org/alfresco/repo/cmis/ws/CmisAllowableActionsType.java +++ b/source/generated/org/alfresco/repo/cmis/ws/CmisAllowableActionsType.java @@ -49,7 +49,6 @@ import org.w3c.dom.Element; * <element name="canCreateDocument" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/> * <element name="canCreateFolder" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/> * <element name="canCreateRelationship" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/> - * <element name="canCreatePolicy" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/> * <element name="canDeleteTree" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/> * <element name="canGetRenditions" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/> * <element name="canGetACL" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/> @@ -91,7 +90,6 @@ import org.w3c.dom.Element; "canCreateDocument", "canCreateFolder", "canCreateRelationship", - "canCreatePolicy", "canDeleteTree", "canGetRenditions", "canGetACL", @@ -125,7 +123,6 @@ public class CmisAllowableActionsType { protected Boolean canCreateDocument; protected Boolean canCreateFolder; protected Boolean canCreateRelationship; - protected Boolean canCreatePolicy; protected Boolean canDeleteTree; protected Boolean canGetRenditions; protected Boolean canGetACL; @@ -735,30 +732,6 @@ public class CmisAllowableActionsType { this.canCreateRelationship = value; } - /** - * Gets the value of the canCreatePolicy property. - * - * @return - * possible object is - * {@link Boolean } - * - */ - public Boolean isCanCreatePolicy() { - return canCreatePolicy; - } - - /** - * Sets the value of the canCreatePolicy property. - * - * @param value - * allowed object is - * {@link Boolean } - * - */ - public void setCanCreatePolicy(Boolean value) { - this.canCreatePolicy = value; - } - /** * Gets the value of the canDeleteTree property. * @@ -873,8 +846,8 @@ public class CmisAllowableActionsType { * *

* Objects of the following type(s) are allowed in the list - * {@link Object } * {@link Element } + * {@link Object } * * */ diff --git a/source/java/org/alfresco/repo/cmis/PropertyFilter.java b/source/java/org/alfresco/repo/cmis/PropertyFilter.java index 7826062fa8..381c39aeb8 100644 --- a/source/java/org/alfresco/repo/cmis/PropertyFilter.java +++ b/source/java/org/alfresco/repo/cmis/PropertyFilter.java @@ -30,7 +30,7 @@ import java.util.regex.Pattern; import org.alfresco.repo.cmis.ws.CmisException; import org.alfresco.repo.cmis.ws.EnumServiceException; -import org.alfresco.repo.cmis.ws.utils.CmisObjectsUtils; +import org.alfresco.repo.cmis.ws.utils.ExceptionUtil; /** * Property filter supporting CMIS filter expression @@ -56,11 +56,11 @@ public class PropertyFilter * @param filter filter value (case insensitive) * @throws FilterNotValidException if filter string isn't valid */ - public PropertyFilter(String filter, CmisObjectsUtils cmisObjectsUtils) throws CmisException + public PropertyFilter(String filter) throws CmisException { if (filter == null || filter.length() < MINIMAL_ALLOWED_STRUCTURE_SIZE ? false : !PROPERTY_FILTER_REGEX.matcher(filter).matches()) { - throw cmisObjectsUtils.createCmisException(("\"" + filter + "\" filter value is invalid"), EnumServiceException.FILTER_NOT_VALID); + throw ExceptionUtil.createCmisException(("\"" + filter + "\" filter value is invalid"), EnumServiceException.FILTER_NOT_VALID); } if (!filter.equals(MATCH_ALL_FILTER) && filter.length() >= MINIMAL_ALLOWED_STRUCTURE_SIZE) diff --git a/source/java/org/alfresco/repo/cmis/PropertyFilterTest.java b/source/java/org/alfresco/repo/cmis/PropertyFilterTest.java index 2de7af62c1..655d245bcd 100755 --- a/source/java/org/alfresco/repo/cmis/PropertyFilterTest.java +++ b/source/java/org/alfresco/repo/cmis/PropertyFilterTest.java @@ -28,7 +28,6 @@ import junit.framework.TestCase; import org.alfresco.repo.cmis.ws.CmisException; import org.alfresco.repo.cmis.ws.EnumServiceException; -import org.alfresco.repo.cmis.ws.utils.CmisObjectsUtils; /** * @author Dmitry Velichkevich @@ -59,23 +58,21 @@ public class PropertyFilterTest extends TestCase private static final String INVALID_FILTER_WITH_DENIED_SYMBOL = "ObjectId; name"; private static final String INVALID_FILTER_WITH_LAST_INVALID_SYMBOL = "ObjectId, name*"; - private CmisObjectsUtils cmisObjectsUtils = new CmisObjectsUtils(); - public void testValidFilters() throws Exception { try { allTokensValidAssertion(new PropertyFilter()); - allTokensValidAssertion(new PropertyFilter(VALID_MATCHE_ALL_EMPTY_FILTER, cmisObjectsUtils)); - allTokensValidAssertion(new PropertyFilter(VALID_MATCHE_ALL_FILTER, cmisObjectsUtils)); + allTokensValidAssertion(new PropertyFilter(VALID_MATCHE_ALL_EMPTY_FILTER)); + allTokensValidAssertion(new PropertyFilter(VALID_MATCHE_ALL_FILTER)); - onlyNameTokensAssertionValid(new PropertyFilter(VALID_FILTER_WITH_NAME, cmisObjectsUtils)); + onlyNameTokensAssertionValid(new PropertyFilter(VALID_FILTER_WITH_NAME)); - nameAndObjectIdTokensAssertionValid(new PropertyFilter(VALID_FILTER_WITH_SEVERAL_TOKENS, cmisObjectsUtils)); - nameAndObjectIdTokensAssertionValid(new PropertyFilter(LONG_VALID_FILTER_WITH_SEVERAL_TOKENS, cmisObjectsUtils)); - nameAndObjectIdTokensAssertionValid(new PropertyFilter(VALID_FILTER_WITH_SEVERAL_TOKENS_WITHOUT_BREAKS, cmisObjectsUtils)); - nameAndObjectIdTokensAssertionValid(new PropertyFilter(VALID_FILTER_WITH_SEVERAL_TOKENS_AND_WITH_BREAKS_IN_SOME_PLACES, cmisObjectsUtils)); - nameAndObjectIdTokensAssertionValid(new PropertyFilter(VALID_FILTER_WITH_SEVERAL_TOKENS_AND_WITH_SEVERAL_BREAKS_IN_SOME_PLACES, cmisObjectsUtils)); + nameAndObjectIdTokensAssertionValid(new PropertyFilter(VALID_FILTER_WITH_SEVERAL_TOKENS)); + nameAndObjectIdTokensAssertionValid(new PropertyFilter(LONG_VALID_FILTER_WITH_SEVERAL_TOKENS)); + nameAndObjectIdTokensAssertionValid(new PropertyFilter(VALID_FILTER_WITH_SEVERAL_TOKENS_WITHOUT_BREAKS)); + nameAndObjectIdTokensAssertionValid(new PropertyFilter(VALID_FILTER_WITH_SEVERAL_TOKENS_AND_WITH_BREAKS_IN_SOME_PLACES)); + nameAndObjectIdTokensAssertionValid(new PropertyFilter(VALID_FILTER_WITH_SEVERAL_TOKENS_AND_WITH_SEVERAL_BREAKS_IN_SOME_PLACES)); } catch (Throwable e) { @@ -144,7 +141,7 @@ public class PropertyFilterTest extends TestCase { try { - new PropertyFilter(filterValue, cmisObjectsUtils); + new PropertyFilter(filterValue); fail("Invalid filter \"" + filterValue + "\" was interpreted as valid"); } diff --git a/source/java/org/alfresco/repo/cmis/reference/AVMPathReference.java b/source/java/org/alfresco/repo/cmis/reference/AVMPathReference.java new file mode 100644 index 0000000000..dde4b797fa --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/reference/AVMPathReference.java @@ -0,0 +1,66 @@ +/* + * 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.repo.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 + "]"; + } + +} diff --git a/source/java/org/alfresco/repo/cmis/reference/AbstractObjectReference.java b/source/java/org/alfresco/repo/cmis/reference/AbstractObjectReference.java new file mode 100644 index 0000000000..730cbdc7e2 --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/reference/AbstractObjectReference.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have received a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.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; + } +} diff --git a/source/java/org/alfresco/repo/cmis/reference/AbstractRepositoryReference.java b/source/java/org/alfresco/repo/cmis/reference/AbstractRepositoryReference.java new file mode 100644 index 0000000000..7f506ee55d --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/reference/AbstractRepositoryReference.java @@ -0,0 +1,56 @@ +/* + * 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.repo.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(); + } + +} diff --git a/source/java/org/alfresco/repo/cmis/reference/AssociationIdRelationshipReference.java b/source/java/org/alfresco/repo/cmis/reference/AssociationIdRelationshipReference.java new file mode 100644 index 0000000000..5d3e49c9b0 --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/reference/AssociationIdRelationshipReference.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have received a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.reference; + +import org.alfresco.cmis.CMISRelationshipReference; +import org.alfresco.cmis.CMISRepositoryReference; +import org.alfresco.cmis.CMISServiceException; +import org.alfresco.cmis.CMISServices; +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.springframework.extensions.webscripts.WebScriptException; + +/** + * Association ID relationship reference. An association ID can be resolved to an {@link AssociationRef}. + * + * @author dward + */ +public class AssociationIdRelationshipReference implements CMISRelationshipReference +{ + private CMISServices cmisServices; + private String assocId; + + /** + * Construct + * + * @param cmisServices + * @param assocId + */ + public AssociationIdRelationshipReference(CMISServices cmisServices, String assocId) + { + this.cmisServices = cmisServices; + this.assocId = assocId; + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISRelationshipReference#getAssocRef() + */ + public AssociationRef getAssocRef() + { + try + { + return cmisServices.getReadableObject(CMISServices.ASSOC_ID_PREFIX + this.assocId, AssociationRef.class); + } + catch (CMISServiceException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISObjectReference#getRepositoryReference() + */ + public CMISRepositoryReference getRepositoryReference() + { + return new AbstractRepositoryReference(cmisServices) + { + public StoreRef getStoreRef() + { + return getAssocRef().getSourceRef().getStoreRef(); + } + }; + } + + @Override + public String toString() + { + return "AssociationIdRelationshipReference[assocId=" + this.assocId + "]"; + } +} diff --git a/source/java/org/alfresco/repo/cmis/reference/DefaultRepositoryReference.java b/source/java/org/alfresco/repo/cmis/reference/DefaultRepositoryReference.java new file mode 100644 index 0000000000..be059c1bc9 --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/reference/DefaultRepositoryReference.java @@ -0,0 +1,57 @@ +/* + * 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.repo.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(); + } + +} diff --git a/source/java/org/alfresco/repo/cmis/reference/NodeIdReference.java b/source/java/org/alfresco/repo/cmis/reference/NodeIdReference.java new file mode 100644 index 0000000000..4c8cbf1618 --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/reference/NodeIdReference.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have received a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.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. This class decodes node 'paths' generated by links.lib.atom.ftl. These are not the same as + * CMIS object IDs. + * + * @author davidc + */ +public class NodeIdReference extends AbstractObjectReference +{ + private String id; + private String[] reference; + + /** + * Construct + * + * @param cmisServices + * @param repo + * @param id + */ + public NodeIdReference(CMISServices cmisServices, CMISRepositoryReference repo, String id) + { + super(cmisServices, repo); + + this.id = id; + + 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 "NodeIdReference[storeRef=" + repo.getStoreRef() + ",id=" + id + "]"; + } + +} diff --git a/source/java/org/alfresco/repo/cmis/reference/ObjectIdReference.java b/source/java/org/alfresco/repo/cmis/reference/ObjectIdReference.java new file mode 100644 index 0000000000..90111e25bc --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/reference/ObjectIdReference.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have received a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.reference; + +import org.alfresco.cmis.CMISObjectReference; +import org.alfresco.cmis.CMISRepositoryReference; +import org.alfresco.cmis.CMISServiceException; +import org.alfresco.cmis.CMISServices; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.springframework.extensions.webscripts.WebScriptException; + +/** + * CMIS Object ID reference. A CMIS object ID encapsulates both a store and a node and identifies a specific version. + * + * @author dward + */ +public class ObjectIdReference implements CMISObjectReference +{ + private CMISServices cmisServices; + private String objectId; + + /** + * Construct + * + * @param cmisServices + * @param storeRef + */ + public ObjectIdReference(CMISServices cmisServices, String objectId) + { + this.cmisServices = cmisServices; + this.objectId = objectId; + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISObjectReference#getNodeRef() + */ + public NodeRef getNodeRef() + { + try + { + return cmisServices.getReadableObject(this.objectId, NodeRef.class); + } + catch (CMISServiceException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } + } + + /* + * (non-Javadoc) + * @see org.alfresco.cmis.CMISObjectReference#getRepositoryReference() + */ + public CMISRepositoryReference getRepositoryReference() + { + return new AbstractRepositoryReference(cmisServices) + { + public StoreRef getStoreRef() + { + return getNodeRef().getStoreRef(); + } + }; + } + + @Override + public String toString() + { + return "ObjectIdReference[objectId=" + this.objectId + "]"; + } + +} diff --git a/source/java/org/alfresco/repo/cmis/reference/ObjectPathReference.java b/source/java/org/alfresco/repo/cmis/reference/ObjectPathReference.java new file mode 100644 index 0000000000..e3fabc4182 --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/reference/ObjectPathReference.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have received a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.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/repo/cmis/reference/ReferenceFactory.java b/source/java/org/alfresco/repo/cmis/reference/ReferenceFactory.java new file mode 100644 index 0000000000..7f0199be29 --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/reference/ReferenceFactory.java @@ -0,0 +1,145 @@ +/* + * 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.repo.cmis.reference; + +import java.util.Map; + +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; + + +/** + * Reference Factory + * + * @author davidc + */ +public class ReferenceFactory +{ + private CMISServices cmisService; + + /** + * @param cmisService + */ + public void setCMISService(CMISServices cmisService) + { + this.cmisService = cmisService; + } + + /** + * 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) + { + // Despite the name of this argument, it is included in the "Object by ID" URL template and actually accepts a + // value in object ID format (including version label suffix) so should be parsed as an object ID rather than a + // NodeRef + String objectId = args.get("noderef"); + if (objectId != null) + { + return new ObjectIdReference(cmisService, objectId); + } + + CMISRepositoryReference repo = createRepoReferenceFromUrl(args, templateArgs); + String id = templateArgs.get("id"); + if (id != null) + { + return new NodeIdReference(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) + { + String assocId = templateArgs.get("assoc_id"); + if (assocId != null) + { + return new AssociationIdRelationshipReference(cmisService, assocId); + } + return null; + } + +} diff --git a/source/java/org/alfresco/repo/cmis/reference/SourceTypeTargetRelationshipReference.java b/source/java/org/alfresco/repo/cmis/reference/SourceTypeTargetRelationshipReference.java new file mode 100644 index 0000000000..fe0d5a2cdb --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/reference/SourceTypeTargetRelationshipReference.java @@ -0,0 +1,93 @@ +/* + * 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.repo.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/repo/cmis/reference/StoreRepositoryReference.java b/source/java/org/alfresco/repo/cmis/reference/StoreRepositoryReference.java new file mode 100644 index 0000000000..6a01a92cf9 --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/reference/StoreRepositoryReference.java @@ -0,0 +1,86 @@ +/* + * 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.repo.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/repo/cmis/rest/CMISChildrenMethod.java b/source/java/org/alfresco/repo/cmis/rest/CMISChildrenMethod.java index ff6c1a5ec4..d196ef38a9 100644 --- a/source/java/org/alfresco/repo/cmis/rest/CMISChildrenMethod.java +++ b/source/java/org/alfresco/repo/cmis/rest/CMISChildrenMethod.java @@ -26,6 +26,7 @@ package org.alfresco.repo.cmis.rest; import java.util.List; +import org.alfresco.cmis.CMISInvalidArgumentException; import org.alfresco.cmis.CMISServices; import org.alfresco.cmis.CMISTypesFilterEnum; import org.alfresco.repo.template.TemplateNode; @@ -33,6 +34,7 @@ import org.alfresco.repo.web.scripts.RepositoryImageResolver; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.TemplateImageResolver; +import org.springframework.extensions.webscripts.WebScriptException; import freemarker.ext.beans.BeanModel; import freemarker.template.TemplateMethodModelEx; @@ -98,7 +100,15 @@ public class CMISChildrenMethod implements TemplateMethodModelEx } // query children - NodeRef[] childNodeRefs = cmisService.getChildren(nodeRef, typesFilter); + NodeRef[] childNodeRefs; + try + { + childNodeRefs = cmisService.getChildren(nodeRef, typesFilter, null); + } + catch (CMISInvalidArgumentException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } children = new TemplateNode[childNodeRefs.length]; for (int i = 0; i < childNodeRefs.length; i++) { diff --git a/source/java/org/alfresco/repo/cmis/rest/CMISPropertyValueMethod.java b/source/java/org/alfresco/repo/cmis/rest/CMISPropertyValueMethod.java index 7bb8933372..8e39aeed03 100644 --- a/source/java/org/alfresco/repo/cmis/rest/CMISPropertyValueMethod.java +++ b/source/java/org/alfresco/repo/cmis/rest/CMISPropertyValueMethod.java @@ -26,9 +26,11 @@ package org.alfresco.repo.cmis.rest; import java.util.List; +import org.alfresco.cmis.CMISInvalidArgumentException; import org.alfresco.cmis.CMISServices; import org.alfresco.repo.template.TemplateAssociation; import org.alfresco.repo.template.TemplateNode; +import org.springframework.extensions.webscripts.WebScriptException; import freemarker.ext.beans.BeanModel; import freemarker.ext.beans.BeansWrapper; @@ -90,7 +92,14 @@ public final class CMISPropertyValueMethod implements TemplateMethodModelEx if (wrapped != null && wrapped instanceof TemplateNode) { // retrieve property value from node - result = cmisService.getProperty(((TemplateNode)wrapped).getNodeRef(), propertyName); + try + { + result = cmisService.getProperty(((TemplateNode)wrapped).getNodeRef(), propertyName); + } + catch (CMISInvalidArgumentException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } } else if (wrapped != null && wrapped instanceof TemplateAssociation) { diff --git a/source/java/org/alfresco/repo/cmis/rest/CMISRenditionsMethod.java b/source/java/org/alfresco/repo/cmis/rest/CMISRenditionsMethod.java index 96054879e6..d94d08f4df 100644 --- a/source/java/org/alfresco/repo/cmis/rest/CMISRenditionsMethod.java +++ b/source/java/org/alfresco/repo/cmis/rest/CMISRenditionsMethod.java @@ -27,12 +27,14 @@ package org.alfresco.repo.cmis.rest; import java.util.List; import java.util.Map; +import org.alfresco.cmis.CMISFilterNotValidException; import org.alfresco.cmis.CMISServices; import org.alfresco.repo.template.TemplateNode; import org.alfresco.repo.web.scripts.RepositoryImageResolver; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.TemplateImageResolver; import org.alfresco.service.cmr.repository.TemplateValueConverter; +import org.springframework.extensions.webscripts.WebScriptException; import freemarker.ext.beans.BeanModel; import freemarker.template.TemplateMethodModelEx; @@ -102,7 +104,15 @@ public class CMISRenditionsMethod implements TemplateMethodModelEx // query renditions if (nodeRef != null) { - Map renditions = cmisService.getRenditions(nodeRef, renditionFilter); + Map renditions; + try + { + renditions = cmisService.getRenditions(nodeRef, renditionFilter); + } + catch (CMISFilterNotValidException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } return templateValueConverter.convertValue(renditions, imageResolver); } diff --git a/source/java/org/alfresco/repo/cmis/rest/CMISScript.java b/source/java/org/alfresco/repo/cmis/rest/CMISScript.java index a9bffa4de0..8ffb6354b1 100644 --- a/source/java/org/alfresco/repo/cmis/rest/CMISScript.java +++ b/source/java/org/alfresco/repo/cmis/rest/CMISScript.java @@ -41,7 +41,10 @@ import org.alfresco.cmis.CMISCapabilityChanges; import org.alfresco.cmis.CMISChangeEvent; import org.alfresco.cmis.CMISChangeLog; import org.alfresco.cmis.CMISChangeLogService; +import org.alfresco.cmis.CMISConstraintException; +import org.alfresco.cmis.CMISDictionaryModel; import org.alfresco.cmis.CMISDictionaryService; +import org.alfresco.cmis.CMISInvalidArgumentException; import org.alfresco.cmis.CMISJoinEnum; import org.alfresco.cmis.CMISObjectReference; import org.alfresco.cmis.CMISPermissionDefinition; @@ -54,14 +57,15 @@ import org.alfresco.cmis.CMISRelationshipDirectionEnum; import org.alfresco.cmis.CMISRelationshipReference; import org.alfresco.cmis.CMISRepositoryReference; import org.alfresco.cmis.CMISResultSet; +import org.alfresco.cmis.CMISServiceException; import org.alfresco.cmis.CMISServices; import org.alfresco.cmis.CMISTypeDefinition; import org.alfresco.cmis.CMISTypesFilterEnum; +import org.alfresco.cmis.CMISVersioningStateEnum; import org.alfresco.cmis.CMISQueryOptions.CMISQueryMode; import org.alfresco.cmis.acl.CMISAccessControlEntryImpl; -import org.alfresco.cmis.reference.NodeRefReference; -import org.alfresco.cmis.reference.ReferenceFactory; -import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.cmis.reference.ObjectIdReference; +import org.alfresco.repo.cmis.reference.ReferenceFactory; import org.alfresco.repo.jscript.Association; import org.alfresco.repo.jscript.BaseScopableProcessorExtension; import org.alfresco.repo.jscript.ScriptNode; @@ -73,16 +77,18 @@ import org.alfresco.repo.web.util.paging.Paging; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.namespace.QName; import org.mozilla.javascript.Context; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptableObject; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; /** - * CMIS Javascript API + * CMIS Javascript API. * - * @author davic + * @author davidc + * @author dward */ public class CMISScript extends BaseScopableProcessorExtension { @@ -117,12 +123,13 @@ public class CMISScript extends BaseScopableProcessorExtension public static final String ARG_THIS_VERSION = "thisVersion"; public static final String ARG_TYPE_ID = "typeId"; public static final String ARG_TYPES = "types"; - public static final String ARG_UNFILE_MULTIFILE_DOCUMENTS = "unfileMultiFiledDocuments"; + public static final String ARG_UNFILE_OBJECTS = "unfileObjects"; public static final String ARG_VERSIONING_STATE = "versioningState"; public static final String ARG_SOURCE_FOLDER_ID = "sourceFolderId"; public static final String ARG_INCLUDE_ACL = "includeACL"; public static final String ARG_RENDITION_FILTER = "renditionFilter"; public static final String ARG_CHANGE_LOG_TOKEN = "changeLogToken"; + public static final String ARG_ORDER_BY = "orderBy"; // service dependencies private ServiceRegistry services; @@ -147,9 +154,10 @@ public class CMISScript extends BaseScopableProcessorExtension } /** - * Set the paging helper + * Set the paging helper. * * @param paging + * the paging helper */ public void setPaging(Paging paging) { @@ -157,9 +165,10 @@ public class CMISScript extends BaseScopableProcessorExtension } /** - * Set the CMIS Service + * Set the CMIS Service. * * @param cmisService + * the cmis service */ public void setCMISService(CMISServices cmisService) { @@ -167,9 +176,10 @@ public class CMISScript extends BaseScopableProcessorExtension } /** - * Set the CMIS Dictionary Service + * Set the CMIS Dictionary Service. * * @param cmisDictionaryService + * the cmis dictionary service */ public void setCMISDictionaryService(CMISDictionaryService cmisDictionaryService) { @@ -177,9 +187,10 @@ public class CMISScript extends BaseScopableProcessorExtension } /** - * Set the CMIS Query Service + * Set the CMIS Query Service. * * @param cmisQueryService + * the cmis query service */ public void setCMISQueryService(CMISQueryService cmisQueryService) { @@ -208,9 +219,10 @@ public class CMISScript extends BaseScopableProcessorExtension } /** - * Set the CMIS Reference Factory - * + * Set the CMIS Reference Factory. + * * @param referenceFactory + * the reference factory */ public void setCMISReferenceFactory(ReferenceFactory referenceFactory) { @@ -337,7 +349,7 @@ public class CMISScript extends BaseScopableProcessorExtension */ public CMISObjectReference createObjectIdReference(String objectId) { - return new NodeRefReference(cmisService, objectId); + return new ObjectIdReference(cmisService, objectId); } /** @@ -375,15 +387,29 @@ public class CMISScript extends BaseScopableProcessorExtension /** * Query for node children * - * @param parent node to query children for - * @param typesFilter types filter - * @param page page to query for - * @return paged result set of children + * @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 + * @param page + * page to query for + * @return paged result set of children */ - public PagedResults queryChildren(ScriptNode parent, String typesFilter, Page page) + public PagedResults queryChildren(ScriptNode parent, String typesFilter, String orderBy, Page page) { CMISTypesFilterEnum filter = resolveTypesFilter(typesFilter); - NodeRef[] children = cmisService.getChildren(parent.getNodeRef(), filter); + NodeRef[] children; + try + { + children = cmisService.getChildren(parent.getNodeRef(), filter, orderBy); + } + catch (CMISInvalidArgumentException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } Cursor cursor = paging.createCursor(children.length, page); ScriptNode[] nodes = new ScriptNode[cursor.getRowCount()]; @@ -408,7 +434,15 @@ public class CMISScript extends BaseScopableProcessorExtension */ public PagedResults queryRelationships(ScriptNode node, CMISTypeDefinition relDef, boolean includeSubTypes, CMISRelationshipDirectionEnum direction, Page page) { - AssociationRef[] relationships = cmisService.getRelationships(node.getNodeRef(), relDef, includeSubTypes, direction); + AssociationRef[] relationships; + try + { + relationships = cmisService.getRelationships(node.getNodeRef(), relDef, includeSubTypes, direction); + } + catch (CMISInvalidArgumentException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } Cursor cursor = paging.createCursor(relationships.length, page); Association[] assocs = new Association[cursor.getRowCount()]; @@ -421,31 +455,6 @@ public class CMISScript extends BaseScopableProcessorExtension return results; } - /** - * Query for items checked-out to user - * - * @param username user - * @param page - * @return paged result set of checked-out items - */ - public PagedResults queryCheckedOut(String username, Page page) - { - return queryCheckedOut(username, null, false, page); - } - - /** - * Query for items checked-out to user within folder - * - * @param username user - * @param folder folder - * @param page - * @return paged result set of checked-out items - */ - public PagedResults queryCheckedOut(String username, ScriptNode folder, Page page) - { - return queryCheckedOut(username, folder, false, page); - } - /** * Query for items checked-out to user within folder (and possibly descendants) * @@ -457,7 +466,15 @@ public class CMISScript extends BaseScopableProcessorExtension */ public PagedResults queryCheckedOut(String username, ScriptNode folder, boolean includeDescendants, Page page) { - NodeRef[] checkedout = cmisService.getCheckedOut(username, (folder == null) ? null : folder.getNodeRef(), includeDescendants); + NodeRef[] checkedout; + try + { + checkedout = cmisService.getCheckedOut(username, (folder == null) ? null : folder.getNodeRef(), includeDescendants, null); + } + catch (CMISInvalidArgumentException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } Cursor cursor = paging.createCursor(checkedout.length, page); ScriptNode[] nodes = new ScriptNode[cursor.getRowCount()]; for (int i = cursor.getStartRow(); i <= cursor.getEndRow(); i++) @@ -470,15 +487,18 @@ public class CMISScript extends BaseScopableProcessorExtension } /** - * Query for child types (of a given type), or the base types (if no type given) + * Query for child types (of a given type), or the base types (if no type given). * * @param typeDef + * the type def * @param page - * @return + * the page + * @return the paged results */ public PagedResults queryTypeChildren(CMISTypeDefinition typeDef, Page page) { - Collection children = (typeDef == null) ? cmisDictionaryService.getBaseTypes() : typeDef.getSubTypes(false); + Collection children = (typeDef == null) ? cmisService.getBaseTypes() : typeDef + .getSubTypes(false); Cursor cursor = paging.createCursor(children.size(), page); // skip @@ -500,47 +520,49 @@ public class CMISScript extends BaseScopableProcessorExtension } /** - * Query for a Type Definition given a CMIS Type Id + * Query for a Type Definition given a CMIS Type Id. * - * @param page - * @return CMIS Type Definition + * @param typeId + * the type id + * @return CMIS Type Definition */ public CMISTypeDefinition queryType(String typeId) { try { - return cmisDictionaryService.findType(typeId); + return cmisService.getTypeDefinition(typeId); } - catch(AlfrescoRuntimeException e) + catch (CMISInvalidArgumentException e) { - return null; + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); } } /** - * Query the Type Definition for the given Node + * Query the Type Definition for the given Node. * * @param node - * @return CMIS Type Definition + * the node + * @return CMIS Type Definition */ public CMISTypeDefinition queryType(ScriptNode node) { try { - QName typeQName = node.getQNameType(); - return cmisDictionaryService.findTypeForClass(typeQName); + return cmisService.getTypeDefinition(node.getNodeRef()); } - catch(AlfrescoRuntimeException e) + catch (CMISInvalidArgumentException e) { - return null; + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); } } /** - * Query the Property Definition for the given Property + * Query the Property Definition for the given Property. * * @param propertyName - * @return + * the property name + * @return the CMIS property definition */ public CMISPropertyDefinition queryProperty(String propertyName) { @@ -553,8 +575,8 @@ public class CMISScript extends BaseScopableProcessorExtension /** * Can you query the private working copy of a document. - * - * @return + * + * @return is the PWC searchable? */ public boolean getPwcSearchable() { @@ -576,7 +598,7 @@ public class CMISScript extends BaseScopableProcessorExtension /** * Get the query support level. * - * @return + * @return the query support level */ public CMISQueryEnum getQuerySupport() { @@ -586,7 +608,7 @@ public class CMISScript extends BaseScopableProcessorExtension /** * Get the join support level in queries. * - * @return + * @return the join support level */ public CMISJoinEnum getJoinSupport() { @@ -594,12 +616,13 @@ public class CMISScript extends BaseScopableProcessorExtension } /** - * Issue query + * Issue query. * - * @param statement query statement + * @param statement + * query statement * @param page - * - * @return paged result set + * the page + * @return paged result set */ public PagedResults query(String statement, Page page) { @@ -624,7 +647,7 @@ public class CMISScript extends BaseScopableProcessorExtension } /** - * Gets the supported permission types + * Gets the supported permission types. * * @return the supported permission types */ @@ -645,6 +668,7 @@ public class CMISScript extends BaseScopableProcessorExtension /** * Get all the permissions defined by the repository. + * * @return a list of permissions */ public List getRepositoryPermissions() @@ -655,6 +679,7 @@ public class CMISScript extends BaseScopableProcessorExtension /** * Get the list of permission mappings. + * * @return get the permission mapping as defined by the CMIS specification. */ public List getPermissionMappings() @@ -684,6 +709,16 @@ public class CMISScript extends BaseScopableProcessorExtension return cmisAccessControlService.getPrincipalAnyone(); } + /** + * Applies an ACL to a node. + * + * @param node + * the node + * @param principalIds + * the principal IDs + * @param permissions + * the permissions for each principal ID + */ @SuppressWarnings("unchecked") public void applyACL(ScriptNode node, Serializable principalIds, Serializable permissions) { @@ -694,7 +729,15 @@ public class CMISScript extends BaseScopableProcessorExtension { acesToApply.add(new CMISAccessControlEntryImpl(principalList.get(i), permissionList.get(i))); } - cmisAccessControlService.applyAcl(node.getNodeRef(), acesToApply); + try + { + cmisAccessControlService.applyAcl(node.getNodeRef(), acesToApply); + } + catch (CMISConstraintException e) + { + // Force the appropriate status code on error + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } } /** @@ -779,7 +822,7 @@ public class CMISScript extends BaseScopableProcessorExtension Scriptable changeNodes = cx.newArray(scope, size); for (int i = 0; i < size; i++) { - ScriptableObject.putProperty(changeNodes, i, new ScriptNode(changeEvents.get(i).getNode(), services, + ScriptableObject.putProperty(changeNodes, i, new ScriptNode(changeEvents.get(i).getChangedNode(), services, scope)); } ScriptableObject.putProperty(changeLogMap, "changeNodes", changeNodes); @@ -811,9 +854,298 @@ public class CMISScript extends BaseScopableProcessorExtension } return changeLogMap; } + catch (CMISInvalidArgumentException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } finally { Context.exit(); } } + + /** + * Applies a versioning state to a new node, potentially resulting in a new node. + * + * @param source + * the source + * @param versioningState + * the versioning state + * @return the node to write changes to + * @throws CMISConstraintException + */ + public ScriptNode applyVersioningState(ScriptNode source, String versioningState) + { + CMISVersioningStateEnum versioningStateEnum = CMISVersioningStateEnum.FACTORY.fromLabel(versioningState); + try + { + return new ScriptNode(cmisService.applyVersioningState(source.getNodeRef(), versioningStateEnum), services, + getScope()); + } + catch (CMISServiceException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } + } + + /** + * Checks out an object by ID. + * + * @param objectId + * the object id + * @return the private working copy node + */ + public ScriptNode checkOut(String objectId) + { + try + { + return new ScriptNode(cmisService.checkOut(objectId), services, getScope()); + } + catch (CMISServiceException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } + } + + /** + * Checks in a given private working copy node. + * + * @param source + * the node + * @param checkinComment + * the checkin comment + * @param isMajor + * is this a major version? + * @return the checked-in node + */ + public ScriptNode checkIn(ScriptNode source, String checkinComment, boolean isMajor) + { + try + { + return new ScriptNode(cmisService.checkIn((String) cmisService.getProperty(source.getNodeRef(), CMISDictionaryModel.PROP_OBJECT_ID), checkinComment, isMajor), services, + getScope()); + } + catch (CMISServiceException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } + } + + /** + * Cancels a check out. + * + * @param source + * the private working copy + */ + public void cancelCheckOut(ScriptNode source) + { + try + { + cmisService.cancelCheckOut((String) cmisService.getProperty(source.getNodeRef(), + CMISDictionaryModel.PROP_OBJECT_ID)); + } + catch (CMISServiceException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } + } + + /** + * Gets all the versions of a node. + * + * @param source + * the node + * @return a Javascript array of all the versions + */ + public Scriptable getAllVersions(ScriptNode source) + { + Scriptable scope = getScope(); + Context cx = Context.enter(); + try + { + List allVersions = cmisService.getAllVersions((String) cmisService.getProperty( + source.getNodeRef(), CMISDictionaryModel.PROP_OBJECT_ID)); + // Wrap the version + int size = allVersions.size(); + Scriptable allVersionsArr = cx.newArray(scope, size); + for (int i = 0; i < size; i++) + { + ScriptableObject.putProperty(allVersionsArr, i, new ScriptNode(allVersions.get(i), services, scope)); + } + return allVersionsArr; + } + catch (CMISServiceException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } + finally + { + Context.exit(); + } + } + + /** + * Gets the required version of a node + * + * @param source + * the node + * @param returnVersion + * value indicating version required + * @return the version + */ + public ScriptNode getReturnVersion(ScriptNode source, String returnVersion) + { + if (returnVersion == null || returnVersion.equals("this")) + { + return source; + } + try + { + return new ScriptNode(cmisService.getLatestVersion((String) cmisService.getProperty(source.getNodeRef(), + CMISDictionaryModel.PROP_OBJECT_ID), returnVersion.equals("latestmajor")), services, getScope()); + } + catch (CMISServiceException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } + } + + /** + * Attempts to delete a folder and all of its children, recording the status in the given status object. + * + * @param source + * the folder node + * @param status + * the status + * @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? + */ + public void deleteTree(ScriptNode source, Status status, boolean continueOnFailure, boolean unfile, + boolean deleteAllVersions) + { + // Let's avoid all deletions getting rolled back by catching the exception and setting the status ourselves + try + { + cmisService.deleteTreeReportLastError((String) cmisService.getProperty(source.getNodeRef(), + CMISDictionaryModel.PROP_OBJECT_ID), continueOnFailure, unfile, deleteAllVersions); + // Success, but no response content + status.setCode(Status.STATUS_NO_CONTENT); + status.setRedirect(true); + } + catch (CMISServiceException e) + { + status.setCode(e.getStatusCode()); + status.setMessage(e.getMessage()); + status.setRedirect(true); + } + } + + /** + * Deletes a node's content stream. + * + * @param source + * the node + */ + public void deleteContentStream(ScriptNode source) + { + try + { + cmisService.deleteContentStream((String) cmisService.getProperty(source.getNodeRef(), + CMISDictionaryModel.PROP_OBJECT_ID)); + } + catch (CMISServiceException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } + } + + /** + * Deletes a node. + * + * @param source + * the node + * @param allVersions + * should we delete all the versions of the node? + */ + public void deleteObject(ScriptNode source, boolean allVersions) + { + try + { + cmisService.deleteObject((String) cmisService.getProperty(source.getNodeRef(), + CMISDictionaryModel.PROP_OBJECT_ID), allVersions); + } + catch (CMISServiceException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } + } + + /** + * Deletes an association. + * + * @param assoc + * the association + */ + public void deleteObject(Association assoc) + { + try + { + cmisService.deleteObject((String) cmisService.getProperty(assoc.getAssociationRef(), + CMISDictionaryModel.PROP_OBJECT_ID), true); + } + catch (CMISServiceException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } + } + + /** + * Adds an object to a folder. + * + * @param child + * the object to add + * @param parent + * the folder + */ + public void addObjectToFolder(ScriptNode child, ScriptNode parent) + { + try + { + cmisService.addObjectToFolder((String) cmisService.getProperty(child.getNodeRef(), + CMISDictionaryModel.PROP_OBJECT_ID), (String) cmisService.getProperty(parent.getNodeRef(), + CMISDictionaryModel.PROP_OBJECT_ID)); + } + catch (CMISServiceException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } + } + + /** + * Moves an object from a source folder to a target folder. + * + * @param child + * the object to move + * @param targetFolder + * the target folder + * @param sourceFolderId + * the source folder object ID + */ + public void moveObject(ScriptNode child, ScriptNode targetFolder, String sourceFolderId) + { + try + { + cmisService.moveObject((String) cmisService.getProperty(child.getNodeRef(), + CMISDictionaryModel.PROP_OBJECT_ID), (String) cmisService.getProperty(targetFolder.getNodeRef(), + CMISDictionaryModel.PROP_OBJECT_ID), sourceFolderId); + } + catch (CMISServiceException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } + } } diff --git a/source/java/org/alfresco/repo/cmis/rest/CMISTemplateResultSet.java b/source/java/org/alfresco/repo/cmis/rest/CMISTemplateResultSet.java index 25814f6356..080b6c896f 100644 --- a/source/java/org/alfresco/repo/cmis/rest/CMISTemplateResultSet.java +++ b/source/java/org/alfresco/repo/cmis/rest/CMISTemplateResultSet.java @@ -31,6 +31,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import org.alfresco.cmis.CMISPropertyDefinition; import org.alfresco.cmis.CMISResultSet; import org.alfresco.cmis.CMISResultSetColumn; import org.alfresco.cmis.CMISResultSetMetaData; @@ -233,6 +234,18 @@ public class CMISTemplateResultSet implements Serializable CMISResultSetColumn col = resultSet.getMetaData().getColumn(colName); return col == null ? null : col.getCMISDataType().getLabel(); } + + /** + * Gets property definition for specified column name + * + * @param colName column name + * @return property definition (or null, if not applicable) + */ + public CMISPropertyDefinition getPropertyDefinition(String colName) + { + CMISResultSetColumn col = resultSet.getMetaData().getColumn(colName); + return col == null ? null : col.getCMISPropertyDefinition(); + } /** * Gets node for specified selector diff --git a/source/java/org/alfresco/repo/cmis/ws/DMAbstractServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMAbstractServicePort.java index 18354a247b..27e5c859e1 100644 --- a/source/java/org/alfresco/repo/cmis/ws/DMAbstractServicePort.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMAbstractServicePort.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,60 +15,61 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have received a copy of the text describing + * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ package org.alfresco.repo.cmis.ws; -import java.io.Serializable; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.InvocationTargetException; import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import javax.xml.bind.JAXBElement; -import javax.xml.ws.Holder; import org.alfresco.cmis.CMISAccessControlEntry; import org.alfresco.cmis.CMISAccessControlFormatEnum; import org.alfresco.cmis.CMISAccessControlReport; import org.alfresco.cmis.CMISAccessControlService; import org.alfresco.cmis.CMISAclPropagationEnum; +import org.alfresco.cmis.CMISActionEvaluator; +import org.alfresco.cmis.CMISAllowedActionEnum; import org.alfresco.cmis.CMISChangeLogService; -import org.alfresco.cmis.CMISDictionaryModel; -import org.alfresco.cmis.CMISDictionaryService; +import org.alfresco.cmis.CMISConstraintException; +import org.alfresco.cmis.CMISFilterNotValidException; +import org.alfresco.cmis.CMISInvalidArgumentException; import org.alfresco.cmis.CMISQueryService; import org.alfresco.cmis.CMISRendition; import org.alfresco.cmis.CMISRenditionService; import org.alfresco.cmis.CMISServices; import org.alfresco.cmis.CMISTypeDefinition; -import org.alfresco.model.ContentModel; +import org.alfresco.cmis.acl.CMISAccessControlEntryImpl; +import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.repo.cmis.PropertyFilter; -import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType; -import org.alfresco.repo.cmis.ws.utils.CmisObjectsUtils; +import org.alfresco.repo.cmis.ws.utils.ExceptionUtil; import org.alfresco.repo.cmis.ws.utils.PropertyUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.version.VersionModel; import org.alfresco.repo.web.util.paging.Cursor; import org.alfresco.repo.web.util.paging.Page; import org.alfresco.repo.web.util.paging.Paging; -import org.alfresco.service.cmr.coci.CheckOutCheckInService; import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.search.SearchService; -import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.version.Version; -import org.alfresco.service.cmr.version.VersionService; -import org.alfresco.service.cmr.version.VersionType; import org.alfresco.service.descriptor.DescriptorService; /** @@ -81,24 +82,41 @@ import org.alfresco.service.descriptor.DescriptorService; */ public class DMAbstractServicePort { - protected static final String INITIAL_VERSION_DESCRIPTION = "Initial version"; + private static final String CMIS_USER = "cmis:user"; private static final String INVALID_REPOSITORY_ID_MESSAGE = "Invalid repository id"; - private static final String INVALID_FOLDER_OBJECT_ID_MESSAGE = "OID for non-existent object or not folder object"; private static final Map ACL_PROPAGATION_ENUM_MAPPGIN; + private static final Map ALLOWED_ACTION_ENUM_MAPPING; static { ACL_PROPAGATION_ENUM_MAPPGIN = new HashMap(); ACL_PROPAGATION_ENUM_MAPPGIN.put(EnumACLPropagation.OBJECTONLY, CMISAclPropagationEnum.OBJECT_ONLY); ACL_PROPAGATION_ENUM_MAPPGIN.put(EnumACLPropagation.PROPAGATE, CMISAclPropagationEnum.PROPAGATE); ACL_PROPAGATION_ENUM_MAPPGIN.put(EnumACLPropagation.REPOSITORYDETERMINED, CMISAclPropagationEnum.REPOSITORY_DETERMINED); + + try + { + ALLOWED_ACTION_ENUM_MAPPING = new HashMap(97); + for (PropertyDescriptor propertyDescriptor : Introspector.getBeanInfo(CmisAllowableActionsType.class, Object.class).getPropertyDescriptors()) + { + String label = propertyDescriptor.getName(); + CMISAllowedActionEnum allowedActionEnum = CMISAllowedActionEnum.FACTORY.fromLabel(label); + if (allowedActionEnum != null) + { + ALLOWED_ACTION_ENUM_MAPPING.put(allowedActionEnum, propertyDescriptor); + } + } + } + catch (IntrospectionException e) + { + throw new ExceptionInInitializerError(e); + } } private Paging paging = new Paging(); protected ObjectFactory cmisObjectFactory = new ObjectFactory(); - protected CMISDictionaryService cmisDictionaryService; protected CMISQueryService cmisQueryService; protected CMISServices cmisService; protected CMISChangeLogService cmisChangeLogService; @@ -107,11 +125,8 @@ public class DMAbstractServicePort protected DescriptorService descriptorService; protected NodeService nodeService; - protected VersionService versionService; protected FileFolderService fileFolderService; - protected CheckOutCheckInService checkOutCheckInService; protected SearchService searchService; - protected CmisObjectsUtils cmisObjectsUtils; protected PropertyUtil propertiesUtil; protected PermissionService permissionService; @@ -120,11 +135,6 @@ public class DMAbstractServicePort this.cmisService = cmisService; } - public void setCmisDictionaryService(CMISDictionaryService cmisDictionaryService) - { - this.cmisDictionaryService = cmisDictionaryService; - } - public void setCmisQueryService(CMISQueryService cmisQueryService) { this.cmisQueryService = cmisQueryService; @@ -155,27 +165,11 @@ public class DMAbstractServicePort this.nodeService = nodeService; } - public void setVersionService(VersionService versionService) - { - this.versionService = versionService; - } - public void setFileFolderService(FileFolderService fileFolderService) { this.fileFolderService = fileFolderService; } - public void setCheckOutCheckInService(CheckOutCheckInService checkOutCheckInService) - { - - this.checkOutCheckInService = checkOutCheckInService; - } - - public void setCmisObjectsUtils(CmisObjectsUtils cmisObjectsUtils) - { - this.cmisObjectsUtils = cmisObjectsUtils; - } - public void setPropertiesUtil(PropertyUtil propertiesUtil) { this.propertiesUtil = propertiesUtil; @@ -193,7 +187,7 @@ public class DMAbstractServicePort protected PropertyFilter createPropertyFilter(String filter) throws CmisException { - return (filter == null) ? (new PropertyFilter()) : (new PropertyFilter(filter, cmisObjectsUtils)); + return (filter == null) ? (new PropertyFilter()) : (new PropertyFilter(filter)); } protected PropertyFilter createPropertyFilter(JAXBElement element) throws CmisException @@ -239,7 +233,7 @@ public class DMAbstractServicePort protected CmisObjectType createCmisObject(Object identifier, PropertyFilter filter, boolean includeAllowableActions, String renditionFilter) throws CmisException { CmisObjectType result = new CmisObjectType(); - result.setProperties(propertiesUtil.getPropertiesType(identifier.toString(), filter)); + result.setProperties(propertiesUtil.getProperties(identifier, filter)); if (includeAllowableActions) { result.setAllowableActions(determineObjectAllowableActions(identifier)); @@ -255,20 +249,6 @@ public class DMAbstractServicePort return result; } - /** - * Asserts "Folder with folderNodeRef exists" - * - * @param folderNodeRef node reference - * @throws FolderNotValidException folderNodeRef doesn't exist or folderNodeRef isn't for folder object - */ - protected void assertExistFolder(NodeRef folderNodeRef) throws CmisException - { - if (!this.cmisObjectsUtils.isFolder(folderNodeRef)) - { - throw new CmisException(INVALID_FOLDER_OBJECT_ID_MESSAGE, cmisObjectsUtils.createCmisException(INVALID_FOLDER_OBJECT_ID_MESSAGE, EnumServiceException.INVALID_ARGUMENT)); - } - } - /** * Checks specified in CMIS request parameters repository Id. * @@ -279,54 +259,29 @@ public class DMAbstractServicePort { if (!this.descriptorService.getCurrentRepositoryDescriptor().getId().equals(repositoryId)) { - throw cmisObjectsUtils.createCmisException(INVALID_REPOSITORY_ID_MESSAGE, EnumServiceException.INVALID_ARGUMENT); + throw ExceptionUtil.createCmisException(INVALID_REPOSITORY_ID_MESSAGE, EnumServiceException.INVALID_ARGUMENT); } } - protected Map createVersionProperties(String versionDescription, VersionType versionType) - { - Map result = new HashMap(); - result.put(Version.PROP_DESCRIPTION, versionDescription); - result.put(VersionModel.PROP_VERSION_TYPE, versionType); - return result; - } - - protected NodeRef checkoutNode(NodeRef documentNodeReference) - { - if (!this.nodeService.hasAspect(documentNodeReference, ContentModel.ASPECT_VERSIONABLE)) - { - this.versionService.createVersion(documentNodeReference, createVersionProperties(INITIAL_VERSION_DESCRIPTION, VersionType.MAJOR)); - } - return checkOutCheckInService.checkout(documentNodeReference); - } - - protected CMISTypeDefinition getCmisTypeDefinition(String typeId) throws CmisException - { - try - { - return cmisDictionaryService.findType(typeId); - } - catch (Exception e) - { - throw new CmisException(("Invalid typeId " + typeId), cmisObjectsUtils.createCmisException(("Invalid typeId " + typeId), EnumServiceException.INVALID_ARGUMENT)); - } - } - - protected List getRenditions(Object objectId, String renditionFilter) throws CmisException + protected List getRenditions(Object object, String renditionFilter) throws CmisException { List result = null; - if (NodeRef.isNodeRef(objectId.toString())) + if (object instanceof Version) { - NodeRef document = new NodeRef(objectId.toString()); + object = ((Version) object).getFrozenStateNodeRef(); + } + if (object instanceof NodeRef) + { + NodeRef document = (NodeRef) object; List renditions = null; try { renditions = cmisRenditionService.getRenditions(document, renditionFilter); } - catch (Exception e) + catch (CMISFilterNotValidException e) { - throw cmisObjectsUtils.createCmisException("Invalid rendition filter", EnumServiceException.FILTER_NOT_VALID); + throw ExceptionUtil.createCmisException(e); } if (renditions != null && !renditions.isEmpty()) { @@ -372,130 +327,44 @@ public class DMAbstractServicePort { return null; } - String typeId = propertiesUtil.getProperty(object, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, null); - CMISTypeDefinition objectType = (null == typeId) ? (null) : (cmisDictionaryService.findType(typeId)); - if (null == objectType) - { - throw cmisObjectsUtils.createCmisException("Type Definition for specified Object was not found", EnumServiceException.STORAGE); - } - if (!objectType.isControllableACL()) - { - throw cmisObjectsUtils.createCmisException("Object that was specified is not ACL Controllable", EnumServiceException.CONSTRAINT); - } - CMISAclPropagationEnum propagation = (null == aclPropagation) ? (CMISAclPropagationEnum.PROPAGATE) : (ACL_PROPAGATION_ENUM_MAPPGIN.get(aclPropagation)); - List acesToAdd = (null == addACEs) ? (null) : (convertToAlfrescoAceEntriesList(addACEs.getPermission())); - List acesToRemove = (null == removeACEs) ? (null) : (convertToAlfrescoAceEntriesList(removeACEs.getPermission())); - CMISAccessControlReport aclReport = null; try { + CMISAclPropagationEnum propagation = (null == aclPropagation) ? (CMISAclPropagationEnum.PROPAGATE) : (ACL_PROPAGATION_ENUM_MAPPGIN.get(aclPropagation)); + List acesToAdd = (null == addACEs) ? (null) : (convertToAlfrescoAceEntriesList(addACEs.getPermission())); + List acesToRemove = (null == removeACEs) ? (null) : (convertToAlfrescoAceEntriesList(removeACEs.getPermission())); + CMISAccessControlReport aclReport = null; aclReport = cmisAclService.applyAcl(object, acesToRemove, acesToAdd, propagation, CMISAccessControlFormatEnum.REPOSITORY_SPECIFIC_PERMISSIONS); + CmisACLType result = convertAclReportToCmisAclType(aclReport); + return result; } - catch (Exception e) + catch (CMISConstraintException e) { - throw cmisObjectsUtils.createCmisException(("Can't perform updating of Object Permissions. Error cause message: " + e.toString()), EnumServiceException.CONSTRAINT); + throw ExceptionUtil.createCmisException(e); } - CmisACLType result = convertAclReportToCmisAclType(aclReport); - return result; } - private List convertToAlfrescoAceEntriesList(List source) + private List convertToAlfrescoAceEntriesList(List source) throws CmisException { List result = new LinkedList(); for (CmisAccessControlEntryType cmisEntry : source) { - result.add(convertToAlfrescoAceEntry(cmisEntry)); + if (!cmisEntry.isDirect()) + { + throw ExceptionUtil.createCmisException("Inherited Permissions can't be updated or deleted from Object", EnumServiceException.NOT_SUPPORTED); + } + String principalId = cmisEntry.getPrincipal().getPrincipalId(); + if (CMIS_USER.equals(principalId)) + { + principalId = AuthenticationUtil.getFullyAuthenticatedUser(); + } + for (String permission : cmisEntry.getPermission()) + { + result.add(new CMISAccessControlEntryImpl(principalId, permission)); + } } return result; } - private CMISAccessControlEntry convertToAlfrescoAceEntry(final CmisAccessControlEntryType entry) - { - final Holder correctPrincipalId = new Holder(entry.getPrincipal().getPrincipalId()); - if ("cmis:user".equals(correctPrincipalId)) - { - correctPrincipalId.value = AuthenticationUtil.getFullyAuthenticatedUser(); - } - CMISAccessControlEntry result = new CMISAccessControlEntry() // FIXME: It is better to use already implemented class of this interface - { - private String principalId; - private String permission; // FIXME: [BUG] It MUST BE a List of permissions!!! - private boolean direct; - { - - principalId = correctPrincipalId.value; - permission = entry.getPermission().iterator().next(); // FIXME: See line 66 - direct = entry.isDirect(); - } - - public String getPrincipalId() - { - return principalId; - } - - public String getPermission() - { - return permission; - } - - public boolean getDirect() - { - return direct; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((permission == null) ? 0 : permission.hashCode()); - result = prime * result + ((principalId == null) ? 0 : principalId.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null) - { - return false; - } - if (getClass() != obj.getClass()) - { - return false; - } - final CMISAccessControlEntry other = (CMISAccessControlEntry) obj; - if (permission == null) - { - if (other.getPermission() != null) - { - return false; - } - } - else if (!permission.equals(other.getPermission())) - { - return false; - } - if (principalId == null) - { - if (other.getPrincipalId() != null) - { - return false; - } - } - else if (!principalId.equals(other.getPrincipalId())) - { - return false; - } - return true; - } - }; - return result; - } - protected CmisACLType convertAclReportToCmisAclType(CMISAccessControlReport aclReport) { CmisACLType result = new CmisACLType(); @@ -515,90 +384,54 @@ public class DMAbstractServicePort return result; } + @SuppressWarnings("unchecked") protected CmisAllowableActionsType determineObjectAllowableActions(Object objectIdentifier) throws CmisException { - if (objectIdentifier instanceof String) + CMISTypeDefinition typeDef; + try { - objectIdentifier = cmisObjectsUtils.getIdentifierInstance(objectIdentifier.toString(), AlfrescoObjectType.ANY_OBJECT); + if (objectIdentifier instanceof AssociationRef) + { + typeDef = cmisService.getTypeDefinition((AssociationRef) objectIdentifier); + } + else + { + if (objectIdentifier instanceof Version) + { + objectIdentifier = ((Version) objectIdentifier).getFrozenStateNodeRef(); + } + typeDef = cmisService.getTypeDefinition((NodeRef) objectIdentifier); + } } - if (objectIdentifier instanceof AssociationRef) + catch (CMISInvalidArgumentException e) { - return determineRelationshipAllowableActions((AssociationRef) objectIdentifier); + throw ExceptionUtil.createCmisException(e); } - - switch (cmisObjectsUtils.determineObjectType(objectIdentifier.toString())) - { - case CMIS_DOCUMENT: - { - return determineDocumentAllowableActions((NodeRef) objectIdentifier); - } - case CMIS_FOLDER: - { - return determineFolderAllowableActions((NodeRef) objectIdentifier); - } - } - - // TODO: determinePolicyAllowableActions() when Policy functionality is ready - throw cmisObjectsUtils.createCmisException("It is impossible to get Allowable actions for the specified Object", EnumServiceException.NOT_SUPPORTED); - } - - private CmisAllowableActionsType determineBaseAllowableActions(NodeRef objectNodeReference) - { CmisAllowableActionsType result = new CmisAllowableActionsType(); - result.setCanGetProperties(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_PROPERTIES) == AccessStatus.ALLOWED); - result.setCanUpdateProperties(this.permissionService.hasPermission(objectNodeReference, PermissionService.WRITE_PROPERTIES) == AccessStatus.ALLOWED); - result.setCanDeleteObject(this.permissionService.hasPermission(objectNodeReference, PermissionService.DELETE) == AccessStatus.ALLOWED); - - // TODO: response.setCanAddPolicy(value); - // TODO: response.setCanRemovePolicy(value); - // TODO: response.setCanGetAppliedPolicies(value); - - return result; - } - - private CmisAllowableActionsType determineDocumentAllowableActions(NodeRef objectNodeReference) - { - CmisAllowableActionsType result = determineBaseAllowableActions(objectNodeReference); - determineCommonFolderDocumentAllowableActions(objectNodeReference, result); - result.setCanGetObjectParents(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_ASSOCIATIONS) == AccessStatus.ALLOWED); - result.setCanGetContentStream(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_CONTENT) == AccessStatus.ALLOWED); - result.setCanSetContentStream(this.permissionService.hasPermission(objectNodeReference, PermissionService.WRITE_CONTENT) == AccessStatus.ALLOWED); - result.setCanCheckOut(this.permissionService.hasPermission(objectNodeReference, PermissionService.CHECK_OUT) == AccessStatus.ALLOWED); - result.setCanCheckIn(this.permissionService.hasPermission(objectNodeReference, PermissionService.CHECK_IN) == AccessStatus.ALLOWED); - result.setCanCancelCheckOut(this.permissionService.hasPermission(objectNodeReference, PermissionService.CANCEL_CHECK_OUT) == AccessStatus.ALLOWED); - result.setCanDeleteContentStream(result.isCanUpdateProperties() && result.isCanSetContentStream()); - return result; - } - - private CmisAllowableActionsType determineFolderAllowableActions(NodeRef objectNodeReference) - { - CmisAllowableActionsType result = determineBaseAllowableActions(objectNodeReference); - determineCommonFolderDocumentAllowableActions(objectNodeReference, result); - - result.setCanGetChildren(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_CHILDREN) == AccessStatus.ALLOWED); - result.setCanCreateDocument(this.permissionService.hasPermission(objectNodeReference, PermissionService.ADD_CHILDREN) == AccessStatus.ALLOWED); - result.setCanGetDescendants(result.isCanGetChildren() && (this.permissionService.hasPermission(objectNodeReference, PermissionService.READ) == AccessStatus.ALLOWED)); - result.setCanDeleteTree(this.permissionService.hasPermission(objectNodeReference, PermissionService.DELETE_CHILDREN) == AccessStatus.ALLOWED); - result.setCanGetFolderParent(result.isCanGetObjectRelationships()); - result.setCanCreateFolder(result.isCanCreateDocument()); - // TODO: response.setCanCreatePolicy(value); - return result; - } - - private void determineCommonFolderDocumentAllowableActions(NodeRef objectNodeReference, CmisAllowableActionsType allowableActions) - { - allowableActions.setCanAddObjectToFolder(this.permissionService.hasPermission(objectNodeReference, PermissionService.CREATE_ASSOCIATIONS) == AccessStatus.ALLOWED); - allowableActions.setCanGetObjectRelationships(this.permissionService.hasPermission(objectNodeReference, PermissionService.READ_ASSOCIATIONS) == AccessStatus.ALLOWED); - allowableActions.setCanMoveObject(allowableActions.isCanUpdateProperties() && allowableActions.isCanAddObjectToFolder()); - allowableActions.setCanRemoveObjectFromFolder(allowableActions.isCanUpdateProperties()); - allowableActions.setCanCreateRelationship(allowableActions.isCanAddObjectToFolder()); - } - - private CmisAllowableActionsType determineRelationshipAllowableActions(AssociationRef association) - { - CmisAllowableActionsType result = new CmisAllowableActionsType(); - result.setCanDeleteObject(this.permissionService.hasPermission(association.getSourceRef(), PermissionService.DELETE_ASSOCIATIONS) == AccessStatus.ALLOWED); - result.setCanGetObjectRelationships(this.permissionService.hasPermission(association.getSourceRef(), PermissionService.READ_ASSOCIATIONS) == AccessStatus.ALLOWED); + for (Entry> entry : typeDef.getActionEvaluators().entrySet()) + { + PropertyDescriptor propertyDescriptor = ALLOWED_ACTION_ENUM_MAPPING.get(entry.getKey()); + if (propertyDescriptor != null) + { + // Let's assume that the evaluator will accept the object + try + { + propertyDescriptor.getWriteMethod().invoke(result, new Boolean(((CMISActionEvaluator) entry.getValue()).isAllowed(objectIdentifier))); + } + catch (IllegalArgumentException e) + { + throw new AlfrescoRuntimeException("Exception setting allowable actions", e); + } + catch (IllegalAccessException e) + { + throw new AlfrescoRuntimeException("Exception setting allowable actions", e); + } + catch (InvocationTargetException e) + { + throw new AlfrescoRuntimeException("Exception setting allowable actions", e.getTargetException()); + } + } + } return result; } } diff --git a/source/java/org/alfresco/repo/cmis/ws/DMAclServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMAclServicePort.java index cc5ceffca9..bb23c92741 100755 --- a/source/java/org/alfresco/repo/cmis/ws/DMAclServicePort.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMAclServicePort.java @@ -26,7 +26,8 @@ package org.alfresco.repo.cmis.ws; import org.alfresco.cmis.CMISAccessControlFormatEnum; import org.alfresco.cmis.CMISAccessControlReport; -import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType; +import org.alfresco.cmis.CMISServiceException; +import org.alfresco.repo.cmis.ws.utils.ExceptionUtil; import org.alfresco.service.cmr.repository.NodeRef; /** @@ -42,7 +43,15 @@ public class DMAclServicePort extends DMAbstractServicePort implements ACLServic CmisExtensionType extension) throws CmisException { checkRepositoryId(repositoryId); - NodeRef object = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.ANY_OBJECT); + NodeRef object; + try + { + object = cmisService.getObject(objectId, NodeRef.class, true, false, false); + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e); + } return applyAclCarefully(object, addACEs, removeACEs, aclPropagation); } @@ -52,10 +61,18 @@ public class DMAclServicePort extends DMAbstractServicePort implements ACLServic public CmisACLType getACL(String repositoryId, String objectId, Boolean onlyBasicPermissions, CmisExtensionType extension) throws CmisException { checkRepositoryId(repositoryId); - NodeRef object = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.ANY_OBJECT); + NodeRef nodeRef; + try + { + nodeRef = cmisService.getReadableObject(objectId, NodeRef.class); + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e); + } CMISAccessControlFormatEnum permissionsKind = ((null == onlyBasicPermissions) || onlyBasicPermissions) ? (CMISAccessControlFormatEnum.CMIS_BASIC_PERMISSIONS) : (CMISAccessControlFormatEnum.REPOSITORY_SPECIFIC_PERMISSIONS); - CMISAccessControlReport aclReport = cmisAclService.getAcl(object, permissionsKind); + CMISAccessControlReport aclReport = cmisAclService.getAcl(nodeRef, permissionsKind); return convertAclReportToCmisAclType(aclReport); } } diff --git a/source/java/org/alfresco/repo/cmis/ws/DMDiscoveryServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMDiscoveryServicePort.java index c91eb8eb8d..ab600a8735 100755 --- a/source/java/org/alfresco/repo/cmis/ws/DMDiscoveryServicePort.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMDiscoveryServicePort.java @@ -26,7 +26,6 @@ package org.alfresco.repo.cmis.ws; import java.io.Serializable; import java.math.BigInteger; -import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -43,8 +42,9 @@ import org.alfresco.cmis.CMISQueryOptions; import org.alfresco.cmis.CMISResultSet; import org.alfresco.cmis.CMISResultSetColumn; import org.alfresco.cmis.CMISResultSetRow; +import org.alfresco.cmis.CMISServiceException; import org.alfresco.repo.cmis.PropertyFilter; -import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType; +import org.alfresco.repo.cmis.ws.utils.ExceptionUtil; /** * Port for Discovery service. @@ -118,7 +118,15 @@ public class DMDiscoveryServicePort extends DMAbstractServicePort implements Dis CmisObjectType object = new CmisObjectType(); object.setProperties(properties); - Object identifier = cmisObjectsUtils.getIdentifierInstance((String) values.get(CMISDictionaryModel.PROP_OBJECT_ID), AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT); + Object identifier; + try + { + identifier = cmisService.getReadableObject((String) values.get(CMISDictionaryModel.PROP_OBJECT_ID), Object.class); + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e); + } if (includeAllowableActions) { object.setAllowableActions(determineObjectAllowableActions(identifier)); @@ -175,26 +183,14 @@ public class DMDiscoveryServicePort extends DMAbstractServicePort implements Dis filter = CMISDictionaryModel.PROP_OBJECT_ID; } - if (changeToken != null) - { - try - { - Long.parseLong(changeToken); - } - catch (Exception e) - { - throw cmisObjectsUtils.createCmisException("Invalid changeLogToken was specified", EnumServiceException.INVALID_ARGUMENT); - } - } - CMISChangeLog changeLog = null; try { changeLog = cmisChangeLogService.getChangeLogEvents(changeToken, maxAmount); } - catch (Exception e) + catch (CMISServiceException e) { - throw cmisObjectsUtils.createCmisException(e.getMessage(), EnumServiceException.STORAGE); + throw ExceptionUtil.createCmisException(e); } if (null == objects.value) { @@ -230,10 +226,10 @@ public class DMDiscoveryServicePort extends DMAbstractServicePort implements Dis CmisObjectType object = new CmisObjectType(); CmisPropertiesType propertiesType = new CmisPropertiesType(); object.setProperties(propertiesType); - propertiesType.getProperty().add(propertiesUtil.createProperty(CMISDictionaryModel.PROP_OBJECT_ID, CMISDataTypeEnum.ID, event.getNode())); - if (nodeService.exists(event.getNode()) && includeAce) + propertiesType.getProperty().add(propertiesUtil.createProperty(CMISDictionaryModel.PROP_OBJECT_ID, CMISDataTypeEnum.ID, event.getObjectId())); + if (nodeService.exists(event.getChangedNode()) && includeAce) { - appendWithAce(event.getNode(), object); + appendWithAce(event.getChangedNode(), object); } CmisChangeEventType changeInfo = new CmisChangeEventType(); XMLGregorianCalendar modificationDate = propertiesUtil.convert(event.getChangeTime()); diff --git a/source/java/org/alfresco/repo/cmis/ws/DMMultiFilingServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMMultiFilingServicePort.java index f14a4ff278..03ad64a92b 100755 --- a/source/java/org/alfresco/repo/cmis/ws/DMMultiFilingServicePort.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMMultiFilingServicePort.java @@ -26,10 +26,8 @@ package org.alfresco.repo.cmis.ws; import javax.xml.ws.Holder; -import org.alfresco.cmis.CMISDictionaryModel; -import org.alfresco.cmis.CMISTypeDefinition; -import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType; -import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.cmis.CMISServiceException; +import org.alfresco.repo.cmis.ws.utils.ExceptionUtil; /** * Port for Multi-Filing service. @@ -51,25 +49,13 @@ public class DMMultiFilingServicePort extends DMAbstractServicePort implements M public void addObjectToFolder(String repositoryId, String objectId, String folderId, Boolean allVersions, Holder extension) throws CmisException { checkRepositoryId(repositoryId); - NodeRef objectNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT); - NodeRef parentFolderNodeRef = cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT); - CMISTypeDefinition objectType = cmisDictionaryService.findType(propertiesUtil.getProperty(objectNodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, (String) null)); - CMISTypeDefinition folderType = cmisDictionaryService.findType(propertiesUtil.getProperty(parentFolderNodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, (String) null)); - if (folderType == null) + try { - throw cmisObjectsUtils.createCmisException("Type of the specified parent folder can't be resovled", EnumServiceException.RUNTIME); + cmisService.addObjectToFolder(objectId, folderId); } - // FIXME [BUG]: folderType.getAllowedTargetTypes() MUST be changed on folderType.getAllowedChildObjectTypeIds() - if (!folderType.getAllowedTargetTypes().isEmpty() && !folderType.getAllowedTargetTypes().contains(objectType)) + catch (CMISServiceException e) { - throw cmisObjectsUtils.createCmisException(("The Object of '" + objectType.getTypeId() + "' Type can't be child of Folder of '" + folderType.getTypeId() + "' Type"), - EnumServiceException.CONSTRAINT); - } - if (!cmisObjectsUtils.addObjectToFolder(objectNodeRef, parentFolderNodeRef)) - { - Throwable exception = cmisObjectsUtils.getLastOperationException(); - throw cmisObjectsUtils.createCmisException(("Can't add specified Object to specified Folder. Cause exception message: " + exception.toString()), - EnumServiceException.STORAGE, exception); + throw ExceptionUtil.createCmisException(e); } } @@ -84,43 +70,13 @@ public class DMMultiFilingServicePort extends DMAbstractServicePort implements M public void removeObjectFromFolder(String repositoryId, String objectId, String folderId, Holder extension) throws CmisException { checkRepositoryId(repositoryId); - NodeRef objectNodeReference = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT); - NodeRef folderNodeReference = checkAndReceiveFolderIdentifier(folderId); - // FIXME [BUG]: if Document is Multi-Filled then removing this Object from Primary Parent Folder MUST treat to determine Primary Parent for Document from other Parent - // Folders - checkObjectChildParentRelationships(objectNodeReference, folderNodeReference); - if (!cmisObjectsUtils.removeObject(objectNodeReference, folderNodeReference)) - { - Throwable exception = cmisObjectsUtils.getLastOperationException(); - if (null != exception) - { - throw cmisObjectsUtils.createCmisException(("Can't remove specified Object from specified Folder. Cause exception message: " + exception.toString()), - EnumServiceException.STORAGE, exception); - } - else - { - throw cmisObjectsUtils.createCmisException("Can't remove specified Object from specified Folder", EnumServiceException.STORAGE, exception); - } - } - } - - private NodeRef checkAndReceiveFolderIdentifier(String folderIdentifier) throws CmisException - { try { - return cmisObjectsUtils.getIdentifierInstance(folderIdentifier, AlfrescoObjectType.FOLDER_OBJECT); + cmisService.removeObjectFromFolder(objectId, folderId); } - catch (Throwable e) + catch (CMISServiceException e) { - throw cmisObjectsUtils.createCmisException("Unfiling is not supported. An Object can't be deleted from all Folders", EnumServiceException.NOT_SUPPORTED, e); - } - } - - private void checkObjectChildParentRelationships(NodeRef objectNodeReference, NodeRef folderNodeReference) throws CmisException - { - if (cmisObjectsUtils.isPrimaryObjectParent(folderNodeReference, objectNodeReference)) - { - throw cmisObjectsUtils.createCmisException("Unfiling is not supported. Use deleteObject() Service instead", EnumServiceException.NOT_SUPPORTED); + throw ExceptionUtil.createCmisException(e); } } } diff --git a/source/java/org/alfresco/repo/cmis/ws/DMNavigationServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMNavigationServicePort.java index 7634f123d5..6a0b9f4a2e 100644 --- a/source/java/org/alfresco/repo/cmis/ws/DMNavigationServicePort.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMNavigationServicePort.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 @@ -15,11 +15,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have received a copy of the text describing + * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ package org.alfresco.repo.cmis.ws; @@ -29,17 +29,16 @@ import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Stack; -import java.util.regex.Pattern; import org.alfresco.cmis.CMISDictionaryModel; +import org.alfresco.cmis.CMISServiceException; import org.alfresco.cmis.CMISTypesFilterEnum; import org.alfresco.repo.cmis.PropertyFilter; -import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType; +import org.alfresco.repo.cmis.ws.utils.ExceptionUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.web.util.paging.Cursor; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; -import org.springframework.extensions.surf.util.Pair; /** * Port for navigation service @@ -55,9 +54,6 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na private static final String FILTER_TOKENS_DELIMETER = ", "; - private static final Pattern ORDER_BY_CLAUSE_MASK = Pattern.compile("^( )*([\\p{Alnum}_]+(( )+((ASC)|(DESC))){1}){1}((,){1}( )*[\\p{Alnum}_]+(( )+((ASC)|(DESC))){1})*( )*$", - Pattern.CASE_INSENSITIVE); - /** * Gets the private working copies of checked-out objects that the user is allowed to update. * @@ -71,35 +67,36 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na checkRepositoryId(repositoryId); PropertyFilter propertyFilter = createPropertyFilter(filter); - NodeRef folderRef = null; - if ((folderId != null) && !folderId.equals("")) + try { - folderRef = cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT); - } + NodeRef folderRef = null; + if ((folderId != null) && !folderId.equals("")) + { + folderRef = cmisService.getFolder(folderId); + } - @SuppressWarnings("unused") - List> orderingFields = null; - if ((orderBy != null) && !orderBy.equals("")) + NodeRef[] nodeRefs = cmisService.getCheckedOut(AuthenticationUtil.getFullyAuthenticatedUser(), folderRef, + (folderRef == null), orderBy); + Cursor cursor = createCursor(nodeRefs.length, skipCount, maxItems); + + CmisObjectListType result = new CmisObjectListType(); + List resultListing = result.getObjects(); + + for (int index = cursor.getStartRow(); index <= cursor.getEndRow(); index++) + { + resultListing.add(createCmisObject(nodeRefs[index], propertyFilter, includeAllowableActions, + renditionFilter)); + } + result.setHasMoreItems(new Boolean(cursor.getEndRow() < (nodeRefs.length - 1))); + + // TODO: includeAllowableActions, includeRelationships, renditions + + return result; + } + catch (CMISServiceException e) { - orderingFields = checkAndParseOrderByClause(orderBy); + throw ExceptionUtil.createCmisException(e); } - - // TODO: Ordering functionality SHOULD be moved to getChildren service method - NodeRef[] nodeRefs = cmisService.getCheckedOut(AuthenticationUtil.getFullyAuthenticatedUser(), folderRef, (folderRef == null)); - Cursor cursor = createCursor(nodeRefs.length, skipCount, maxItems); - - CmisObjectListType result = new CmisObjectListType(); - List resultListing = result.getObjects(); - - for (int index = cursor.getStartRow(); index <= cursor.getEndRow(); index++) - { - resultListing.add(createCmisObject(nodeRefs[index].toString(), propertyFilter, includeAllowableActions, renditionFilter)); - } - result.setHasMoreItems(new Boolean(cursor.getEndRow() < (nodeRefs.length - 1))); - - // TODO: includeAllowableActions, includeRelationships, renditions - - return result; } /** @@ -111,46 +108,48 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na * @return collection of CmisObjectType and boolean hasMoreItems * @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, FILTER_NOT_VALID) */ - public CmisObjectInFolderListType getChildren(String repositoryId, String folderId, String filter, String orderBy, Boolean includeAllowableActions, - EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments, BigInteger maxItems, BigInteger skipCount, - CmisExtensionType extension) throws CmisException + public CmisObjectInFolderListType getChildren(String repositoryId, String folderId, String filter, String orderBy, + Boolean includeAllowableActions, EnumIncludeRelationships includeRelationships, String renditionFilter, + Boolean includePathSegments, BigInteger maxItems, BigInteger skipCount, CmisExtensionType extension) + throws CmisException { checkRepositoryId(repositoryId); PropertyFilter propertyFilter = createPropertyFilter(filter); - NodeRef folderNodeRef = cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT); - - @SuppressWarnings("unused") - List> orderingFields = null; - if ((orderBy != null) && !orderBy.equals("")) + try { - orderingFields = checkAndParseOrderByClause(orderBy); - } + NodeRef folderNodeRef = cmisService.getFolder(folderId); - // TODO: Ordering functionality SHOULD be moved to getChildren service method - NodeRef[] listing = cmisService.getChildren(folderNodeRef, CMISTypesFilterEnum.ANY); + NodeRef[] listing = cmisService.getChildren(folderNodeRef, CMISTypesFilterEnum.ANY, orderBy); - CmisObjectInFolderListType result = new CmisObjectInFolderListType(); + CmisObjectInFolderListType result = new CmisObjectInFolderListType(); - Cursor cursor = createCursor(listing.length, skipCount, maxItems); + Cursor cursor = createCursor(listing.length, skipCount, maxItems); - for (int index = cursor.getStartRow(); index <= cursor.getEndRow(); index++) - { - CmisObjectType cmisObject = createCmisObject(listing[index].toString(), propertyFilter, includeAllowableActions, renditionFilter); - CmisObjectInFolderType cmisObjectInFolder = new CmisObjectInFolderType(); - cmisObjectInFolder.setObject(cmisObject); - if (includePathSegments != null && includePathSegments) + for (int index = cursor.getStartRow(); index <= cursor.getEndRow(); index++) { - cmisObjectInFolder.setPathSegment(propertiesUtil.getProperty(listing[index], CMISDictionaryModel.PROP_NAME, "")); + CmisObjectType cmisObject = createCmisObject(listing[index], propertyFilter, includeAllowableActions, + renditionFilter); + CmisObjectInFolderType cmisObjectInFolder = new CmisObjectInFolderType(); + cmisObjectInFolder.setObject(cmisObject); + if (includePathSegments != null && includePathSegments) + { + cmisObjectInFolder.setPathSegment(propertiesUtil.getProperty(listing[index], + CMISDictionaryModel.PROP_NAME, "")); + } + result.getObjects().add(cmisObjectInFolder); } - result.getObjects().add(cmisObjectInFolder); + + result.setHasMoreItems(cursor.getEndRow() < (listing.length - 1)); + result.setNumItems(BigInteger.valueOf(listing.length)); + + // TODO: Process includeRelationships, includeACL + return result; + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e); } - - result.setHasMoreItems(cursor.getEndRow() < (listing.length - 1)); - result.setNumItems(BigInteger.valueOf(listing.length)); - - // TODO: Process includeRelationships, includeACL - return result; } /** @@ -165,7 +164,7 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na public List getDescendants(String repositoryId, String folderId, BigInteger depth, String filter, Boolean includeAllowableActions, EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments, CmisExtensionType extension) throws CmisException { - CmisObjectInFolderContainerType objectInFolderContainerType = getDescedantsTree(repositoryId, folderId, depth, filter, includeAllowableActions, includeRelationships, + CmisObjectInFolderContainerType objectInFolderContainerType = getDescendantsTree(repositoryId, folderId, depth, filter, includeAllowableActions, includeRelationships, renditionFilter, includePathSegments, CMISTypesFilterEnum.ANY); return objectInFolderContainerType.getChildren(); } @@ -182,7 +181,7 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na public List getFolderTree(String repositoryId, String folderId, BigInteger depth, String filter, Boolean includeAllowableActions, EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments, CmisExtensionType extension) throws CmisException { - CmisObjectInFolderContainerType objectInFolderContainerType = getDescedantsTree(repositoryId, folderId, depth, filter, includeAllowableActions, includeRelationships, + CmisObjectInFolderContainerType objectInFolderContainerType = getDescendantsTree(repositoryId, folderId, depth, filter, includeAllowableActions, includeRelationships, renditionFilter, includePathSegments, CMISTypesFilterEnum.FOLDERS); return objectInFolderContainerType.getChildren(); } @@ -211,9 +210,17 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na } } PropertyFilter propertyFilter = createPropertyFilter(filter); - NodeRef parentRef = receiveParent(folderId); + NodeRef parentRef; + try + { + parentRef = cmisService.getFolderParent(folderId); + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e); + } + CmisObjectType result = createCmisObject(parentRef, propertyFilter, false, null); - // TODO: It is not clear whether ACL etc should be returned return result; } @@ -231,7 +238,15 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na checkRepositoryId(repositoryId); PropertyFilter propertyFilter = createPropertyFilter(filter); - NodeRef childNode = (NodeRef) cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT); + NodeRef childNode; + try + { + childNode = (NodeRef) cmisService.getReadableObject(objectId, NodeRef.class); + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e); + } List parents = receiveObjectParents(childNode); List result = new ArrayList(); @@ -252,7 +267,7 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na return result; } - private CmisObjectInFolderContainerType getDescedantsTree(String repositoryId, String folderId, BigInteger depth, String filter, Boolean includeAllowableActions, + private CmisObjectInFolderContainerType getDescendantsTree(String repositoryId, String folderId, BigInteger depth, String filter, Boolean includeAllowableActions, EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments, CMISTypesFilterEnum types) throws CmisException { checkRepositoryId(repositoryId); @@ -262,34 +277,43 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na long maxDepth = depth.longValue(); checkDepthParameter(depth); - NodeRef folderNodeRef = cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT); - Stack descedantsStack = new Stack(); - CmisObjectInFolderContainerType objectInFolderContainer = createObjectInFolderContainer(folderNodeRef, propertyFilter, includeAllowableActions, includeRelationships, - renditionFilter, includePathSegments); - NodeRef[] children = cmisService.getChildren(folderNodeRef, types); - for (NodeRef childRef : children) + try { - descedantsStack.push(new RecursiveElement(objectInFolderContainer, 1, childRef)); - } - while (!descedantsStack.isEmpty()) - { - RecursiveElement element = descedantsStack.pop(); - CmisObjectInFolderContainerType currentContainer = createObjectInFolderContainer(element.getCurrentNodeRef(), propertyFilter, includeAllowableActions, - includeRelationships, renditionFilter, includePathSegments); - element.getParentContainerType().getChildren().add(currentContainer); - if (element.getDepth() <= maxDepth) + NodeRef folderNodeRef = cmisService.getFolder(folderId); + Stack descedantsStack = new Stack(); + CmisObjectInFolderContainerType objectInFolderContainer = createObjectInFolderContainer(folderNodeRef, + propertyFilter, includeAllowableActions, includeRelationships, renditionFilter, includePathSegments); + NodeRef[] children = cmisService.getChildren(folderNodeRef, types, null); + for (NodeRef childRef : children) { - children = cmisService.getChildren(element.getCurrentNodeRef(), types); - if (children != null) + descedantsStack.push(new RecursiveElement(objectInFolderContainer, 1, childRef)); + } + while (!descedantsStack.isEmpty()) + { + RecursiveElement element = descedantsStack.pop(); + CmisObjectInFolderContainerType currentContainer = createObjectInFolderContainer(element + .getCurrentNodeRef(), propertyFilter, includeAllowableActions, includeRelationships, + renditionFilter, includePathSegments); + element.getParentContainerType().getChildren().add(currentContainer); + if (element.getDepth() <= maxDepth) { - for (NodeRef childRef : children) + children = cmisService.getChildren(element.getCurrentNodeRef(), types, null); + if (children != null) { - descedantsStack.push(new RecursiveElement(currentContainer, element.getDepth() + 1, childRef)); + for (NodeRef childRef : children) + { + descedantsStack.push(new RecursiveElement(currentContainer, element.getDepth() + 1, + childRef)); + } } } } + return objectInFolderContainer; + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e); } - return objectInFolderContainer; } private CmisObjectInFolderContainerType createObjectInFolderContainer(NodeRef nodeRef, PropertyFilter filter, Boolean includeAllowableActions, @@ -311,56 +335,15 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na return result; } - private List> checkAndParseOrderByClause(String orderByClause) throws CmisException - { - List> result = new LinkedList>(); - - if (!ORDER_BY_CLAUSE_MASK.matcher(orderByClause).matches()) - { - throw cmisObjectsUtils.createCmisException(("\"" + orderByClause + "\" Order By Clause is invalid!"), EnumServiceException.INVALID_ARGUMENT); - } - - for (String token : orderByClause.split(",")) - { - token = token.trim(); - - String[] direction = token.split(" "); - String fieldName = direction[0]; - result.add(new Pair(fieldName, direction[direction.length - 1].toLowerCase().equals("asc"))); - } - - return result; - } - - private NodeRef receiveParent(String targetChildIdentifier) throws CmisException - { - if (cmisService.getDefaultRootNodeRef().toString().equals(targetChildIdentifier)) - { - throw cmisObjectsUtils.createCmisException("Root Folder has no parents", EnumServiceException.INVALID_ARGUMENT); - } - NodeRef identifierInstance = (NodeRef) cmisObjectsUtils.getIdentifierInstance(targetChildIdentifier, AlfrescoObjectType.FOLDER_OBJECT); - return receiveNextParentNodeReference(identifierInstance, new LinkedList()); - } - private void checkDepthParameter(BigInteger depth) throws CmisException { if (depth.equals(BigInteger.ZERO) || (depth.compareTo(FULL_DESCENDANTS_HIERARCHY_CONDITION) < EQUALS_CONDITION_VALUE)) { - throw cmisObjectsUtils.createCmisException("The specified descendants depth is not valid. Valid depth values are: -1 (full hierarchy), N > 0", + throw ExceptionUtil.createCmisException("The specified descendants depth is not valid. Valid depth values are: -1 (full hierarchy), N > 0", EnumServiceException.INVALID_ARGUMENT); } } - private NodeRef receiveNextParentNodeReference(NodeRef currentParent, List parents) - { - currentParent = nodeService.getPrimaryParent(currentParent).getParentRef(); - if (currentParent != null) - { - parents.add(currentParent); - } - return currentParent; - } - private List receiveObjectParents(NodeRef objectId) throws CmisException { List parents = new LinkedList(); diff --git a/source/java/org/alfresco/repo/cmis/ws/DMObjectServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMObjectServicePort.java index 0e4bd1055c..d9e56943e5 100644 --- a/source/java/org/alfresco/repo/cmis/ws/DMObjectServicePort.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMObjectServicePort.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.repo.cmis.ws; @@ -29,39 +29,36 @@ import java.io.InputStream; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; import javax.activation.DataHandler; import javax.xml.ws.Holder; +import org.alfresco.cmis.CMISConstraintException; import org.alfresco.cmis.CMISContentStreamAllowedEnum; import org.alfresco.cmis.CMISDictionaryModel; +import org.alfresco.cmis.CMISInvalidArgumentException; import org.alfresco.cmis.CMISRenditionKind; import org.alfresco.cmis.CMISScope; +import org.alfresco.cmis.CMISServiceException; import org.alfresco.cmis.CMISTypeDefinition; -import org.alfresco.cmis.dictionary.CMISFolderTypeDefinition; -import org.alfresco.model.ContentModel; +import org.alfresco.cmis.CMISVersioningStateEnum; import org.alfresco.repo.cmis.PropertyFilter; import org.alfresco.repo.cmis.ws.DeleteTreeResponse.FailedToDelete; -import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType; -import org.alfresco.repo.cmis.ws.utils.CmisObjectsUtils; -import org.alfresco.repo.security.permissions.AccessDeniedException; +import org.alfresco.repo.cmis.ws.utils.ExceptionUtil; import org.alfresco.repo.web.util.paging.Cursor; import org.alfresco.service.cmr.dictionary.AssociationDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.TypeDefinition; -import org.alfresco.service.cmr.lock.NodeLockedException; import org.alfresco.service.cmr.model.FileExistsException; import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.model.FileNotFoundException; -import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.FileTypeImageSize; -import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.version.VersionType; import org.alfresco.service.namespace.QName; /** @@ -73,12 +70,21 @@ import org.alfresco.service.namespace.QName; @javax.jws.WebService(name = "ObjectServicePort", serviceName = "ObjectService", portName = "ObjectServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200908/", endpointInterface = "org.alfresco.repo.cmis.ws.ObjectServicePort") public class DMObjectServicePort extends DMAbstractServicePort implements ObjectServicePort { - private static final String VERSION_DELIMETER = "."; + private static final Map VERSIONING_STATE_ENUM_MAPPING; private DictionaryService dictionaryService; private FileTypeIconRetriever iconRetriever; + static + { + VERSIONING_STATE_ENUM_MAPPING = new HashMap(7); + VERSIONING_STATE_ENUM_MAPPING.put(EnumVersioningState.NONE, CMISVersioningStateEnum.NONE); + VERSIONING_STATE_ENUM_MAPPING.put(EnumVersioningState.CHECKEDOUT, CMISVersioningStateEnum.CHECKED_OUT); + VERSIONING_STATE_ENUM_MAPPING.put(EnumVersioningState.MAJOR, CMISVersioningStateEnum.MAJOR); + VERSIONING_STATE_ENUM_MAPPING.put(EnumVersioningState.MINOR, CMISVersioningStateEnum.MINOR); + } + public void setDictionaryService(DictionaryService dictionaryService) { this.dictionaryService = dictionaryService; @@ -101,43 +107,50 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object throws CmisException { checkRepositoryId(repositoryId); - NodeRef parentNodeRef = safeGetFolderNodeRef(folderId); + try + { + NodeRef parentNodeRef = cmisService.getFolder(folderId); + Map propertiesMap = propertiesUtil.getPropertiesMap(properties); + String typeId = extractAndAssertTypeId(propertiesMap); + CMISTypeDefinition typeDef = cmisService.getTypeDefinition(typeId); + String documentName = checkConstraintsAndGetName(typeId, typeDef, parentNodeRef, contentStream, propertiesMap, versioningState); + NodeRef newDocumentNodeRef = fileFolderService.create(parentNodeRef, documentName, typeDef.getTypeId().getQName()).getNodeRef(); + + if (null != contentStream) + { + ContentWriter writer = fileFolderService.getWriter(newDocumentNodeRef); + String mimeType = (String) propertiesMap.get(CMISDictionaryModel.PROP_CONTENT_STREAM_MIME_TYPE); + mimeType = (null == mimeType) ? (contentStream.getMimeType()) : (mimeType); + if (null != mimeType) + { + writer.setMimetype(mimeType); + } + else + { + throw ExceptionUtil.createCmisException("Content Stream Mime Type was not specified", EnumServiceException.INVALID_ARGUMENT); + } + InputStream inputstream = null; + try + { + inputstream = contentStream.getStream().getInputStream(); + } + catch (IOException e) + { + throw ExceptionUtil.createCmisException(e.getMessage(), EnumServiceException.RUNTIME, e); + } + writer.putContent(inputstream); + } + PropertyFilter propertyFilter = createPropertyFilter(createIgnoringFilter(new String[] { CMISDictionaryModel.PROP_NAME, CMISDictionaryModel.PROP_OBJECT_TYPE_ID })); + appendDataToDocument(newDocumentNodeRef, properties, versioningState, policies, addACEs, removeACEs, objectId, propertyFilter); + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e); + } if (null == properties) { - throw cmisObjectsUtils.createCmisException("Properties input parameter is Mandatory", EnumServiceException.INVALID_ARGUMENT); + throw ExceptionUtil.createCmisException("Properties input parameter is Mandatory", EnumServiceException.INVALID_ARGUMENT); } - Map propertiesMap = propertiesUtil.getPropertiesMap(properties); - String typeId = extractAndAssertTypeId(propertiesMap); - CMISTypeDefinition typeDef = cmisDictionaryService.findType(typeId); - String documentName = checkConstraintsAndGetName(typeId, typeDef, parentNodeRef, contentStream, propertiesMap, versioningState); - NodeRef newDocumentNodeRef = fileFolderService.create(parentNodeRef, documentName, typeDef.getTypeId().getQName()).getNodeRef(); - - if (null != contentStream) - { - ContentWriter writer = fileFolderService.getWriter(newDocumentNodeRef); - String mimeType = (String) propertiesMap.get(CMISDictionaryModel.PROP_CONTENT_STREAM_MIME_TYPE); - mimeType = (null == mimeType) ? (contentStream.getMimeType()) : (mimeType); - if (null != mimeType) - { - writer.setMimetype(mimeType); - } - else - { - throw cmisObjectsUtils.createCmisException("Content Stream Mime Type was not specified", EnumServiceException.STORAGE); - } - InputStream inputstream = null; - try - { - inputstream = contentStream.getStream().getInputStream(); - } - catch (IOException e) - { - throw cmisObjectsUtils.createCmisException(e.toString(), EnumServiceException.CONSTRAINT); - } - writer.putContent(inputstream); - } - PropertyFilter propertyFilter = createPropertyFilter(createIgnoringFilter(new String[] { CMISDictionaryModel.PROP_NAME, CMISDictionaryModel.PROP_OBJECT_TYPE_ID })); - appendDataToDocument(newDocumentNodeRef, properties, versioningState, policies, addACEs, removeACEs, objectId, propertyFilter); } /** @@ -157,24 +170,31 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object throws CmisException { checkRepositoryId(repositoryId); - NodeRef folderNodeRef = cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT); - NodeRef sourceNodeRef = cmisObjectsUtils.getIdentifierInstance(sourceId, AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT); - String name = propertiesUtil.getProperty(sourceNodeRef, CMISDictionaryModel.PROP_NAME, null); - NodeRef newDocumentNodeRef; try { - newDocumentNodeRef = fileFolderService.copy(sourceNodeRef, folderNodeRef, name).getNodeRef(); + NodeRef folderNodeRef = cmisService.getFolder(folderId); + NodeRef sourceNodeRef = cmisService.getReadableObject(sourceId, NodeRef.class); + String name = propertiesUtil.getProperty(sourceNodeRef, CMISDictionaryModel.PROP_NAME, null); + NodeRef newDocumentNodeRef; + try + { + newDocumentNodeRef = fileFolderService.copy(sourceNodeRef, folderNodeRef, name).getNodeRef(); + } + catch (FileExistsException e) + { + throw ExceptionUtil.createCmisException("Document already exists", EnumServiceException.CONTENT_ALREADY_EXISTS); + } + catch (FileNotFoundException e) + { + throw ExceptionUtil.createCmisException("Source document not found", EnumServiceException.INVALID_ARGUMENT); + } + PropertyFilter propertyFilter = createPropertyFilter(createIgnoringFilter(new String[] { CMISDictionaryModel.PROP_OBJECT_TYPE_ID })); + appendDataToDocument(newDocumentNodeRef, properties, versioningState, policies, addACEs, removeACEs, objectId, propertyFilter); } - catch (FileExistsException e) + catch (CMISServiceException e) { - throw cmisObjectsUtils.createCmisException("Document already exists", EnumServiceException.CONTENT_ALREADY_EXISTS); + throw ExceptionUtil.createCmisException(e); } - catch (FileNotFoundException e) - { - throw cmisObjectsUtils.createCmisException("Source document not found", EnumServiceException.INVALID_ARGUMENT); - } - PropertyFilter propertyFilter = createPropertyFilter(createIgnoringFilter(new String[] { CMISDictionaryModel.PROP_OBJECT_TYPE_ID })); - appendDataToDocument(newDocumentNodeRef, properties, versioningState, policies, addACEs, removeACEs, objectId, propertyFilter); } /** @@ -193,40 +213,37 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object // TODO: process Policies checkRepositoryId(repositoryId); - NodeRef folderNodeRef = null; try { - folderNodeRef = cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT); - } - catch (CmisException e) - { - e.getFaultInfo().setType(EnumServiceException.CONSTRAINT); - throw e; - } - assertExistFolder(folderNodeRef); - Map propertiesMap = propertiesUtil.getPropertiesMap(properties); - String typeId = extractAndAssertTypeId(propertiesMap); - CMISTypeDefinition type = getCmisTypeDefinition(typeId); - TypeDefinition nativeType = dictionaryService.getType(nodeService.getType(folderNodeRef)); - if (type == null || type.getTypeId() == null || type.getTypeId().getScope() != CMISScope.FOLDER) - { - throw cmisObjectsUtils.createCmisException("The typeID is not an Object-Type whose baseType is 'Folder': " + typeId, EnumServiceException.CONSTRAINT); - } + NodeRef folderNodeRef = cmisService.getFolder(folderId); + Map propertiesMap = propertiesUtil.getPropertiesMap(properties); + String typeId = extractAndAssertTypeId(propertiesMap); + CMISTypeDefinition type = cmisService.getTypeDefinition(typeId); + TypeDefinition nativeType = dictionaryService.getType(nodeService.getType(folderNodeRef)); + if (type == null || type.getTypeId() == null || type.getTypeId().getScope() != CMISScope.FOLDER) + { + throw ExceptionUtil.createCmisException("The typeID is not an Object-Type whose baseType is 'Folder': " + typeId, EnumServiceException.CONSTRAINT); + } - String name = propertiesUtil.getCmisPropertyValue(properties, CMISDictionaryModel.PROP_NAME, null); - propertiesUtil.checkProperty(nativeType, type, CMISDictionaryModel.PROP_NAME, name, false); + String name = propertiesUtil.getCmisPropertyValue(properties, CMISDictionaryModel.PROP_NAME, null); + propertiesUtil.checkProperty(nativeType, type, CMISDictionaryModel.PROP_NAME, name, false); - try - { - NodeRef newFolderNodeRef = fileFolderService.create(folderNodeRef, name, type.getTypeId().getQName()).getNodeRef(); - propertiesUtil.setProperties(newFolderNodeRef, properties, createPropertyFilter(createIgnoringFilter(new String[] { CMISDictionaryModel.PROP_NAME, - CMISDictionaryModel.PROP_OBJECT_TYPE_ID }))); - applyAclCarefully(newFolderNodeRef, addACEs, removeACEs, EnumACLPropagation.PROPAGATE); - objectId.value = propertiesUtil.getProperty(newFolderNodeRef, CMISDictionaryModel.PROP_OBJECT_ID, null); + try + { + NodeRef newFolderNodeRef = fileFolderService.create(folderNodeRef, name, type.getTypeId().getQName()).getNodeRef(); + propertiesUtil.setProperties(newFolderNodeRef, properties, createPropertyFilter(createIgnoringFilter(new String[] { CMISDictionaryModel.PROP_NAME, + CMISDictionaryModel.PROP_OBJECT_TYPE_ID }))); + applyAclCarefully(newFolderNodeRef, addACEs, removeACEs, EnumACLPropagation.PROPAGATE); + objectId.value = propertiesUtil.getProperty(newFolderNodeRef, CMISDictionaryModel.PROP_OBJECT_ID, null); + } + catch (FileExistsException e) + { + throw ExceptionUtil.createCmisException("Folder already exists", EnumServiceException.CONTENT_ALREADY_EXISTS); + } } - catch (FileExistsException e) + catch (CMISServiceException e) { - throw cmisObjectsUtils.createCmisException("Folder already exists", EnumServiceException.CONTENT_ALREADY_EXISTS); + throw ExceptionUtil.createCmisException(e); } } @@ -242,7 +259,7 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object public void createPolicy(String repositoryId, CmisPropertiesType properties, String folderId, List policies, CmisAccessControlListType addACEs, CmisAccessControlListType removeACEs, Holder extension, Holder objectId) throws CmisException { - throw cmisObjectsUtils.createCmisException("Policy objects not supported", EnumServiceException.NOT_SUPPORTED); + throw ExceptionUtil.createCmisException("Policy objects not supported", EnumServiceException.NOT_SUPPORTED); } /** @@ -267,47 +284,54 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object checkRepositoryId(repositoryId); - NodeRef sourceNodeRef = cmisObjectsUtils.getIdentifierInstance(sourceObjectId, AlfrescoObjectType.ANY_OBJECT); - NodeRef targetNodeRef = cmisObjectsUtils.getIdentifierInstance(targetObjectId, AlfrescoObjectType.ANY_OBJECT); - - String typeId = (String) propertiesMap.get(CMISDictionaryModel.PROP_OBJECT_TYPE_ID); - - CMISTypeDefinition relationshipType = cmisDictionaryService.findType(typeId); - if (relationshipType == null || relationshipType.getTypeId() == null || relationshipType.getTypeId().getScope() != CMISScope.RELATIONSHIP) + try { - throw cmisObjectsUtils.createCmisException(typeId, EnumServiceException.INVALID_ARGUMENT); - } + NodeRef sourceNodeRef = cmisService.getObject(sourceObjectId, NodeRef.class, true, false, false); + NodeRef targetNodeRef = cmisService.getObject(targetObjectId, NodeRef.class, true, false, false); - CMISTypeDefinition sourceType = cmisDictionaryService.findType(propertiesUtil.getProperty(sourceNodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, (String) null)); - CMISTypeDefinition targetType = cmisDictionaryService.findType(propertiesUtil.getProperty(targetNodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, (String) null)); + String typeId = (String) propertiesMap.get(CMISDictionaryModel.PROP_OBJECT_TYPE_ID); - if ((null != relationshipType.getAllowedSourceTypes()) && !relationshipType.getAllowedSourceTypes().contains(sourceType)) - { - throw cmisObjectsUtils.createCmisException(("Source object type is not allowed for \"" + typeId + "\" Relationship type"), EnumServiceException.CONSTRAINT); - } - if ((null != relationshipType.getAllowedTargetTypes()) && !relationshipType.getAllowedTargetTypes().contains(targetType)) - { - throw cmisObjectsUtils.createCmisException(("Target object type is not allowed for \"" + typeId + "\" Relationship type"), EnumServiceException.CONSTRAINT); - } - - QName relationshipTypeQName = relationshipType.getTypeId().getQName(); - AssociationDefinition associationDef = dictionaryService.getAssociation(relationshipTypeQName); - if (associationDef != null) - { - if (!dictionaryService.isSubClass(nodeService.getType(sourceNodeRef), associationDef.getSourceClass().getName())) + CMISTypeDefinition relationshipType = cmisService.getTypeDefinition(typeId); + if (relationshipType == null || relationshipType.getTypeId() == null || relationshipType.getTypeId().getScope() != CMISScope.RELATIONSHIP) { - throw cmisObjectsUtils.createCmisException("Source object type isn't allowed as source type", EnumServiceException.CONSTRAINT); + throw ExceptionUtil.createCmisException(typeId, EnumServiceException.INVALID_ARGUMENT); } - if (!dictionaryService.isSubClass(nodeService.getType(targetNodeRef), associationDef.getTargetClass().getName())) + + CMISTypeDefinition sourceType = cmisService.getTypeDefinition(sourceNodeRef); + CMISTypeDefinition targetType = cmisService.getTypeDefinition(targetNodeRef); + + if ((null != relationshipType.getAllowedSourceTypes()) && !relationshipType.getAllowedSourceTypes().contains(sourceType)) { - throw cmisObjectsUtils.createCmisException("Target object type isn't allowed as target type", EnumServiceException.CONSTRAINT); + throw ExceptionUtil.createCmisException(("Source object type is not allowed for \"" + typeId + "\" Relationship type"), EnumServiceException.CONSTRAINT); + } + if ((null != relationshipType.getAllowedTargetTypes()) && !relationshipType.getAllowedTargetTypes().contains(targetType)) + { + throw ExceptionUtil.createCmisException(("Target object type is not allowed for \"" + typeId + "\" Relationship type"), EnumServiceException.CONSTRAINT); + } + + QName relationshipTypeQName = relationshipType.getTypeId().getQName(); + AssociationDefinition associationDef = dictionaryService.getAssociation(relationshipTypeQName); + if (associationDef != null) + { + if (!dictionaryService.isSubClass(nodeService.getType(sourceNodeRef), associationDef.getSourceClass().getName())) + { + throw ExceptionUtil.createCmisException("Source object type isn't allowed as source type", EnumServiceException.CONSTRAINT); + } + if (!dictionaryService.isSubClass(nodeService.getType(targetNodeRef), associationDef.getTargetClass().getName())) + { + throw ExceptionUtil.createCmisException("Target object type isn't allowed as target type", EnumServiceException.CONSTRAINT); + } + String createdId = nodeService.createAssociation(sourceNodeRef, targetNodeRef, relationshipTypeQName).toString(); + objectId.value = createdId; + } + else + { + throw ExceptionUtil.createCmisException((relationshipType.getTypeId().getQName() + " Relationship type not found"), EnumServiceException.INVALID_ARGUMENT); } - String createdId = nodeService.createAssociation(sourceNodeRef, targetNodeRef, relationshipTypeQName).toString(); - objectId.value = createdId; } - else + catch (CMISServiceException e) { - throw cmisObjectsUtils.createCmisException((relationshipType.getTypeId().getQName() + " Relationship type not found"), EnumServiceException.INVALID_ARGUMENT); + throw ExceptionUtil.createCmisException(e); } } @@ -324,16 +348,14 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object { // TODO: Process changeToken checkRepositoryId(repositoryId); - NodeRef currentNode = cmisObjectsUtils.getIdentifierInstance(objectId.value, AlfrescoObjectType.DOCUMENT_OBJECT); - - CMISTypeDefinition typeDef = cmisDictionaryService.findType(propertiesUtil.getProperty(currentNode, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, (String) null)); - if (CMISContentStreamAllowedEnum.REQUIRED.equals(typeDef.getContentStreamAllowed())) + try { - throw cmisObjectsUtils.createCmisException("The 'contentStreamAllowed' attribute of the specified Object-Type definition is set to 'required'.", - EnumServiceException.CONSTRAINT); + cmisService.deleteContentStream(objectId.value); + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e); } - - safeDeleteContentStream(currentNode); } /** @@ -346,44 +368,14 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object */ public void deleteObject(String repositoryId, String objectId, Boolean allVersions, Holder extension) throws CmisException { - // TODO: Process flag allVersions - checkRepositoryId(repositoryId); - - Object identifier = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.ANY_OBJECT); - NodeRef objectNodeReference = null; - if (identifier instanceof AssociationRef) + try { - AssociationRef assocRef = (AssociationRef) identifier; - try - { - nodeService.removeAssociation(assocRef.getSourceRef(), assocRef.getTargetRef(), assocRef.getTypeQName()); - } - catch (InvalidNodeRefException e) - { - throw cmisObjectsUtils.createCmisException("Invalid object identifier", EnumServiceException.INVALID_ARGUMENT); - } + cmisService.deleteObject(objectId, allVersions == null || allVersions); } - else + catch (CMISServiceException e) { - objectNodeReference = (NodeRef) identifier; - checkForRootObject(repositoryId, objectId); - checkObjectTypeAndAppropriateStates(objectNodeReference); - QName type = nodeService.getType(objectNodeReference); - CMISTypeDefinition typeDef = (null != type) ? (cmisDictionaryService.findTypeForClass(type)) : (null); - if (null == typeDef) - { - throw cmisObjectsUtils.createCmisException("Specified Object has invalid Type", EnumServiceException.INVALID_ARGUMENT); - } - if (!cmisObjectsUtils.isFolder(objectNodeReference) && typeDef.isVersionable() && (null != allVersions) && allVersions) - { - deleteAllVersions(repositoryId, objectId); - } - if (!cmisObjectsUtils.deleteObject(objectNodeReference)) - { - throw cmisObjectsUtils.createCmisException("Currently authenticated User has no appropriate Permissions to delete specified Object", - EnumServiceException.PERMISSION_DENIED); - } + throw ExceptionUtil.createCmisException(e); } } @@ -405,14 +397,19 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object // TODO: Process allVersions checkRepositoryId(repositoryId); checkUnfilingIsNotRequested(unfileObject); - checkForRootObject(repositoryId, folderId); - NodeRef folderNodeReference = cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT); - FailedToDelete responce = new FailedToDelete(); - allVersions = allVersions == null ? Boolean.FALSE : allVersions; - responce.getObjectIds().addAll(cmisObjectsUtils.deleteFolder(folderNodeReference, continueOnFailure, unfileObject, allVersions)); - - return responce; + List failedToDelete; + try + { + failedToDelete = cmisService.deleteTree(folderId, continueOnFailure, unfileObject != EnumUnfileObject.DELETE, allVersions == null || allVersions); + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e); + } + FailedToDelete response = new FailedToDelete(); + response.getObjectIds().addAll(failedToDelete); + return response; } /** @@ -430,21 +427,29 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object { checkRepositoryId(repositoryId); - Object identifierInstance = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.ANY_OBJECT); - PropertyFilter propertyFilter = createPropertyFilter(filter); - boolean includeActions = (null != includeAllowableActions) ? (includeAllowableActions.booleanValue()) : (false); - CmisObjectType object = createCmisObject(identifierInstance, propertyFilter, includeActions, renditionFilter); - - // TODO: process relationships - // TODO: process policyIds - - boolean includeAcl = (null != includeACL) ? (includeACL.booleanValue()) : (false); - if (includeAcl && (identifierInstance instanceof NodeRef)) + try { - appendWithAce((NodeRef) identifierInstance, object); - } + NodeRef object = cmisService.getReadableObject(objectId, NodeRef.class); + PropertyFilter propertyFilter = createPropertyFilter(filter); + boolean includeActions = (null != includeAllowableActions) ? (includeAllowableActions.booleanValue()) : (false); + CmisObjectType cmisObject = createCmisObject(object, propertyFilter, includeActions, renditionFilter); - return object; + // TODO: process relationships + // TODO: process policyIds + + Object versionSeries = cmisService.getVersionSeries(objectId, Object.class, false); + boolean includeAcl = (null != includeACL) ? (includeACL.booleanValue()) : (false); + if (includeAcl && (versionSeries instanceof NodeRef)) + { + appendWithAce((NodeRef) versionSeries, cmisObject); + } + + return cmisObject; + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e); + } } /** @@ -463,11 +468,12 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object NodeRef objectNodeRef = resolvePathInfo(path); if (null == objectNodeRef) { - throw cmisObjectsUtils.createCmisException("Path to Folder was not specified or Folder Path is invalid", EnumServiceException.INVALID_ARGUMENT); + throw ExceptionUtil.createCmisException("Path to Folder was not specified or Folder Path is invalid", EnumServiceException.INVALID_ARGUMENT); } PropertyFilter propertyFilter = createPropertyFilter(filter); CmisObjectType object = createCmisObject(objectNodeRef, propertyFilter, includeAllowableActions, renditionFilter); - if (includeACL) + boolean includeAcl = (null != includeACL) ? (includeACL.booleanValue()) : (false); + if (includeAcl) { appendWithAce(objectNodeRef, object); } @@ -488,7 +494,16 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object public CmisAllowableActionsType getAllowableActions(String repositoryId, String objectId, CmisExtensionType extension) throws CmisException { checkRepositoryId(repositoryId); - return determineObjectAllowableActions(cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.ANY_OBJECT)); + Object object; + try + { + object = cmisService.getReadableObject(objectId, Object.class); + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e); + } + return determineObjectAllowableActions(object); } /** @@ -503,62 +518,68 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object throws CmisException { checkRepositoryId(repositoryId); - NodeRef nodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT); - - CMISTypeDefinition typeDefinition = cmisDictionaryService.findType(propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, (String) null)); - if (CMISContentStreamAllowedEnum.NOT_ALLOWED == typeDefinition.getContentStreamAllowed()) + try { - throw cmisObjectsUtils.createCmisException("Content stream not allowed", EnumServiceException.STREAM_NOT_SUPPORTED); - } - - String filename = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_NAME, null); - - ContentReaderDataSource dataSource = null; - if (streamId != null && streamId.length() > 0) - { - FileTypeImageSize streamIcon = null; - if (streamId.equals(CMISRenditionKind.ICON16.getLabel())) + NodeRef nodeRef = cmisService.getReadableObject(objectId, NodeRef.class); + CMISTypeDefinition typeDefinition = cmisService.getTypeDefinition(nodeRef); + if (CMISContentStreamAllowedEnum.NOT_ALLOWED == typeDefinition.getContentStreamAllowed()) { - streamIcon = FileTypeImageSize.Small; + throw ExceptionUtil.createCmisException("Content stream not allowed", EnumServiceException.STREAM_NOT_SUPPORTED); } - else if (streamId.equals(CMISRenditionKind.ICON32.getLabel())) + + String filename = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_NAME, null); + + ContentReaderDataSource dataSource = null; + if (streamId != null && streamId.length() > 0) { - streamIcon = FileTypeImageSize.Medium; - } - if (streamIcon != null) - { - InputStream iconInputStream = iconRetriever.getIconContent(filename, streamIcon); - String iconMimetype = iconRetriever.getIconMimetype(filename, streamIcon); - if (iconInputStream != null && iconMimetype != null) + FileTypeImageSize streamIcon = null; + if (streamId.equals(CMISRenditionKind.ICON16.getLabel())) { - dataSource = new ContentReaderDataSource(iconInputStream, iconMimetype, filename, offset, length); + streamIcon = FileTypeImageSize.Small; + } + else if (streamId.equals(CMISRenditionKind.ICON32.getLabel())) + { + streamIcon = FileTypeImageSize.Medium; + } + if (streamIcon != null) + { + InputStream iconInputStream = iconRetriever.getIconContent(filename, streamIcon); + String iconMimetype = iconRetriever.getIconMimetype(filename, streamIcon); + if (iconInputStream != null && iconMimetype != null) + { + dataSource = new ContentReaderDataSource(iconInputStream, iconMimetype, filename, offset, length); + } + } + else + { + NodeRef renditionNodeRef = new NodeRef(streamId); + ContentReader reader = safeGetContentReader(renditionNodeRef); + dataSource = new ContentReaderDataSource(reader, filename, offset, length, reader.getSize()); } } else { - NodeRef renditionNodeRef = cmisObjectsUtils.getIdentifierInstance(streamId, AlfrescoObjectType.DOCUMENT_OBJECT); - ContentReader reader = safeGetContentReader(renditionNodeRef); + ContentReader reader = safeGetContentReader(nodeRef); dataSource = new ContentReaderDataSource(reader, filename, offset, length, reader.getSize()); } + + CmisContentStreamType response = new CmisContentStreamType(); + + response.setFilename(filename); + + if (dataSource != null) + { + response.setMimeType(dataSource.getContentType()); + response.setStream(new DataHandler(dataSource)); + response.setLength(BigInteger.valueOf(dataSource.getSizeToRead())); + } + + return response; } - else + catch (CMISServiceException e) { - ContentReader reader = safeGetContentReader(nodeRef); - dataSource = new ContentReaderDataSource(reader, filename, offset, length, reader.getSize()); + throw ExceptionUtil.createCmisException(e); } - - CmisContentStreamType response = new CmisContentStreamType(); - - response.setFilename(filename); - - if (dataSource != null) - { - response.setMimeType(dataSource.getContentType()); - response.setStream(new DataHandler(dataSource)); - response.setLength(BigInteger.valueOf(dataSource.getSizeToRead())); - } - - return response; } /** @@ -574,40 +595,13 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object public void moveObject(String repositoryId, Holder objectId, String targetFolderId, String sourceFolderId, Holder extension) throws CmisException { checkRepositoryId(repositoryId); - NodeRef objectNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId.value, AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT); - // TODO: maybe this check will be need in terms of document version instead of final document (version specific filing is not supported) - // checkOnLatestVersion(objectNodeRef); - - NodeRef sourceFolderNodeRef = cmisObjectsUtils.getIdentifierInstance(sourceFolderId, AlfrescoObjectType.FOLDER_OBJECT); - if (!cmisObjectsUtils.isChildOfThisFolder(objectNodeRef, sourceFolderNodeRef)) + try { - throw cmisObjectsUtils.createCmisException("The Docuemnt is not a Child of Source Forlder that was specified", EnumServiceException.INVALID_ARGUMENT); + cmisService.moveObject(objectId.value, targetFolderId, sourceFolderId); } - NodeRef targetFolderNodeRef = cmisObjectsUtils.getIdentifierInstance(targetFolderId, AlfrescoObjectType.FOLDER_OBJECT); - String objectType = propertiesUtil.getProperty(objectNodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, null); - String targetType = propertiesUtil.getProperty(targetFolderNodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, null); - CMISFolderTypeDefinition targetTypeDef = (CMISFolderTypeDefinition) ((null != targetType) ? (cmisDictionaryService.findType(targetType)) : (null)); - if (null == targetTypeDef) + catch (CMISServiceException e) { - throw cmisObjectsUtils.createCmisException("Type Definition for Target Folder was not found", EnumServiceException.RUNTIME); - } - - // TODO: cmis:allowedChildObjectTypes - // FIXME: targetTypeDef.getAllowedTargetTypes() should be changed to something like targetTypeDef.getAllowedChildTypes() - CMISTypeDefinition objectTypeDef = (null != objectType) ? (cmisDictionaryService.findType(objectType)) : (null); - if (!targetTypeDef.getAllowedTargetTypes().isEmpty() && !targetTypeDef.getAllowedTargetTypes().contains(objectTypeDef)) - { - throw cmisObjectsUtils.createCmisException(("Object with '" + objectType + "' Type can't be moved to Folder with '" + targetType + "' Type"), - EnumServiceException.CONSTRAINT); - } - if (!cmisObjectsUtils.isPrimaryObjectParent(sourceFolderNodeRef, objectNodeRef)) - { - changeObjectParentAssociation(objectNodeRef, targetFolderNodeRef, sourceFolderNodeRef); - } - else - { - // FIXME: it is necessary to reconsider how to convert TransactionRollback exception to nameConstraintViolation - safeMove(objectNodeRef, targetFolderNodeRef); + throw ExceptionUtil.createCmisException(e); } } @@ -626,44 +620,18 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object Holder extension) throws CmisException { checkRepositoryId(repositoryId); - - // TODO:Process changeToken - - NodeRef nodeRef = cmisObjectsUtils.getIdentifierInstance(objectId.value, AlfrescoObjectType.DOCUMENT_OBJECT); - - CMISTypeDefinition typeDef = cmisDictionaryService.findType(propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, (String) null)); - if (CMISContentStreamAllowedEnum.NOT_ALLOWED.equals(typeDef.getContentStreamAllowed())) - { - throw cmisObjectsUtils.createCmisException("The Object's Object-Type definition 'contentStreamAllowed' attribute is set to 'notAllowed'.", - EnumServiceException.CONSTRAINT); - } - - if ((null == contentStream) || (contentStream.getStream() == null)) - { - throw cmisObjectsUtils.createCmisException("New Content Stream was not provided", EnumServiceException.STORAGE); - } - - ContentReader reader = fileFolderService.getReader(nodeRef); - if ((null != reader) && !overwriteFlag) - { - throw cmisObjectsUtils.createCmisException("Content already exists", EnumServiceException.CONTENT_ALREADY_EXISTS); - } - - ContentWriter writer = fileFolderService.getWriter(nodeRef); - InputStream inputstream = null; try { - inputstream = contentStream.getStream().getInputStream(); + cmisService.setContentStream(objectId.value, null, overwriteFlag == null || overwriteFlag, contentStream.getStream().getInputStream(), contentStream.getMimeType()); } - catch (IOException e) + catch (CMISServiceException e) { - throw cmisObjectsUtils.createCmisException(e.getMessage(), EnumServiceException.UPDATE_CONFLICT); + throw ExceptionUtil.createCmisException(e); + } + catch (Exception e) + { + throw ExceptionUtil.createCmisException(e.getMessage(), EnumServiceException.RUNTIME, e); } - - writer.setMimetype(contentStream.getMimeType()); - writer.putContent(inputstream); - - objectId.value = propertiesUtil.getProperty(cmisObjectsUtils.getLatestNode(nodeRef, false), CMISDictionaryModel.PROP_OBJECT_ID, objectId.value); } /** @@ -679,14 +647,18 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object public void updateProperties(String repositoryId, Holder objectId, Holder changeToken, CmisPropertiesType properties, Holder extension) throws CmisException { - // TODO: Process changeToken checkRepositoryId(repositoryId); - NodeRef objectNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId.value, AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT); + NodeRef objectNodeRef; + try + { + objectNodeRef = cmisService.getObject(objectId.value, NodeRef.class, true, false, false); + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e); + } propertiesUtil.setProperties(objectNodeRef, properties, null); - - // no new version - objectId.value = propertiesUtil.getProperty(objectNodeRef, CMISDictionaryModel.PROP_OBJECT_ID, objectId.value); } /** @@ -702,10 +674,16 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object PropertyFilter propertyFilter = createPropertyFilter(filter); - Object identifierInstance = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.ANY_OBJECT); - String identifier = identifierInstance.toString(); - - CmisPropertiesType result = propertiesUtil.getPropertiesType(identifier, propertyFilter); + Object identifierInstance; + try + { + identifierInstance = cmisService.getReadableObject(objectId, Object.class); + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e); + } + CmisPropertiesType result = propertiesUtil.getProperties(identifierInstance, propertyFilter); return result; } @@ -721,7 +699,15 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object CmisExtensionType extension) throws CmisException { checkRepositoryId(repositoryId); - NodeRef objectNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT); + NodeRef objectNodeRef; + try + { + objectNodeRef = cmisService.getReadableObject(objectId, NodeRef.class); + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e); + } List result = new ArrayList(); List renditions = getRenditions(objectNodeRef, renditionFilter); if (renditions != null) @@ -736,37 +722,23 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object } private void appendDataToDocument(NodeRef targetDocumentNodeRef, CmisPropertiesType properties, EnumVersioningState versioningState, List policies, - CmisAccessControlListType addACEs, CmisAccessControlListType removeACEs, Holder objectId, PropertyFilter propertyFilter) throws CmisException + CmisAccessControlListType addACEs, CmisAccessControlListType removeACEs, Holder objectId, PropertyFilter propertyFilter) throws CMISConstraintException, + CmisException, CMISInvalidArgumentException { // TODO: process Policies propertiesUtil.setProperties(targetDocumentNodeRef, properties, propertyFilter); - String versionLabel = null; + // Apply the ACL before potentially creating a PWC + applyAclCarefully(targetDocumentNodeRef, addACEs, removeACEs, EnumACLPropagation.PROPAGATE); - // FIXME: change condition below to "typeDef.isVersionable()" when dictionary problem will be fixed - if (true) + if (versioningState == null) { - versioningState = (null == versioningState) ? (EnumVersioningState.MINOR) : (versioningState); - switch (versioningState) - { - case CHECKEDOUT: - targetDocumentNodeRef = checkoutNode(targetDocumentNodeRef); - break; - case MAJOR: - this.versionService.createVersion(targetDocumentNodeRef, createVersionProperties(INITIAL_VERSION_DESCRIPTION, VersionType.MAJOR)); - break; - case MINOR: - this.versionService.createVersion(targetDocumentNodeRef, createVersionProperties(INITIAL_VERSION_DESCRIPTION, VersionType.MINOR)); - break; - } - versionLabel = propertiesUtil.getProperty(targetDocumentNodeRef, CMISDictionaryModel.PROP_VERSION_LABEL, ""); + versioningState = EnumVersioningState.MAJOR; } - String createdObjectId = ((null != versionLabel) && versionLabel.contains(VERSION_DELIMETER)) ? (targetDocumentNodeRef.toString() - + CmisObjectsUtils.NODE_REFERENCE_ID_DELIMITER + versionLabel) : (targetDocumentNodeRef.toString()); - NodeRef objectNodeRef = cmisObjectsUtils.getIdentifierInstance(createdObjectId, AlfrescoObjectType.DOCUMENT_OBJECT); - applyAclCarefully(objectNodeRef, addACEs, removeACEs, EnumACLPropagation.PROPAGATE); - objectId.value = createdObjectId; + + targetDocumentNodeRef = cmisService.applyVersioningState(targetDocumentNodeRef, VERSIONING_STATE_ENUM_MAPPING.get(versioningState)); + objectId.value = targetDocumentNodeRef.toString(); } private String createIgnoringFilter(String[] propertyNames) @@ -795,7 +767,7 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object String typeId = (String) propertiesMap.get(CMISDictionaryModel.PROP_OBJECT_TYPE_ID); if ((null == typeId) || "".equals(typeId)) { - throw cmisObjectsUtils.createCmisException("Type Id property required", EnumServiceException.INVALID_ARGUMENT); + throw ExceptionUtil.createCmisException("Type Id property required", EnumServiceException.INVALID_ARGUMENT); } return typeId; } @@ -805,60 +777,58 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object { if ((null == typeDef) || (null == typeDef.getTypeId())) { - throw cmisObjectsUtils.createCmisException(("Type with " + documentTypeId + "typeId was not found"), EnumServiceException.RUNTIME); + throw ExceptionUtil.createCmisException(("Type with " + documentTypeId + "typeId was not found"), EnumServiceException.RUNTIME); } if ((CMISScope.DOCUMENT != typeDef.getTypeId().getScope()) || !typeDef.isCreatable()) { - throw cmisObjectsUtils.createCmisException(("Invalid document type \"" + documentTypeId + "\". This type is not a Creatable Document type"), + throw ExceptionUtil.createCmisException(("Invalid document type \"" + documentTypeId + "\". This type is not a Creatable Document type"), EnumServiceException.CONSTRAINT); } if ((null != contentStream) && CMISContentStreamAllowedEnum.NOT_ALLOWED == typeDef.getContentStreamAllowed()) { - throw cmisObjectsUtils.createCmisException(("Content stream not allowed for \"" + documentTypeId + "\" document object type"), - EnumServiceException.STREAM_NOT_SUPPORTED); + throw ExceptionUtil.createCmisException(("Content stream not allowed for \"" + documentTypeId + "\" document object type"), EnumServiceException.STREAM_NOT_SUPPORTED); } else { if ((CMISContentStreamAllowedEnum.REQUIRED == typeDef.getContentStreamAllowed()) && (null == contentStream)) { - throw cmisObjectsUtils.createCmisException("Content stream for document object of " + documentTypeId + " type is required", EnumServiceException.CONSTRAINT); + throw ExceptionUtil.createCmisException("Content stream for document object of " + documentTypeId + " type is required", EnumServiceException.CONSTRAINT); } } // FIXME: change condition below to "!typeDef.isVersionable() && (null != versioningState)" when dictionary problem will be fixed if (false) { - throw cmisObjectsUtils.createCmisException(("Verioning for \"" + documentTypeId + "\" document type is not allowed"), EnumServiceException.CONSTRAINT); + throw ExceptionUtil.createCmisException(("Verioning for \"" + documentTypeId + "\" document type is not allowed"), EnumServiceException.CONSTRAINT); } - String folderTypeId = propertiesUtil.getProperty(parentNodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, null); - CMISTypeDefinition folderTypeDefinition = cmisDictionaryService.findType(folderTypeId); + CMISTypeDefinition folderTypeDefinition; + try + { + folderTypeDefinition = cmisService.getTypeDefinition(parentNodeRef); + } + catch (CMISInvalidArgumentException e) + { + throw ExceptionUtil.createCmisException(e.getMessage(), EnumServiceException.INVALID_ARGUMENT, e); + } if ((null != folderTypeDefinition.getAllowedTargetTypes()) && !folderTypeDefinition.getAllowedTargetTypes().isEmpty() && !folderTypeDefinition.getAllowedTargetTypes().contains(typeDef)) { - throw cmisObjectsUtils.createCmisException(("Children of \"" + documentTypeId + "\" type are not allowed for specified folder"), EnumServiceException.CONSTRAINT); + throw ExceptionUtil.createCmisException(("Children of \"" + documentTypeId + "\" type are not allowed for specified folder"), EnumServiceException.CONSTRAINT); } String result = (String) propertiesMap.get(CMISDictionaryModel.PROP_NAME); if (null == result) { - throw cmisObjectsUtils.createCmisException("Name property not found", EnumServiceException.INVALID_ARGUMENT); + throw ExceptionUtil.createCmisException("Name property not found", EnumServiceException.INVALID_ARGUMENT); } propertiesUtil.checkProperty(null, typeDef, CMISDictionaryModel.PROP_NAME, result, (EnumVersioningState.CHECKEDOUT == versioningState)); return result; } - private void changeObjectParentAssociation(NodeRef objectNodeRef, NodeRef targetFolderNodeRef, NodeRef sourceFolderNodeReference) throws CmisException - { - if (!cmisObjectsUtils.removeObject(objectNodeRef, sourceFolderNodeReference) || !cmisObjectsUtils.addObjectToFolder(objectNodeRef, targetFolderNodeRef)) - { - determineException(cmisObjectsUtils.getLastOperationException()); - } - } - private NodeRef resolvePathInfo(String folderPath) throws CmisException { NodeRef result = null; @@ -886,100 +856,24 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object return result; } - private void safeMove(NodeRef objectNodeRef, NodeRef targetFolderNodeRef) throws CmisException - { - try - { - fileFolderService.move(objectNodeRef, targetFolderNodeRef, null); - } - catch (Exception e) - { - determineException(e); - } - } - - private void safeDeleteContentStream(NodeRef documentNodeReference) throws CmisException - { - try - { - nodeService.setProperty(documentNodeReference, ContentModel.PROP_CONTENT, null); - } - catch (NodeLockedException e) - { - throw cmisObjectsUtils.createCmisException("Content Stream Deletion is not allowed for specified Object", EnumServiceException.UPDATE_CONFLICT); - } - } - - private void deleteAllVersions(String repositoryId, String versionSeriesId) throws CmisException - { - checkRepositoryId(repositoryId); - NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(versionSeriesId, AlfrescoObjectType.DOCUMENT_OBJECT); - NodeRef workingCopyRef = (cmisObjectsUtils.isWorkingCopy(documentNodeRef)) ? (documentNodeRef) : (checkOutCheckInService.getWorkingCopy(documentNodeRef)); - if ((null != workingCopyRef) && cmisObjectsUtils.isWorkingCopy(workingCopyRef)) - { - documentNodeRef = checkOutCheckInService.cancelCheckout(workingCopyRef); - } - - versionService.deleteVersionHistory(documentNodeRef); - } - private ContentReader safeGetContentReader(NodeRef objectNodeReference) throws CmisException { ContentReader reader = fileFolderService.getReader(objectNodeReference); if (reader == null) { - throw cmisObjectsUtils.createCmisException("The specified Document has no Content Stream", EnumServiceException.CONSTRAINT); + throw ExceptionUtil.createCmisException("The specified Document has no Content Stream", EnumServiceException.CONSTRAINT); } return reader; } - private NodeRef safeGetFolderNodeRef(String folderId) throws CmisException - { - try - { - return this.cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT); - } - catch (CmisException e) - { - throw cmisObjectsUtils.createCmisException("Unfiling is not suppoerted. Each Document must have existent parent Folder", EnumServiceException.CONSTRAINT, e); - } - } - - private void checkObjectTypeAndAppropriateStates(NodeRef objectNodeReference) throws CmisException - { - if (cmisObjectsUtils.isFolder(objectNodeReference) && (nodeService.getChildAssocs(objectNodeReference).size() > 0)) - { - throw cmisObjectsUtils.createCmisException("Could not delete folder with at least one Child", EnumServiceException.CONSTRAINT); - } - } - private void checkUnfilingIsNotRequested(EnumUnfileObject unfileNonfolderObjects) throws CmisException { if (unfileNonfolderObjects == EnumUnfileObject.UNFILE) { - throw cmisObjectsUtils.createCmisException("Unfiling is not supported", EnumServiceException.NOT_SUPPORTED); + throw ExceptionUtil.createCmisException("Unfiling is not supported", EnumServiceException.NOT_SUPPORTED); } } - private void checkForRootObject(String repositoryId, String objectId) throws CmisException - { - if (this.cmisService.getDefaultRootNodeRef().toString().equals(objectId) || repositoryId.equals(objectId)) - { - throw cmisObjectsUtils.createCmisException("Could not delete Repository object or Root Folder object - operation is not allowed or not supported", - EnumServiceException.NOT_SUPPORTED); - } - } - - private void determineException(Throwable lastException) throws CmisException - { - if (lastException instanceof AccessDeniedException) - { - throw cmisObjectsUtils.createCmisException(lastException.toString(), EnumServiceException.PERMISSION_DENIED); - } - - throw cmisObjectsUtils.createCmisException("Couldn't to relocate multi-filed Object", EnumServiceException.UPDATE_CONFLICT); - } - public void setFileTypeIconRetriever(FileTypeIconRetriever iconRetriever) { this.iconRetriever = iconRetriever; diff --git a/source/java/org/alfresco/repo/cmis/ws/DMPolicyServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMPolicyServicePort.java index b52586f698..2a9e458bf8 100755 --- a/source/java/org/alfresco/repo/cmis/ws/DMPolicyServicePort.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMPolicyServicePort.java @@ -28,6 +28,8 @@ import java.util.List; import javax.xml.ws.Holder; +import org.alfresco.repo.cmis.ws.utils.ExceptionUtil; + @javax.jws.WebService(name = "PolicyServicePort", serviceName = "PolicyServicePort", portName = "PolicyServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200908/", endpointInterface = "org.alfresco.repo.cmis.ws.PolicyServicePort") public class DMPolicyServicePort extends DMAbstractServicePort implements PolicyServicePort { @@ -43,7 +45,7 @@ public class DMPolicyServicePort extends DMAbstractServicePort implements Policy */ public void applyPolicy(String repositoryId, String policyId, String objectId, Holder extension) throws CmisException { - throw cmisObjectsUtils.createCmisException(POLICY_NOT_SUPPORTED_MESSAGE, EnumServiceException.RUNTIME); + throw ExceptionUtil.createCmisException(POLICY_NOT_SUPPORTED_MESSAGE, EnumServiceException.RUNTIME); } /** @@ -54,7 +56,7 @@ public class DMPolicyServicePort extends DMAbstractServicePort implements Policy */ public List getAppliedPolicies(String repositoryId, String objectId, String filter, CmisExtensionType extension) throws CmisException { - throw cmisObjectsUtils.createCmisException(POLICY_NOT_SUPPORTED_MESSAGE, EnumServiceException.RUNTIME); + throw ExceptionUtil.createCmisException(POLICY_NOT_SUPPORTED_MESSAGE, EnumServiceException.RUNTIME); } /** @@ -67,6 +69,6 @@ public class DMPolicyServicePort extends DMAbstractServicePort implements Policy */ public void removePolicy(String repositoryId, String policyId, String objectId, Holder extension) throws CmisException { - throw cmisObjectsUtils.createCmisException(POLICY_NOT_SUPPORTED_MESSAGE, EnumServiceException.RUNTIME); + throw ExceptionUtil.createCmisException(POLICY_NOT_SUPPORTED_MESSAGE, EnumServiceException.RUNTIME); } } diff --git a/source/java/org/alfresco/repo/cmis/ws/DMRelationshipServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMRelationshipServicePort.java index b0c819da26..1bc9fa9f9d 100755 --- a/source/java/org/alfresco/repo/cmis/ws/DMRelationshipServicePort.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMRelationshipServicePort.java @@ -25,18 +25,17 @@ package org.alfresco.repo.cmis.ws; import java.math.BigInteger; -import java.util.List; +import java.util.HashMap; +import java.util.Map; -import org.alfresco.cmis.CMISScope; +import org.alfresco.cmis.CMISRelationshipDirectionEnum; +import org.alfresco.cmis.CMISServiceException; import org.alfresco.cmis.CMISTypeDefinition; import org.alfresco.repo.cmis.PropertyFilter; -import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType; +import org.alfresco.repo.cmis.ws.utils.ExceptionUtil; import org.alfresco.repo.web.util.paging.Cursor; -import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.namespace.QNamePattern; /** * Port for relationship service @@ -46,11 +45,13 @@ import org.alfresco.service.namespace.QNamePattern; @javax.jws.WebService(name = "RelationshipServicePort", serviceName = "RelationshipService", portName = "RelationshipServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200908/", endpointInterface = "org.alfresco.repo.cmis.ws.RelationshipServicePort") public class DMRelationshipServicePort extends DMAbstractServicePort implements RelationshipServicePort { - private DictionaryService dictionaryService; - - public void setDictionaryService(DictionaryService dictionaryService) + private static final Map RELATIONSHIP_DIRECTION_MAPPING; + static { - this.dictionaryService = dictionaryService; + RELATIONSHIP_DIRECTION_MAPPING = new HashMap(5); + RELATIONSHIP_DIRECTION_MAPPING.put(EnumRelationshipDirection.SOURCE, CMISRelationshipDirectionEnum.SOURCE); + RELATIONSHIP_DIRECTION_MAPPING.put(EnumRelationshipDirection.TARGET, CMISRelationshipDirectionEnum.TARGET); + RELATIONSHIP_DIRECTION_MAPPING.put(EnumRelationshipDirection.EITHER, CMISRelationshipDirectionEnum.BOTH); } /** @@ -66,31 +67,25 @@ public class DMRelationshipServicePort extends DMAbstractServicePort implements String typeId, String filter, Boolean includeAllowableActions, BigInteger maxItems, BigInteger skipCount, CmisExtensionType extension) throws CmisException { checkRepositoryId(repositoryId); - NodeRef objectNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT); - if (null == includeSubRelationshipTypes) + if ((null == objectId) || "".equals(objectId) || !NodeRef.isNodeRef(objectId)) { - throw cmisObjectsUtils.createCmisException("includeSubRelationshipTypes input parameter is required", EnumServiceException.INVALID_ARGUMENT); + throw ExceptionUtil.createCmisException(("Object with Id='" + objectId + "' is not exist!"), EnumServiceException.OBJECT_NOT_FOUND); } - relationshipDirection = (null != relationshipDirection) ? relationshipDirection : EnumRelationshipDirection.SOURCE; - skipCount = (null != skipCount) ? skipCount : BigInteger.ZERO; - maxItems = (null != maxItems) ? maxItems : BigInteger.ZERO; - QName associationType = null; - if ((null != typeId) && !"".equals(typeId)) - { - CMISTypeDefinition cmisTypeDef = cmisDictionaryService.findType(typeId); - associationType = cmisTypeDef.getTypeId().getQName(); - } - PropertyFilter propertyFilter = createPropertyFilter(filter); - List assocs = null; try { - assocs = cmisObjectsUtils.receiveAssociations(objectNodeRef, new RelationshipTypeFilter(associationType, includeSubRelationshipTypes), relationshipDirection); + CMISTypeDefinition relDef = (null != typeId) ? (cmisService.getTypeDefinition(typeId)):(null); + NodeRef nodeRef = cmisService.getReadableObject(objectId, NodeRef.class); + AssociationRef[] assocs = cmisService.getRelationships(nodeRef, relDef, includeSubRelationshipTypes != null && includeSubRelationshipTypes, + relationshipDirection == null ? CMISRelationshipDirectionEnum.SOURCE : RELATIONSHIP_DIRECTION_MAPPING.get(relationshipDirection)); + skipCount = (null != skipCount) ? skipCount : BigInteger.ZERO; + maxItems = (null != maxItems) ? maxItems : BigInteger.ZERO; + PropertyFilter propertyFilter = createPropertyFilter(filter); + return createResult(propertyFilter, includeAllowableActions, assocs, skipCount, maxItems); } - catch (Exception e) + catch (CMISServiceException e) { - throw cmisObjectsUtils.createCmisException("Can't receive associations", e); + throw ExceptionUtil.createCmisException(e); } - return createResult(propertyFilter, includeAllowableActions, assocs.toArray(), skipCount, maxItems); } private CmisObjectListType createResult(PropertyFilter filter, boolean includeAllowableActions, Object[] sourceArray, BigInteger skipCount, BigInteger maxItems) @@ -100,39 +95,10 @@ public class DMRelationshipServicePort extends DMAbstractServicePort implements CmisObjectListType result = new CmisObjectListType(); for (int i = cursor.getStartRow(); i <= cursor.getEndRow(); i++) { - result.getObjects().add(createCmisObject(sourceArray[i].toString(), filter, includeAllowableActions, null)); + result.getObjects().add(createCmisObject(sourceArray[i], filter, includeAllowableActions, null)); } result.setHasMoreItems(cursor.getEndRow() < sourceArray.length); result.setNumItems(BigInteger.valueOf(cursor.getPageSize())); return result; } - - private class RelationshipTypeFilter implements QNamePattern - { - private boolean includeSubtypes; - private QName relationshipType; - - public RelationshipTypeFilter(QName ralationshipType, boolean includeSubtypes) - { - this.relationshipType = ralationshipType; - this.includeSubtypes = includeSubtypes; - } - - public boolean isMatch(QName qname) - { - if (relationshipType == null) - { - return true; - } - else if (includeSubtypes) - { - return null != dictionaryService.getAssociation(qname); - } - else - { - CMISTypeDefinition typeDef = cmisDictionaryService.findTypeForClass(qname, CMISScope.RELATIONSHIP); - return typeDef != null && relationshipType.equals(qname); - } - } - } } diff --git a/source/java/org/alfresco/repo/cmis/ws/DMRepositoryServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMRepositoryServicePort.java index c9fbc01d9f..af863f6d43 100644 --- a/source/java/org/alfresco/repo/cmis/ws/DMRepositoryServicePort.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMRepositoryServicePort.java @@ -33,7 +33,6 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Queue; import org.alfresco.cmis.CMISAclCapabilityEnum; import org.alfresco.cmis.CMISAclPropagationEnum; @@ -50,8 +49,10 @@ import org.alfresco.cmis.CMISPermissionDefinition; import org.alfresco.cmis.CMISPermissionMapping; import org.alfresco.cmis.CMISPropertyDefinition; import org.alfresco.cmis.CMISQueryEnum; +import org.alfresco.cmis.CMISServiceException; import org.alfresco.cmis.CMISTypeDefinition; import org.alfresco.cmis.CMISUpdatabilityEnum; +import org.alfresco.repo.cmis.ws.utils.ExceptionUtil; import org.alfresco.repo.web.util.paging.Cursor; import org.alfresco.service.descriptor.Descriptor; @@ -324,7 +325,7 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re } default: { - throw cmisObjectsUtils.createCmisException(type.getLabel(), EnumServiceException.OBJECT_NOT_FOUND); + throw ExceptionUtil.createCmisException(type.getLabel(), EnumServiceException.OBJECT_NOT_FOUND); } } } @@ -379,7 +380,7 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re { if (typeDef == null) { - throw cmisObjectsUtils.createCmisException("Type not found", EnumServiceException.OBJECT_NOT_FOUND); + throw ExceptionUtil.createCmisException("Type not found", EnumServiceException.OBJECT_NOT_FOUND); } CmisTypeDefinitionType result = null; @@ -439,7 +440,7 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re result = relationshipDefinitionType; break; case UNKNOWN: - throw cmisObjectsUtils.createCmisException("Unknown CMIS Type", EnumServiceException.INVALID_ARGUMENT); + throw ExceptionUtil.createCmisException("Unknown CMIS Type", EnumServiceException.INVALID_ARGUMENT); } return result; @@ -572,7 +573,15 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re CmisExtensionType extension) throws CmisException { checkRepositoryId(repositoryId); - Collection typeDefs = getBaseTypesCollection(typeId, true); + Collection typeDefs; + try + { + typeDefs = typeId == null ? cmisService.getBaseTypes() : cmisService.getTypeDefinition(typeId).getSubTypes(false); + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e); + } // skip Cursor cursor = createCursor(typeDefs.size(), skipCount, maxItems); Iterator iterTypeDefs = typeDefs.iterator(); @@ -593,7 +602,7 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re } else { - throw cmisObjectsUtils.createCmisException(("Subtypes collection is corrupted. Type id: " + typeId), EnumServiceException.STORAGE); + throw ExceptionUtil.createCmisException(("Subtypes collection is corrupted. Type id: " + typeId), EnumServiceException.STORAGE); } } result.setHasMoreItems(((maxItems == null) || (0 == maxItems.intValue())) ? (false) : ((cursor.getEndRow() < (typeDefs.size() - 1)))); @@ -614,11 +623,11 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re CMISTypeDefinition typeDef; try { - typeDef = cmisDictionaryService.findType(typeId); + typeDef = cmisService.getTypeDefinition(typeId); } - catch (Exception e) + catch (CMISServiceException e) { - throw cmisObjectsUtils.createCmisException(e.toString(), EnumServiceException.INVALID_ARGUMENT); + throw ExceptionUtil.createCmisException(e); } return getCmisTypeDefinition(typeDef, true); } @@ -634,39 +643,39 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re throws CmisException { checkRepositoryId(repositoryId); - long depthLong = (null == depth) ? (-1) : (depth.longValue()); + long depthLong = (null == depth || null == typeId) ? (-1) : (depth.longValue()); if (0 == depthLong) { - throw cmisObjectsUtils.createCmisException("Depth parameter equal to '0' have no sence", EnumServiceException.INVALID_ARGUMENT); + throw ExceptionUtil.createCmisException("Invalid depth '0'", EnumServiceException.INVALID_ARGUMENT); } - boolean includePropertyDefsBool = (null == includePropertyDefinitions) ? (false) : (includePropertyDefinitions); List result = new LinkedList(); - Queue typesQueue = new LinkedList(); - Collection typeDefs = getBaseTypesCollection(typeId, false); - for (CMISTypeDefinition typeDef : typeDefs) + CMISTypeDefinition typeDef; + try { - typesQueue.add(new TypeElement(0L, typeDef, createTypeContainer(typeDef, includePropertyDefsBool))); + typeDef = typeId == null ? null : cmisService.getTypeDefinition(typeId); } - for (TypeElement element = typesQueue.peek(); !typesQueue.isEmpty(); element = (typeDefs.isEmpty()) ? (null) : (typesQueue.peek())) + catch (CMISServiceException e) { - typesQueue.poll(); - result.add(element.getContainer()); - long nextLevel = element.getLevel() + 1; - Collection subTypes = element.getTypeDefinition().getSubTypes(false); - if (null != subTypes) + throw ExceptionUtil.createCmisException(e); + } + getTypeDescendants(typeDef, result, includePropertyDefinitions != null && includePropertyDefinitions, 1, depthLong); + return result; + } + + private void getTypeDescendants(CMISTypeDefinition parent, List result, boolean includePropertyDefs, long depth, long maxDepth) throws CmisException + { + Collection subtypes = parent == null ? cmisService.getBaseTypes() : parent.getSubTypes(false); + for (CMISTypeDefinition typeDef : subtypes) + { + result.add(createTypeContainer(typeDef, includePropertyDefs)); + } + if (maxDepth == -1 || depth + 1 <= maxDepth) + { + for (CMISTypeDefinition typeDef : subtypes) { - for (CMISTypeDefinition typeDef : subTypes) - { - CmisTypeContainer childContainer = createTypeContainer(typeDef, includePropertyDefsBool); - if ((-1 == depthLong) || (nextLevel <= depthLong)) - { - element.getContainer().getChildren().add(childContainer); - typesQueue.add(new TypeElement(nextLevel, typeDef, childContainer)); - } - } + getTypeDescendants(typeDef, result, includePropertyDefs, depth + 1, maxDepth); } } - return result; } private CmisTypeContainer createTypeContainer(CMISTypeDefinition parentType, boolean includeProperties) throws CmisException @@ -675,70 +684,4 @@ public class DMRepositoryServicePort extends DMAbstractServicePort implements Re result.setType(getCmisTypeDefinition(parentType, includeProperties)); return result; } - - private class TypeElement - { - private long level; - private CMISTypeDefinition typeDefinition; - private CmisTypeContainer container; - - public TypeElement(long level, CMISTypeDefinition typeDefinition, CmisTypeContainer container) - { - this.level = level; - this.typeDefinition = typeDefinition; - this.container = container; - } - - public long getLevel() - { - return level; - } - - public CMISTypeDefinition getTypeDefinition() - { - return typeDefinition; - } - - public CmisTypeContainer getContainer() - { - return container; - } - } - - private Collection getBaseTypesCollection(String typeId, boolean includeSubtypes) throws CmisException - { - Collection typeDefs = new LinkedList(); - if ((null == typeId) || "".equals(typeId)) - { - typeDefs = cmisDictionaryService.getBaseTypes(); - } - else - { - CMISTypeDefinition typeDef = null; - try - { - typeDef = cmisDictionaryService.findType(typeId); - } - catch (Exception e) - { - throw cmisObjectsUtils.createCmisException(e.toString(), EnumServiceException.INVALID_ARGUMENT); - } - - if (null == typeDef) - { - throw cmisObjectsUtils.createCmisException(("Invalid type id: \"" + typeId + "\""), EnumServiceException.INVALID_ARGUMENT); - } - typeDefs.add(typeDef); - - if (includeSubtypes) - { - Collection subTypes = typeDef.getSubTypes(false); - if (null != subTypes) - { - typeDefs.addAll(subTypes); - } - } - } - return typeDefs; - } } diff --git a/source/java/org/alfresco/repo/cmis/ws/DMServicePortThrowsAdvice.java b/source/java/org/alfresco/repo/cmis/ws/DMServicePortThrowsAdvice.java index ca62c92ddc..95dfbfaa13 100644 --- a/source/java/org/alfresco/repo/cmis/ws/DMServicePortThrowsAdvice.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMServicePortThrowsAdvice.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 @@ -15,16 +15,16 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have received a copy of the text describing + * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ package org.alfresco.repo.cmis.ws; -import org.alfresco.repo.cmis.ws.utils.CmisObjectsUtils; +import org.alfresco.repo.cmis.ws.utils.ExceptionUtil; import org.alfresco.repo.security.permissions.AccessDeniedException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -40,13 +40,6 @@ public class DMServicePortThrowsAdvice implements ThrowsAdvice { private static final Log LOGGER = LogFactory.getLog("org.alfresco.repo.cmis.ws"); - private CmisObjectsUtils cmisObjectsUtils; - - public void setCmisObjectsUtils(CmisObjectsUtils cmisObjectsUtils) - { - this.cmisObjectsUtils = cmisObjectsUtils; - } - public void afterThrowing(AccessDeniedException e) throws CmisException { if (LOGGER.isInfoEnabled()) @@ -54,7 +47,7 @@ public class DMServicePortThrowsAdvice implements ThrowsAdvice LOGGER.error(e.toString(), e); } - throw cmisObjectsUtils.createCmisException(("Access denied. Message: " + e.toString()), e); + throw ExceptionUtil.createCmisException(("Access denied. Message: " + e.toString()), e); } public void afterThrowing(java.lang.RuntimeException e) throws CmisException @@ -64,7 +57,7 @@ public class DMServicePortThrowsAdvice implements ThrowsAdvice LOGGER.error(e.toString(), e); } - throw cmisObjectsUtils.createCmisException(("Runtime error. Message: " + e.toString()), e); + throw ExceptionUtil.createCmisException(("Runtime error. Message: " + e.toString()), e); } public void afterThrowing(java.lang.Exception e) throws CmisException @@ -76,7 +69,7 @@ public class DMServicePortThrowsAdvice implements ThrowsAdvice if (!(e instanceof CmisException)) { - throw cmisObjectsUtils.createCmisException(("Some error occured during last service invokation. Message: " + e.toString()), e); + throw ExceptionUtil.createCmisException(("Some error occured during last service invokation. Message: " + e.toString()), e); } else { diff --git a/source/java/org/alfresco/repo/cmis/ws/DMVersioningServicePort.java b/source/java/org/alfresco/repo/cmis/ws/DMVersioningServicePort.java index d6393a6e7e..1b404d64ca 100755 --- a/source/java/org/alfresco/repo/cmis/ws/DMVersioningServicePort.java +++ b/source/java/org/alfresco/repo/cmis/ws/DMVersioningServicePort.java @@ -31,18 +31,12 @@ import javax.xml.ws.Holder; import org.alfresco.cmis.CMISContentStreamAllowedEnum; import org.alfresco.cmis.CMISDictionaryModel; +import org.alfresco.cmis.CMISServiceException; import org.alfresco.cmis.CMISTypeDefinition; -import org.alfresco.model.ContentModel; import org.alfresco.repo.cmis.PropertyFilter; -import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType; -import org.alfresco.repo.security.permissions.AccessDeniedException; -import org.alfresco.service.cmr.lock.LockService; -import org.alfresco.service.cmr.lock.LockStatus; +import org.alfresco.repo.cmis.ws.utils.ExceptionUtil; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.version.Version; -import org.alfresco.service.cmr.version.VersionHistory; -import org.alfresco.service.cmr.version.VersionType; /** * Port for versioning service. @@ -53,13 +47,6 @@ import org.alfresco.service.cmr.version.VersionType; @javax.jws.WebService(name = "VersioningServicePort", serviceName = "VersioningService", portName = "VersioningServicePort", targetNamespace = "http://docs.oasis-open.org/ns/cmis/ws/200908/", endpointInterface = "org.alfresco.repo.cmis.ws.VersioningServicePort") public class DMVersioningServicePort extends DMAbstractServicePort implements VersioningServicePort { - private LockService lockService; - - public void setLockService(LockService lockService) - { - this.lockService = lockService; - } - /** * Reverses the effect of a check-out. Removes the private working copy of the checked-out document object, allowing other documents in the version series to be checked out * again. @@ -73,31 +60,14 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve public void cancelCheckOut(String repositoryId, String objectId, Holder extension) throws CmisException { checkRepositoryId(repositoryId); - NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT); - assertVersionableIsTrue(documentNodeRef); - boolean checkedOut = propertiesUtil.getProperty(documentNodeRef, CMISDictionaryModel.PROP_IS_VERSION_SERIES_CHECKED_OUT, false); - NodeRef workingCopyNodeRef = definitelyGetWorkingCopy(checkedOut, documentNodeRef); - checkOutCheckInService.cancelCheckout(workingCopyNodeRef); - } - - private void assertVersionableIsTrue(NodeRef workingCopyNodeRef) throws CmisException - { - if (!getTypeDefinition(workingCopyNodeRef).isVersionable()) + try { - // FIXME: uncomment this when CMIS dictionary model will be corrected - // throw cmisObjectsUtils.createCmisException("Document that was specified is not versionable", EnumServiceException.CONSTRAINT); + cmisService.cancelCheckOut(objectId); } - } - - private CMISTypeDefinition getTypeDefinition(NodeRef nodeRef) throws CmisException - { - String typeId = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_OBJECT_TYPE_ID, null); - CMISTypeDefinition typeDefinition = (null != typeId) ? (cmisDictionaryService.findType(typeId)) : (null); - if (null == typeDefinition) + catch (CMISServiceException e) { - throw cmisObjectsUtils.createCmisException(("Object type property is invalid"), EnumServiceException.RUNTIME); + throw ExceptionUtil.createCmisException(e); } - return typeDefinition; } /** @@ -117,46 +87,41 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve List policies, CmisAccessControlListType addACEs, CmisAccessControlListType removeACEs, Holder extension) throws CmisException { checkRepositoryId(repositoryId); - NodeRef workingCopyNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId.value, AlfrescoObjectType.DOCUMENT_OBJECT); - assertVersionableIsTrue(workingCopyNodeRef); - assertLatestVersion(workingCopyNodeRef, true); - - String versionSeriesId = propertiesUtil.getProperty(workingCopyNodeRef, CMISDictionaryModel.PROP_VERSION_SERIES_ID, null); - CMISTypeDefinition seriesObjectTypeDefinition = getTypeDefinition((NodeRef) cmisObjectsUtils.getIdentifierInstance(versionSeriesId, AlfrescoObjectType.DOCUMENT_OBJECT)); - - if ((null != contentStream) && (CMISContentStreamAllowedEnum.NOT_ALLOWED == seriesObjectTypeDefinition.getContentStreamAllowed())) - { - throw cmisObjectsUtils.createCmisException("Content stream is not allowed", EnumServiceException.STREAM_NOT_SUPPORTED); - } - - if (contentStream != null) - { - try - { - ContentWriter writer = fileFolderService.getWriter(workingCopyNodeRef); - writer.setMimetype(contentStream.getMimeType()); - writer.putContent(contentStream.getStream().getInputStream()); - } - catch (Exception e) - { - throw cmisObjectsUtils.createCmisException("Exception while updating content stream", EnumServiceException.UPDATE_CONFLICT, e); - } - } - - NodeRef nodeRef; try { - nodeRef = checkOutCheckInService.checkin(workingCopyNodeRef, createVersionProperties(checkinComment, ((null == major) || major) ? (VersionType.MAJOR) - : (VersionType.MINOR))); - propertiesUtil.setProperties(nodeRef, properties, null); + NodeRef workingCopyNodeRef = cmisService.getObject(objectId.value, NodeRef.class, true, true, true); + CMISTypeDefinition seriesObjectTypeDefinition = cmisService.getTypeDefinition(workingCopyNodeRef); + + if ((null != contentStream) && (CMISContentStreamAllowedEnum.NOT_ALLOWED == seriesObjectTypeDefinition.getContentStreamAllowed())) + { + throw ExceptionUtil.createCmisException("Content stream is not allowed", EnumServiceException.STREAM_NOT_SUPPORTED); + } + + if (contentStream != null) + { + try + { + ContentWriter writer = fileFolderService.getWriter(workingCopyNodeRef); + writer.setMimetype(contentStream.getMimeType()); + writer.putContent(contentStream.getStream().getInputStream()); + } + catch (Exception e) + { + throw ExceptionUtil.createCmisException("Exception while updating content stream", EnumServiceException.RUNTIME, e); + } + } + + propertiesUtil.setProperties(workingCopyNodeRef, properties, null); + NodeRef nodeRef = cmisService.checkIn(objectId.value, checkinComment, major == null || major); + + // TODO: applyPolicies + applyAclCarefully(nodeRef, addACEs, removeACEs, EnumACLPropagation.PROPAGATE); + objectId.value = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_OBJECT_ID, objectId.value); } - catch (Exception e) + catch (CMISServiceException e) { - throw cmisObjectsUtils.createCmisException("Unable to check in Private Working Copy object that was specified", EnumServiceException.STORAGE, e); + throw ExceptionUtil.createCmisException(e); } - // TODO: applyPolicies - applyAclCarefully(nodeRef, addACEs, removeACEs, EnumACLPropagation.PROPAGATE); - objectId.value = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_OBJECT_ID, objectId.value); } /** @@ -172,48 +137,18 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve public void checkOut(String repositoryId, Holder objectId, Holder extension, Holder contentCopied) throws CmisException { checkRepositoryId(repositoryId); - NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId.value, AlfrescoObjectType.DOCUMENT_OBJECT); - assertVersionableIsTrue(documentNodeRef); - assertLatestVersion(documentNodeRef, false); - - LockStatus lockStatus = lockService.getLockStatus(documentNodeRef); - if (lockStatus.equals(LockStatus.LOCKED) || lockStatus.equals(LockStatus.LOCK_OWNER) || nodeService.hasAspect(documentNodeRef, ContentModel.ASPECT_WORKING_COPY)) - { - throw cmisObjectsUtils.createCmisException("Object is locked or already checked out", EnumServiceException.UPDATE_CONFLICT); - } - try { - NodeRef pwcNodeRef = checkoutNode(documentNodeRef); + NodeRef pwcNodeRef = cmisService.checkOut(objectId.value); objectId.value = propertiesUtil.getProperty(pwcNodeRef, CMISDictionaryModel.PROP_OBJECT_ID, objectId.value); contentCopied.value = null != fileFolderService.getReader(pwcNodeRef); } - catch (Exception e) + catch (CMISServiceException e) { - throw cmisObjectsUtils.createCmisException(("Unable to execute Check Out services. Cause message: " + e.toString()), EnumServiceException.STORAGE); + throw ExceptionUtil.createCmisException(e); } } - /** - * Deletes all document versions in the specified version series. - * - * @param repositoryId repository Id - * @param versionSeriesId version series Id - * @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME) - */ - public void deleteAllVersions(String repositoryId, String versionSeriesId) throws CmisException - { - checkRepositoryId(repositoryId); - NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(versionSeriesId, AlfrescoObjectType.DOCUMENT_OBJECT); - NodeRef workingCopyRef = (cmisObjectsUtils.isWorkingCopy(documentNodeRef)) ? (documentNodeRef) : (checkOutCheckInService.getWorkingCopy(documentNodeRef)); - if ((null != workingCopyRef) && cmisObjectsUtils.isWorkingCopy(workingCopyRef)) - { - documentNodeRef = checkOutCheckInService.cancelCheckout(workingCopyRef); - } - - versionService.deleteVersionHistory(documentNodeRef); - } - /** * Gets the list of all document versions for the specified version series. * @@ -225,38 +160,23 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve throws CmisException { checkRepositoryId(repositoryId); - NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT); - documentNodeRef = cmisObjectsUtils.getLatestNode(documentNodeRef, false); PropertyFilter propertyFilter = createPropertyFilter(filter); List objects = new LinkedList(); - includeAllowableActions = (null == includeAllowableActions) ? (false) : (includeAllowableActions); - + if (includeAllowableActions == null) + { + includeAllowableActions = false; + } try { - NodeRef workingCopyNodeReference = cmisObjectsUtils.isWorkingCopy(documentNodeRef) ? documentNodeRef : checkOutCheckInService.getWorkingCopy(documentNodeRef); - if (null != workingCopyNodeReference) + for (NodeRef nodeRef : cmisService.getAllVersions(objectId)) { - objects.add(createCmisObject(workingCopyNodeReference, propertyFilter, includeAllowableActions, null)); + objects.add(createCmisObject(nodeRef, propertyFilter, includeAllowableActions, null)); } } - catch (Exception e) + catch (CMISServiceException e) { - if (!(e instanceof AccessDeniedException)) - { - throw cmisObjectsUtils.createCmisException(e.toString(), EnumServiceException.RUNTIME); - } + throw ExceptionUtil.createCmisException(e); } - - VersionHistory versionHistory = versionService.getVersionHistory(documentNodeRef); - if (null != versionHistory) - { - for (Version version = versionService.getCurrentVersion(documentNodeRef); null != version; version = versionHistory.getPredecessor(version)) - { - objects.add(createCmisObject(version.getFrozenStateNodeRef(), propertyFilter, includeAllowableActions, null)); - } - } - // TODO: includeRelationships - return objects; } @@ -271,43 +191,17 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve public CmisPropertiesType getPropertiesOfLatestVersion(String repositoryId, String objectId, Boolean major, String filter, CmisExtensionType extension) throws CmisException { checkRepositoryId(repositoryId); - NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT); + NodeRef latestVersionNodeRef; + try + { + latestVersionNodeRef = cmisService.getLatestVersion(objectId, major != null && major); + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e); + } PropertyFilter propertyFilter = createPropertyFilter(filter); - major = (null == major) ? (false) : (major); - NodeRef latestVersionNodeRef = getAndCheckLatestNodeRef(documentNodeRef, major); - return propertiesUtil.getPropertiesType(latestVersionNodeRef.toString(), propertyFilter); - } - - private void assertLatestVersion(NodeRef nodeRef, boolean mustBePwc) throws CmisException - { - if (mustBePwc) - { - boolean checkedOut = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_IS_VERSION_SERIES_CHECKED_OUT, false); - definitelyGetWorkingCopy(checkedOut, nodeRef); - } - else - { - Boolean latestVersion = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_IS_LATEST_VERSION, false); - if (!latestVersion && !cmisObjectsUtils.isWorkingCopy(nodeRef)) - { - throw cmisObjectsUtils.createCmisException("Operation can be executed only on the latest document version", EnumServiceException.VERSIONING); - } - } - } - - private NodeRef definitelyGetWorkingCopy(boolean checkedOut, NodeRef nodeRef) throws CmisException - { - NodeRef workingCopy = null; - String workingCopyId = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_VERSION_SERIES_CHECKED_OUT_ID, null); - if (checkedOut && (null != workingCopyId) && !"".equals(workingCopyId)) - { - workingCopy = cmisObjectsUtils.getIdentifierInstance(workingCopyId, AlfrescoObjectType.DOCUMENT_OBJECT); - } - if ((null == workingCopy) || !cmisObjectsUtils.isWorkingCopy(workingCopy)) - { - throw cmisObjectsUtils.createCmisException("Object isn't checked out", EnumServiceException.UPDATE_CONFLICT); - } - return workingCopy; + return propertiesUtil.getProperties(latestVersionNodeRef, propertyFilter); } /** @@ -318,29 +212,23 @@ public class DMVersioningServicePort extends DMAbstractServicePort implements Ve EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePolicyIds, Boolean includeACL, CmisExtensionType extension) throws CmisException { checkRepositoryId(repositoryId); - NodeRef documentNodeRef = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT); - PropertyFilter propertyFilter = createPropertyFilter(filter); - includeAllowableActions = (null == includeAllowableActions) ? (false) : (includeAllowableActions); - major = (null == major) ? (false) : (major); - NodeRef latestVersionNodeRef = getAndCheckLatestNodeRef(documentNodeRef, major); - // TODO: includeRelationships - // TODO: includePolicyIds - CmisObjectType result = createCmisObject(latestVersionNodeRef.toString(), propertyFilter, includeAllowableActions, renditionFilter); - if (includeACL) + try { - appendWithAce(documentNodeRef, result); - } - return result; - } + NodeRef latestVersionNodeRef = cmisService.getLatestVersion(objectId, major != null && major); + // TODO: includeRelationships + // TODO: includePolicyIds + PropertyFilter propertyFilter = createPropertyFilter(filter); + CmisObjectType result = createCmisObject(latestVersionNodeRef, propertyFilter, includeAllowableActions, renditionFilter); + if (includeACL) + { + appendWithAce(cmisService.getVersionSeries(objectId, NodeRef.class, false), result); + } - private NodeRef getAndCheckLatestNodeRef(NodeRef documentNodeRef, Boolean major) throws CmisException - { - NodeRef latestVersionNodeRef = cmisObjectsUtils.getLatestNode(documentNodeRef, major); - Boolean majorVersionProperty = propertiesUtil.getProperty(latestVersionNodeRef, CMISDictionaryModel.PROP_IS_MAJOR_VERSION, false); - if (major && !majorVersionProperty) - { - throw cmisObjectsUtils.createCmisException("Object that was specified has no latest major version", EnumServiceException.OBJECT_NOT_FOUND); + return result; + } + catch (CMISServiceException e) + { + throw ExceptionUtil.createCmisException(e); } - return latestVersionNodeRef; } } diff --git a/source/java/org/alfresco/repo/cmis/ws/utils/AlfrescoObjectType.java b/source/java/org/alfresco/repo/cmis/ws/utils/AlfrescoObjectType.java deleted file mode 100755 index e0039d5106..0000000000 --- a/source/java/org/alfresco/repo/cmis/ws/utils/AlfrescoObjectType.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2005-2008 Alfresco Software Limited. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" - */ -package org.alfresco.repo.cmis.ws.utils; - -import java.util.HashMap; -import java.util.Map; - -import org.alfresco.cmis.mapping.CMISMapping; -import org.alfresco.model.ContentModel; - -/** - * @author Dmitry Velichkevich - */ -public enum AlfrescoObjectType -{ - DOCUMENT_OBJECT(ContentModel.TYPE_CONTENT.toString()), - FOLDER_OBJECT(ContentModel.TYPE_FOLDER.toString()), - DOCUMENT_OR_FOLDER_OBJECT("DOCUMENT_OR_FOLDER"), - RELATIONSHIP_OBJECT(CMISMapping.RELATIONSHIP_QNAME.toString()), - ANY_OBJECT("ANY"); - - String value; - - final static Map VALUES; - static - { - VALUES = new HashMap(); - VALUES.put(DOCUMENT_OBJECT.getValue(), DOCUMENT_OBJECT); - VALUES.put(FOLDER_OBJECT.getValue(), FOLDER_OBJECT); - } - - AlfrescoObjectType(String value) - { - this.value = value; - } - - public String getValue() - { - return this.value; - } - - public static AlfrescoObjectType fromValue(String valueName) - { - AlfrescoObjectType result = VALUES.get(valueName); - if (result == null) - { - result = ANY_OBJECT; - } - return result; - } -} diff --git a/source/java/org/alfresco/repo/cmis/ws/utils/CmisObjectIterator.java b/source/java/org/alfresco/repo/cmis/ws/utils/CmisObjectIterator.java deleted file mode 100755 index aceb0fce3f..0000000000 --- a/source/java/org/alfresco/repo/cmis/ws/utils/CmisObjectIterator.java +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright (C) 2005-2009 Alfresco Software Limited. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" - */ -package org.alfresco.repo.cmis.ws.utils; - -import java.io.Serializable; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.cmis.ws.EnumUnfileObject; -import org.alfresco.repo.model.filefolder.FileInfoImpl; -import org.alfresco.service.cmr.coci.CheckOutCheckInService; -import org.alfresco.service.cmr.model.FileFolderService; -import org.alfresco.service.cmr.model.FileInfo; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.ContentData; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.version.VersionService; -import org.alfresco.service.namespace.QName; - -/** - * This class enumerates Documents and Folders hierarchy that begins from specified folder. Iterator returns Document or Empty Folder Objects those may be removed or deleted from - * repository according to {@link EnumUnfileObject} unfileObject and {@link Boolean} continueOnFailure parameters. After hierarchy enumerating completion iterator may - * introduce Object Id(s) {@link List} those were not deleted due to {@link Exception}(s) - * - * @author Dmitry Velichkevich - */ -public class CmisObjectIterator implements Iterator -{ - private EnumUnfileObject unfillingStrategy; - private boolean continueOnFailure; - - private NodeService nodeService; - private FileFolderService fileFolderService; - private VersionService versionService; - private CheckOutCheckInService checkOutCheckInService; - private CmisObjectsUtils objectsUtils; - - private Map> hierarchy = new HashMap>(); - private LinkedList objects = new LinkedList(); - private List failToDelete = new LinkedList(); - - private FileInfo next; - private boolean lastDeleted; - private boolean nextFound; - private boolean deleteAllVersions; - - /** - * Mandatory constructor - * - * @param rootObject - {@link NodeRef} instance that represents Root folder for hierarchy - * @param unfillingStrategy - {@link EnumUnfileObject} value that determines File-able Objects deletion or removing strategy - * @param continueOnFailure - {@link Boolean} value that determines whether it is necessary continue deletion after some {@link Exception} occurred - * @param nodeService - A {@link NodeService} implementation instance for manipulating with Object Properties - * @param fileFolderService - A {@link FileFolderService} implementation instance for manipulating with Objects - * @param objectsUtils - {@link CmisObjectsUtils} service instance for simplifying manipulations with Objects and Object Properties - */ - public CmisObjectIterator(NodeRef rootObject, EnumUnfileObject unfillingStrategy, boolean continueOnFailure, boolean deleteAllVersions, NodeService nodeService, - FileFolderService fileFolderService, VersionService versionService, CheckOutCheckInService checkOutCheckInService, CmisObjectsUtils objectsUtils) - { - this.unfillingStrategy = unfillingStrategy; - this.deleteAllVersions = deleteAllVersions; - this.continueOnFailure = continueOnFailure; - this.nodeService = nodeService; - this.fileFolderService = fileFolderService; - this.versionService = versionService; - this.checkOutCheckInService = checkOutCheckInService; - this.objectsUtils = objectsUtils; - objects.add(new ParentedFileInfo(fileFolderService.getFileInfo(rootObject), null)); - } - - /** - * This method performs searching for next Object (see {@link CmisObjectIterator}) - */ - public boolean hasNext() - { - if (nextFound) - { - return true; - } - if (objects.isEmpty() || (!failToDelete.isEmpty() && !continueOnFailure)) - { - return false; - } - for (next = objects.removeFirst(); processFolder() && !objects.isEmpty(); next = objects.removeFirst()) - { - } - nextFound = (null != next) && (!next.isFolder() || (null == receiveChildren(next.getNodeRef()))); - return nextFound; - } - - private boolean processFolder() - { - if (next.isFolder()) - { - List children = receiveChildren(next.getNodeRef()); - if (null != children) - { - objects.addFirst(next); - for (ChildAssociationRef child : children) - { - FileInfo info = fileFolderService.getFileInfo(child.getChildRef()); - ParentedFileInfo childInfo = new ParentedFileInfo(info, next); - objects.addFirst(childInfo); - addChildToParent(next, childInfo); - } - return true; - } - } - return false; - } - - private void addChildToParent(FileInfo parent, FileInfo child) - { - if (null != parent) - { - List children; - if (hierarchy.containsKey(parent)) - { - children = hierarchy.get(parent); - } - else - { - children = new LinkedList(); - hierarchy.put(parent, children); - } - children.add(child); - } - } - - private List receiveChildren(NodeRef folderRef) - { - if (null != folderRef) - { - List result = nodeService.getChildAssocs(folderRef); - if ((null != result) && !result.isEmpty()) - { - return result; - } - } - return null; - } - - /** - * This method returns currently enumerated Object and changes flag to enumerate next Object - * - * @see CmisObjectIterator - * @see CmisObjectIterator#hasNext() - * @see CmisObjectIterator#remove() - */ - public FileInfo next() - { - nextFound = false; - return next; - } - - /** - * This method removes currently enumerated Object (see {@link CmisObjectIterator}). If Object deletion or removing fails due to {@link Exception} then according to - * continueOnFailure parameter current Object Id and (if continueOnFailure="true") current Object Parent(s)' Id(s) will be stored in failedToDelete - * {@link List}. Not deleted Object and its Parent(s) never will be enumerated again - * - * @see CmisObjectIterator - * @see CmisObjectIterator#hasNext() - * @see CmisObjectIterator#next() - */ - public void remove() - { - lastDeleted = false; - NodeRef parentRef = null; - ParentedFileInfo info = null; - if (null != next) - { - info = (ParentedFileInfo) next; - EnumUnfileObject howToDelete = null; - parentRef = (null != info.getExactParent()) ? (info.getExactParent().getNodeRef()) : (null); - if ((null != parentRef) && ((EnumUnfileObject.DELETESINGLEFILED == unfillingStrategy) || !objectsUtils.isPrimaryObjectParent(parentRef, info.getNodeRef()))) - { - howToDelete = EnumUnfileObject.DELETESINGLEFILED; - } - else - { - howToDelete = EnumUnfileObject.DELETE; - } - if (EnumUnfileObject.DELETESINGLEFILED == howToDelete) - { - lastDeleted = objectsUtils.removeObject(info.getNodeRef(), parentRef); - } - else - { - if (deleteAllVersions) - { - NodeRef workingCopyRef = (objectsUtils.isWorkingCopy(info.getNodeRef())) ? (info.getNodeRef()) : (checkOutCheckInService.getWorkingCopy(info.getNodeRef())); - if (null == workingCopyRef) - { - versionService.deleteVersionHistory(info.getNodeRef()); - } - } - lastDeleted = (objectsUtils.deleteObject(info.getNodeRef())); - } - } - if (!lastDeleted && (null != info)) - { - failToDelete.add(generateId(info)); - if ((null == info.getExactParent()) && info.isFolder()) - { - removeFolderFromCollections(info); - } - if (continueOnFailure) - { - for (; null != info.getExactParent(); info = (ParentedFileInfo) info.getExactParent()) - { - failToDelete.add(generateId(info.getExactParent())); - removeFolderFromCollections(info.getExactParent()); - } - } - } - } - - private void removeFolderFromCollections(FileInfo object) - { - if (hierarchy.containsKey(object)) - { - hierarchy.remove(object); - objects.remove(object); - } - } - - private String generateId(FileInfo object) - { - StringBuilder generator = new StringBuilder(object.getNodeRef().toString()); - Map properties = object.getProperties(); - String versionLabel = (null != properties) ? ((String) properties.get(ContentModel.PROP_VERSION_LABEL)) : (null); - if (null != versionLabel) - { - generator.append(CmisObjectsUtils.NODE_REFERENCE_ID_DELIMITER).append(versionLabel); - } - return generator.toString(); - } - - public boolean wasLastRemoved() - { - return lastDeleted; - } - - public List getFailToDelete() - { - return failToDelete; - } - - /** - * This class is {@link org.alfresco.jlan.server.filesys.FileInfo} implementation that uses {@link FileInfoImpl} instances to delegate core functionality. The main target of - * this class is extended standard {@link FileInfo} Objects with Parent Object - * - * @author Dmitry Velichkevich - */ - private class ParentedFileInfo implements FileInfo, Serializable - { - private static final long serialVersionUID = -3024276223816623074L; - - private FileInfo delegator; - private FileInfo exactParent; - - public ParentedFileInfo(FileInfo delegator, FileInfo exactParent) - { - this.delegator = delegator; - this.exactParent = exactParent; - } - - public ContentData getContentData() - { - return delegator.getContentData(); - } - - public Date getCreatedDate() - { - return delegator.getCreatedDate(); - } - - public NodeRef getLinkNodeRef() - { - return delegator.getLinkNodeRef(); - } - - public Date getModifiedDate() - { - return delegator.getModifiedDate(); - } - - public String getName() - { - return delegator.getName(); - } - - public NodeRef getNodeRef() - { - return delegator.getNodeRef(); - } - - public Map getProperties() - { - return delegator.getProperties(); - } - - public boolean isFolder() - { - return delegator.isFolder(); - } - - public boolean isLink() - { - return delegator.isLink(); - } - - public FileInfo getExactParent() - { - return exactParent; - } - - @Override - public boolean equals(Object obj) - { - return delegator.equals(obj); - } - - @Override - public int hashCode() - { - return delegator.hashCode(); - } - - @Override - public String toString() - { - return delegator.toString(); - } - } -} diff --git a/source/java/org/alfresco/repo/cmis/ws/utils/CmisObjectsUtils.java b/source/java/org/alfresco/repo/cmis/ws/utils/CmisObjectsUtils.java deleted file mode 100755 index 9d4db8016d..0000000000 --- a/source/java/org/alfresco/repo/cmis/ws/utils/CmisObjectsUtils.java +++ /dev/null @@ -1,566 +0,0 @@ -/* - * Copyright (C) 2005-2008 Alfresco Software Limited. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" - */ -package org.alfresco.repo.cmis.ws.utils; - -import java.math.BigInteger; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import org.alfresco.cmis.CMISDictionaryService; -import org.alfresco.cmis.CMISQueryException; -import org.alfresco.cmis.CMISScope; -import org.alfresco.cmis.CMISTypeDefinition; -import org.alfresco.model.ContentModel; -import org.alfresco.repo.cmis.ws.CmisException; -import org.alfresco.repo.cmis.ws.CmisFaultType; -import org.alfresco.repo.cmis.ws.EnumBaseObjectTypeIds; -import org.alfresco.repo.cmis.ws.EnumRelationshipDirection; -import org.alfresco.repo.cmis.ws.EnumServiceException; -import org.alfresco.repo.cmis.ws.EnumUnfileObject; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.permissions.AccessDeniedException; -import org.alfresco.service.cmr.coci.CheckOutCheckInService; -import org.alfresco.service.cmr.lock.LockService; -import org.alfresco.service.cmr.lock.LockStatus; -import org.alfresco.service.cmr.model.FileFolderService; -import org.alfresco.service.cmr.repository.AssociationRef; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.ContentIOException; -import org.alfresco.service.cmr.repository.InvalidNodeRefException; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.security.AuthorityService; -import org.alfresco.service.cmr.version.Version; -import org.alfresco.service.cmr.version.VersionHistory; -import org.alfresco.service.cmr.version.VersionService; -import org.alfresco.service.cmr.version.VersionType; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.namespace.QNamePattern; -import org.springframework.extensions.surf.util.Pair; - -/** - * @author Dmitry Velichkevich - */ -public class CmisObjectsUtils -{ - public static final String NODE_REFERENCE_ID_DELIMITER = ";"; - - private static final Pattern VERSION_LABEL_MATCHING_COMPILED_PATTERN = Pattern.compile("([\\p{Graph}])+([\\p{Digit}]*)\\.([\\p{Digit}]*)$"); - - private static final String INVALID_OBJECT_IDENTIFIER_MESSAGE = "Invalid Object Identifier was specified: Identifier is incorrect or Object with the specified Identifier does not exist"; - - private static final List DOCUMENT_AND_FOLDER_TYPES; - static - { - DOCUMENT_AND_FOLDER_TYPES = new LinkedList(); - DOCUMENT_AND_FOLDER_TYPES.add(ContentModel.TYPE_CONTENT); - DOCUMENT_AND_FOLDER_TYPES.add(ContentModel.TYPE_FOLDER); - } - - private static final Map CLASS_TO_ENUM_EXCEPTION_MAPPING; - static - { - CLASS_TO_ENUM_EXCEPTION_MAPPING = new HashMap(); - CLASS_TO_ENUM_EXCEPTION_MAPPING.put(AccessDeniedException.class.getName(), EnumServiceException.PERMISSION_DENIED); - CLASS_TO_ENUM_EXCEPTION_MAPPING.put(java.lang.RuntimeException.class.getName(), EnumServiceException.RUNTIME); - CLASS_TO_ENUM_EXCEPTION_MAPPING.put(UnsupportedOperationException.class.getName(), EnumServiceException.NOT_SUPPORTED); - CLASS_TO_ENUM_EXCEPTION_MAPPING.put(InvalidNodeRefException.class.getName(), EnumServiceException.INVALID_ARGUMENT); - CLASS_TO_ENUM_EXCEPTION_MAPPING.put(ContentIOException.class.getName(), EnumServiceException.NOT_SUPPORTED); - CLASS_TO_ENUM_EXCEPTION_MAPPING.put(CMISQueryException.class.getName(), EnumServiceException.INVALID_ARGUMENT); - // TODO: insert CLASS_TO_ENUM_EXCEPTION_MAPPING.put(.class.getName(), EnumServiceException.); - } - - private CheckOutCheckInService checkOutCheckInService; - private CMISDictionaryService cmisDictionaryService; - private FileFolderService fileFolderService; - private AuthorityService authorityService; - private VersionService versionService; - private NodeService nodeService; - private LockService lockService; - - private Throwable lastException; - - public void setCmisDictionaryService(CMISDictionaryService cmisDictionaryService) - { - this.cmisDictionaryService = cmisDictionaryService; - } - - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - - public void setFileFolderService(FileFolderService fileFolderService) - { - this.fileFolderService = fileFolderService; - } - - public void setLockService(LockService lockService) - { - this.lockService = lockService; - } - - public void setCheckOutCheckInService(CheckOutCheckInService checkOutCheckInService) - { - this.checkOutCheckInService = checkOutCheckInService; - } - - public void setAuthorityService(AuthorityService authorityService) - { - this.authorityService = authorityService; - } - - public void setVersionService(VersionService versionService) - { - this.versionService = versionService; - } - - public CmisException createCmisException(String message, EnumServiceException exceptionType) - { - return createCmisException(message, exceptionType, null, 0); - } - - public CmisException createCmisException(String message, Throwable cause) - { - EnumServiceException exceptionType = null; - - if (CLASS_TO_ENUM_EXCEPTION_MAPPING.containsKey(cause.getClass().getName())) - { - exceptionType = CLASS_TO_ENUM_EXCEPTION_MAPPING.get(cause.getClass().getName()); - } - - exceptionType = (exceptionType == null) ? (EnumServiceException.RUNTIME) : (exceptionType); - - return createCmisException(message, exceptionType, cause, 0); - } - - public CmisException createCmisException(String message, EnumServiceException exceptionType, Throwable cause) - { - return createCmisException(message, exceptionType, cause, 0); - } - - public CmisException createCmisException(String message, EnumServiceException exceptionType, Throwable cause, int errorCode) - { - CmisFaultType fault = new CmisFaultType(); - fault.setMessage(message); - fault.setType(exceptionType); - fault.setCode(BigInteger.valueOf(errorCode)); - - return new CmisException(message, fault, cause); - } - - @SuppressWarnings("unchecked") - public IdentifierType getIdentifierInstance(String identifier, AlfrescoObjectType expectedType) throws CmisException - { - if (!(identifier instanceof String)) - { - throw createCmisException("Invalid Object Identifier was specified", EnumServiceException.INVALID_ARGUMENT); - } - - IdentifierType result; - AlfrescoObjectType actualObjectType; - - if (isRelationship(identifier)) - { - result = (IdentifierType) safeGetAssociationRef(identifier); - actualObjectType = AlfrescoObjectType.RELATIONSHIP_OBJECT; - } - else - { - NodeRef nodeReference = safeGetNodeRef(identifier); - result = (IdentifierType) nodeReference; - actualObjectType = determineActualObjectType(expectedType, this.nodeService.getType(nodeReference)); - } - - if ((AlfrescoObjectType.ANY_OBJECT == expectedType) || (actualObjectType == expectedType)) - { - return result; - } - - throw createCmisException(("Unexpected object type of the specified Object with \"" + identifier + "\" identifier"), EnumServiceException.INVALID_ARGUMENT); - } - - public List deleteFolder(NodeRef folderNodeReference, boolean continueOnFailure, EnumUnfileObject unfillingStrategy, boolean deleteAllVersions) throws CmisException - { - CmisObjectIterator iterator = new CmisObjectIterator(folderNodeReference, unfillingStrategy, continueOnFailure, deleteAllVersions, nodeService, fileFolderService, - versionService, checkOutCheckInService, this); - if (iterator.hasNext()) - { - for (; iterator.hasNext(); iterator.next()) - { - iterator.remove(); - } - } - return iterator.getFailToDelete(); - } - - public boolean deleteObject(NodeRef objectNodeReference) - { - if (null == objectNodeReference) - { - return false; - } - - if (versionService.getVersionStoreReference().getIdentifier().equals(objectNodeReference.getStoreRef().getIdentifier())) - { - String versionLabel = (String) nodeService.getProperty(objectNodeReference, ContentModel.PROP_VERSION_LABEL); - - if ((null != versionLabel) && !versionLabel.equals("")) - { - Version currentVersion = versionService.getCurrentVersion(objectNodeReference); - - if ((null != currentVersion) && nodeService.exists(currentVersion.getVersionedNodeRef())) - { - versionService.deleteVersion(currentVersion.getVersionedNodeRef(), currentVersion); - return true; - } - } - - return false; - } - - return canLock(objectNodeReference) && performNodeDeletion(objectNodeReference); - } - - public boolean removeObject(NodeRef objectNodeReference, NodeRef folderNodeReference) - { - if (isChildOfThisFolder(objectNodeReference, folderNodeReference)) - { - try - { - this.nodeService.removeChild(folderNodeReference, objectNodeReference); - } - catch (Throwable e) - { - lastException = e; - return false; - } - return true; - } - return false; - } - - public boolean addObjectToFolder(NodeRef objectNodeRef, NodeRef parentFolderNodeRef) - { - try - { - QName name = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName((String) nodeService.getProperty(objectNodeRef, - ContentModel.PROP_NAME))); - nodeService.addChild(parentFolderNodeRef, objectNodeRef, ContentModel.ASSOC_CONTAINS, name); - return true; - } - catch (Throwable e) - { - lastException = e; - return false; - } - } - - public boolean isFolder(NodeRef folderNodeRef) - { - if (folderNodeRef == null) - { - return false; - } - QName typeQName = nodeService.getType(folderNodeRef); - CMISTypeDefinition typeDef = cmisDictionaryService.findTypeForClass(typeQName, CMISScope.FOLDER); - return typeDef != null; - } - - public boolean isDocument(NodeRef documentNodeRef) - { - if (documentNodeRef == null) - { - return false; - } - QName typeQName = nodeService.getType(documentNodeRef); - CMISTypeDefinition typeDef = cmisDictionaryService.findTypeForClass(typeQName, CMISScope.DOCUMENT); - return typeDef != null; - } - - public boolean isRelationship(String identifier) - { - try - { - new AssociationRef(identifier); - return true; - } - catch (Throwable e) - { - return false; - } - } - - public boolean isPolicy(NodeRef policyNodeRef) - { - // TODO: Policy - return false; - } - - public EnumBaseObjectTypeIds determineObjectType(String identifier) - { - if (isRelationship(identifier)) - { - return EnumBaseObjectTypeIds.CMIS_RELATIONSHIP; - } - - NodeRef objectNodeReference = new NodeRef(identifier); - if (isFolder(objectNodeReference)) - { - return EnumBaseObjectTypeIds.CMIS_FOLDER; - } - - if (isDocument(objectNodeReference)) - { - return EnumBaseObjectTypeIds.CMIS_DOCUMENT; - } - - return EnumBaseObjectTypeIds.CMIS_POLICY; - } - - public boolean isChildOfThisFolder(NodeRef objectNodeReference, NodeRef folderNodeReference) - { - NodeRef searchedObjectNodeReference = fileFolderService.searchSimple(folderNodeReference, (String) nodeService.getProperty(objectNodeReference, ContentModel.PROP_NAME)); - return (searchedObjectNodeReference != null) && searchedObjectNodeReference.equals(objectNodeReference); - } - - public boolean isPrimaryObjectParent(NodeRef folderNodeReference, NodeRef objectNodeReference) - { - NodeRef searchedParentObject = nodeService.getPrimaryParent(objectNodeReference).getParentRef(); - return (searchedParentObject != null) && searchedParentObject.equals(folderNodeReference); - } - - public boolean isWorkingCopy(NodeRef objectIdentifier) - { - return nodeService.hasAspect(objectIdentifier, ContentModel.ASPECT_WORKING_COPY); - } - - public List receiveAssociations(NodeRef objectNodeReference, QNamePattern qnameFilter, EnumRelationshipDirection direction) - { - List result = new LinkedList(); - - if ((direction == EnumRelationshipDirection.EITHER) || (direction == EnumRelationshipDirection.TARGET)) - { - result.addAll(nodeService.getSourceAssocs(objectNodeReference, qnameFilter)); - } - - if ((direction == EnumRelationshipDirection.EITHER) || (direction == EnumRelationshipDirection.SOURCE)) - { - result.addAll(nodeService.getTargetAssocs(objectNodeReference, qnameFilter)); - } - - return result; - } - - /** - * Returns latest minor or major version of document - * - * @param documentNodeRef document node reference - * @param major need latest major version - * @return latest version node reference - */ - public NodeRef getLatestNode(NodeRef documentNodeRef, boolean major) - { - NodeRef latestVersionNodeRef = documentNodeRef; - VersionHistory versionHistory = versionService.getVersionHistory(documentNodeRef); - if (null != versionHistory) - { - Collection allVersions = versionHistory.getAllVersions(); - Iterator versionsIterator = ((null != allVersions) && !allVersions.isEmpty()) ? (allVersions.iterator()) : (null); - Version latestVersion = (null == versionsIterator) ? (null) : (versionsIterator.next()); - String currentVersionLabel = (null != latestVersion) ? (latestVersion.getVersionLabel()) : (null); - if (major && (null != latestVersion)) - { - for (; (VersionType.MAJOR != latestVersion.getVersionType()) && versionsIterator.hasNext(); latestVersion = versionsIterator.next()) - { - } - latestVersion = (VersionType.MAJOR != latestVersion.getVersionType()) ? (null) : (latestVersion); - } - if ((null != latestVersion) && (null != latestVersion.getVersionLabel())) - { - latestVersionNodeRef = (!latestVersion.getVersionLabel().equals(currentVersionLabel) || (null == latestVersion.getVersionedNodeRef()) || !nodeService - .exists(latestVersion.getVersionedNodeRef())) ? (latestVersion.getFrozenStateNodeRef()) : (latestVersion.getVersionedNodeRef()); - } - } - - return latestVersionNodeRef; - } - - private boolean performNodeDeletion(NodeRef objectNodeReference) - { - if (nodeService.hasAspect(objectNodeReference, ContentModel.ASPECT_WORKING_COPY)) - { - checkOutCheckInService.cancelCheckout(objectNodeReference); - return true; - } - - try - { - List associations = receiveAssociations(objectNodeReference, new MatcheAllQNames(), EnumRelationshipDirection.EITHER); - for (AssociationRef association : associations) - { - if ((null != association) && (null != association.getSourceRef()) && (null != association.getTargetRef()) && (null != association.getTypeQName())) - { - nodeService.removeAssociation(association.getSourceRef(), association.getTargetRef(), association.getTypeQName()); - } - } - - for (ChildAssociationRef parentAssociation : nodeService.getParentAssocs(objectNodeReference)) - { - if (!parentAssociation.isPrimary()) - { - nodeService.removeChildAssociation(parentAssociation); - } - } - - nodeService.deleteNode(objectNodeReference); - } - catch (Throwable e) - { - lastException = e; - return false; - } - return true; - } - - private boolean canLock(NodeRef objectNodeReference) - { - String currentUserName = AuthenticationUtil.getFullyAuthenticatedUser(); - return (this.lockService.getLockStatus(objectNodeReference, currentUserName) != LockStatus.LOCKED) || authorityService.isAdminAuthority(currentUserName); - } - - private AssociationRef safeGetAssociationRef(String identifier) throws CmisException - { - AssociationRef result = new AssociationRef(identifier); - - if (!nodeService.exists(result.getSourceRef()) || !nodeService.exists(result.getTargetRef())) - { - throw createCmisException(INVALID_OBJECT_IDENTIFIER_MESSAGE, EnumServiceException.INVALID_ARGUMENT); - } - - return result; - } - - private NodeRef safeGetNodeRef(String nodeIdentifier) throws CmisException - { - Pair nodeRefAndVersionLabel = (null != nodeIdentifier) ? (splitOnNodeRefAndVersionLabel(nodeIdentifier)) : (null); - if ((null != nodeRefAndVersionLabel) && (null != nodeRefAndVersionLabel.getFirst()) && NodeRef.isNodeRef(nodeRefAndVersionLabel.getFirst())) - { - NodeRef result = new NodeRef(nodeRefAndVersionLabel.getFirst()); - if (nodeService.exists(result)) - { - result = getNodeRefFromVersion(result, nodeRefAndVersionLabel.getSecond()); - - if ((null != result) && nodeService.exists(result)) - { - return result; - } - } - } - - throw createCmisException(INVALID_OBJECT_IDENTIFIER_MESSAGE, EnumServiceException.OBJECT_NOT_FOUND); - } - - private Pair splitOnNodeRefAndVersionLabel(String nodeIdentifier) - { - String versionLabel = null; - int versionDelimeterIndex = nodeIdentifier.lastIndexOf(NODE_REFERENCE_ID_DELIMITER); - if (versionDelimeterIndex > 0) - { - versionLabel = nodeIdentifier.substring(versionDelimeterIndex + 1); - if ((null != versionLabel) && !versionLabel.equals("") && VERSION_LABEL_MATCHING_COMPILED_PATTERN.matcher(versionLabel).matches()) - { - nodeIdentifier = nodeIdentifier.substring(0, versionDelimeterIndex); - } - else - { - versionLabel = null; - } - } - - return new Pair(nodeIdentifier, versionLabel); - } - - private NodeRef getNodeRefFromVersion(NodeRef nodeRef, String versionLabel) throws CmisException - { - NodeRef result = nodeRef; - - NodeRef latestNodeRef = ((null != versionLabel) && (null != nodeRef)) ? (getLatestNode(nodeRef, false)) : (null); - if ((null != latestNodeRef) && nodeService.exists(latestNodeRef) && !versionLabel.equals(nodeService.getProperty(latestNodeRef, ContentModel.PROP_VERSION_LABEL))) - { - VersionHistory versionHistory = versionService.getVersionHistory(latestNodeRef); - if (null != versionHistory) - { - Version version = versionHistory.getVersion(versionLabel); - - if ((null == version) || (null == version.getFrozenStateNodeRef())) - { - throw createCmisException(("Specified object has no " + versionLabel + " version"), EnumServiceException.INVALID_ARGUMENT); - } - - result = version.getFrozenStateNodeRef(); - } - } - - return result; - } - - private AlfrescoObjectType determineActualObjectType(AlfrescoObjectType expectedType, QName objectType) - { - CMISTypeDefinition typeDef = cmisDictionaryService.findTypeForClass(objectType); - if ((expectedType == AlfrescoObjectType.DOCUMENT_OBJECT || expectedType == AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT) - && typeDef.getTypeId().getScope() == CMISScope.DOCUMENT) - { - return expectedType; - } - if ((expectedType == AlfrescoObjectType.FOLDER_OBJECT || expectedType == AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT) - && typeDef.getTypeId().getScope() == CMISScope.FOLDER) - { - return expectedType; - } - return AlfrescoObjectType.ANY_OBJECT; - } - - private class MatcheAllQNames implements QNamePattern - { - public boolean isMatch(QName qname) - { - return true; - } - } - - public Throwable getLastOperationException() - { - Throwable result = lastException; - lastException = null; - return result; - } -} diff --git a/source/java/org/alfresco/repo/cmis/ws/utils/ExceptionUtil.java b/source/java/org/alfresco/repo/cmis/ws/utils/ExceptionUtil.java new file mode 100755 index 0000000000..84c37cc2b4 --- /dev/null +++ b/source/java/org/alfresco/repo/cmis/ws/utils/ExceptionUtil.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have received a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.cmis.ws.utils; + +import java.math.BigInteger; +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.cmis.CMISQueryException; +import org.alfresco.cmis.CMISServiceException; +import org.alfresco.repo.cmis.ws.CmisException; +import org.alfresco.repo.cmis.ws.CmisFaultType; +import org.alfresco.repo.cmis.ws.EnumServiceException; +import org.alfresco.repo.security.permissions.AccessDeniedException; +import org.alfresco.service.cmr.repository.ContentIOException; +import org.alfresco.service.cmr.repository.InvalidNodeRefException; + +/** + * @author Dmitry Velichkevich + */ +public abstract class ExceptionUtil +{ + private static final Map CLASS_TO_ENUM_EXCEPTION_MAPPING; + static + { + CLASS_TO_ENUM_EXCEPTION_MAPPING = new HashMap(); + CLASS_TO_ENUM_EXCEPTION_MAPPING.put(AccessDeniedException.class.getName(), EnumServiceException.PERMISSION_DENIED); + CLASS_TO_ENUM_EXCEPTION_MAPPING.put(java.lang.RuntimeException.class.getName(), EnumServiceException.RUNTIME); + CLASS_TO_ENUM_EXCEPTION_MAPPING.put(UnsupportedOperationException.class.getName(), EnumServiceException.NOT_SUPPORTED); + CLASS_TO_ENUM_EXCEPTION_MAPPING.put(InvalidNodeRefException.class.getName(), EnumServiceException.INVALID_ARGUMENT); + CLASS_TO_ENUM_EXCEPTION_MAPPING.put(ContentIOException.class.getName(), EnumServiceException.NOT_SUPPORTED); + CLASS_TO_ENUM_EXCEPTION_MAPPING.put(CMISQueryException.class.getName(), EnumServiceException.INVALID_ARGUMENT); + } + + public static CmisException createCmisException(String message, EnumServiceException exceptionType) + { + return createCmisException(message, exceptionType, null, 0); + } + + public static CmisException createCmisException(String message, Throwable cause) + { + EnumServiceException exceptionType = null; + + if (cause instanceof CMISServiceException) + { + return createCmisException((CMISServiceException)cause); + } + + if (CLASS_TO_ENUM_EXCEPTION_MAPPING.containsKey(cause.getClass().getName())) + { + exceptionType = CLASS_TO_ENUM_EXCEPTION_MAPPING.get(cause.getClass().getName()); + } + + exceptionType = (exceptionType == null) ? (EnumServiceException.RUNTIME) : (exceptionType); + + return createCmisException(message, exceptionType, cause, 0); + } + + public static CmisException createCmisException(String message, EnumServiceException exceptionType, Throwable cause) + { + return createCmisException(message, exceptionType, cause, 0); + } + + public static CmisException createCmisException(CMISServiceException exception) + { + return createCmisException(exception.getMessage(), EnumServiceException.fromValue(exception.getFaultName()), exception, exception.getStatusCode()); + } + + public static CmisException createCmisException(String message, EnumServiceException exceptionType, Throwable cause, int errorCode) + { + CmisFaultType fault = new CmisFaultType(); + fault.setMessage(message); + fault.setType(exceptionType); + fault.setCode(BigInteger.valueOf(errorCode)); + + return new CmisException(message, fault, cause); + } +} diff --git a/source/java/org/alfresco/repo/cmis/ws/utils/PropertyUtil.java b/source/java/org/alfresco/repo/cmis/ws/utils/PropertyUtil.java index 6c702c7476..00e3608c72 100755 --- a/source/java/org/alfresco/repo/cmis/ws/utils/PropertyUtil.java +++ b/source/java/org/alfresco/repo/cmis/ws/utils/PropertyUtil.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.repo.cmis.ws.utils; @@ -40,6 +40,7 @@ import javax.xml.datatype.XMLGregorianCalendar; import org.alfresco.cmis.CMISDataTypeEnum; import org.alfresco.cmis.CMISDictionaryModel; import org.alfresco.cmis.CMISDictionaryService; +import org.alfresco.cmis.CMISInvalidArgumentException; import org.alfresco.cmis.CMISPropertyDefinition; import org.alfresco.cmis.CMISScope; import org.alfresco.cmis.CMISServices; @@ -65,6 +66,7 @@ import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.version.Version; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; @@ -98,7 +100,6 @@ public class PropertyUtil private NamespaceService namespaceService; private CMISServices cmisService; private CMISDictionaryService cmisDictionaryService; - private CmisObjectsUtils cmisObjectsUtils; public PropertyUtil() { @@ -129,11 +130,6 @@ public class PropertyUtil this.cmisDictionaryService = cmisDictionaryService; } - public void setCmisObjectsUtils(CmisObjectsUtils cmisObjectsUtils) - { - this.cmisObjectsUtils = cmisObjectsUtils; - } - /** * Gets property value by its name from Node Reference object * @@ -275,7 +271,7 @@ public class PropertyUtil if ((PropertyMultiValueStateEnum.PROPERTY_NOT_MULTIVALUED == state) && (values.size() > 1)) { - throw cmisObjectsUtils.createCmisException("\"" + propertyName + "\" property is not Multi Valued", EnumServiceException.INVALID_ARGUMENT); + throw ExceptionUtil.createCmisException("\"" + propertyName + "\" property is not Multi Valued", EnumServiceException.INVALID_ARGUMENT); } return PropertyMultiValueStateEnum.PROPERTY_MULTIVALUED == state; @@ -379,7 +375,7 @@ public class PropertyUtil if ((null == cmisObjectType) && (null == nativeObjectType)) { - throw cmisObjectsUtils.createCmisException(("Can't find type definition for current object with \"" + typeId + "\" type Id"), EnumServiceException.INVALID_ARGUMENT); + throw ExceptionUtil.createCmisException(("Can't find type definition for current object with \"" + typeId + "\" type Id"), EnumServiceException.INVALID_ARGUMENT); } for (CmisProperty property : properties.getProperty()) @@ -406,7 +402,7 @@ public class PropertyUtil } case PROPERTY_NOT_UPDATABLE: { - throw cmisObjectsUtils.createCmisException(("\"" + propertyName + "\" property is not updatable by repository for specified Object id"), + throw ExceptionUtil.createCmisException(("\"" + propertyName + "\" property is not updatable by repository for specified Object id"), EnumServiceException.CONSTRAINT); } } @@ -479,7 +475,7 @@ public class PropertyUtil if (propertyDefinition.isRequired() && (null == value)) { - throw cmisObjectsUtils.createCmisException((propertyName + " property required"), EnumServiceException.CONSTRAINT); + throw ExceptionUtil.createCmisException((propertyName + " property required"), EnumServiceException.CONSTRAINT); } switch (propertyDefinition.getDataType()) @@ -514,7 +510,7 @@ public class PropertyUtil { if (value != null && (propertyDefinition.getMaximumLength() > 0) && (value.length() > propertyDefinition.getMaximumLength())) { - throw cmisObjectsUtils.createCmisException((propertyName + " property value is too long"), EnumServiceException.CONSTRAINT); + throw ExceptionUtil.createCmisException((propertyName + " property value is too long"), EnumServiceException.CONSTRAINT); } } @@ -525,21 +521,32 @@ public class PropertyUtil * @param filter property filter * @return properties */ - public CmisPropertiesType getPropertiesType(String identifier, PropertyFilter filter) throws CmisException + public CmisPropertiesType getProperties(Object object, PropertyFilter filter) throws CmisException { - Map properties; - if (!identifier.contains("|")) + try { - properties = cmisService.getProperties(new NodeRef(identifier)); - } - else - { - properties = createBaseRelationshipProperties(new AssociationRef(identifier)); - } + Map properties; + if (object instanceof NodeRef) + { + properties = cmisService.getProperties((NodeRef) object); + } + else if (object instanceof Version) + { + properties = cmisService.getProperties(((Version) object).getFrozenStateNodeRef()); + } + else + { + properties = createBaseRelationshipProperties((AssociationRef) object); + } - CmisPropertiesType result = new CmisPropertiesType(); - convertToCmisProperties(properties, filter, result); - return result; + CmisPropertiesType result = new CmisPropertiesType(); + convertToCmisProperties(properties, filter, result); + return result; + } + catch (CMISInvalidArgumentException e) + { + throw ExceptionUtil.createCmisException(e.getMessage(), EnumServiceException.INVALID_ARGUMENT, e); + } } private Map createBaseRelationshipProperties(AssociationRef association) @@ -562,7 +569,7 @@ public class PropertyUtil if (null == type) { - throw cmisObjectsUtils.createCmisException(("Type with " + typeId + " typeId was not found"), EnumServiceException.RUNTIME); + throw ExceptionUtil.createCmisException(("Type with " + typeId + " typeId was not found"), EnumServiceException.RUNTIME); } for (String propertyName : properties.keySet()) diff --git a/source/java/org/alfresco/repo/web/scripts/content/ContentDelete.java b/source/java/org/alfresco/repo/web/scripts/content/ContentDelete.java index a62185a8d7..d844cf07d9 100644 --- a/source/java/org/alfresco/repo/web/scripts/content/ContentDelete.java +++ b/source/java/org/alfresco/repo/web/scripts/content/ContentDelete.java @@ -31,8 +31,8 @@ import java.util.Map; import javax.servlet.http.HttpServletResponse; import org.alfresco.cmis.CMISObjectReference; -import org.alfresco.cmis.reference.ReferenceFactory; import org.alfresco.model.ContentModel; +import org.alfresco.repo.cmis.reference.ReferenceFactory; import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; diff --git a/source/java/org/alfresco/repo/web/scripts/content/ContentGet.java b/source/java/org/alfresco/repo/web/scripts/content/ContentGet.java index b40996050a..134a84703c 100644 --- a/source/java/org/alfresco/repo/web/scripts/content/ContentGet.java +++ b/source/java/org/alfresco/repo/web/scripts/content/ContentGet.java @@ -31,8 +31,8 @@ import java.util.Map; import javax.servlet.http.HttpServletResponse; import org.alfresco.cmis.CMISObjectReference; -import org.alfresco.cmis.reference.ReferenceFactory; import org.alfresco.model.ContentModel; +import org.alfresco.repo.cmis.reference.ReferenceFactory; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; diff --git a/source/java/org/alfresco/repo/web/scripts/content/ContentSet.java b/source/java/org/alfresco/repo/web/scripts/content/ContentSet.java index dc58713403..46ac7692e4 100644 --- a/source/java/org/alfresco/repo/web/scripts/content/ContentSet.java +++ b/source/java/org/alfresco/repo/web/scripts/content/ContentSet.java @@ -24,26 +24,22 @@ */ package org.alfresco.repo.web.scripts.content; -import java.io.BufferedInputStream; import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletResponse; +import org.alfresco.cmis.CMISDictionaryModel; import org.alfresco.cmis.CMISObjectReference; -import org.alfresco.cmis.reference.ObjectPathReference; -import org.alfresco.cmis.reference.ReferenceFactory; +import org.alfresco.cmis.CMISServiceException; +import org.alfresco.cmis.CMISServices; import org.alfresco.model.ContentModel; -import org.alfresco.repo.content.encoding.ContentCharsetFinder; +import org.alfresco.repo.cmis.reference.ObjectPathReference; +import org.alfresco.repo.cmis.reference.ReferenceFactory; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.PropertyDefinition; -import org.alfresco.service.cmr.repository.ContentReader; -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.namespace.NamespaceService; @@ -74,7 +70,7 @@ public class ContentSet extends AbstractWebScript private ReferenceFactory referenceFactory; private DictionaryService dictionaryService; private NamespaceService namespaceService; - private ContentService contentService; + private CMISServices cmisService; private MimetypeService mimetypeService; /** @@ -102,11 +98,11 @@ public class ContentSet extends AbstractWebScript } /** - * @param contentService + * @param cmisServices */ - public void setContentService(ContentService contentService) + public void setCmisService(CMISServices cmisService) { - this.contentService = contentService; + this.cmisService = cmisService; } /** @@ -168,22 +164,7 @@ public class ContentSet extends AbstractWebScript } // ensure content can be overwritten - // TODO: check parameter name String overwrite = req.getParameter("overwriteFlag"); - if (overwrite != null && overwrite.equalsIgnoreCase("false")) - { - ContentReader reader = contentService.getReader(nodeRef, propertyQName); - if (reader != null) - { - // error code as per CMIS specification - throw new WebScriptException(HttpServletResponse.SC_CONFLICT, "Content already exists."); - } - } - - // setup content writer - ContentReader reader = contentService.getReader(nodeRef, propertyQName); - boolean isUpdate = (reader != null && reader.exists()); - ContentWriter writer = contentService.getWriter(nodeRef, propertyQName, true); // establish mimetype String mimetype = req.getContentType(); @@ -194,24 +175,19 @@ public class ContentSet extends AbstractWebScript mimetype = mimetypeService.guessMimetype(((ObjectPathReference)reference).getPath()); } } - if (mimetype != null) - { - writer.setMimetype(mimetype); - } - - // get the input stream from the request data - InputStream is = req.getContent().getInputStream(); - is = is.markSupported() ? is : new BufferedInputStream(is); - - // establish content encoding - ContentCharsetFinder charsetFinder = mimetypeService.getContentCharsetFinder(); - Charset encoding = charsetFinder.getCharset(is, mimetype); - writer.setEncoding(encoding.name()); - // write the new data - writer.putContent(is); - - // set status - res.setStatus(isUpdate ? Status.STATUS_OK : Status.STATUS_CREATED); + try + { + boolean isUpdate = cmisService.setContentStream((String) cmisService.getProperty(nodeRef, + CMISDictionaryModel.PROP_OBJECT_ID), propertyQName, overwrite == null || overwrite.equals("true"), + req.getContent().getInputStream(), mimetype); + + // set status + res.setStatus(isUpdate ? Status.STATUS_OK : Status.STATUS_CREATED); + } + catch (CMISServiceException e) + { + throw new WebScriptException(e.getStatusCode(), e.getMessage(), e); + } } } \ No newline at end of file diff --git a/source/test/java/org/alfresco/repo/cmis/ws/DMNavigationServiceTest.java b/source/test/java/org/alfresco/repo/cmis/ws/DMNavigationServiceTest.java index c10f584aba..e156d5e253 100755 --- a/source/test/java/org/alfresco/repo/cmis/ws/DMNavigationServiceTest.java +++ b/source/test/java/org/alfresco/repo/cmis/ws/DMNavigationServiceTest.java @@ -82,7 +82,7 @@ public class DMNavigationServiceTest extends AbstractServiceTest helper.versioningServicePort.checkOut(repositoryId, documentIdHolder1, new Holder(), contentCopied); assertTrue(contentCopied.value); - List result = getCheckedoutDocs(null, 0, 0); + List result = getCheckedoutDocs(null, "cmis:lastModificationDate DESC", 0, 0); if (result == null || result.size() < 2) { @@ -90,23 +90,25 @@ public class DMNavigationServiceTest extends AbstractServiceTest helper.versioningServicePort.checkIn(repositoryId, documentIdHolder, false, null, null, null, null, null, null, new Holder()); fail("Not all checkout docs have been found"); } + + assertEquals("Wrong order", documentIdHolder1.value, getIdProperty(result.get(0).getProperties(), CMISDictionaryModel.PROP_OBJECT_ID)); validateResponse(result); - result = getCheckedoutDocs(null, 1, 0); + result = getCheckedoutDocs(null, "cmis:lastModificationDate DESC", 1, 0); assertNotNull(result); assertTrue(result.size() == 1); // check in helper.versioningServicePort.checkIn(repositoryId, documentIdHolder, false, null, null, null, null, null, null, new Holder()); - result = getCheckedoutDocs(companyHomeId, 0, 0); + result = getCheckedoutDocs(companyHomeId, "cmis:lastModificationDate ASC", 0, 0); assertFalse("Wrong results", isExistItemWithProperty(result, CMISDictionaryModel.PROP_NAME, documentName)); } public void testGetChildren() throws Exception { - List response = getChildren(companyHomeId, 100, true); + List response = getChildren(companyHomeId, null, 100, true); if (null != response) { @@ -134,10 +136,10 @@ public class DMNavigationServiceTest extends AbstractServiceTest @SuppressWarnings("unused") String documentId1 = helper.createDocument(documentName1, folderId, CMISDictionaryModel.DOCUMENT_TYPE_ID, EnumVersioningState.MAJOR); - response = getChildren(folderId, 2, false); + response = getChildren(folderId, CMISDictionaryModel.PROP_NAME + " ASC", 2, false); assertEquals(2, response.size()); - assertTrue(getStringProperty(response.get(0).getObject().getProperties(), CMISDictionaryModel.PROP_NAME).equals(folderName1)); - assertTrue(getStringProperty(response.get(1).getObject().getProperties(), CMISDictionaryModel.PROP_NAME).equals(documentName1)); + assertTrue(getStringProperty(response.get(0).getObject().getProperties(), CMISDictionaryModel.PROP_NAME).equals(documentName1)); + assertTrue(getStringProperty(response.get(1).getObject().getProperties(), CMISDictionaryModel.PROP_NAME).equals(folderName1)); // TODO: not implemented // assertNotNull(response.getObject().get(0).getAllowableActions()); @@ -290,9 +292,9 @@ public class DMNavigationServiceTest extends AbstractServiceTest return result; } - private List getChildren(String folderId, int maxItems, boolean includePathSegments) throws Exception + private List getChildren(String folderId, String orderBy, int maxItems, boolean includePathSegments) throws Exception { - CmisObjectInFolderListType result = ((NavigationServicePort) servicePort).getChildren(repositoryId, folderId, "*", "", false, null, "", includePathSegments, BigInteger + CmisObjectInFolderListType result = ((NavigationServicePort) servicePort).getChildren(repositoryId, folderId, "*", orderBy, false, null, "", includePathSegments, BigInteger .valueOf(maxItems), BigInteger.valueOf(0), null); assertNotNull("Get Children response is undefined", result); return result.getObjects(); @@ -318,9 +320,9 @@ public class DMNavigationServiceTest extends AbstractServiceTest return response; } - private List getCheckedoutDocs(String folderId, long maxItems, long skipCount) throws Exception + private List getCheckedoutDocs(String folderId, String orderBy, long maxItems, long skipCount) throws Exception { - CmisObjectListType result = ((NavigationServicePort) servicePort).getCheckedOutDocs(repositoryId, folderId, "*", null, false, null, "", BigInteger.valueOf(maxItems), + CmisObjectListType result = ((NavigationServicePort) servicePort).getCheckedOutDocs(repositoryId, folderId, "*", orderBy, false, null, "", BigInteger.valueOf(maxItems), BigInteger.valueOf(skipCount), null); assertNotNull(result); return result.getObjects(); diff --git a/source/test/java/org/alfresco/repo/cmis/ws/DMVersioningServiceTest.java b/source/test/java/org/alfresco/repo/cmis/ws/DMVersioningServiceTest.java index 7e769d8df2..b1bd7d5de3 100755 --- a/source/test/java/org/alfresco/repo/cmis/ws/DMVersioningServiceTest.java +++ b/source/test/java/org/alfresco/repo/cmis/ws/DMVersioningServiceTest.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 @@ -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" */ @@ -88,7 +88,7 @@ public class DMVersioningServiceTest extends AbstractServiceTest new Holder()); documentId = documentIdHolder.value; - assertEquals(checkinComment, getStringProperty(helper.getObjectProperties(documentIdHolder.value).getProperties(), CMISDictionaryModel.PROP_CHECKIN_COMMENT)); + assertEquals(checkinComment, getStringProperty(((VersioningServicePort) servicePort).getPropertiesOfLatestVersion(repositoryId, documentId, true, null, null), CMISDictionaryModel.PROP_CHECKIN_COMMENT)); } public void testCheckOutCheckInDefault() throws Exception @@ -139,7 +139,7 @@ public class DMVersioningServiceTest extends AbstractServiceTest } catch (CmisException e) { - assertTrue(e.getFaultInfo().getType().equals(EnumServiceException.UPDATE_CONFLICT)); + assertTrue(e.getFaultInfo().getType().equals(EnumServiceException.VERSIONING)); } } @@ -154,20 +154,20 @@ public class DMVersioningServiceTest extends AbstractServiceTest } catch (CmisException e) { - assertTrue(e.getFaultInfo().getType().equals(EnumServiceException.UPDATE_CONFLICT)); + assertTrue(e.getFaultInfo().getType().equals(EnumServiceException.VERSIONING)); } } public void testGetPropertiesOfLatestVersion() throws Exception { - CmisPropertiesType objectType = ((VersioningServicePort) servicePort).getPropertiesOfLatestVersion(repositoryId, documentId, true, "*", null); + CmisPropertiesType objectType = ((VersioningServicePort) servicePort).getPropertiesOfLatestVersion(repositoryId, documentId, false, "*", null); assertNotNull(objectType); assertTrue(getBooleanProperty(objectType, CMISDictionaryModel.PROP_IS_LATEST_VERSION)); } public void testGetPropertiesOfLatestVersionDefault() throws Exception { - CmisPropertiesType cmisObjectType = ((VersioningServicePort) servicePort).getPropertiesOfLatestVersion(repositoryId, documentId, true, "", null); + CmisPropertiesType cmisObjectType = ((VersioningServicePort) servicePort).getPropertiesOfLatestVersion(repositoryId, documentId, false, "", null); assertNotNull(cmisObjectType); assertTrue(getBooleanProperty(cmisObjectType, CMISDictionaryModel.PROP_IS_LATEST_VERSION)); } @@ -184,10 +184,10 @@ public class DMVersioningServiceTest extends AbstractServiceTest List response = ((VersioningServicePort) servicePort).getAllVersions(repositoryId, documentId, "", null, null); assertNotNull(response); - assertFalse(response.isEmpty()); - CmisObjectType firstElement = response.iterator().next(); - assertNotNull(firstElement); - assertEquals(checkinComment, getStringProperty(firstElement.getProperties(), CMISDictionaryModel.PROP_CHECKIN_COMMENT)); + assertTrue("Expected three versions", response.size() == 3); + CmisObjectType lastVersion = response.get(1); + assertNotNull(lastVersion); + assertEquals(checkinComment, getStringProperty(lastVersion.getProperties(), CMISDictionaryModel.PROP_CHECKIN_COMMENT)); } public void testGetAllVersions() throws Exception @@ -202,10 +202,10 @@ public class DMVersioningServiceTest extends AbstractServiceTest List response = ((VersioningServicePort) servicePort).getAllVersions(repositoryId, documentId, "*", false, null); assertNotNull(response); - assertFalse(response.isEmpty()); - CmisObjectType firstElement = response.iterator().next(); - assertNotNull(firstElement); - assertEquals(checkinComment, getStringProperty(firstElement.getProperties(), CMISDictionaryModel.PROP_CHECKIN_COMMENT)); + assertTrue("Expected three versions", response.size() == 3); + CmisObjectType lastVersion = response.get(1); + assertNotNull(lastVersion); + assertEquals(checkinComment, getStringProperty(lastVersion.getProperties(), CMISDictionaryModel.PROP_CHECKIN_COMMENT)); } public void testGetAllVersionsForNoVersionHistory() throws Exception diff --git a/source/wsdl/CMIS-Core.xsd b/source/wsdl/CMIS-Core.xsd index fa935e80b0..5cf6e1e460 100755 --- a/source/wsdl/CMIS-Core.xsd +++ b/source/wsdl/CMIS-Core.xsd @@ -1,7 +1,7 @@ @@ -556,8 +556,6 @@ minOccurs="0" maxOccurs="1" /> -