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

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

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

View File

@@ -280,6 +280,7 @@
<value>dmDiscoveryService</value>
<value>dmRelationshipService</value>
<value>dmPolicyService</value>
<value>dmAclService</value>
</list>
</property>
<property name="interceptorNames">
@@ -305,25 +306,12 @@
<bean id="exceptionPointcutAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice">
<bean class="org.alfresco.repo.cmis.ws.DMServicePortThrowsAdvice">
<property name="cmisObjectsUtils" ref="cmisObjectsUtils" />
</bean>
<bean class="org.alfresco.repo.cmis.ws.DMServicePortThrowsAdvice" />
</property>
</bean>
<bean id="cmisObjectsUtils" class="org.alfresco.repo.cmis.ws.utils.CmisObjectsUtils">
<property name="lockService" ref="LockService" />
<property name="checkOutCheckInService" ref="CheckoutCheckinService" />
<property name="authorityService" ref="AuthorityService" />
<property name="versionService" ref="VersionService" />
<property name="cmisDictionaryService" ref="CMISDictionaryService" />
<property name="fileFolderService" ref="FileFolderService" />
<property name="nodeService" ref="NodeService" />
</bean>
<bean id="propertiesUtils" class="org.alfresco.repo.cmis.ws.utils.PropertyUtil">
<property name="cmisDictionaryService" ref="CMISDictionaryService" />
<property name="cmisObjectsUtils" ref="cmisObjectsUtils" />
<property name="cmisService" ref="CMISService" />
<property name="nodeService" ref="NodeService" />
<property name="dictionaryService" ref="DictionaryService" />
@@ -341,15 +329,11 @@
<bean id="dmMultiFilingService" parent="dmAbstractService" class="org.alfresco.repo.cmis.ws.DMMultiFilingServicePort" />
<bean id="dmVersioningService" parent="dmAbstractService" class="org.alfresco.repo.cmis.ws.DMVersioningServicePort">
<property name="lockService" ref="LockService" />
</bean>
<bean id="dmVersioningService" parent="dmAbstractService" class="org.alfresco.repo.cmis.ws.DMVersioningServicePort" />
<bean id="dmDiscoveryService" parent="dmAbstractService" class="org.alfresco.repo.cmis.ws.DMDiscoveryServicePort" />
<bean id="dmRelationshipService" parent="dmAbstractService" class="org.alfresco.repo.cmis.ws.DMRelationshipServicePort" >
<property name="dictionaryService" ref="DictionaryService" />
</bean>
<bean id="dmRelationshipService" parent="dmAbstractService" class="org.alfresco.repo.cmis.ws.DMRelationshipServicePort" />
<bean id="dmPolicyService" parent="dmAbstractService" class="org.alfresco.repo.cmis.ws.DMPolicyServicePort" />
@@ -358,20 +342,16 @@
<bean id="dmAbstractService" abstract="true" class="org.alfresco.repo.cmis.ws.DMAbstractServicePort">
<property name="cmisService" ref="CMISService" />
<property name="cmisQueryService" ref="CMISQueryService" />
<property name="cmisDictionaryService" ref="CMISDictionaryService" />
<property name="cmisRenditionService" ref="CMISRenditionService" />
<property name="cmisChangeLogService" ref="CMISChangeLogService" />
<property name="cmisAclService" ref="CMISAccessControlService" />
<property name="descriptorService" ref="DescriptorService" />
<property name="nodeService" ref="NodeService" />
<property name="versionService" ref="VersionService" />
<property name="fileFolderService" ref="FileFolderService" />
<property name="checkOutCheckInService" ref="CheckoutCheckinService" />
<property name="searchService" ref="SearchService" />
<property name="permissionService" ref="PermissionService" />
<property name="cmisObjectsUtils" ref="cmisObjectsUtils" />
<property name="propertiesUtil" ref="propertiesUtils" />
</bean>

View File

@@ -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

View File

@@ -36,14 +36,14 @@ If no “maxItems” value is provided, then the Repository will determine an ap
</description>
<!-- by object id -->
<url>/cmis/i/{id}/children?types={types}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}&amp;renditionFilter={renditionFilter?}</url>
<url>/cmis/s/{store}/i/{id}/children?types={types}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}&amp;renditionFilter={renditionFilter?}</url>
<url>/cmis/i/{id}/children?types={types}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}&amp;renditionFilter={renditionFilter?}&amp;orderBy={orderBy?}</url>
<url>/cmis/s/{store}/i/{id}/children?types={types}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}&amp;renditionFilter={renditionFilter?}&amp;orderBy={orderBy?}</url>
<!-- by path -->
<url>/cmis/p{path}/children?types={types}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}&amp;renditionFilter={renditionFilter?}</url>
<url>/cmis/s/{store}/p{path}/children?types={types}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}&amp;renditionFilter={renditionFilter?}</url>
<url>/cmis/p{path}/children?types={types}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}&amp;renditionFilter={renditionFilter?}&amp;orderBy={orderBy?}</url>
<url>/cmis/s/{store}/p{path}/children?types={types}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}&amp;renditionFilter={renditionFilter?}&amp;orderBy={orderBy?}</url>
<!-- alfresco style -->
<url>/api/node/{store_type}/{store_id}/{id}/children?types={types}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}&amp;renditionFilter={renditionFilter?}</url>
<url>/api/path/{store_type}/{store_id}/{path}/children?types={types}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}&amp;renditionFilter={renditionFilter?}</url>
<url>/api/node/{store_type}/{store_id}/{id}/children?types={types}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}&amp;renditionFilter={renditionFilter?}&amp;orderBy={orderBy?}</url>
<url>/api/path/{store_type}/{store_id}/{path}/children?types={types}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}&amp;renditionFilter={renditionFilter?}&amp;orderBy={orderBy?}</url>
<authentication>guest</authentication>
<transaction allow="readonly"/>

View File

@@ -34,13 +34,16 @@ 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;
}

View File

@@ -21,24 +21,33 @@ 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
else if (sourceFolderId == null || sourceFolderId.length == 0)
{
// locate node and its source folder
// Add node
var object = getObjectFromObjectId(objectId);
if (object.node == null)
{
@@ -46,44 +55,25 @@ script:
}
node = object.node;
cmis.addObjectToFolder(node, model.parent);
}
else
{
// 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)
// locate node
var object = getObjectFromObjectId(objectId);
if (object.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;
node = object.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;

View File

@@ -42,14 +42,14 @@ Root folder can not be created using this service.<br>
]]>
</description>
<url>/cmis/i/{id}/children?sourceFolderId={sourceFolderId}</url>
<url>/cmis/s/{store}/i/{id}/children?sourceFolderId={sourceFolderId}</url>
<url>/cmis/i/{id}/children?sourceFolderId={sourceFolderId}&amp;versioningState={versioningState?}</url>
<url>/cmis/s/{store}/i/{id}/children?sourceFolderId={sourceFolderId}&amp;versioningState={versioningState?}</url>
<!-- by path -->
<url>/cmis/p{path}/children?sourceFolderId={sourceFolderId}</url>
<url>/cmis/s/{store}/p{path}/children?sourceFolderId={sourceFolderId}</url>
<url>/cmis/p{path}/children?sourceFolderId={sourceFolderId}&amp;versioningState={versioningState?}</url>
<url>/cmis/s/{store}/p{path}/children?sourceFolderId={sourceFolderId}&amp;versioningState={versioningState?}</url>
<!-- alfresco style -->
<url>/api/node/{store_type}/{store_id}/{id}/children?sourceFolderId={sourceFolderId}</url>
<url>/api/path/{store_type}/{store_id}/{path}/children?sourceFolderId={sourceFolderId}</url>
<url>/api/node/{store_type}/{store_id}/{id}/children?sourceFolderId={sourceFolderId}&amp;versioningState={versioningState?}</url>
<url>/api/path/{store_type}/{store_id}/{path}/children?sourceFolderId={sourceFolderId}&amp;versioningState={versioningState?}</url>
<authentication>user</authentication>
<format default="atomentry"/>

View File

@@ -8,38 +8,9 @@ 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;
}
// 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;
}
cmis.deleteContentStream(node);
status.code = 204; // Success, but no response content
status.redirect = true;

View File

@@ -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;

View File

@@ -25,7 +25,6 @@ Does not return the content-stream of a document<br>
PropertyCollection includes changeToken (if applicable to repository)<br>
]]>
</description>
<!-- TODO: spec issue: returnVersion or returnCurrent? -->
<!-- by object id -->
<url>/cmis/i/{id}?filter={filter?}&amp;returnVersion={returnVersion?}&amp;includeAllowableActions={includeAllowableActions?}&amp;includeACL={includeACL?}&amp;renditionFilter={renditionFilter?}</url>

View File

@@ -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];

View File

@@ -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]
</cmis:properties>
[/#macro]
@@ -69,7 +69,7 @@
[#-- ATOM Entry for Version --]
[#-- --]
[#macro version node version propfilter="*" ns=""]
[#macro version node propfilter="*" ns=""]
[@entry ns]
<author><name>${node.properties.creator!""}</name></author>
[@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]
</cmis:properties>
@@ -289,7 +298,7 @@
<updated>${xmldate(event.changeTime)}</updated>
<cmisra:object>
<cmis:properties>
[@propvalue "cmis:objectId" node.nodeRef?string cmisconstants.DATATYPE_ID/]
[@propvalue event.objectId cmisconstants.DATATYPE_ID "cmis:objectId"/]
</cmis:properties>
<cmis:changeEventInfo>
<cmis:changeType>${event.changeType.label}</cmis:changeType>
@@ -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]
<cmis:propertyString propertyDefinitionId="${name}">[@values value;v]<cmis:value>[@stringvalue v/]</cmis:value>[/@values]</cmis:propertyString>
<cmis:propertyString [@propargs name displayname queryname localname/]>[@values value;v]<cmis:value>[@stringvalue v/]</cmis:value>[/@values]</cmis:propertyString>
[#elseif type == cmisconstants.DATATYPE_INTEGER]
<cmis:propertyInteger propertyDefinitionId="${name}">[@values value;v]<cmis:value>[@integervalue v/]</cmis:value>[/@values]</cmis:propertyInteger>
<cmis:propertyInteger [@propargs name displayname queryname localname/]>[@values value;v]<cmis:value>[@integervalue v/]</cmis:value>[/@values]</cmis:propertyInteger>
[#elseif type == cmisconstants.DATATYPE_DECIMAL]
<cmis:propertyDecimal propertyDefinitionId="${name}">[@values value;v]<cmis:value>[@decimalvalue v/]</cmis:value>[/@values]</cmis:propertyDecimal>
<cmis:propertyDecimal [@propargs name displayname queryname localname/]>[@values value;v]<cmis:value>[@decimalvalue v/]</cmis:value>[/@values]</cmis:propertyDecimal>
[#elseif type == cmisconstants.DATATYPE_BOOLEAN]
<cmis:propertyBoolean propertyDefinitionId="${name}">[@values value;v]<cmis:value>[@booleanvalue v/]</cmis:value>[/@values]</cmis:propertyBoolean>
<cmis:propertyBoolean [@propargs name displayname queryname localname/]>[@values value;v]<cmis:value>[@booleanvalue v/]</cmis:value>[/@values]</cmis:propertyBoolean>
[#elseif type == cmisconstants.DATATYPE_DATETIME]
<cmis:propertyDateTime propertyDefinitionId="${name}">[@values value;v]<cmis:value>[@datetimevalue v/]</cmis:value>[/@values]</cmis:propertyDateTime>
<cmis:propertyDateTime [@propargs name displayname queryname localname/]>[@values value;v]<cmis:value>[@datetimevalue v/]</cmis:value>[/@values]</cmis:propertyDateTime>
[#elseif type == cmisconstants.DATATYPE_URI]
[#-- TODO: check validity of abs url prefix --]
<cmis:propertyUri propertyDefinitionId="${name}">[@values value;v]<cmis:value>[@urivalue absurl(url.serviceContext) + v/]</cmis:value>[/@values]</cmis:propertyUri>
<cmis:propertyUri [@propargs name displayname queryname localname/]>[@values value;v]<cmis:value>[@urivalue absurl(url.serviceContext) + v/]</cmis:value>[/@values]</cmis:propertyUri>
[#elseif type == cmisconstants.DATATYPE_ID]
<cmis:propertyId propertyDefinitionId="${name}">[@values value;v]<cmis:value>[@idvalue v/]</cmis:value>[/@values]</cmis:propertyId>
<cmis:propertyId [@propargs name displayname queryname localname/]>[@values value;v]<cmis:value>[@idvalue v/]</cmis:value>[/@values]</cmis:propertyId>
[#-- 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]
<cmis:propertyString propertyDefinitionId="${name}"/>
<cmis:propertyString [@propargs name displayname queryname localname/]/>
[#elseif type == cmisconstants.DATATYPE_INTEGER]
<cmis:propertyInteger propertyDefinitionId="${name}"/>
<cmis:propertyInteger [@propargs name displayname queryname localname/]/>
[#elseif type == cmisconstants.DATATYPE_DECIMAL]
<cmis:propertyDecimal propertyDefinitionId="${name}"/>
<cmis:propertyDecimal [@propargs name displayname queryname localname/]/>
[#elseif type == cmisconstants.DATATYPE_BOOLEAN]
<cmis:propertyBoolean propertyDefinitionId="${name}"/>
<cmis:propertyBoolean [@propargs name displayname queryname localname/]/>
[#elseif type == cmisconstants.DATATYPE_DATETIME]
<cmis:propertyDateTime propertyDefinitionId="${name}"/>
<cmis:propertyDateTime [@propargs name displayname queryname localname/]/>
[#elseif type == cmisconstants.DATATYPE_URI]
<cmis:propertyUri propertyDefinitionId="${name}"/>
<cmis:propertyUri [@propargs name displayname queryname localname/]/>
[#elseif type == cmisconstants.DATATYPE_ID]
<cmis:propertyId propertyDefinitionId="${name}"/>
<cmis:propertyId [@propargs name displayname queryname localname/]/>
[#-- 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 --]

View File

@@ -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]

View File

@@ -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)
{

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -3,7 +3,7 @@
<description>
</description>
<url>/cmis/rel/s/{store}/i/{id}/type/{rel_type}/target/s/{target_store}/i/{target_id}</url>
<url>/cmis/rel/{assoc_id}</url>
<authentication>user</authentication>
<format default="atomentry"/>

View File

@@ -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;

View File

@@ -3,7 +3,7 @@
<description>
</description>
<url>/cmis/rel/s/{store}/i/{id}/type/{rel_type}/target/s/{target_store}/i/{target_id}?filter={filter?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/cmis/rel/{assoc_id}?filter={filter?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<authentication>guest</authentication>
<transaction allow="readonly"/>

View File

@@ -4,14 +4,14 @@
</description>
<!-- by object id -->
<url>/cmis/i/{id}/tree?continueOnFailure={continueOnFailure?}&amp;unfileMultiFiledDocuments={unfileMultiFiledDocuments}</url>
<url>/cmis/s/{store}/i/{id}/tree?continueOnFailure={continueOnFailure?}&amp;unfileMultiFiledDocuments={unfileMultiFiledDocuments}</url>
<url>/cmis/i/{id}/tree?continueOnFailure={continueOnFailure?}&amp;unfileObjects={unfileObjects}</url>
<url>/cmis/s/{store}/i/{id}/tree?continueOnFailure={continueOnFailure?}&amp;unfileObjects={unfileObjects}</url>
<!-- by path -->
<url>/cmis/p{path}/tree?continueOnFailure={continueOnFailure?}&amp;unfileMultiFiledDocuments={unfileMultiFiledDocuments}</url>
<url>/cmis/s/{store}/p{path}/tree?continueOnFailure={continueOnFailure?}&amp;unfileMultiFiledDocuments={unfileMultiFiledDocuments}</url>
<url>/cmis/p{path}/tree?continueOnFailure={continueOnFailure?}&amp;unfileObjects={unfileObjects}</url>
<url>/cmis/s/{store}/p{path}/tree?continueOnFailure={continueOnFailure?}&amp;unfileObjects={unfileObjects}</url>
<!-- alfresco style -->
<url>/api/node/{store_type}/{store_id}/{id}/tree?continueOnFailure={continueOnFailure?}&amp;unfileMultiFiledDocuments={unfileMultiFiledDocuments}</url>
<url>/api/path/{store_type}/{store_id}/{path}/tree?continueOnFailure={continueOnFailure?}&amp;unfileMultiFiledDocuments={unfileMultiFiledDocuments}</url>
<url>/api/node/{store_type}/{store_id}/{id}/tree?continueOnFailure={continueOnFailure?}&amp;unfileObjects={unfileObjects}</url>
<url>/api/path/{store_type}/{store_id}/{path}/tree?continueOnFailure={continueOnFailure?}&amp;unfileObjects={unfileObjects}</url>
<authentication>user</authentication>
<format default="atomfeed"/>

View File

@@ -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";
unfileObjects = "delete";
}
// We only support delete and deletesinglefiled
if (unfileObjects == "unfile")
{
status.code = 405;
status.message = "Unfiling is not supported";
status.redirect = true;
break script;
}
// TODO: Checked-out documents - are they automatically cancelled?
var continueOnFailure = (args[cmis.ARG_CONTINUE_ON_FAILURE] == "true");
if (!node.remove())
{
status.code = 500;
status.message = "Failed to delete object " + object.ref;
status.redirect = true;
break script;
}
status.code = 204; // Success, but no response content
status.redirect = true;
// Intentionally pass allVersions=false, even though this isn't the default!
cmis.deleteTree(node, status, continueOnFailure, unfileObjects != "delete", false);
}

View File

@@ -17,7 +17,7 @@
[/@feedLib.generic]
[#list nodes as version]
[@entryLib.version version versions[version_index]/]
[@entryLib.version version/]
[/#list]
</feed>

View File

@@ -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);
}

View File

@@ -269,6 +269,10 @@
</bean>
<!-- CMIS Javsascript API -->
<bean id="CMISReferenceFactory" class="org.alfresco.repo.cmis.reference.ReferenceFactory">
<property name="CMISService" ref="CMISService" />
</bean>
<bean id="webscripts.js.cmis" parent="baseJavaScriptExtension" class="org.alfresco.repo.cmis.rest.CMISScript">
<property name="extensionName"><value>cmis</value></property>
<property name="serviceRegistry" ref="ServiceRegistry" />
@@ -299,7 +303,7 @@
<property name="referenceFactory" ref="CMISReferenceFactory" />
<property name="dictionaryService" ref="DictionaryService" />
<property name="namespaceService" ref="NamespaceService" />
<property name="contentService" ref="ContentService" />
<property name="cmisService" ref="CMISService" />
<property name="mimetypeService" ref="MimetypeService" />
</bean>

View File

@@ -49,7 +49,6 @@ import org.w3c.dom.Element;
* &lt;element name="canCreateDocument" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
* &lt;element name="canCreateFolder" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
* &lt;element name="canCreateRelationship" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
* &lt;element name="canCreatePolicy" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
* &lt;element name="canDeleteTree" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
* &lt;element name="canGetRenditions" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
* &lt;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 {
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link Object }
* {@link Element }
* {@link Object }
*
*
*/

View File

@@ -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)

View File

@@ -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");
}

View File

@@ -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 + "]";
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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 + "]";
}
}

View File

@@ -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();
}
}

View File

@@ -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 + "]";
}
}

View File

@@ -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 + "]";
}
}

View File

@@ -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 + "]";
}
}

View File

@@ -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<String, String> args, Map<String, String> 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<String, String> args, Map<String, String> 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<String, String> args, Map<String, String> templateArgs)
{
String assocId = templateArgs.get("assoc_id");
if (assocId != null)
{
return new AssociationIdRelationshipReference(cmisService, assocId);
}
return null;
}
}

View File

@@ -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() + "]";
}
}

View File

@@ -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;
}
}

View File

@@ -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++)
{

View File

@@ -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,8 +92,15 @@ public final class CMISPropertyValueMethod implements TemplateMethodModelEx
if (wrapped != null && wrapped instanceof TemplateNode)
{
// retrieve property value from node
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)
{
// retrieve property value from node

View File

@@ -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<String, Object> renditions = cmisService.getRenditions(nodeRef, renditionFilter);
Map<String, Object> renditions;
try
{
renditions = cmisService.getRenditions(nodeRef, renditionFilter);
}
catch (CMISFilterNotValidException e)
{
throw new WebScriptException(e.getStatusCode(), e.getMessage(), e);
}
return templateValueConverter.convertValue(renditions, imageResolver);
}

View File

@@ -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
* @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<CMISTypeDefinition> children = (typeDef == null) ? cmisDictionaryService.getBaseTypes() : typeDef.getSubTypes(false);
Collection<CMISTypeDefinition> 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
* @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
* 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)
{
@@ -554,7 +576,7 @@ 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,11 +616,12 @@ public class CMISScript extends BaseScopableProcessorExtension
}
/**
* Issue query
* Issue query.
*
* @param statement query statement
* @param statement
* query statement
* @param page
*
* 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<CMISPermissionDefinition> 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<? extends CMISPermissionMapping> 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,8 +729,16 @@ public class CMISScript extends BaseScopableProcessorExtension
{
acesToApply.add(new CMISAccessControlEntryImpl(principalList.get(i), permissionList.get(i)));
}
try
{
cmisAccessControlService.applyAcl(node.getNodeRef(), acesToApply);
}
catch (CMISConstraintException e)
{
// Force the appropriate status code on error
throw new WebScriptException(e.getStatusCode(), e.getMessage(), e);
}
}
/**
* Gets the change log capability.
@@ -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<NodeRef> 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);
}
}
}

View File

@@ -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;
@@ -234,6 +235,18 @@ public class CMISTemplateResultSet implements Serializable
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
*

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -18,57 +18,58 @@
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.cmis.ws;
import java.io.Serializable;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.bind.JAXBElement;
import javax.xml.ws.Holder;
import org.alfresco.cmis.CMISAccessControlEntry;
import org.alfresco.cmis.CMISAccessControlFormatEnum;
import org.alfresco.cmis.CMISAccessControlReport;
import org.alfresco.cmis.CMISAccessControlService;
import org.alfresco.cmis.CMISAclPropagationEnum;
import org.alfresco.cmis.CMISActionEvaluator;
import org.alfresco.cmis.CMISAllowedActionEnum;
import org.alfresco.cmis.CMISChangeLogService;
import org.alfresco.cmis.CMISDictionaryModel;
import org.alfresco.cmis.CMISDictionaryService;
import org.alfresco.cmis.CMISConstraintException;
import org.alfresco.cmis.CMISFilterNotValidException;
import org.alfresco.cmis.CMISInvalidArgumentException;
import org.alfresco.cmis.CMISQueryService;
import org.alfresco.cmis.CMISRendition;
import org.alfresco.cmis.CMISRenditionService;
import org.alfresco.cmis.CMISServices;
import org.alfresco.cmis.CMISTypeDefinition;
import org.alfresco.model.ContentModel;
import org.alfresco.cmis.acl.CMISAccessControlEntryImpl;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.cmis.PropertyFilter;
import org.alfresco.repo.cmis.ws.utils.AlfrescoObjectType;
import org.alfresco.repo.cmis.ws.utils.CmisObjectsUtils;
import org.alfresco.repo.cmis.ws.utils.ExceptionUtil;
import org.alfresco.repo.cmis.ws.utils.PropertyUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.repo.web.util.paging.Cursor;
import org.alfresco.repo.web.util.paging.Page;
import org.alfresco.repo.web.util.paging.Paging;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.service.descriptor.DescriptorService;
/**
@@ -81,24 +82,41 @@ import org.alfresco.service.descriptor.DescriptorService;
*/
public class DMAbstractServicePort
{
protected static final String INITIAL_VERSION_DESCRIPTION = "Initial version";
private static final String CMIS_USER = "cmis:user";
private static final String INVALID_REPOSITORY_ID_MESSAGE = "Invalid repository id";
private static final String INVALID_FOLDER_OBJECT_ID_MESSAGE = "OID for non-existent object or not folder object";
private static final Map<EnumACLPropagation, CMISAclPropagationEnum> ACL_PROPAGATION_ENUM_MAPPGIN;
private static final Map<CMISAllowedActionEnum, PropertyDescriptor> ALLOWED_ACTION_ENUM_MAPPING;
static
{
ACL_PROPAGATION_ENUM_MAPPGIN = new HashMap<EnumACLPropagation, CMISAclPropagationEnum>();
ACL_PROPAGATION_ENUM_MAPPGIN.put(EnumACLPropagation.OBJECTONLY, CMISAclPropagationEnum.OBJECT_ONLY);
ACL_PROPAGATION_ENUM_MAPPGIN.put(EnumACLPropagation.PROPAGATE, CMISAclPropagationEnum.PROPAGATE);
ACL_PROPAGATION_ENUM_MAPPGIN.put(EnumACLPropagation.REPOSITORYDETERMINED, CMISAclPropagationEnum.REPOSITORY_DETERMINED);
try
{
ALLOWED_ACTION_ENUM_MAPPING = new HashMap<CMISAllowedActionEnum, PropertyDescriptor>(97);
for (PropertyDescriptor propertyDescriptor : Introspector.getBeanInfo(CmisAllowableActionsType.class, Object.class).getPropertyDescriptors())
{
String label = propertyDescriptor.getName();
CMISAllowedActionEnum allowedActionEnum = CMISAllowedActionEnum.FACTORY.fromLabel(label);
if (allowedActionEnum != null)
{
ALLOWED_ACTION_ENUM_MAPPING.put(allowedActionEnum, propertyDescriptor);
}
}
}
catch (IntrospectionException e)
{
throw new ExceptionInInitializerError(e);
}
}
private Paging paging = new Paging();
protected ObjectFactory cmisObjectFactory = new ObjectFactory();
protected CMISDictionaryService cmisDictionaryService;
protected CMISQueryService cmisQueryService;
protected CMISServices cmisService;
protected CMISChangeLogService cmisChangeLogService;
@@ -107,11 +125,8 @@ public class DMAbstractServicePort
protected DescriptorService descriptorService;
protected NodeService nodeService;
protected VersionService versionService;
protected FileFolderService fileFolderService;
protected CheckOutCheckInService checkOutCheckInService;
protected SearchService searchService;
protected CmisObjectsUtils cmisObjectsUtils;
protected PropertyUtil propertiesUtil;
protected PermissionService permissionService;
@@ -120,11 +135,6 @@ public class DMAbstractServicePort
this.cmisService = cmisService;
}
public void setCmisDictionaryService(CMISDictionaryService cmisDictionaryService)
{
this.cmisDictionaryService = cmisDictionaryService;
}
public void setCmisQueryService(CMISQueryService cmisQueryService)
{
this.cmisQueryService = cmisQueryService;
@@ -155,27 +165,11 @@ public class DMAbstractServicePort
this.nodeService = nodeService;
}
public void setVersionService(VersionService versionService)
{
this.versionService = versionService;
}
public void setFileFolderService(FileFolderService fileFolderService)
{
this.fileFolderService = fileFolderService;
}
public void setCheckOutCheckInService(CheckOutCheckInService checkOutCheckInService)
{
this.checkOutCheckInService = checkOutCheckInService;
}
public void setCmisObjectsUtils(CmisObjectsUtils cmisObjectsUtils)
{
this.cmisObjectsUtils = cmisObjectsUtils;
}
public void setPropertiesUtil(PropertyUtil propertiesUtil)
{
this.propertiesUtil = propertiesUtil;
@@ -193,7 +187,7 @@ public class DMAbstractServicePort
protected PropertyFilter createPropertyFilter(String filter) throws CmisException
{
return (filter == null) ? (new PropertyFilter()) : (new PropertyFilter(filter, cmisObjectsUtils));
return (filter == null) ? (new PropertyFilter()) : (new PropertyFilter(filter));
}
protected PropertyFilter createPropertyFilter(JAXBElement<String> element) throws CmisException
@@ -239,7 +233,7 @@ public class DMAbstractServicePort
protected CmisObjectType createCmisObject(Object identifier, PropertyFilter filter, boolean includeAllowableActions, String renditionFilter) throws CmisException
{
CmisObjectType result = new CmisObjectType();
result.setProperties(propertiesUtil.getPropertiesType(identifier.toString(), filter));
result.setProperties(propertiesUtil.getProperties(identifier, filter));
if (includeAllowableActions)
{
result.setAllowableActions(determineObjectAllowableActions(identifier));
@@ -255,20 +249,6 @@ public class DMAbstractServicePort
return result;
}
/**
* Asserts "Folder with folderNodeRef exists"
*
* @param folderNodeRef node reference
* @throws FolderNotValidException folderNodeRef doesn't exist or folderNodeRef isn't for folder object
*/
protected void assertExistFolder(NodeRef folderNodeRef) throws CmisException
{
if (!this.cmisObjectsUtils.isFolder(folderNodeRef))
{
throw new CmisException(INVALID_FOLDER_OBJECT_ID_MESSAGE, cmisObjectsUtils.createCmisException(INVALID_FOLDER_OBJECT_ID_MESSAGE, EnumServiceException.INVALID_ARGUMENT));
}
}
/**
* Checks specified in CMIS request parameters repository Id.
*
@@ -279,54 +259,29 @@ public class DMAbstractServicePort
{
if (!this.descriptorService.getCurrentRepositoryDescriptor().getId().equals(repositoryId))
{
throw cmisObjectsUtils.createCmisException(INVALID_REPOSITORY_ID_MESSAGE, EnumServiceException.INVALID_ARGUMENT);
throw ExceptionUtil.createCmisException(INVALID_REPOSITORY_ID_MESSAGE, EnumServiceException.INVALID_ARGUMENT);
}
}
protected Map<String, Serializable> createVersionProperties(String versionDescription, VersionType versionType)
{
Map<String, Serializable> result = new HashMap<String, Serializable>();
result.put(Version.PROP_DESCRIPTION, versionDescription);
result.put(VersionModel.PROP_VERSION_TYPE, versionType);
return result;
}
protected NodeRef checkoutNode(NodeRef documentNodeReference)
{
if (!this.nodeService.hasAspect(documentNodeReference, ContentModel.ASPECT_VERSIONABLE))
{
this.versionService.createVersion(documentNodeReference, createVersionProperties(INITIAL_VERSION_DESCRIPTION, VersionType.MAJOR));
}
return checkOutCheckInService.checkout(documentNodeReference);
}
protected CMISTypeDefinition getCmisTypeDefinition(String typeId) throws CmisException
{
try
{
return cmisDictionaryService.findType(typeId);
}
catch (Exception e)
{
throw new CmisException(("Invalid typeId " + typeId), cmisObjectsUtils.createCmisException(("Invalid typeId " + typeId), EnumServiceException.INVALID_ARGUMENT));
}
}
protected List<CmisRenditionType> getRenditions(Object objectId, String renditionFilter) throws CmisException
protected List<CmisRenditionType> getRenditions(Object object, String renditionFilter) throws CmisException
{
List<CmisRenditionType> result = null;
if (NodeRef.isNodeRef(objectId.toString()))
if (object instanceof Version)
{
NodeRef document = new NodeRef(objectId.toString());
object = ((Version) object).getFrozenStateNodeRef();
}
if (object instanceof NodeRef)
{
NodeRef document = (NodeRef) object;
List<CMISRendition> renditions = null;
try
{
renditions = cmisRenditionService.getRenditions(document, renditionFilter);
}
catch (Exception e)
catch (CMISFilterNotValidException e)
{
throw cmisObjectsUtils.createCmisException("Invalid rendition filter", EnumServiceException.FILTER_NOT_VALID);
throw ExceptionUtil.createCmisException(e);
}
if (renditions != null && !renditions.isEmpty())
{
@@ -372,127 +327,41 @@ 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)
try
{
throw cmisObjectsUtils.createCmisException("Type Definition for specified Object was not found", EnumServiceException.STORAGE);
}
if (!objectType.isControllableACL())
{
throw cmisObjectsUtils.createCmisException("Object that was specified is not ACL Controllable", EnumServiceException.CONSTRAINT);
}
CMISAclPropagationEnum propagation = (null == aclPropagation) ? (CMISAclPropagationEnum.PROPAGATE) : (ACL_PROPAGATION_ENUM_MAPPGIN.get(aclPropagation));
List<CMISAccessControlEntry> acesToAdd = (null == addACEs) ? (null) : (convertToAlfrescoAceEntriesList(addACEs.getPermission()));
List<CMISAccessControlEntry> acesToRemove = (null == removeACEs) ? (null) : (convertToAlfrescoAceEntriesList(removeACEs.getPermission()));
CMISAccessControlReport aclReport = null;
try
{
aclReport = cmisAclService.applyAcl(object, acesToRemove, acesToAdd, propagation, CMISAccessControlFormatEnum.REPOSITORY_SPECIFIC_PERMISSIONS);
}
catch (Exception e)
{
throw cmisObjectsUtils.createCmisException(("Can't perform updating of Object Permissions. Error cause message: " + e.toString()), EnumServiceException.CONSTRAINT);
}
CmisACLType result = convertAclReportToCmisAclType(aclReport);
return result;
}
catch (CMISConstraintException e)
{
throw ExceptionUtil.createCmisException(e);
}
}
private List<CMISAccessControlEntry> convertToAlfrescoAceEntriesList(List<CmisAccessControlEntryType> source)
private List<CMISAccessControlEntry> convertToAlfrescoAceEntriesList(List<CmisAccessControlEntryType> source) throws CmisException
{
List<CMISAccessControlEntry> result = new LinkedList<CMISAccessControlEntry>();
for (CmisAccessControlEntryType cmisEntry : source)
{
result.add(convertToAlfrescoAceEntry(cmisEntry));
if (!cmisEntry.isDirect())
{
throw ExceptionUtil.createCmisException("Inherited Permissions can't be updated or deleted from Object", EnumServiceException.NOT_SUPPORTED);
}
return result;
String principalId = cmisEntry.getPrincipal().getPrincipalId();
if (CMIS_USER.equals(principalId))
{
principalId = AuthenticationUtil.getFullyAuthenticatedUser();
}
private CMISAccessControlEntry convertToAlfrescoAceEntry(final CmisAccessControlEntryType entry)
for (String permission : cmisEntry.getPermission())
{
final Holder<String> correctPrincipalId = new Holder<String>(entry.getPrincipal().getPrincipalId());
if ("cmis:user".equals(correctPrincipalId))
{
correctPrincipalId.value = AuthenticationUtil.getFullyAuthenticatedUser();
}
CMISAccessControlEntry result = new CMISAccessControlEntry() // FIXME: It is better to use already implemented class of this interface
{
private String principalId;
private String permission; // FIXME: [BUG] It MUST BE a List of permissions!!!
private boolean direct;
{
principalId = correctPrincipalId.value;
permission = entry.getPermission().iterator().next(); // FIXME: See line 66
direct = entry.isDirect();
}
public String getPrincipalId()
{
return principalId;
}
public String getPermission()
{
return permission;
}
public boolean getDirect()
{
return direct;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((permission == null) ? 0 : permission.hashCode());
result = prime * result + ((principalId == null) ? 0 : principalId.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final CMISAccessControlEntry other = (CMISAccessControlEntry) obj;
if (permission == null)
{
if (other.getPermission() != null)
{
return false;
result.add(new CMISAccessControlEntryImpl(principalId, permission));
}
}
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;
}
@@ -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)
{
return determineRelationshipAllowableActions((AssociationRef) objectIdentifier);
typeDef = cmisService.getTypeDefinition((AssociationRef) objectIdentifier);
}
switch (cmisObjectsUtils.determineObjectType(objectIdentifier.toString()))
else
{
case CMIS_DOCUMENT:
if (objectIdentifier instanceof Version)
{
return determineDocumentAllowableActions((NodeRef) objectIdentifier);
objectIdentifier = ((Version) objectIdentifier).getFrozenStateNodeRef();
}
case CMIS_FOLDER:
typeDef = cmisService.getTypeDefinition((NodeRef) objectIdentifier);
}
}
catch (CMISInvalidArgumentException e)
{
return determineFolderAllowableActions((NodeRef) objectIdentifier);
throw ExceptionUtil.createCmisException(e);
}
}
// 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)
for (Entry<CMISAllowedActionEnum, CMISActionEvaluator<? extends Object>> entry : typeDef.getActionEvaluators().entrySet())
{
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)
PropertyDescriptor propertyDescriptor = ALLOWED_ACTION_ENUM_MAPPING.get(entry.getKey());
if (propertyDescriptor != null)
{
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)
// Let's assume that the evaluator will accept the object
try
{
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());
propertyDescriptor.getWriteMethod().invoke(result, new Boolean(((CMISActionEvaluator) entry.getValue()).isAllowed(objectIdentifier)));
}
private CmisAllowableActionsType determineRelationshipAllowableActions(AssociationRef association)
catch (IllegalArgumentException e)
{
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);
throw new AlfrescoRuntimeException("Exception setting allowable actions", e);
}
catch (IllegalAccessException e)
{
throw new AlfrescoRuntimeException("Exception setting allowable actions", e);
}
catch (InvocationTargetException e)
{
throw new AlfrescoRuntimeException("Exception setting allowable actions", e.getTargetException());
}
}
}
return result;
}
}

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2008 Alfresco Software Limited.
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -18,7 +18,7 @@
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
@@ -29,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,21 +67,16 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
checkRepositoryId(repositoryId);
PropertyFilter propertyFilter = createPropertyFilter(filter);
try
{
NodeRef folderRef = null;
if ((folderId != null) && !folderId.equals(""))
{
folderRef = cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT);
folderRef = cmisService.getFolder(folderId);
}
@SuppressWarnings("unused")
List<Pair<String, Boolean>> orderingFields = null;
if ((orderBy != null) && !orderBy.equals(""))
{
orderingFields = checkAndParseOrderByClause(orderBy);
}
// TODO: Ordering functionality SHOULD be moved to getChildren service method
NodeRef[] nodeRefs = cmisService.getCheckedOut(AuthenticationUtil.getFullyAuthenticatedUser(), folderRef, (folderRef == null));
NodeRef[] nodeRefs = cmisService.getCheckedOut(AuthenticationUtil.getFullyAuthenticatedUser(), folderRef,
(folderRef == null), orderBy);
Cursor cursor = createCursor(nodeRefs.length, skipCount, maxItems);
CmisObjectListType result = new CmisObjectListType();
@@ -93,7 +84,8 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
for (int index = cursor.getStartRow(); index <= cursor.getEndRow(); index++)
{
resultListing.add(createCmisObject(nodeRefs[index].toString(), propertyFilter, includeAllowableActions, renditionFilter));
resultListing.add(createCmisObject(nodeRefs[index], propertyFilter, includeAllowableActions,
renditionFilter));
}
result.setHasMoreItems(new Boolean(cursor.getEndRow() < (nodeRefs.length - 1)));
@@ -101,6 +93,11 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
return result;
}
catch (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
}
/**
* Gets the list of child objects contained in the specified folder. Only the filter-selected properties associated with each object are returned. The content-streams of
@@ -111,24 +108,19 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
* @return collection of CmisObjectType and boolean hasMoreItems
* @throws CmisException (with following {@link EnumServiceException} : INVALID_ARGUMENT, OBJECT_NOT_FOUND, NOT_SUPPORTED, PERMISSION_DENIED, RUNTIME, FILTER_NOT_VALID)
*/
public CmisObjectInFolderListType getChildren(String repositoryId, String folderId, String filter, String orderBy, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments, BigInteger maxItems, BigInteger skipCount,
CmisExtensionType extension) throws CmisException
public CmisObjectInFolderListType getChildren(String repositoryId, String folderId, String filter, String orderBy,
Boolean includeAllowableActions, EnumIncludeRelationships includeRelationships, String renditionFilter,
Boolean includePathSegments, BigInteger maxItems, BigInteger skipCount, CmisExtensionType extension)
throws CmisException
{
checkRepositoryId(repositoryId);
PropertyFilter propertyFilter = createPropertyFilter(filter);
NodeRef folderNodeRef = cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT);
@SuppressWarnings("unused")
List<Pair<String, Boolean>> orderingFields = null;
if ((orderBy != null) && !orderBy.equals(""))
try
{
orderingFields = checkAndParseOrderByClause(orderBy);
}
NodeRef folderNodeRef = cmisService.getFolder(folderId);
// TODO: Ordering functionality SHOULD be moved to getChildren service method
NodeRef[] listing = cmisService.getChildren(folderNodeRef, CMISTypesFilterEnum.ANY);
NodeRef[] listing = cmisService.getChildren(folderNodeRef, CMISTypesFilterEnum.ANY, orderBy);
CmisObjectInFolderListType result = new CmisObjectInFolderListType();
@@ -136,12 +128,14 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
for (int index = cursor.getStartRow(); index <= cursor.getEndRow(); index++)
{
CmisObjectType cmisObject = createCmisObject(listing[index].toString(), propertyFilter, includeAllowableActions, renditionFilter);
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, ""));
cmisObjectInFolder.setPathSegment(propertiesUtil.getProperty(listing[index],
CMISDictionaryModel.PROP_NAME, ""));
}
result.getObjects().add(cmisObjectInFolder);
}
@@ -152,6 +146,11 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
// TODO: Process includeRelationships, includeACL
return result;
}
catch (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
}
/**
* Gets the list of descendant objects contained at one or more levels in the tree rooted at the specified folder. Only the filter-selected properties associated with each
@@ -165,7 +164,7 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
public List<CmisObjectInFolderContainerType> getDescendants(String repositoryId, String folderId, BigInteger depth, String filter, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments, CmisExtensionType extension) throws CmisException
{
CmisObjectInFolderContainerType objectInFolderContainerType = getDescedantsTree(repositoryId, folderId, depth, filter, includeAllowableActions, includeRelationships,
CmisObjectInFolderContainerType objectInFolderContainerType = getDescendantsTree(repositoryId, folderId, depth, filter, includeAllowableActions, includeRelationships,
renditionFilter, includePathSegments, CMISTypesFilterEnum.ANY);
return objectInFolderContainerType.getChildren();
}
@@ -182,7 +181,7 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
public List<CmisObjectInFolderContainerType> getFolderTree(String repositoryId, String folderId, BigInteger depth, String filter, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments, CmisExtensionType extension) throws CmisException
{
CmisObjectInFolderContainerType objectInFolderContainerType = getDescedantsTree(repositoryId, folderId, depth, filter, includeAllowableActions, includeRelationships,
CmisObjectInFolderContainerType objectInFolderContainerType = getDescendantsTree(repositoryId, folderId, depth, filter, includeAllowableActions, includeRelationships,
renditionFilter, includePathSegments, CMISTypesFilterEnum.FOLDERS);
return objectInFolderContainerType.getChildren();
}
@@ -211,9 +210,17 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
}
}
PropertyFilter propertyFilter = createPropertyFilter(filter);
NodeRef parentRef = receiveParent(folderId);
NodeRef parentRef;
try
{
parentRef = cmisService.getFolderParent(folderId);
}
catch (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
CmisObjectType result = createCmisObject(parentRef, propertyFilter, false, null);
// TODO: It is not clear whether ACL etc should be returned
return result;
}
@@ -231,7 +238,15 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
checkRepositoryId(repositoryId);
PropertyFilter propertyFilter = createPropertyFilter(filter);
NodeRef childNode = (NodeRef) cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.DOCUMENT_OBJECT);
NodeRef childNode;
try
{
childNode = (NodeRef) cmisService.getReadableObject(objectId, NodeRef.class);
}
catch (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
List<NodeRef> parents = receiveObjectParents(childNode);
List<CmisObjectParentsType> result = new ArrayList<CmisObjectParentsType>();
@@ -252,7 +267,7 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
return result;
}
private CmisObjectInFolderContainerType getDescedantsTree(String repositoryId, String folderId, BigInteger depth, String filter, Boolean includeAllowableActions,
private CmisObjectInFolderContainerType getDescendantsTree(String repositoryId, String folderId, BigInteger depth, String filter, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments, CMISTypesFilterEnum types) throws CmisException
{
checkRepositoryId(repositoryId);
@@ -262,11 +277,13 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
long maxDepth = depth.longValue();
checkDepthParameter(depth);
NodeRef folderNodeRef = cmisObjectsUtils.getIdentifierInstance(folderId, AlfrescoObjectType.FOLDER_OBJECT);
try
{
NodeRef folderNodeRef = cmisService.getFolder(folderId);
Stack<RecursiveElement> descedantsStack = new Stack<RecursiveElement>();
CmisObjectInFolderContainerType objectInFolderContainer = createObjectInFolderContainer(folderNodeRef, propertyFilter, includeAllowableActions, includeRelationships,
renditionFilter, includePathSegments);
NodeRef[] children = cmisService.getChildren(folderNodeRef, types);
CmisObjectInFolderContainerType objectInFolderContainer = createObjectInFolderContainer(folderNodeRef,
propertyFilter, includeAllowableActions, includeRelationships, renditionFilter, includePathSegments);
NodeRef[] children = cmisService.getChildren(folderNodeRef, types, null);
for (NodeRef childRef : children)
{
descedantsStack.push(new RecursiveElement(objectInFolderContainer, 1, childRef));
@@ -274,23 +291,30 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
while (!descedantsStack.isEmpty())
{
RecursiveElement element = descedantsStack.pop();
CmisObjectInFolderContainerType currentContainer = createObjectInFolderContainer(element.getCurrentNodeRef(), propertyFilter, includeAllowableActions,
includeRelationships, renditionFilter, includePathSegments);
CmisObjectInFolderContainerType currentContainer = createObjectInFolderContainer(element
.getCurrentNodeRef(), propertyFilter, includeAllowableActions, includeRelationships,
renditionFilter, includePathSegments);
element.getParentContainerType().getChildren().add(currentContainer);
if (element.getDepth() <= maxDepth)
{
children = cmisService.getChildren(element.getCurrentNodeRef(), types);
children = cmisService.getChildren(element.getCurrentNodeRef(), types, null);
if (children != null)
{
for (NodeRef childRef : children)
{
descedantsStack.push(new RecursiveElement(currentContainer, element.getDepth() + 1, childRef));
descedantsStack.push(new RecursiveElement(currentContainer, element.getDepth() + 1,
childRef));
}
}
}
}
return objectInFolderContainer;
}
catch (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
}
private CmisObjectInFolderContainerType createObjectInFolderContainer(NodeRef nodeRef, PropertyFilter filter, Boolean includeAllowableActions,
EnumIncludeRelationships includeRelationships, String renditionFilter, Boolean includePathSegments) throws CmisException
@@ -311,56 +335,15 @@ public class DMNavigationServicePort extends DMAbstractServicePort implements Na
return result;
}
private List<Pair<String, Boolean>> checkAndParseOrderByClause(String orderByClause) throws CmisException
{
List<Pair<String, Boolean>> result = new LinkedList<Pair<String, Boolean>>();
if (!ORDER_BY_CLAUSE_MASK.matcher(orderByClause).matches())
{
throw cmisObjectsUtils.createCmisException(("\"" + orderByClause + "\" Order By Clause is invalid!"), EnumServiceException.INVALID_ARGUMENT);
}
for (String token : orderByClause.split(","))
{
token = token.trim();
String[] direction = token.split(" ");
String fieldName = direction[0];
result.add(new Pair<String, Boolean>(fieldName, direction[direction.length - 1].toLowerCase().equals("asc")));
}
return result;
}
private NodeRef receiveParent(String targetChildIdentifier) throws CmisException
{
if (cmisService.getDefaultRootNodeRef().toString().equals(targetChildIdentifier))
{
throw cmisObjectsUtils.createCmisException("Root Folder has no parents", EnumServiceException.INVALID_ARGUMENT);
}
NodeRef identifierInstance = (NodeRef) cmisObjectsUtils.getIdentifierInstance(targetChildIdentifier, AlfrescoObjectType.FOLDER_OBJECT);
return receiveNextParentNodeReference(identifierInstance, new LinkedList<NodeRef>());
}
private void checkDepthParameter(BigInteger depth) throws CmisException
{
if (depth.equals(BigInteger.ZERO) || (depth.compareTo(FULL_DESCENDANTS_HIERARCHY_CONDITION) < EQUALS_CONDITION_VALUE))
{
throw cmisObjectsUtils.createCmisException("The specified descendants depth is not valid. Valid depth values are: -1 (full hierarchy), N > 0",
throw ExceptionUtil.createCmisException("The specified descendants depth is not valid. Valid depth values are: -1 (full hierarchy), N > 0",
EnumServiceException.INVALID_ARGUMENT);
}
}
private NodeRef receiveNextParentNodeReference(NodeRef currentParent, List<NodeRef> parents)
{
currentParent = nodeService.getPrimaryParent(currentParent).getParentRef();
if (currentParent != null)
{
parents.add(currentParent);
}
return currentParent;
}
private List<NodeRef> receiveObjectParents(NodeRef objectId) throws CmisException
{
List<NodeRef> parents = new LinkedList<NodeRef>();

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -18,7 +18,7 @@
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
@@ -29,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<EnumVersioningState, CMISVersioningStateEnum> VERSIONING_STATE_ENUM_MAPPING;
private DictionaryService dictionaryService;
private FileTypeIconRetriever iconRetriever;
static
{
VERSIONING_STATE_ENUM_MAPPING = new HashMap<EnumVersioningState, CMISVersioningStateEnum>(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,14 +107,12 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
throws CmisException
{
checkRepositoryId(repositoryId);
NodeRef parentNodeRef = safeGetFolderNodeRef(folderId);
if (null == properties)
try
{
throw cmisObjectsUtils.createCmisException("Properties input parameter is Mandatory", EnumServiceException.INVALID_ARGUMENT);
}
NodeRef parentNodeRef = cmisService.getFolder(folderId);
Map<String, Object> propertiesMap = propertiesUtil.getPropertiesMap(properties);
String typeId = extractAndAssertTypeId(propertiesMap);
CMISTypeDefinition typeDef = cmisDictionaryService.findType(typeId);
CMISTypeDefinition typeDef = cmisService.getTypeDefinition(typeId);
String documentName = checkConstraintsAndGetName(typeId, typeDef, parentNodeRef, contentStream, propertiesMap, versioningState);
NodeRef newDocumentNodeRef = fileFolderService.create(parentNodeRef, documentName, typeDef.getTypeId().getQName()).getNodeRef();
@@ -123,7 +127,7 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
}
else
{
throw cmisObjectsUtils.createCmisException("Content Stream Mime Type was not specified", EnumServiceException.STORAGE);
throw ExceptionUtil.createCmisException("Content Stream Mime Type was not specified", EnumServiceException.INVALID_ARGUMENT);
}
InputStream inputstream = null;
try
@@ -132,13 +136,22 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
}
catch (IOException e)
{
throw cmisObjectsUtils.createCmisException(e.toString(), EnumServiceException.CONSTRAINT);
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 ExceptionUtil.createCmisException("Properties input parameter is Mandatory", EnumServiceException.INVALID_ARGUMENT);
}
}
/**
* Creates a document object as a copy of the given source document in the specified location
@@ -157,8 +170,10 @@ 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);
try
{
NodeRef folderNodeRef = cmisService.getFolder(folderId);
NodeRef sourceNodeRef = cmisService.getReadableObject(sourceId, NodeRef.class);
String name = propertiesUtil.getProperty(sourceNodeRef, CMISDictionaryModel.PROP_NAME, null);
NodeRef newDocumentNodeRef;
try
@@ -167,15 +182,20 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
}
catch (FileExistsException e)
{
throw cmisObjectsUtils.createCmisException("Document already exists", EnumServiceException.CONTENT_ALREADY_EXISTS);
throw ExceptionUtil.createCmisException("Document already exists", EnumServiceException.CONTENT_ALREADY_EXISTS);
}
catch (FileNotFoundException e)
{
throw cmisObjectsUtils.createCmisException("Source document not found", EnumServiceException.INVALID_ARGUMENT);
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 (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
}
/**
* Creates a folder object of the specified type.
@@ -193,24 +213,16 @@ 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);
NodeRef folderNodeRef = cmisService.getFolder(folderId);
Map<String, Object> propertiesMap = propertiesUtil.getPropertiesMap(properties);
String typeId = extractAndAssertTypeId(propertiesMap);
CMISTypeDefinition type = getCmisTypeDefinition(typeId);
CMISTypeDefinition type = cmisService.getTypeDefinition(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);
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);
@@ -226,7 +238,12 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
}
catch (FileExistsException e)
{
throw cmisObjectsUtils.createCmisException("Folder already exists", EnumServiceException.CONTENT_ALREADY_EXISTS);
throw ExceptionUtil.createCmisException("Folder already exists", EnumServiceException.CONTENT_ALREADY_EXISTS);
}
}
catch (CMISServiceException e)
{
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<String> policies, CmisAccessControlListType addACEs,
CmisAccessControlListType removeACEs, Holder<CmisExtensionType> extension, Holder<String> objectId) throws CmisException
{
throw cmisObjectsUtils.createCmisException("Policy objects not supported", EnumServiceException.NOT_SUPPORTED);
throw ExceptionUtil.createCmisException("Policy objects not supported", EnumServiceException.NOT_SUPPORTED);
}
/**
@@ -267,27 +284,29 @@ 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);
try
{
NodeRef sourceNodeRef = cmisService.getObject(sourceObjectId, NodeRef.class, true, false, false);
NodeRef targetNodeRef = cmisService.getObject(targetObjectId, NodeRef.class, true, false, false);
String typeId = (String) propertiesMap.get(CMISDictionaryModel.PROP_OBJECT_TYPE_ID);
CMISTypeDefinition relationshipType = cmisDictionaryService.findType(typeId);
CMISTypeDefinition relationshipType = cmisService.getTypeDefinition(typeId);
if (relationshipType == null || relationshipType.getTypeId() == null || relationshipType.getTypeId().getScope() != CMISScope.RELATIONSHIP)
{
throw cmisObjectsUtils.createCmisException(typeId, EnumServiceException.INVALID_ARGUMENT);
throw ExceptionUtil.createCmisException(typeId, EnumServiceException.INVALID_ARGUMENT);
}
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));
CMISTypeDefinition sourceType = cmisService.getTypeDefinition(sourceNodeRef);
CMISTypeDefinition targetType = cmisService.getTypeDefinition(targetNodeRef);
if ((null != relationshipType.getAllowedSourceTypes()) && !relationshipType.getAllowedSourceTypes().contains(sourceType))
{
throw cmisObjectsUtils.createCmisException(("Source object type is not allowed for \"" + typeId + "\" Relationship 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 cmisObjectsUtils.createCmisException(("Target object type is not allowed for \"" + typeId + "\" Relationship type"), EnumServiceException.CONSTRAINT);
throw ExceptionUtil.createCmisException(("Target object type is not allowed for \"" + typeId + "\" Relationship type"), EnumServiceException.CONSTRAINT);
}
QName relationshipTypeQName = relationshipType.getTypeId().getQName();
@@ -296,18 +315,23 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
{
if (!dictionaryService.isSubClass(nodeService.getType(sourceNodeRef), associationDef.getSourceClass().getName()))
{
throw cmisObjectsUtils.createCmisException("Source object type isn't allowed as source type", EnumServiceException.CONSTRAINT);
throw ExceptionUtil.createCmisException("Source object type isn't allowed as source type", EnumServiceException.CONSTRAINT);
}
if (!dictionaryService.isSubClass(nodeService.getType(targetNodeRef), associationDef.getTargetClass().getName()))
{
throw cmisObjectsUtils.createCmisException("Target object type isn't allowed as target type", EnumServiceException.CONSTRAINT);
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 cmisObjectsUtils.createCmisException((relationshipType.getTypeId().getQName() + " Relationship type not found"), EnumServiceException.INVALID_ARGUMENT);
throw ExceptionUtil.createCmisException((relationshipType.getTypeId().getQName() + " Relationship type not found"), EnumServiceException.INVALID_ARGUMENT);
}
}
catch (CMISServiceException e)
{
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<CmisExtensionType> extension) throws CmisException
{
// TODO: Process flag allVersions
checkRepositoryId(repositoryId);
Object identifier = cmisObjectsUtils.getIdentifierInstance(objectId, AlfrescoObjectType.ANY_OBJECT);
NodeRef objectNodeReference = null;
if (identifier instanceof AssociationRef)
{
AssociationRef assocRef = (AssociationRef) identifier;
try
{
nodeService.removeAssociation(assocRef.getSourceRef(), assocRef.getTargetRef(), assocRef.getTypeQName());
cmisService.deleteObject(objectId, allVersions == null || allVersions);
}
catch (InvalidNodeRefException e)
catch (CMISServiceException e)
{
throw cmisObjectsUtils.createCmisException("Invalid object identifier", EnumServiceException.INVALID_ARGUMENT);
}
}
else
{
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<String> 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);
try
{
NodeRef object = cmisService.getReadableObject(objectId, NodeRef.class);
PropertyFilter propertyFilter = createPropertyFilter(filter);
boolean includeActions = (null != includeAllowableActions) ? (includeAllowableActions.booleanValue()) : (false);
CmisObjectType object = createCmisObject(identifierInstance, propertyFilter, includeActions, renditionFilter);
CmisObjectType cmisObject = createCmisObject(object, propertyFilter, includeActions, renditionFilter);
// TODO: process relationships
// TODO: process policyIds
Object versionSeries = cmisService.getVersionSeries(objectId, Object.class, false);
boolean includeAcl = (null != includeACL) ? (includeACL.booleanValue()) : (false);
if (includeAcl && (identifierInstance instanceof NodeRef))
if (includeAcl && (versionSeries instanceof NodeRef))
{
appendWithAce((NodeRef) identifierInstance, object);
appendWithAce((NodeRef) versionSeries, cmisObject);
}
return object;
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,12 +518,13 @@ 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));
try
{
NodeRef nodeRef = cmisService.getReadableObject(objectId, NodeRef.class);
CMISTypeDefinition typeDefinition = cmisService.getTypeDefinition(nodeRef);
if (CMISContentStreamAllowedEnum.NOT_ALLOWED == typeDefinition.getContentStreamAllowed())
{
throw cmisObjectsUtils.createCmisException("Content stream not allowed", EnumServiceException.STREAM_NOT_SUPPORTED);
throw ExceptionUtil.createCmisException("Content stream not allowed", EnumServiceException.STREAM_NOT_SUPPORTED);
}
String filename = propertiesUtil.getProperty(nodeRef, CMISDictionaryModel.PROP_NAME, null);
@@ -536,7 +552,7 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
}
else
{
NodeRef renditionNodeRef = cmisObjectsUtils.getIdentifierInstance(streamId, AlfrescoObjectType.DOCUMENT_OBJECT);
NodeRef renditionNodeRef = new NodeRef(streamId);
ContentReader reader = safeGetContentReader(renditionNodeRef);
dataSource = new ContentReaderDataSource(reader, filename, offset, length, reader.getSize());
}
@@ -560,6 +576,11 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
return response;
}
catch (CMISServiceException e)
{
throw ExceptionUtil.createCmisException(e);
}
}
/**
* Moves the specified filed object from one folder to another
@@ -574,40 +595,13 @@ public class DMObjectServicePort extends DMAbstractServicePort implements Object
public void moveObject(String repositoryId, Holder<String> objectId, String targetFolderId, String sourceFolderId, Holder<CmisExtensionType> 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<CmisExtensionType> 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<String> objectId, Holder<String> changeToken, CmisPropertiesType properties, Holder<CmisExtensionType> 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<CmisRenditionType> result = new ArrayList<CmisRenditionType>();
List<CmisRenditionType> 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<String> policies,
CmisAccessControlListType addACEs, CmisAccessControlListType removeACEs, Holder<String> objectId, PropertyFilter propertyFilter) throws CmisException
CmisAccessControlListType addACEs, CmisAccessControlListType removeACEs, Holder<String> 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;
versioningState = EnumVersioningState.MAJOR;
}
versionLabel = propertiesUtil.getProperty(targetDocumentNodeRef, CMISDictionaryModel.PROP_VERSION_LABEL, "");
}
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;

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2008 Alfresco Software Limited.
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -18,13 +18,13 @@
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.cmis.ws;
import org.alfresco.repo.cmis.ws.utils.CmisObjectsUtils;
import org.alfresco.repo.cmis.ws.utils.ExceptionUtil;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -40,13 +40,6 @@ public class DMServicePortThrowsAdvice implements ThrowsAdvice
{
private static final Log LOGGER = LogFactory.getLog("org.alfresco.repo.cmis.ws");
private CmisObjectsUtils cmisObjectsUtils;
public void setCmisObjectsUtils(CmisObjectsUtils cmisObjectsUtils)
{
this.cmisObjectsUtils = cmisObjectsUtils;
}
public void afterThrowing(AccessDeniedException e) throws CmisException
{
if (LOGGER.isInfoEnabled())
@@ -54,7 +47,7 @@ public class DMServicePortThrowsAdvice implements ThrowsAdvice
LOGGER.error(e.toString(), e);
}
throw cmisObjectsUtils.createCmisException(("Access denied. Message: " + e.toString()), e);
throw ExceptionUtil.createCmisException(("Access denied. Message: " + e.toString()), e);
}
public void afterThrowing(java.lang.RuntimeException e) throws CmisException
@@ -64,7 +57,7 @@ public class DMServicePortThrowsAdvice implements ThrowsAdvice
LOGGER.error(e.toString(), e);
}
throw cmisObjectsUtils.createCmisException(("Runtime error. Message: " + e.toString()), e);
throw ExceptionUtil.createCmisException(("Runtime error. Message: " + e.toString()), e);
}
public void afterThrowing(java.lang.Exception e) throws CmisException
@@ -76,7 +69,7 @@ public class DMServicePortThrowsAdvice implements ThrowsAdvice
if (!(e instanceof CmisException))
{
throw cmisObjectsUtils.createCmisException(("Some error occured during last service invokation. Message: " + e.toString()), e);
throw ExceptionUtil.createCmisException(("Some error occured during last service invokation. Message: " + e.toString()), e);
}
else
{

View File

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

View File

@@ -1,73 +0,0 @@
/*
* Copyright (C) 2005-2008 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.cmis.ws.utils;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.cmis.mapping.CMISMapping;
import org.alfresco.model.ContentModel;
/**
* @author Dmitry Velichkevich
*/
public enum AlfrescoObjectType
{
DOCUMENT_OBJECT(ContentModel.TYPE_CONTENT.toString()),
FOLDER_OBJECT(ContentModel.TYPE_FOLDER.toString()),
DOCUMENT_OR_FOLDER_OBJECT("DOCUMENT_OR_FOLDER"),
RELATIONSHIP_OBJECT(CMISMapping.RELATIONSHIP_QNAME.toString()),
ANY_OBJECT("ANY");
String value;
final static Map<String, AlfrescoObjectType> VALUES;
static
{
VALUES = new HashMap<String, AlfrescoObjectType>();
VALUES.put(DOCUMENT_OBJECT.getValue(), DOCUMENT_OBJECT);
VALUES.put(FOLDER_OBJECT.getValue(), FOLDER_OBJECT);
}
AlfrescoObjectType(String value)
{
this.value = value;
}
public String getValue()
{
return this.value;
}
public static AlfrescoObjectType fromValue(String valueName)
{
AlfrescoObjectType result = VALUES.get(valueName);
if (result == null)
{
result = ANY_OBJECT;
}
return result;
}
}

View File

@@ -1,364 +0,0 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.cmis.ws.utils;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.cmis.ws.EnumUnfileObject;
import org.alfresco.repo.model.filefolder.FileInfoImpl;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.namespace.QName;
/**
* This class enumerates Documents and Folders hierarchy that begins from specified folder. Iterator returns Document or Empty Folder Objects those may be removed or deleted from
* repository according to {@link EnumUnfileObject} <b>unfileObject</b> and {@link Boolean} <b>continueOnFailure</b> parameters. After hierarchy enumerating completion iterator may
* introduce Object Id(s) {@link List} those were not deleted due to {@link Exception}(s)
*
* @author Dmitry Velichkevich
*/
public class CmisObjectIterator implements Iterator<FileInfo>
{
private EnumUnfileObject unfillingStrategy;
private boolean continueOnFailure;
private NodeService nodeService;
private FileFolderService fileFolderService;
private VersionService versionService;
private CheckOutCheckInService checkOutCheckInService;
private CmisObjectsUtils objectsUtils;
private Map<FileInfo, List<FileInfo>> hierarchy = new HashMap<FileInfo, List<FileInfo>>();
private LinkedList<FileInfo> objects = new LinkedList<FileInfo>();
private List<String> failToDelete = new LinkedList<String>();
private FileInfo next;
private boolean lastDeleted;
private boolean nextFound;
private boolean deleteAllVersions;
/**
* Mandatory constructor
*
* @param rootObject - {@link NodeRef} instance that represents Root folder for hierarchy
* @param unfillingStrategy - {@link EnumUnfileObject} value that determines File-able Objects deletion or removing strategy
* @param continueOnFailure - {@link Boolean} value that determines whether it is necessary continue deletion after some {@link Exception} occurred
* @param nodeService - A {@link NodeService} implementation instance for manipulating with Object Properties
* @param fileFolderService - A {@link FileFolderService} implementation instance for manipulating with Objects
* @param objectsUtils - {@link CmisObjectsUtils} service instance for simplifying manipulations with Objects and Object Properties
*/
public CmisObjectIterator(NodeRef rootObject, EnumUnfileObject unfillingStrategy, boolean continueOnFailure, boolean deleteAllVersions, NodeService nodeService,
FileFolderService fileFolderService, VersionService versionService, CheckOutCheckInService checkOutCheckInService, CmisObjectsUtils objectsUtils)
{
this.unfillingStrategy = unfillingStrategy;
this.deleteAllVersions = deleteAllVersions;
this.continueOnFailure = continueOnFailure;
this.nodeService = nodeService;
this.fileFolderService = fileFolderService;
this.versionService = versionService;
this.checkOutCheckInService = checkOutCheckInService;
this.objectsUtils = objectsUtils;
objects.add(new ParentedFileInfo(fileFolderService.getFileInfo(rootObject), null));
}
/**
* This method performs searching for next Object (see {@link CmisObjectIterator})
*/
public boolean hasNext()
{
if (nextFound)
{
return true;
}
if (objects.isEmpty() || (!failToDelete.isEmpty() && !continueOnFailure))
{
return false;
}
for (next = objects.removeFirst(); processFolder() && !objects.isEmpty(); next = objects.removeFirst())
{
}
nextFound = (null != next) && (!next.isFolder() || (null == receiveChildren(next.getNodeRef())));
return nextFound;
}
private boolean processFolder()
{
if (next.isFolder())
{
List<ChildAssociationRef> children = receiveChildren(next.getNodeRef());
if (null != children)
{
objects.addFirst(next);
for (ChildAssociationRef child : children)
{
FileInfo info = fileFolderService.getFileInfo(child.getChildRef());
ParentedFileInfo childInfo = new ParentedFileInfo(info, next);
objects.addFirst(childInfo);
addChildToParent(next, childInfo);
}
return true;
}
}
return false;
}
private void addChildToParent(FileInfo parent, FileInfo child)
{
if (null != parent)
{
List<FileInfo> children;
if (hierarchy.containsKey(parent))
{
children = hierarchy.get(parent);
}
else
{
children = new LinkedList<FileInfo>();
hierarchy.put(parent, children);
}
children.add(child);
}
}
private List<ChildAssociationRef> receiveChildren(NodeRef folderRef)
{
if (null != folderRef)
{
List<ChildAssociationRef> result = nodeService.getChildAssocs(folderRef);
if ((null != result) && !result.isEmpty())
{
return result;
}
}
return null;
}
/**
* This method returns currently enumerated Object and changes flag to enumerate next Object
*
* @see CmisObjectIterator
* @see CmisObjectIterator#hasNext()
* @see CmisObjectIterator#remove()
*/
public FileInfo next()
{
nextFound = false;
return next;
}
/**
* This method removes currently enumerated Object (see {@link CmisObjectIterator}). If Object deletion or removing fails due to {@link Exception} then according to
* <b>continueOnFailure</b> parameter current Object Id and (if <b>continueOnFailure</b>="<b>true</b>") current Object Parent(s)' Id(s) will be stored in <b>failedToDelete</b>
* {@link List}. Not deleted Object and its Parent(s) never will be enumerated again
*
* @see CmisObjectIterator
* @see CmisObjectIterator#hasNext()
* @see CmisObjectIterator#next()
*/
public void remove()
{
lastDeleted = false;
NodeRef parentRef = null;
ParentedFileInfo info = null;
if (null != next)
{
info = (ParentedFileInfo) next;
EnumUnfileObject howToDelete = null;
parentRef = (null != info.getExactParent()) ? (info.getExactParent().getNodeRef()) : (null);
if ((null != parentRef) && ((EnumUnfileObject.DELETESINGLEFILED == unfillingStrategy) || !objectsUtils.isPrimaryObjectParent(parentRef, info.getNodeRef())))
{
howToDelete = EnumUnfileObject.DELETESINGLEFILED;
}
else
{
howToDelete = EnumUnfileObject.DELETE;
}
if (EnumUnfileObject.DELETESINGLEFILED == howToDelete)
{
lastDeleted = objectsUtils.removeObject(info.getNodeRef(), parentRef);
}
else
{
if (deleteAllVersions)
{
NodeRef workingCopyRef = (objectsUtils.isWorkingCopy(info.getNodeRef())) ? (info.getNodeRef()) : (checkOutCheckInService.getWorkingCopy(info.getNodeRef()));
if (null == workingCopyRef)
{
versionService.deleteVersionHistory(info.getNodeRef());
}
}
lastDeleted = (objectsUtils.deleteObject(info.getNodeRef()));
}
}
if (!lastDeleted && (null != info))
{
failToDelete.add(generateId(info));
if ((null == info.getExactParent()) && info.isFolder())
{
removeFolderFromCollections(info);
}
if (continueOnFailure)
{
for (; null != info.getExactParent(); info = (ParentedFileInfo) info.getExactParent())
{
failToDelete.add(generateId(info.getExactParent()));
removeFolderFromCollections(info.getExactParent());
}
}
}
}
private void removeFolderFromCollections(FileInfo object)
{
if (hierarchy.containsKey(object))
{
hierarchy.remove(object);
objects.remove(object);
}
}
private String generateId(FileInfo object)
{
StringBuilder generator = new StringBuilder(object.getNodeRef().toString());
Map<QName, Serializable> properties = object.getProperties();
String versionLabel = (null != properties) ? ((String) properties.get(ContentModel.PROP_VERSION_LABEL)) : (null);
if (null != versionLabel)
{
generator.append(CmisObjectsUtils.NODE_REFERENCE_ID_DELIMITER).append(versionLabel);
}
return generator.toString();
}
public boolean wasLastRemoved()
{
return lastDeleted;
}
public List<String> getFailToDelete()
{
return failToDelete;
}
/**
* This class is {@link org.alfresco.jlan.server.filesys.FileInfo} implementation that uses {@link FileInfoImpl} instances to delegate core functionality. The main target of
* this class is extended standard {@link FileInfo} Objects with Parent Object
*
* @author Dmitry Velichkevich
*/
private class ParentedFileInfo implements FileInfo, Serializable
{
private static final long serialVersionUID = -3024276223816623074L;
private FileInfo delegator;
private FileInfo exactParent;
public ParentedFileInfo(FileInfo delegator, FileInfo exactParent)
{
this.delegator = delegator;
this.exactParent = exactParent;
}
public ContentData getContentData()
{
return delegator.getContentData();
}
public Date getCreatedDate()
{
return delegator.getCreatedDate();
}
public NodeRef getLinkNodeRef()
{
return delegator.getLinkNodeRef();
}
public Date getModifiedDate()
{
return delegator.getModifiedDate();
}
public String getName()
{
return delegator.getName();
}
public NodeRef getNodeRef()
{
return delegator.getNodeRef();
}
public Map<QName, Serializable> getProperties()
{
return delegator.getProperties();
}
public boolean isFolder()
{
return delegator.isFolder();
}
public boolean isLink()
{
return delegator.isLink();
}
public FileInfo getExactParent()
{
return exactParent;
}
@Override
public boolean equals(Object obj)
{
return delegator.equals(obj);
}
@Override
public int hashCode()
{
return delegator.hashCode();
}
@Override
public String toString()
{
return delegator.toString();
}
}
}

View File

@@ -1,566 +0,0 @@
/*
* Copyright (C) 2005-2008 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.cmis.ws.utils;
import java.math.BigInteger;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.alfresco.cmis.CMISDictionaryService;
import org.alfresco.cmis.CMISQueryException;
import org.alfresco.cmis.CMISScope;
import org.alfresco.cmis.CMISTypeDefinition;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.cmis.ws.CmisException;
import org.alfresco.repo.cmis.ws.CmisFaultType;
import org.alfresco.repo.cmis.ws.EnumBaseObjectTypeIds;
import org.alfresco.repo.cmis.ws.EnumRelationshipDirection;
import org.alfresco.repo.cmis.ws.EnumServiceException;
import org.alfresco.repo.cmis.ws.EnumUnfileObject;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.lock.LockStatus;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.QNamePattern;
import org.springframework.extensions.surf.util.Pair;
/**
* @author Dmitry Velichkevich
*/
public class CmisObjectsUtils
{
public static final String NODE_REFERENCE_ID_DELIMITER = ";";
private static final Pattern VERSION_LABEL_MATCHING_COMPILED_PATTERN = Pattern.compile("([\\p{Graph}])+([\\p{Digit}]*)\\.([\\p{Digit}]*)$");
private static final String INVALID_OBJECT_IDENTIFIER_MESSAGE = "Invalid Object Identifier was specified: Identifier is incorrect or Object with the specified Identifier does not exist";
private static final List<QName> DOCUMENT_AND_FOLDER_TYPES;
static
{
DOCUMENT_AND_FOLDER_TYPES = new LinkedList<QName>();
DOCUMENT_AND_FOLDER_TYPES.add(ContentModel.TYPE_CONTENT);
DOCUMENT_AND_FOLDER_TYPES.add(ContentModel.TYPE_FOLDER);
}
private static final Map<String, EnumServiceException> CLASS_TO_ENUM_EXCEPTION_MAPPING;
static
{
CLASS_TO_ENUM_EXCEPTION_MAPPING = new HashMap<String, EnumServiceException>();
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(AccessDeniedException.class.getName(), EnumServiceException.PERMISSION_DENIED);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(java.lang.RuntimeException.class.getName(), EnumServiceException.RUNTIME);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(UnsupportedOperationException.class.getName(), EnumServiceException.NOT_SUPPORTED);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(InvalidNodeRefException.class.getName(), EnumServiceException.INVALID_ARGUMENT);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(ContentIOException.class.getName(), EnumServiceException.NOT_SUPPORTED);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(CMISQueryException.class.getName(), EnumServiceException.INVALID_ARGUMENT);
// TODO: insert CLASS_TO_ENUM_EXCEPTION_MAPPING.put(<Concreate_Exception_Type>.class.getName(), EnumServiceException.<Appropriate_Enum_value>);
}
private CheckOutCheckInService checkOutCheckInService;
private CMISDictionaryService cmisDictionaryService;
private FileFolderService fileFolderService;
private AuthorityService authorityService;
private VersionService versionService;
private NodeService nodeService;
private LockService lockService;
private Throwable lastException;
public void setCmisDictionaryService(CMISDictionaryService cmisDictionaryService)
{
this.cmisDictionaryService = cmisDictionaryService;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setFileFolderService(FileFolderService fileFolderService)
{
this.fileFolderService = fileFolderService;
}
public void setLockService(LockService lockService)
{
this.lockService = lockService;
}
public void setCheckOutCheckInService(CheckOutCheckInService checkOutCheckInService)
{
this.checkOutCheckInService = checkOutCheckInService;
}
public void setAuthorityService(AuthorityService authorityService)
{
this.authorityService = authorityService;
}
public void setVersionService(VersionService versionService)
{
this.versionService = versionService;
}
public CmisException createCmisException(String message, EnumServiceException exceptionType)
{
return createCmisException(message, exceptionType, null, 0);
}
public CmisException createCmisException(String message, Throwable cause)
{
EnumServiceException exceptionType = null;
if (CLASS_TO_ENUM_EXCEPTION_MAPPING.containsKey(cause.getClass().getName()))
{
exceptionType = CLASS_TO_ENUM_EXCEPTION_MAPPING.get(cause.getClass().getName());
}
exceptionType = (exceptionType == null) ? (EnumServiceException.RUNTIME) : (exceptionType);
return createCmisException(message, exceptionType, cause, 0);
}
public CmisException createCmisException(String message, EnumServiceException exceptionType, Throwable cause)
{
return createCmisException(message, exceptionType, cause, 0);
}
public CmisException createCmisException(String message, EnumServiceException exceptionType, Throwable cause, int errorCode)
{
CmisFaultType fault = new CmisFaultType();
fault.setMessage(message);
fault.setType(exceptionType);
fault.setCode(BigInteger.valueOf(errorCode));
return new CmisException(message, fault, cause);
}
@SuppressWarnings("unchecked")
public <IdentifierType> IdentifierType getIdentifierInstance(String identifier, AlfrescoObjectType expectedType) throws CmisException
{
if (!(identifier instanceof String))
{
throw createCmisException("Invalid Object Identifier was specified", EnumServiceException.INVALID_ARGUMENT);
}
IdentifierType result;
AlfrescoObjectType actualObjectType;
if (isRelationship(identifier))
{
result = (IdentifierType) safeGetAssociationRef(identifier);
actualObjectType = AlfrescoObjectType.RELATIONSHIP_OBJECT;
}
else
{
NodeRef nodeReference = safeGetNodeRef(identifier);
result = (IdentifierType) nodeReference;
actualObjectType = determineActualObjectType(expectedType, this.nodeService.getType(nodeReference));
}
if ((AlfrescoObjectType.ANY_OBJECT == expectedType) || (actualObjectType == expectedType))
{
return result;
}
throw createCmisException(("Unexpected object type of the specified Object with \"" + identifier + "\" identifier"), EnumServiceException.INVALID_ARGUMENT);
}
public List<String> deleteFolder(NodeRef folderNodeReference, boolean continueOnFailure, EnumUnfileObject unfillingStrategy, boolean deleteAllVersions) throws CmisException
{
CmisObjectIterator iterator = new CmisObjectIterator(folderNodeReference, unfillingStrategy, continueOnFailure, deleteAllVersions, nodeService, fileFolderService,
versionService, checkOutCheckInService, this);
if (iterator.hasNext())
{
for (; iterator.hasNext(); iterator.next())
{
iterator.remove();
}
}
return iterator.getFailToDelete();
}
public boolean deleteObject(NodeRef objectNodeReference)
{
if (null == objectNodeReference)
{
return false;
}
if (versionService.getVersionStoreReference().getIdentifier().equals(objectNodeReference.getStoreRef().getIdentifier()))
{
String versionLabel = (String) nodeService.getProperty(objectNodeReference, ContentModel.PROP_VERSION_LABEL);
if ((null != versionLabel) && !versionLabel.equals(""))
{
Version currentVersion = versionService.getCurrentVersion(objectNodeReference);
if ((null != currentVersion) && nodeService.exists(currentVersion.getVersionedNodeRef()))
{
versionService.deleteVersion(currentVersion.getVersionedNodeRef(), currentVersion);
return true;
}
}
return false;
}
return canLock(objectNodeReference) && performNodeDeletion(objectNodeReference);
}
public boolean removeObject(NodeRef objectNodeReference, NodeRef folderNodeReference)
{
if (isChildOfThisFolder(objectNodeReference, folderNodeReference))
{
try
{
this.nodeService.removeChild(folderNodeReference, objectNodeReference);
}
catch (Throwable e)
{
lastException = e;
return false;
}
return true;
}
return false;
}
public boolean addObjectToFolder(NodeRef objectNodeRef, NodeRef parentFolderNodeRef)
{
try
{
QName name = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName((String) nodeService.getProperty(objectNodeRef,
ContentModel.PROP_NAME)));
nodeService.addChild(parentFolderNodeRef, objectNodeRef, ContentModel.ASSOC_CONTAINS, name);
return true;
}
catch (Throwable e)
{
lastException = e;
return false;
}
}
public boolean isFolder(NodeRef folderNodeRef)
{
if (folderNodeRef == null)
{
return false;
}
QName typeQName = nodeService.getType(folderNodeRef);
CMISTypeDefinition typeDef = cmisDictionaryService.findTypeForClass(typeQName, CMISScope.FOLDER);
return typeDef != null;
}
public boolean isDocument(NodeRef documentNodeRef)
{
if (documentNodeRef == null)
{
return false;
}
QName typeQName = nodeService.getType(documentNodeRef);
CMISTypeDefinition typeDef = cmisDictionaryService.findTypeForClass(typeQName, CMISScope.DOCUMENT);
return typeDef != null;
}
public boolean isRelationship(String identifier)
{
try
{
new AssociationRef(identifier);
return true;
}
catch (Throwable e)
{
return false;
}
}
public boolean isPolicy(NodeRef policyNodeRef)
{
// TODO: Policy
return false;
}
public EnumBaseObjectTypeIds determineObjectType(String identifier)
{
if (isRelationship(identifier))
{
return EnumBaseObjectTypeIds.CMIS_RELATIONSHIP;
}
NodeRef objectNodeReference = new NodeRef(identifier);
if (isFolder(objectNodeReference))
{
return EnumBaseObjectTypeIds.CMIS_FOLDER;
}
if (isDocument(objectNodeReference))
{
return EnumBaseObjectTypeIds.CMIS_DOCUMENT;
}
return EnumBaseObjectTypeIds.CMIS_POLICY;
}
public boolean isChildOfThisFolder(NodeRef objectNodeReference, NodeRef folderNodeReference)
{
NodeRef searchedObjectNodeReference = fileFolderService.searchSimple(folderNodeReference, (String) nodeService.getProperty(objectNodeReference, ContentModel.PROP_NAME));
return (searchedObjectNodeReference != null) && searchedObjectNodeReference.equals(objectNodeReference);
}
public boolean isPrimaryObjectParent(NodeRef folderNodeReference, NodeRef objectNodeReference)
{
NodeRef searchedParentObject = nodeService.getPrimaryParent(objectNodeReference).getParentRef();
return (searchedParentObject != null) && searchedParentObject.equals(folderNodeReference);
}
public boolean isWorkingCopy(NodeRef objectIdentifier)
{
return nodeService.hasAspect(objectIdentifier, ContentModel.ASPECT_WORKING_COPY);
}
public List<AssociationRef> receiveAssociations(NodeRef objectNodeReference, QNamePattern qnameFilter, EnumRelationshipDirection direction)
{
List<AssociationRef> result = new LinkedList<AssociationRef>();
if ((direction == EnumRelationshipDirection.EITHER) || (direction == EnumRelationshipDirection.TARGET))
{
result.addAll(nodeService.getSourceAssocs(objectNodeReference, qnameFilter));
}
if ((direction == EnumRelationshipDirection.EITHER) || (direction == EnumRelationshipDirection.SOURCE))
{
result.addAll(nodeService.getTargetAssocs(objectNodeReference, qnameFilter));
}
return result;
}
/**
* Returns latest minor or major version of document
*
* @param documentNodeRef document node reference
* @param major need latest major version
* @return latest version node reference
*/
public NodeRef getLatestNode(NodeRef documentNodeRef, boolean major)
{
NodeRef latestVersionNodeRef = documentNodeRef;
VersionHistory versionHistory = versionService.getVersionHistory(documentNodeRef);
if (null != versionHistory)
{
Collection<Version> allVersions = versionHistory.getAllVersions();
Iterator<Version> versionsIterator = ((null != allVersions) && !allVersions.isEmpty()) ? (allVersions.iterator()) : (null);
Version latestVersion = (null == versionsIterator) ? (null) : (versionsIterator.next());
String currentVersionLabel = (null != latestVersion) ? (latestVersion.getVersionLabel()) : (null);
if (major && (null != latestVersion))
{
for (; (VersionType.MAJOR != latestVersion.getVersionType()) && versionsIterator.hasNext(); latestVersion = versionsIterator.next())
{
}
latestVersion = (VersionType.MAJOR != latestVersion.getVersionType()) ? (null) : (latestVersion);
}
if ((null != latestVersion) && (null != latestVersion.getVersionLabel()))
{
latestVersionNodeRef = (!latestVersion.getVersionLabel().equals(currentVersionLabel) || (null == latestVersion.getVersionedNodeRef()) || !nodeService
.exists(latestVersion.getVersionedNodeRef())) ? (latestVersion.getFrozenStateNodeRef()) : (latestVersion.getVersionedNodeRef());
}
}
return latestVersionNodeRef;
}
private boolean performNodeDeletion(NodeRef objectNodeReference)
{
if (nodeService.hasAspect(objectNodeReference, ContentModel.ASPECT_WORKING_COPY))
{
checkOutCheckInService.cancelCheckout(objectNodeReference);
return true;
}
try
{
List<AssociationRef> associations = receiveAssociations(objectNodeReference, new MatcheAllQNames(), EnumRelationshipDirection.EITHER);
for (AssociationRef association : associations)
{
if ((null != association) && (null != association.getSourceRef()) && (null != association.getTargetRef()) && (null != association.getTypeQName()))
{
nodeService.removeAssociation(association.getSourceRef(), association.getTargetRef(), association.getTypeQName());
}
}
for (ChildAssociationRef parentAssociation : nodeService.getParentAssocs(objectNodeReference))
{
if (!parentAssociation.isPrimary())
{
nodeService.removeChildAssociation(parentAssociation);
}
}
nodeService.deleteNode(objectNodeReference);
}
catch (Throwable e)
{
lastException = e;
return false;
}
return true;
}
private boolean canLock(NodeRef objectNodeReference)
{
String currentUserName = AuthenticationUtil.getFullyAuthenticatedUser();
return (this.lockService.getLockStatus(objectNodeReference, currentUserName) != LockStatus.LOCKED) || authorityService.isAdminAuthority(currentUserName);
}
private AssociationRef safeGetAssociationRef(String identifier) throws CmisException
{
AssociationRef result = new AssociationRef(identifier);
if (!nodeService.exists(result.getSourceRef()) || !nodeService.exists(result.getTargetRef()))
{
throw createCmisException(INVALID_OBJECT_IDENTIFIER_MESSAGE, EnumServiceException.INVALID_ARGUMENT);
}
return result;
}
private NodeRef safeGetNodeRef(String nodeIdentifier) throws CmisException
{
Pair<String, String> nodeRefAndVersionLabel = (null != nodeIdentifier) ? (splitOnNodeRefAndVersionLabel(nodeIdentifier)) : (null);
if ((null != nodeRefAndVersionLabel) && (null != nodeRefAndVersionLabel.getFirst()) && NodeRef.isNodeRef(nodeRefAndVersionLabel.getFirst()))
{
NodeRef result = new NodeRef(nodeRefAndVersionLabel.getFirst());
if (nodeService.exists(result))
{
result = getNodeRefFromVersion(result, nodeRefAndVersionLabel.getSecond());
if ((null != result) && nodeService.exists(result))
{
return result;
}
}
}
throw createCmisException(INVALID_OBJECT_IDENTIFIER_MESSAGE, EnumServiceException.OBJECT_NOT_FOUND);
}
private Pair<String, String> splitOnNodeRefAndVersionLabel(String nodeIdentifier)
{
String versionLabel = null;
int versionDelimeterIndex = nodeIdentifier.lastIndexOf(NODE_REFERENCE_ID_DELIMITER);
if (versionDelimeterIndex > 0)
{
versionLabel = nodeIdentifier.substring(versionDelimeterIndex + 1);
if ((null != versionLabel) && !versionLabel.equals("") && VERSION_LABEL_MATCHING_COMPILED_PATTERN.matcher(versionLabel).matches())
{
nodeIdentifier = nodeIdentifier.substring(0, versionDelimeterIndex);
}
else
{
versionLabel = null;
}
}
return new Pair<String, String>(nodeIdentifier, versionLabel);
}
private NodeRef getNodeRefFromVersion(NodeRef nodeRef, String versionLabel) throws CmisException
{
NodeRef result = nodeRef;
NodeRef latestNodeRef = ((null != versionLabel) && (null != nodeRef)) ? (getLatestNode(nodeRef, false)) : (null);
if ((null != latestNodeRef) && nodeService.exists(latestNodeRef) && !versionLabel.equals(nodeService.getProperty(latestNodeRef, ContentModel.PROP_VERSION_LABEL)))
{
VersionHistory versionHistory = versionService.getVersionHistory(latestNodeRef);
if (null != versionHistory)
{
Version version = versionHistory.getVersion(versionLabel);
if ((null == version) || (null == version.getFrozenStateNodeRef()))
{
throw createCmisException(("Specified object has no " + versionLabel + " version"), EnumServiceException.INVALID_ARGUMENT);
}
result = version.getFrozenStateNodeRef();
}
}
return result;
}
private AlfrescoObjectType determineActualObjectType(AlfrescoObjectType expectedType, QName objectType)
{
CMISTypeDefinition typeDef = cmisDictionaryService.findTypeForClass(objectType);
if ((expectedType == AlfrescoObjectType.DOCUMENT_OBJECT || expectedType == AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT)
&& typeDef.getTypeId().getScope() == CMISScope.DOCUMENT)
{
return expectedType;
}
if ((expectedType == AlfrescoObjectType.FOLDER_OBJECT || expectedType == AlfrescoObjectType.DOCUMENT_OR_FOLDER_OBJECT)
&& typeDef.getTypeId().getScope() == CMISScope.FOLDER)
{
return expectedType;
}
return AlfrescoObjectType.ANY_OBJECT;
}
private class MatcheAllQNames implements QNamePattern
{
public boolean isMatch(QName qname)
{
return true;
}
}
public Throwable getLastOperationException()
{
Throwable result = lastException;
lastException = null;
return result;
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.cmis.ws.utils;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.cmis.CMISQueryException;
import org.alfresco.cmis.CMISServiceException;
import org.alfresco.repo.cmis.ws.CmisException;
import org.alfresco.repo.cmis.ws.CmisFaultType;
import org.alfresco.repo.cmis.ws.EnumServiceException;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
/**
* @author Dmitry Velichkevich
*/
public abstract class ExceptionUtil
{
private static final Map<String, EnumServiceException> CLASS_TO_ENUM_EXCEPTION_MAPPING;
static
{
CLASS_TO_ENUM_EXCEPTION_MAPPING = new HashMap<String, EnumServiceException>();
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(AccessDeniedException.class.getName(), EnumServiceException.PERMISSION_DENIED);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(java.lang.RuntimeException.class.getName(), EnumServiceException.RUNTIME);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(UnsupportedOperationException.class.getName(), EnumServiceException.NOT_SUPPORTED);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(InvalidNodeRefException.class.getName(), EnumServiceException.INVALID_ARGUMENT);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(ContentIOException.class.getName(), EnumServiceException.NOT_SUPPORTED);
CLASS_TO_ENUM_EXCEPTION_MAPPING.put(CMISQueryException.class.getName(), EnumServiceException.INVALID_ARGUMENT);
}
public static CmisException createCmisException(String message, EnumServiceException exceptionType)
{
return createCmisException(message, exceptionType, null, 0);
}
public static CmisException createCmisException(String message, Throwable cause)
{
EnumServiceException exceptionType = null;
if (cause instanceof CMISServiceException)
{
return createCmisException((CMISServiceException)cause);
}
if (CLASS_TO_ENUM_EXCEPTION_MAPPING.containsKey(cause.getClass().getName()))
{
exceptionType = CLASS_TO_ENUM_EXCEPTION_MAPPING.get(cause.getClass().getName());
}
exceptionType = (exceptionType == null) ? (EnumServiceException.RUNTIME) : (exceptionType);
return createCmisException(message, exceptionType, cause, 0);
}
public static CmisException createCmisException(String message, EnumServiceException exceptionType, Throwable cause)
{
return createCmisException(message, exceptionType, cause, 0);
}
public static CmisException createCmisException(CMISServiceException exception)
{
return createCmisException(exception.getMessage(), EnumServiceException.fromValue(exception.getFaultName()), exception, exception.getStatusCode());
}
public static CmisException createCmisException(String message, EnumServiceException exceptionType, Throwable cause, int errorCode)
{
CmisFaultType fault = new CmisFaultType();
fault.setMessage(message);
fault.setType(exceptionType);
fault.setCode(BigInteger.valueOf(errorCode));
return new CmisException(message, fault, cause);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -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"
*/
@@ -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,22 +521,33 @@ 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
{
try
{
Map<String, Serializable> properties;
if (!identifier.contains("|"))
if (object instanceof NodeRef)
{
properties = cmisService.getProperties(new NodeRef(identifier));
properties = cmisService.getProperties((NodeRef) object);
}
else if (object instanceof Version)
{
properties = cmisService.getProperties(((Version) object).getFrozenStateNodeRef());
}
else
{
properties = createBaseRelationshipProperties(new AssociationRef(identifier));
properties = createBaseRelationshipProperties((AssociationRef) object);
}
CmisPropertiesType result = new CmisPropertiesType();
convertToCmisProperties(properties, filter, result);
return result;
}
catch (CMISInvalidArgumentException e)
{
throw ExceptionUtil.createCmisException(e.getMessage(), EnumServiceException.INVALID_ARGUMENT, e);
}
}
private Map<String, Serializable> createBaseRelationshipProperties(AssociationRef association)
{
@@ -562,7 +569,7 @@ public class PropertyUtil
if (null == type)
{
throw cmisObjectsUtils.createCmisException(("Type with " + typeId + " typeId was not found"), EnumServiceException.RUNTIME);
throw ExceptionUtil.createCmisException(("Type with " + typeId + " typeId was not found"), EnumServiceException.RUNTIME);
}
for (String propertyName : properties.keySet())

View File

@@ -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;

View File

@@ -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;

View File

@@ -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)
try
{
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);
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);
}
}
}

View File

@@ -82,7 +82,7 @@ public class DMNavigationServiceTest extends AbstractServiceTest
helper.versioningServicePort.checkOut(repositoryId, documentIdHolder1, new Holder<CmisExtensionType>(), contentCopied);
assertTrue(contentCopied.value);
List<CmisObjectType> result = getCheckedoutDocs(null, 0, 0);
List<CmisObjectType> 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<CmisExtensionType>());
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<CmisExtensionType>());
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<CmisObjectInFolderType> response = getChildren(companyHomeId, 100, true);
List<CmisObjectInFolderType> 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<CmisObjectInFolderType> getChildren(String folderId, int maxItems, boolean includePathSegments) throws Exception
private List<CmisObjectInFolderType> 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<CmisObjectType> getCheckedoutDocs(String folderId, long maxItems, long skipCount) throws Exception
private List<CmisObjectType> 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();

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2008 Alfresco Software Limited.
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -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<CmisExtensionType>());
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<CmisObjectType> 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<CmisObjectType> 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

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
$Revision: 149 $ $Date: 2009-12-22 08:01:48 -0800 (Tue, 22 Dec 2009) $
$Author: fmueller $ $HeadURL:
$Revision: 169 $ $Date: 2010-01-25 10:34:39 -0800 (Mon, 25 Jan 2010) $
$Author: albertcbrown $ $HeadURL:
http://tools.oasis-open.org/version-control/svn/cmis/trunk/SchemaProject/schema/CMIS-Core.xsd
$
-->
@@ -556,8 +556,6 @@
minOccurs="0" maxOccurs="1" />
<xs:element name="canCreateRelationship" type="xs:boolean"
minOccurs="0" maxOccurs="1" />
<xs:element name="canCreatePolicy" type="xs:boolean"
minOccurs="0" maxOccurs="1" />
<xs:element name="canDeleteTree" type="xs:boolean"
minOccurs="0" maxOccurs="1" />