Merged CMIS063 to HEAD

17100: Chemistry: AtomPub TCK updates, Alfresco CMIS URL bindings, Delete Content Stream

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@17258 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
David Caruana
2009-10-30 14:23:42 +00:00
parent ae1cbc22ab
commit be4912981e
80 changed files with 944 additions and 564 deletions

View File

@@ -93,7 +93,7 @@
<author><name>${node.properties.creator}</name></author>
[@contentstream node/]
<id>urn:uuid:${node.id}</id>
[#assign pwcuri]/api/pwc/[@linksLib.noderef node/][/#assign]
[#assign pwcuri]/cmis/pwc/[@linksLib.noderef node/][/#assign]
[@linksLib.linkself href="${pwcuri}"/]
[@linksLib.linkstream node "enclosure"/]
[@linksLib.linknodeedit node/]
@@ -204,7 +204,7 @@
[/#macro]
[#macro assocCMISLinks assoc]
[#-- TODO: <link rel="allowableactions" href="${absurl(url.serviceContext)}/api/node/${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}/permissions"/> --]
[#-- TODO: <link rel="allowableactions" href="${absurl(url.serviceContext)}/cmis/node/${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}/permissions"/> --]
[@linksLib.linktype assoc/]
[@linksLib.linktosource assoc.source/]
[@linksLib.linktotarget assoc.target/]

View File

@@ -21,7 +21,7 @@
<icon>${absurl(url.context)}/images/logo/AlfrescoLogo16.ico</icon>
<id>${id}</id>
[#nested] [#-- NOTE: Custom links --]
<title>${title}</title>
<title>${title?xml}</title>
<updated>${xmldate(date)}</updated>
[/#macro]
@@ -36,6 +36,6 @@
<icon>${absurl(url.context)}/images/logo/AlfrescoLogo16.ico</icon>
<id>urn:uuid:${node.id}[#if kind != ""]-${kind}[/#if]</id>
[#nested] [#-- NOTE: Custom links --]
<title>${node.name}[#if kind != ""] ${kind?capitalize}[/#if]</title>
<title>${node.name?xml}[#if kind != ""] ${kind?capitalize}[/#if]</title>
<updated>${xmldate(node.properties.modified)}</updated>
[/#macro]

View File

@@ -10,21 +10,21 @@
<atom:title>root collection</atom:title>
<cmisra:collectionType>root</cmisra:collectionType>
</collection>
<collection href="${absurl(url.serviceContext)}/api/types">
<collection href="${absurl(url.serviceContext)}/cmis/types">
<atom:title>type collection</atom:title>
<cmisra:collectionType>types</cmisra:collectionType>
</collection>
<collection href="${absurl(url.serviceContext)}/api/checkedout">
<collection href="${absurl(url.serviceContext)}/cmis/checkedout">
<atom:title>checkedout collection</atom:title>
<accept>${cmisconstants.MIMETYPE_ENTRY}</accept>
<cmisra:collectionType>checkedout</cmisra:collectionType>
</collection>
<collection href="${absurl(url.serviceContext)}/api/unfiled">
<collection href="${absurl(url.serviceContext)}/cmis/unfiled">
<atom:title>unfiled collection</atom:title>
<accept>${cmisconstants.MIMETYPE_ENTRY}</accept>
<cmisra:collectionType>unfiled</cmisra:collectionType>
</collection>
<collection href="${absurl(url.serviceContext)}/api/queries">
<collection href="${absurl(url.serviceContext)}/cmis/queries">
<atom:title>query collection</atom:title>
<accept>${cmisconstants.MIMETYPE_CMIS_QUERY}</accept>
<cmisra:collectionType>query</cmisra:collectionType>
@@ -32,7 +32,7 @@
<atom:link title="root folder tree" type="${cmisconstants.MIMETYPE_CMISTREE}" rel="${cmisconstants.REL_FOLDER_TREE}" href="${absurl(url.serviceContext)}[@linksLib.nodeuri defaultRootFolder/]/tree"/>
<atom:link title="root descendants" type="${cmisconstants.MIMETYPE_CMISTREE}" rel="${cmisconstants.REL_ROOT_DESCENDANTS}" href="${absurl(url.serviceContext)}[@linksLib.nodeuri defaultRootFolder/]/descendants"/>
<atom:link title="type descendants" type="${cmisconstants.MIMETYPE_CMISTREE}" rel="${cmisconstants.REL_TYPES_DESCENDANTS}" href="${absurl(url.serviceContext)}/api/types/descendants"/>
<atom:link title="type descendants" type="${cmisconstants.MIMETYPE_CMISTREE}" rel="${cmisconstants.REL_TYPES_DESCENDANTS}" href="${absurl(url.serviceContext)}/cmis/types/descendants"/>
<cmisra:repositoryInfo>
<cmis:repositoryId>${server.id}</cmis:repositoryId>
@@ -70,22 +70,23 @@
</cmisra:repositoryInfo>
<cmisra:uritemplate>
<cmisra:template>${absurl(url.serviceContext)}/api/node/{id}?filter={filter}&amp;includeAllowableActions={includeAllowableActions}&amp;includePolicyIds={includePolicyIds}&amp;includeRelationships={includeRelationships}&amp;includeACL={includeACL}&amp;renditionFilter={renditionFilter}</cmisra:template>
<cmisra:template>${absurl(url.serviceContext)}/cmis/arg/n?noderef={id}&amp;filter={filter}&amp;includeAllowableActions={includeAllowableActions}&amp;includePolicyIds={includePolicyIds}&amp;includeRelationships={includeRelationships}&amp;includeACL={includeACL}&amp;renditionFilter={renditionFilter}</cmisra:template>
<cmisra:type>${cmisconstants.URI_OBJECT_BY_ID}</cmisra:type>
<cmisra:mediatype>${cmisconstants.MIMETYPE_ENTRY}</cmisra:mediatype>
</cmisra:uritemplate>
<cmisra:uritemplate>
<cmisra:template>${absurl(url.serviceContext)}/api/path/{path}?filter={filter}&amp;includeAllowableActions={includeAllowableActions}&amp;includePolicyIds={includePolicyIds}&amp;includeRelationships={includeRelationships}&amp;includeACL={includeACL}&amp;renditionFilter={renditionFilter}</cmisra:template>
[#-- NOTE: path provided as URL argument for safe handling by URI template generators --]
<cmisra:template>${absurl(url.serviceContext)}/cmis/s/${defaultRootFolder.storeType}:${defaultRootFolder.storeId}/arg/p?path={path}&amp;filter={filter}&amp;includeAllowableActions={includeAllowableActions}&amp;includePolicyIds={includePolicyIds}&amp;includeRelationships={includeRelationships}&amp;includeACL={includeACL}&amp;renditionFilter={renditionFilter}</cmisra:template>
<cmisra:type>${cmisconstants.URI_OBJECT_BY_PATH}</cmisra:type>
<cmisra:mediatype>${cmisconstants.MIMETYPE_ENTRY}</cmisra:mediatype>
</cmisra:uritemplate>
<cmisra:uritemplate>
<cmisra:template>${absurl(url.serviceContext)}/api/type/{id}</cmisra:template>
<cmisra:template>${absurl(url.serviceContext)}/cmis/type/{id}</cmisra:template>
<cmisra:type>${cmisconstants.URI_TYPE_BY_ID}</cmisra:type>
<cmisra:mediatype>${cmisconstants.MIMETYPE_ENTRY}</cmisra:mediatype>
</cmisra:uritemplate>
<cmisra:uritemplate>
<cmisra:template>${absurl(url.serviceContext)}/api/query?q={q}&amp;searchAllVersions={searchAllVersions}&amp;maxItems={maxItems}&amp;skipCount={skipCount}&amp;includeAllowableActions={includeAllowableActions}&amp;includeRelationships={includeRelationships}</cmisra:template>
<cmisra:template>${absurl(url.serviceContext)}/cmis/query?q={q}&amp;searchAllVersions={searchAllVersions}&amp;maxItems={maxItems}&amp;skipCount={skipCount}&amp;includeAllowableActions={includeAllowableActions}&amp;includeRelationships={includeRelationships}</cmisra:template>
<cmisra:type>${cmisconstants.URI_QUERY}</cmisra:type>
<cmisra:mediatype>${cmisconstants.MIMETYPE_FEED}</cmisra:mediatype>
</cmisra:uritemplate>

View File

@@ -1,9 +1,11 @@
<webscript>
<shortname>CMIS Front Page</shortname>
<shortname>CMIS AtomPub Service Document</shortname>
<description>
</description>
<url>/cmis</url>
<format default="html"/>
<format default="atomsvc"/>
<authentication>none</authentication>
<family>CMIS</family>
</webscript>

View File

@@ -1,7 +1,6 @@
var tckRunner = Packages.org.apache.chemistry.tck.atompub.tools.TCKRunner();
model.tckTests = tckRunner.getTestNames();
model.tckOptions = tckRunner.getOptions();
model.cmisVersion = cmis.version;
model.defaultRootFolder = cmis.defaultRootFolder;
model.defaultRootFolderPath = cmis.defaultRootFolderPath;
model.querySupport = cmis.querySupport.label;
model.joinSupport = cmis.joinSupport.label;
model.pwcSearchable = cmis.pwcSearchable;

View File

@@ -0,0 +1,12 @@
<webscript>
<shortname>CMIS Index Page</shortname>
<description>
</description>
<url>/cmis/index</url>
<url>/cmis/index.html</url>
<format default="html"/>
<authentication>none</authentication>
<family>CMIS</family>
</webscript>

View File

@@ -0,0 +1,153 @@
[#ftl]
[#import "/org/alfresco/cmis/links.lib.atom.ftl" as linksLib/]
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Alfresco CMIS</title>
<link rel="stylesheet" href="${url.context}/css-boilerplate/screen.css" type="text/css" media="screen" charset="utf-8">
<!--[if lte IE 6]><link rel="stylesheet" href="${url.context}/css-boilerplate/lib/ie.css" type="text/css" media="screen" charset="utf-8"><![endif]-->
<script type="text/javascript">
function toggleDisplay(toggle)
{
var toggleBody = document.getElementById(toggle.id + "_body");
if (!toggleBody) return true;
if (toggleBody.style.display == "none")
{
toggleBody.style.display = "block";
toggle.innerHTML = "[-]";
}
else
{
toggleBody.style.display = "none";
toggle.innerHTML = "[+]";
}
return true;
}
</script>
</head>
<body>
<div id="page">
<div id="header">
<a href="http://www.alfresco.com"><img id="alflogo" src="${url.context}/images/logo/AlfrescoLogo200.png"/></a><a href="http://www.oasis-open.org/committees/cmis"><img id="alflogo" height="55px" src="${url.context}/images/logo/cmis_logo_100.png"/></a>
</div>
<div id="body" class="wrapper">
<div id="introduction">
<h2>Explore and Test CMIS</h2>
<p>The CMIS (Content Management Interoperability Services) specification is now very close to Public Review.</p>
<p>This site hosts a <a href="#repo">CMIS Repository</a> and <a href="#testatompub">CMIS AtomPub TCK</a> to assist the development of the specification and promote interoperability between up-and-coming implementations. Feel free to use them for building and testing your own CMIS clients and servers.</p>
<p>Frequent updates are made to both the Repository and TCK as issues are resolved or new capabilities added. Currently, <strong class="highlight">version ${cmisVersion}</strong> of the CMIS specification is supported.</p>
<a name="repo"></a>
<h3>Alfresco CMIS Repository</h3>
<p>Point your CMIS client to one of the following Alfresco CMIS bindings (with <strong>user=admin</strong> and <strong>password=admin</strong>).</p>
<ul>
<li>CMIS AtomPub Binding: <a href="${url.serviceContext}/cmis">AtomPub Service Document</a></li>
<li>CMIS Web Services Binding: <a href="${url.context}/cmis">WSDL Documents</a></li>
</ul>
<p>You can also browse this repository via the <a href="${url.context}/cmisbrowse?url=${absurl(url.serviceContext)}/cmis">CMIS FileShare browser</a>.</p>
<h5><span id="repoinfo" class="toggle" onclick="return toggleDisplay(this)">[+]</span> CMIS Repository Information</h5>
<table id="repoinfo_body" style="display: none;">
<tr><td>Version Supported</td><td>${cmisVersion}</td></tr>
<tr><td>Repository Id</td><td>${server.id}</td></tr>
<tr><td>Repository Name</td><td>${server.name}</td></tr>
<tr><td>Repository Description</td><td>[none]</td></tr>
<tr><td>Vendor Name</td><td>Alfresco</td></tr>
<tr><td>Product Name</td><td>Alfresco Repository (${server.edition})</td></tr>
<tr><td>Product Version</td><td>${server.version}</td></tr>
</table>
<h5><span id="repocapabilities" class="toggle" onclick="return toggleDisplay(this)">[+]</span> CMIS Repository Capabilities</h5>
<table id="repocapabilities_body" style="display: none;">
<tr><td>ACL</td><td>none</td></tr>
<tr><td>AllVersionsSearchable</td><td>${allVersionsSearchable?string}</td></tr>
<tr><td>Changes</td><td>[#-- TODO --]none</td></tr>
<tr><td>ContentStreamUpdatability</td><td>anytime</td></tr>
<tr><td>GetDescendants</td><td>true</td></tr>
<tr><td>GetFolderTree</td><td>true</td></tr>
<tr><td>Multifiling</td><td>true</td></tr>
<tr><td>PWCSearchable</td><td>${pwcSearchable?string}</td></tr>
<tr><td>PWCUpdateable</td><td>true</td></tr>
<tr><td>Query</td><td>${querySupport}</td></tr>
<tr><td>Join</td><td>${joinSupport}</td></tr>
<tr><td>Renditions</td><td>none</td></tr>
<tr><td>Unfiling</td><td>false</td></tr>
<tr><td>VersionSpecificFiling</td><td>false</td></tr>
</table>
<p><em>Note: The contents of this repository may be cleaned at any time.</em><p>
<a name="testatompub"></a>
<h3>CMIS AtomPub TCK</h3>
<p>Point the TCK (Test Compatibility Kit) at your CMIS Repository AtomPub Service Document. Provide credentials (or leave blank, if authentication not required) and adjust options as necessary. Hit the '<strong>Start TCK</strong>' button for a test report.</p>
<p><em>Tip: Enable the 'Trace Reqs/Responses' option for examples of conversations with a CMIS Repository via AtomPub.</em></p>
<p><em>Note: This TCK is now contributed to <a href="http://incubator.apache.org/chemistry/">Apache Chemistry</a>.</em></p>
<form action="${url.serviceContext}/cmis/test" method="post" class="hform">
<fieldset>
<legend>CMIS Repository</legend>
<p><label>Service Document</label><input type="text" name="chemistry.tck.serviceUrl" size="50" value="${absurl(url.serviceContext)}/cmis"></p>
<p><label>Username</label><input type="text" name="chemistry.tck.user" value="admin"></p>
<p><label>Password</label><input type="text" name="chemistry.tck.password" value="admin"></p>
</fieldset>
<fieldset>
<legend>Options</legend>
<p class="checkbox"><label>Validate Responses</label><input type="checkbox" name="chemistry.tck.validate" value="true"[#if tckOptions.validate] checked="checked"[/#if]></p>
<p class="checkbox"><label>Fail on Validation Error</label><input type="checkbox" name="chemistry.tck.failOnValidationError" value="true"[#if tckOptions.failOnValidationError] checked="checked"[/#if]></p>
<p class="checkbox"><label>Trace Reqs/Responses</label><input type="checkbox" name="chemistry.tck.traceRequests" value="true"[#if tckOptions.traceRequests] checked="checked"[/#if]><p>
<p><label>Tests</label><input name="chemistry.tck.tests" value="RepositoryServiceTest.testRepository"></p>
<p><label><span id="availtests" class="toggle" onclick="return toggleDisplay(this)">[+]</span> Available Tests</label>
<table id="availtests_body" style="display: none;">
<tr><td>Note: Use wildcard * to execute multiple tests</td></tr>
[#list tckTests as test]<tr><td>${test}</td></tr>[/#list]
</table></p>
</fieldset>
<p><input type="submit" name="submit" value="Start TCK" class="button"></p>
</form>
</div>
<div id="resources">
<h3>CMIS Resources</h3>
<ul>
<li><a href="http://www.oasis-open.org/committees/cmis">OASIS Technical Committee</a></li>
<li><a href="http://xml.coverpages.org/cmis.html">Cover Pages</a></li>
<li><a href="http://www.oasis-open.org/committees/download.php/34413/CMIS-70b3.zip"><strong>Specification v0.7</strong></a></li>
</ul>
<h3>Alfresco Resources</h3>
<ul>
<li><a href="http://wiki.alfresco.com/wiki/CMIS">CMIS Wiki</a></li>
<li><a href="http://blogs.alfresco.com/cmis/">CMIS Blog</a></li>
<li><a href="http://wiki.alfresco.com/wiki/Download_Community_Edition">Download</a> Repository</a></li>
<li><a href="http://wiki.alfresco.com/wiki/Alfresco_SVN_Development_Environment">Source Code</a> for Repository</li>
<li><a href="http://svn.alfresco.com/repos/alfresco-open-mirror/alfresco/HEAD/root/design/changes_v0.62f_to_v0.7.txt">Changes from v0.62 to v0.7</li>
</ul>
<h3>Apache Chemistry</h3>
<ul>
<li><a href="http://incubator.apache.org/chemistry/">Home Page</a></li>
<li><a href="http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/">Source Code</a> for TCK</li>
</ul>
<h3>CMIS FileShare</h3>
<ul>
<li><a href="http://cmisfs.fmui.de/">Home Page</a></li>
</ul>
<h3>Provide Feedback</h3>
<ul>
<li><a href="http://forums.alfresco.com/en/viewforum.php?f=45">CMIS Forum</a></li>
<li><a href="https://issues.alfresco.com/jira/secure/IssueNavigator.jspa?reset=true&mode=hide&pid=10103&sorter/order=DESC&sorter/field=priority&resolution=-1&component=10459">Find / Raise Issues</li>
<li><a href="http://groups.google.com/group/cmis-interop">CMIS Interop Group</a></li>
</ul>
</div>
</div>
<div id="footer">
<p>Last Updated: $Date: 2009-10-16 23:17:08 +0100 (Fri, 16 Oct 2009) $, Alfresco Software, Inc</p>
</div>
</div>
</body>
</html>

View File

@@ -1,6 +1,7 @@
var tckRunner = Packages.org.apache.chemistry.tck.atompub.tools.TCKRunner();
model.tckTests = tckRunner.getTestNames();
model.tckOptions = tckRunner.getOptions();
model.cmisVersion = cmis.version;
model.defaultRootFolder = cmis.defaultRootFolder;
model.defaultRootFolderPath = cmis.defaultRootFolderPath;
model.querySupport = cmis.querySupport.label;
model.joinSupport = cmis.joinSupport.label;
model.pwcSearchable = cmis.pwcSearchable;

View File

@@ -6,7 +6,7 @@
[#-- Link to repository service document --]
[#macro linkservice]
<link rel="${cmisconstants.REL_SERVICE}" href="${absurl(url.serviceContext)}/api/repository"/>
<link rel="${cmisconstants.REL_SERVICE}" href="${absurl(url.serviceContext)}/cmis"/>
[/#macro]
[#-- Link to node allowable actions --]
@@ -111,7 +111,7 @@
[/#macro]
[#macro linkassocedit assoc]
<link rel="edit" href="${absurl(url.serviceContext)}[@nodeuri node/]"/>
<link rel="edit" href="${absurl(url.serviceContext)}[@assocuri assoc/]"/>
[/#macro]
[#-- Link to via --]
@@ -125,19 +125,22 @@
[#-- --]
[#-- Helper to render Alfresco service document uri --]
[#macro serviceuri]${absurl(url.serviceContext)}/api/repository[/#macro]
[#macro serviceuri]${absurl(url.serviceContext)}/cmis[/#macro]
[#-- Helper to render Alfresco content stream uri --]
[#macro contenturi node]${absurl(url.serviceContext)}/api/node/${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}/content[#if node.properties.name?? && node.properties.name?last_index_of(".") != -1]${encodeuri(node.properties.name?substring(node.properties.name?last_index_of(".")))}[/#if][/#macro]
[#macro contenturi node]${absurl(url.serviceContext)}/cmis/[@noderef node/]/content[#if node.properties.name?? && node.properties.name?last_index_of(".") != -1]${encodeuri(node.properties.name?substring(node.properties.name?last_index_of(".")))}[/#if][/#macro]
[#-- Helper to render Store Ref --]
[#macro storeref store]s/${store.protocol}:${store.identifier}[/#macro]
[#-- Helper to render Node Ref --]
[#macro noderef node]${node.nodeRef.storeRef.protocol}/${node.nodeRef.storeRef.identifier}/${node.nodeRef.id}[/#macro]
[#macro noderef node][@storeref node.nodeRef.storeRef/]/i/${node.nodeRef.id}[/#macro]
[#-- Helper to render Alfresco Node uri --]
[#macro nodeuri node]/api/node/[@noderef node/][/#macro]
[#macro nodeuri node]/cmis/[@noderef node/][/#macro]
[#-- Helper to render Alfresco Assoc uri --]
[#macro assocuri assoc]/api/rel/[@noderef assoc.source/]/type/${cmistype(assoc).typeId.id!"undefined"}/target/[@noderef assoc.target/][/#macro]
[#macro assocuri assoc]/cmis/rel/[@noderef assoc.source/]/type/${cmistype(assoc).typeId.id!"undefined"}/target/[@noderef assoc.target/][/#macro]
[#-- Helper to render Alfresco Type uri --]
[#macro typeuri typedef]/api/type/${typedef.typeId.id}[/#macro]
[#macro typeuri typedef]/cmis/type/${typedef.typeId.id}[/#macro]

View File

@@ -23,6 +23,7 @@ function createNode(parent, entry, slug)
}
// construct node of folder or file
var node = null;
var name = (slug !== null) ? slug : entry.title;
var baseType = type.typeId.baseTypeId;
if (baseType == DOCUMENT_TYPE_ID)

View File

@@ -0,0 +1,62 @@
//
// Get Node from URL
//
// @return node (or null, if not found)
function getObjectFromUrl()
{
var ret = new Object();
ret.ref = cmis.createObjectReferenceFromUrl(args, url.templateArgs);
if (ret.ref == null)
{
status.setCode(400, "Cannot determine object reference from URL");
return ret;
}
ret.node = cmis.getNode(ret.ref);
if (ret.node === null)
{
status.setCode(404, "Cannot find object for " + ret.ref.toString());
}
return ret;
}
//
// Get Node from Object Id
//
// @return node (or null, if not found)
function getObjectFromObjectId(objectId)
{
var ret = new Object();
ret.ref = cmis.createObjectIdReference(objectId);
if (ret.ref == null)
{
status.setCode(400, "Cannot create object id reference from " + objectId);
return ret;
}
ret.node = cmis.getNode(ret.ref);
if (ret.node === null)
{
status.setCode(404, "Cannot find object for " + ret.ref.toString());
}
return ret;
}
//
// Get Association from URL
//
// @return association (or null, if not found)
function getAssocFromUrl()
{
var ret = new Object();
ret.ref = cmis.createRelationshipReferenceFromUrl(args, url.templateArgs);
if (ret.ref == null)
{
status.setCode(400, "Cannot determine association reference from URL");
return ret;
}
ret.assoc = cmis.getAssociation(ret.ref);
if (ret.assoc === null)
{
status.setCode(404, "Cannot find association for " + ret.ref.toString());
}
return ret;
}

View File

@@ -13,7 +13,7 @@ boolean trace: true => trace request and response bodies
String tests: names of tests to execute (use * in test name to represent wildcard) (Default: *)<br>
]]>
</description>
<url>/api/cmis/test?url={serviceUrl}&amp;user={user?}&amp;validate={validate?}&amp;trace={trace?}&amp;tests={tests?}</url>
<url>/cmis/test?url={serviceUrl}&amp;user={user?}&amp;validate={validate?}&amp;trace={trace?}&amp;tests={tests?}</url>
<authentication>none</authentication>
<format default="text"/>
<family>CMIS</family>

View File

@@ -1,39 +0,0 @@
<webscript>
<shortname>Repository AtomPub Service Document (getRepositoryInfo)</shortname>
<description>
<![CDATA[
This service is used to retrieve information about the CMIS repository and the capabilities it supports.
<br>
<br>
Outputs:<br>
<br>
ID repositoryId: Repository Id (same as input)<br>
String repositoryName: Repository name<br>
URI repositoryURI: URI for this repository<br>
String repositoryDescription: Description of this repository<br>
ID rootFolderId: Root folder Id<br>
String vendorName: Repository vendor name<br>
String productName: Repository product name<br>
String productVersion: Product Version Information<br>
String cmisVersionsSupported: Version of CMIS standard supported.<br>
XML repositorySpecificInformation: Repository-specific information<br>
<br>
Capabilities:<br>
<br>
boolean capabilityMultifiling<br>
boolean capabilitiyUnfiling<br>
Boolean capabilityVersionSpecificFiling<br>
Boolean capabilityPWCUpdatable<br>
Boolean capabilityAllVersionsSearchable<br>
Boolean capabilityPWCSearchable<br>
Enum capabilityJoin: nojoin, inneronly, innerAndouter<br>
Enum capabilityFulltext: nofulltext, fulltextonly, fulltextandstructured<br>
&lt;Array&gt; relatedRepositories
]]>
</description>
<url>/api/repository</url>
<url>/api/cmis</url>
<format default="atomsvc"/>
<authentication>user</authentication>
<family>CMIS</family>
</webscript>

View File

@@ -66,7 +66,7 @@ script:
}
// construct query uri
model.queryUri = "/api/query";
model.queryUri = "/cmis/query";
model.queryArgs = cmis.ARG_QUERY_STATEMENT + "=" + model.statement;
if (model.includeAllowableActions) model.queryArgs += "&" + cmis.ARG_INCLUDE_ALLOWABLE_ACTIONS + "=true";
model.queryArgs += "&" + cmis.ARG_SKIP_COUNT + "=" + page.number;

View File

@@ -29,7 +29,7 @@ It is recommended that “includeAllowableActions” be used with query statemen
"IncludeRelationships" indicates whether relationships are also returned for each returned object. If it is set to "source" or "target", relationships for which the returned object is a source, or respectively a target, will also be returned. If it is set to "both", relationships for which the returned object is either a source or a target will be returned. If it is set to "none", relationships are not returned.<br>
]]>
</description>
<url>/api/queries</url>
<url>/cmis/queries</url>
<authentication>user</authentication>
<transaction allow="readonly"/>
<format default="atomfeed"/>

View File

@@ -29,7 +29,7 @@ It is recommended that “includeAllowableActions” be used with query statemen
"IncludeRelationships" indicates whether relationships are also returned for each returned object. If it is set to "source" or "target", relationships for which the returned object is a source, or respectively a target, will also be returned. If it is set to "both", relationships for which the returned object is either a source or a target will be returned. If it is set to "none", relationships are not returned.<br>
]]>
</description>
<url>/api/query?q={q}&amp;includeAllowableActions={includeAllowableActions?}&amp;searchAllVersions={searchAllVersions?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}</url>
<url>/cmis/query?q={q}&amp;includeAllowableActions={includeAllowableActions?}&amp;searchAllVersions={searchAllVersions?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}</url>
<authentication>user</authentication>
<transaction allow="readonly"/>
<format default="atomfeed"/>

View File

@@ -1,8 +1,15 @@
<webscript>
<shortname>Retrieve Allowable Actions</shortname>
<description>Retrieve Allowable Actions</description>
<!-- by object id -->
<url>/cmis/i/{id}/allowableactions</url>
<url>/cmis/s/{store}/i/{id}/allowableactions</url>
<!-- by path -->
<url>/cmis/p{path}/allowableactions</url>
<url>/cmis/s/{store}/p{path}/allowableactions</url>
<!-- old style; backwards compatibility -->
<url>/api/node/{store_type}/{store_id}/{id}/allowableactions</url>
<url>/api/path/{store_type}/{store_id}/{id}/allowableactions</url>
<url>/api/path/{store_type}/{store_id}/{path}/allowableactions</url>
<authentication>guest</authentication>
<transaction allow="readonly"/>
<format default="cmisallowableactions">argument</format>

View File

@@ -1,14 +1,15 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
script:
{
// locate node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
model.node = cmis.findNode(pathSegments[2], reference);
if (model.node === null)
var object = getObjectFromUrl();
if (object.node == null)
{
break script
}
model.node = object.node;
if (model.node == null)
{
status.code = 404;
status.message = "Repository " + pathSegments[2] + " " + reference.join("/") + " not found";
status.redirect = true;
break script;
}

View File

@@ -28,7 +28,7 @@ If “includeAllowableActions” is TRUE, the repository will return the allowab
If no “maxItems” value is provided, then the Repository will determine an appropriate number of items to return. How the Repository determines this value is repository-specific and opaque to CMIS.<br>
]]>
</description>
<url>/api/checkedout?folderId={folderId?}&amp;includeDescendants={includeDescendants?}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/cmis/checkedout?folderId={folderId?}&amp;includeDescendants={includeDescendants?}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<authentication>user</authentication>
<transaction allow="readonly"/>
<format default="atomfeed"/>

View File

@@ -1,3 +1,5 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
script:
{
// locate (optional) folder
@@ -5,18 +7,16 @@ script:
var folderId = args[cmis.ARG_FOLDER_ID];
if (folderId !== null)
{
model.folder = cmis.findNode(folderId);
if (model.folder === null)
var folder = getObjectFromObjectId(folderId);
if (folder.node === null)
{
status.code = 400;
status.message = "Folder " + folderId + " not found";
status.redirect = true;
break script;
}
model.folder = folder.node;
if (!model.folder.isContainer)
{
status.code = 400;
status.message = "Folder id " + folderId + " does not refer to a folder";
status.message = "Folder id " + folder.ref + " does not refer to a folder";
status.redirect = true;
break script;
}

View File

@@ -1,3 +1,5 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
script:
{
// ensure atom entry is posted
@@ -21,20 +23,18 @@ script:
}
// locate node
model.node = cmis.findNode(objectId);
if (model.node === null)
var object = getObjectFromObjectId(objectId);
if (object.node === null)
{
status.code = 400;
status.message = "Repository node " + objectId + " not found";
status.redirect = true;
break script;
}
model.node = object.node;
// ensure node can be checked-out
if (!model.node.isDocument)
{
status.code = 400;
status.message = "Cannot checkout node " + objectId + " as it is not a document";
status.message = "Cannot checkout node " + object.ref + " as it is not a document";
status.redirect = true;
break script;
}
@@ -43,7 +43,7 @@ script:
if (model.node.isLocked || model.node.hasAspect("cm:workingCopy"))
{
status.code = 400;
status.message = "Cannot checkout node " + objectId + " as it is already checked-out";
status.message = "Cannot checkout node " + object.ref + " as it is already checked-out";
status.redirect = true;
break script;
}
@@ -61,6 +61,6 @@ script:
// setup for 201 Created response
// TODO: set Content-Location
status.code = 201;
status.location = url.server + url.serviceContext + "/api/pwc/" + model.pwc.nodeRef.storeRef.protocol + "/" + model.pwc.nodeRef.storeRef.identifier + "/" + model.pwc.nodeRef.id;
status.location = url.server + url.serviceContext + "/cmis/pwc/s/" + model.pwc.nodeRef.storeRef.protocol + ":" + model.pwc.nodeRef.storeRef.identifier + "/i/" + model.pwc.nodeRef.id;
status.redirect = true;
}

View File

@@ -23,7 +23,7 @@ CheckOut() on a non-document object will throw OperationNotSupportedException.<b
Some repositories may not support updating of private working copies and the updates MUST be supplied via checkIn().<br>
]]>
</description>
<url>/api/checkedout</url>
<url>/cmis/checkedout</url>
<authentication>user</authentication>
<format default="atomentry"/>
<family>CMIS</family>

View File

@@ -34,8 +34,17 @@ If “includeAllowableActions” is TRUE, the repository will return the allowab
If no “maxItems” value is provided, then the Repository will determine an appropriate number of items to return. How the Repository determines this value is repository-specific and opaque to CMIS.<br>
]]>
</description>
<!-- by object id -->
<url>/cmis/i/{id}/children?types={types}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/cmis/s/{store}/i/{id}/children?types={types}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<!-- by path -->
<url>/cmis/p{path}/children?types={types}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/cmis/s/{store}/p{path}/children?types={types}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}</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?}</url>
<url>/api/path/{store_type}/{store_id}/{id}/children?types={types}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/api/path/{store_type}/{store_id}/{path}/children?types={types}&amp;filter={filter?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<authentication>guest</authentication>
<transaction allow="readonly"/>
<format default="atomfeed">argument</format>

View File

@@ -1,16 +1,14 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
script:
{
// locate node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
model.node = cmis.findNode(pathSegments[2], reference);
if (model.node === null)
var object = getObjectFromUrl();
if (object.node == null)
{
status.code = 404;
status.message = "Repository " + pathSegments[2] + " " + reference.join("/") + " not found";
status.redirect = true;
break script;
}
model.node = object.node;
// handle filters
model.types = args[cmis.ARG_TYPES] === null ? cmis.defaultTypesFilter : args[cmis.ARG_TYPES];

View File

@@ -1,5 +1,6 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/constants.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/atomentry.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/modify.lib.js">
script:
{
@@ -13,16 +14,12 @@ script:
}
// locate parent node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
model.parent = cmis.findNode(pathSegments[2], reference);
if (model.parent === null)
var parent = getObjectFromUrl();
if (parent.node == null)
{
status.code = 404;
status.message = "Repository " + pathSegments[2] + " " + reference.join("/") + " not found";
status.redirect = true;
break script;
}
model.parent = parent.node;
// is this a create or move?
var object = entry.getExtension(atom.names.cmisra_object);
@@ -41,40 +38,45 @@ script:
}
else
{
// locate node and its source folder
var object = getObjectFromObjectId(objectId);
if (object.node == null)
{
break script;
}
node = object.node;
// move node
var sourceFolderId = args[cmis.ARG_SOURCE_FOLDER_ID];
if (sourceFolderId == null)
{
status.code = 400;
status.message = "Move of object " + objectId + " requires sourceFolderId argument";
status.message = "Move of object " + object.ref + " requires sourceFolderId argument";
status.redirect = true;
break script;
}
// locate node and its source folder
node = search.findNode(objectId);
if (node == null)
var sourceFolderObject = getObjectFromObjectId(sourceFolderId);
if (sourceFolderObject.node == null)
{
status.code = 400;
status.message = "Object " + objectId + " does not exist";
status.redirect = true;
break script;
}
sourceFolder = search.findNode(sourceFolderId);
if (sourceFolder == null || !(sourceFolder.nodeRef.equals(node.parent.nodeRef)))
{
status.code = 400;
status.message = "Source Folder " + sourceFolderId + " is not valid for object " + objectId;
break script;
}
if (!sourceFolderObject.node.nodeRef.equals(node.parent.nodeRef))
{
status.code = 400;
status.message = "Source Folder " + sourceFolderObject.ref + " is not parent of object " + object.ref;
status.redirect = true;
break script;
}
var sourceFolder = sourceFolderObject.node;
// perform move
var success = node.move(model.parent);
if (!success)
{
status.code = 500;
status.message = "Failed to move object " + objectId + " from folder " + sourceFolderId + " to folder " + model.parent.nodeRef;
status.message = "Failed to move object " + object.ref + " from folder " + sourceFolderObject.ref + " to folder " + parent.ref;
status.redirect = true;
break script;
}
@@ -85,6 +87,6 @@ script:
model.node = node;
// TODO: set Content-Location
status.code = 201;
status.location = url.server + url.serviceContext + "/api/node/" + node.nodeRef.storeRef.protocol + "/" + node.nodeRef.storeRef.identifier + "/" + node.nodeRef.id;
status.location = url.server + url.serviceContext + "/cmis/s/" + node.nodeRef.storeRef.protocol + ":" + node.nodeRef.storeRef.identifier + "/i/" + node.nodeRef.id;
status.redirect = true;
}

View File

@@ -41,8 +41,16 @@ If the to-be-created Folders Object Type is not one of the “Allowed_Child_O
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>
<!-- by path -->
<url>/cmis/p{path}/children?sourceFolderId={sourceFolderId}</url>
<url>/cmis/s/{store}/p{path}/children?sourceFolderId={sourceFolderId}</url>
<!-- alfresco style -->
<url>/api/node/{store_type}/{store_id}/{id}/children?sourceFolderId={sourceFolderId}</url>
<url>/api/path/{store_type}/{store_id}/{id}/children?sourceFolderId={sourceFolderId}</url>
<url>/api/path/{store_type}/{store_id}/{path}/children?sourceFolderId={sourceFolderId}</url>
<authentication>user</authentication>
<format default="atomentry"/>
<family>CMIS</family>

View File

@@ -2,11 +2,20 @@
<shortname>Content Delete (deleteContent)</shortname>
<description>
</description>
<!-- by object id -->
<url>/cmis/i/{id}/content{property}</url>
<url>/cmis/s/{store}/i/{id}/content{property}</url>
<!-- by path -->
<url>/cmis/p{path}/content{property}</url>
<url>/cmis/s/{store}/p{path}/content{property}</url>
<url>/api/node/content{property}/{store_type}/{store_id}/{id}</url>
<url>/api/path/content{property}/{store_type}/{store_id}/{id}</url>
<url>/api/avmpath/content{property}/{store_id}/{id}</url>
<url>/api/node/{store_type}/{store_id}/{id}/content{property}</url>
<url>/api/path/{store_type}/{store_id}/{id}/content{property}</url>
<authentication>guest</authentication>
<format default="atomentry">argument</format>
<family>CMIS</family>

View File

@@ -1,16 +1,14 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
script:
{
// locate node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
var node = cmis.findNode(pathSegments[2], reference);
if (node === null)
var object = getObjectFromUrl();
if (object.node == null)
{
status.code = 404;
status.message = "Repository " + pathSegments[2] + " " + reference.join("/") + " not found";
status.redirect = true;
break script;
}
node = object.node;
if (!node.hasPermission("Delete"))
{

View File

@@ -20,11 +20,21 @@ Some CMIS protocol bindings MAY choose not to explicitly implement a “getConte
Each CMIS protocol binding will provide a way for fetching a sub-range within a content stream, in a manner appropriate to that protocol.<br>
]]>
</description>
<!-- by object id -->
<url>/cmis/i/{id}/content{property}?a={attach?}</url>
<url>/cmis/s/{store}/i/{id}/content{property}?a={attach?}</url>
<!-- by path -->
<url>/cmis/p{path}/content{property}?a={attach?}</url>
<url>/cmis/s/{store}/p{path}/content{property}?a={attach?}</url>
<!-- alfresco style -->
<url>/api/node/content{property}/{store_type}/{store_id}/{id}?a={attach?}</url>
<url>/api/path/content{property}/{store_type}/{store_id}/{id}?a={attach?}</url>
<url>/api/avmpath/content{property}/{store_id}/{id}?a={attach?}</url>
<url>/api/path/content{property}/{store_type}/{store_id}/{path}?a={attach?}</url>
<url>/api/avmpath/content{property}/{store_id}/{avmpath}?a={attach?}</url>
<url>/api/node/{store_type}/{store_id}/{id}/content{property}?a={attach?}</url>
<url>/api/path/{store_type}/{store_id}/{id}/content{property}?a={attach?}</url>
<url>/api/path/{store_type}/{store_id}/{path}/content{property}?a={attach?}</url>
<authentication>guest</authentication>
<transaction allow="readonly"/>
<format default="">argument</format>

View File

@@ -1,11 +1,21 @@
<webscript>
<shortname>Content Write (setContent)</shortname>
<description>TODO</description>
<!-- by object id -->
<url>/cmis/i/{id}/content{property}?overwriteFlag={overwriteFlag?}</url>
<url>/cmis/s/{store}/i/{id}/content{property}?overwriteFlag={overwriteFlag?}</url>
<!-- by path -->
<url>/cmis/p{path}/content{property}?overwriteFlag={overwriteFlag?}</url>
<url>/cmis/s/{store}/p{path}/content{property}?overwriteFlag={overwriteFlag?}</url>
<!-- alfresco style -->
<url>/api/node/content{property}/{store_type}/{store_id}/{id}?overwriteFlag={overwriteFlag?}</url>
<url>/api/path/content{property}/{store_type}/{store_id}/{id}?overwriteFlag={overwriteFlag?}</url>
<url>/api/avmpath/content{property}/{store_id}/{id}?overwriteFlag={overwriteFlag?}</url>
<url>/api/node/{store_type}/{store_id}/{id}/content{property}?overwriteFlag={overwriteFlag?}</url>
<url>/api/path/{store_type}/{store_id}/{id}/content{property}?overwriteFlag={overwriteFlag?}</url>
<authentication>guest</authentication>
<format default="text">argument</format>
<family>CMIS</family>

View File

@@ -29,8 +29,17 @@ Does not specify the order in which delete will happen<br>
o However, any objects that are not deleted (e.g. because a previous object failed to delete), they MUST remain valid CMIS objects (including any applicable filing constraint for each object).<br>
]]>
</description>
<!-- by object id -->
<url>/cmis/i/{id}/descendants?continueOnFailure={continueOnFailure?}&amp;unfileMultiFiledDocuments={unfileMultiFiledDocuments}</url>
<url>/cmis/s/{store}/i/{id}/descendants?continueOnFailure={continueOnFailure?}&amp;unfileMultiFiledDocuments={unfileMultiFiledDocuments}</url>
<!-- by path -->
<url>/cmis/p{path}/descendants?continueOnFailure={continueOnFailure?}&amp;unfileMultiFiledDocuments={unfileMultiFiledDocuments}</url>
<url>/cmis/s/{store}/p{path}/descendants?continueOnFailure={continueOnFailure?}&amp;unfileMultiFiledDocuments={unfileMultiFiledDocuments}</url>
<!-- alfresco style -->
<url>/api/node/{store_type}/{store_id}/{id}/descendants?continueOnFailure={continueOnFailure?}&amp;unfileMultiFiledDocuments={unfileMultiFiledDocuments}</url>
<url>/api/path/{store_type}/{store_id}/{id}/descendants?continueOnFailure={continueOnFailure?}&amp;unfileMultiFiledDocuments={unfileMultiFiledDocuments}</url>
<url>/api/path/{store_type}/{store_id}/{path}/descendants?continueOnFailure={continueOnFailure?}&amp;unfileMultiFiledDocuments={unfileMultiFiledDocuments}</url>
<authentication>user</authentication>
<format default="atomfeed"/>
<family>CMIS</family>

View File

@@ -1,16 +1,14 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
script:
{
// locate node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
var node = cmis.findNode(pathSegments[2], reference);
if (node === null)
var object = getObjectFromUrl();
if (object.node == null)
{
status.code = 404;
status.message = "Repository " + pathSegments[2] + " " + reference.join("/") + " not found";
status.redirect = true;
break script;
}
var node = object.node;
// NOTE: Ignore continueOnDelete as complete tree is deleted in single transaction
// TODO: Throw error on invalid unfileMultiFiledDocuments error
@@ -28,7 +26,7 @@ script:
if (!node.remove())
{
status.code = 500;
status.message = "Failed to delete node " + pathSegments[2] + " " + reference.join("/");
status.message = "Failed to delete object " + object.ref;
status.redirect = true;
break script;
}

View File

@@ -32,8 +32,17 @@ When returning the results of a call where the caller specified “Any” type,
If “includeAllowableActions” is TRUE, the repository will return the allowable actions for the current user for each descendant object as part of the output.<br>
"IncludeRelationships" indicates whether relationships are also returned for each returned object. If it is set to "source" or "target", relationships for which the returned object is a source, or respectively a target, will also be returned. If it is set to "both", relationships for which the returned object is either a source or a target will be returned. If it is set to "none", relationships are not returned.]]>
</description>
<!-- by object id -->
<url>/cmis/i/{id}/descendants?types={types}&amp;filter={filter?}&amp;depth={depth?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/cmis/s/{store}/i/{id}/descendants?types={types}&amp;filter={filter?}&amp;depth={depth?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<!-- by path -->
<url>/cmis/p{path}/descendants?types={types}&amp;filter={filter?}&amp;depth={depth?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/cmis/s/{store}/p{path}/descendants?types={types}&amp;filter={filter?}&amp;depth={depth?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<!-- alfresco style -->
<url>/api/node/{store_type}/{store_id}/{id}/descendants?types={types}&amp;filter={filter?}&amp;depth={depth?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/api/path/{store_type}/{store_id}/{id}/descendants?types={types}&amp;filter={filter?}&amp;depth={depth?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/api/path/{store_type}/{store_id}/{path}/descendants?types={types}&amp;filter={filter?}&amp;depth={depth?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<authentication>guest</authentication>
<transaction allow="readonly"/>
<format default="atomfeed">argument</format>

View File

@@ -1,16 +1,13 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
script:
{
// locate node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
model.node = cmis.findNode(pathSegments[2], reference);
if (model.node === null)
var object = getObjectFromUrl();
if (object.node == null)
{
status.code = 404;
status.message = "Repository " + pathSegments[2] + " " + reference.join("/") + " not found";
status.redirect = true;
break script;
}
model.node = object.node;
// handle filters
model.types = args[cmis.ARG_TYPES] === null ? cmis.defaultTypesFilter : args[ARG_TYPES];

View File

@@ -17,8 +17,17 @@ This service deletes a specific version of a document object. To delete all ver
Deletion of a private working copy (checked out version) is the same as to cancel checkout.<br>
]]>
</description>
<!-- by object id -->
<url>/cmis/i/{id}?includeChildren={includeChildren?}</url>
<url>/cmis/s/{store}/i/{id}?includeChildren={includeChildren?}</url>
<!-- by path -->
<url>/cmis/p{path}?includeChildren={includeChildren?}</url>
<url>/cmis/s/{store}/p{path}?includeChildren={includeChildren?}</url>
<!-- alfresco style -->
<url>/api/node/{store_type}/{store_id}/{id}?includeChildren={includeChildren?}</url>
<url>/api/path/{store_type}/{store_id}/{id}?includeChildren={includeChildren?}</url>
<url>/api/path/{store_type}/{store_id}/{path}?includeChildren={includeChildren?}</url>
<authentication>user</authentication>
<format default="atomentry"/>
<family>CMIS</family>

View File

@@ -1,21 +1,19 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
script:
{
// locate node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
var node = cmis.findNode(pathSegments[2], reference);
if (node === null)
var object = getObjectFromUrl();
if (object.node == null)
{
status.code = 404;
status.message = "Repository " + pathSegments[2] + " " + reference.join("/") + " not found";
status.redirect = true;
break script;
}
var node = object.node;
if (!node.hasPermission("Delete"))
{
status.code = 403;
status.message = "Permission to delete is denied";
status.message = "Permission to delete object " + object.ref + " is denied";
status.redirect = true;
break script;
}
@@ -28,7 +26,7 @@ script:
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.message = "Cannot delete folder " + object.ref + " as it's not empty";
status.redirect = true;
break script;
}
@@ -38,7 +36,7 @@ script:
if (!node.remove())
{
status.code = 500;
status.message = "Failed to delete node " + pathSegments[2] + " " + reference.join("/");
status.message = "Failed to delete object " + object.ref;
status.redirect = true;
break script;
}

View File

@@ -26,9 +26,23 @@ 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?}</url>
<url>/cmis/s/{store}/i/{id}?filter={filter?}&amp;returnVersion={returnVersion?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<!-- by object path -->
<url>/cmis/p{path}?filter={filter?}&amp;returnVersion={returnVersion?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/cmis/s/{store}/p{path}?filter={filter?}&amp;returnVersion={returnVersion?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<!-- for CMIS URI template generators -->
<url>/cmis/s/{store}/arg/i?id={id}&amp;filter={filter?}&amp;returnVersion={returnVersion?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/cmis/s/{store}/arg/p?path={path}&amp;filter={filter?}&amp;returnVersion={returnVersion?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/cmis/arg/n?noderef={noderef}&amp;filter={filter?}&amp;returnVersion={returnVersion?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<!-- alfresco style -->
<url>/api/node/{store_type}/{store_id}/{id}?filter={filter?}&amp;returnVersion={returnVersion?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/api/path/{store_type}/{store_id}/{id}?filter={filter?}&amp;returnVersion={returnVersion?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<!-- TODO: consider /api/node/{store_type}/{store_id}/{id}/{child_node} for atom relative paths -->
<url>/api/path/{store_type}/{store_id}/{path}?filter={filter?}&amp;returnVersion={returnVersion?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<authentication>guest</authentication>
<transaction allow="readonly"/>
<format default="atomentry">argument</format>

View File

@@ -1,22 +1,19 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
script:
{
// locate node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
model.node = cmis.findNode(pathSegments[2], reference);
if (model.node === null)
var object = getObjectFromUrl();
if (object.node === null)
{
status.code = 404;
status.message = "Repository " + pathSegments[2] + " " + reference.join("/") + " not found";
status.redirect = true;
break script;
}
model.node = object.node;
// TODO: handle version??
// property filter
model.filter = args[cmis.ARG_FILTER];
if (model.filter === null)
if (model.filter === null || model.filter == "")
{
model.filter = "*";
}

View File

@@ -1,5 +1,6 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/constants.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/atomentry.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/modify.lib.js">
script:
{
@@ -13,16 +14,12 @@ script:
}
// locate node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
model.node = cmis.findNode(pathSegments[2], reference);
if (model.node === null)
var object = getObjectFromUrl();
if (object.node == null)
{
status.code = 404;
status.message = "Repository " + pathSegments[2] + " " + reference.join("/") + " not found";
status.redirect = true;
break script;
}
model.node = object.node;
// update properties
var updated = updateNode(model.node, entry, null, function(propDef) {return patchValidator(propDef, false);});

View File

@@ -27,8 +27,17 @@ If this is a private working copy, some repositories may not support updates.<br
Because repositories MAY automatically create new Document Versions on a users behalf, the objectId returned may not match the one provided as an input to this method.<br>
]]>
</description>
<!-- by object id -->
<url>/cmis/i/{id}</url>
<url>/cmis/s/{store}/i/{id}</url>
<!-- by path -->
<url>/cmis/p{path}</url>
<url>/cmis/s/{store}/p{path}</url>
<!-- alfresco style -->
<url>/api/node/{store_type}/{store_id}/{id}</url>
<url>/api/path/{store_type}/{store_id}/{id}</url>
<url>/api/path/{store_type}/{store_id}/{path}</url>
<authentication>user</authentication>
<format default="atomentry">argument</format>
<family>CMIS</family>

View File

@@ -1,5 +1,6 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/constants.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/atomentry.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/modify.lib.js">
script:
{
@@ -13,16 +14,12 @@ script:
}
// locate node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
model.node = cmis.findNode(pathSegments[2], reference);
if (model.node === null)
var object = getObjectFromUrl();
if (object.node == null)
{
status.code = 404;
status.message = "Repository " + pathSegments[2] + " " + reference.join("/") + " not found";
status.redirect = true;
break script;
}
model.node = object.node;
// update properties
var updated = updateNode(model.node, entry, null, function(propDef) {return putValidator(propDef, false);});

View File

@@ -27,8 +27,17 @@ If this is a private working copy, some repositories may not support updates.<br
Because repositories MAY automatically create new Document Versions on a users behalf, the objectId returned may not match the one provided as an input to this method.<br>
]]>
</description>
<!-- by object id -->
<url>/cmis/i/{id}</url>
<url>/cmis/s/{store}/i/{id}</url>
<!-- by path -->
<url>/cmis/p{path}</url>
<url>/cmis/s/{store}/p{path}</url>
<!-- alfresco style -->
<url>/api/node/{store_type}/{store_id}/{id}</url>
<url>/api/path/{store_type}/{store_id}/{id}</url>
<url>/api/path/{store_type}/{store_id}/{path}</url>
<authentication>user</authentication>
<format default="atomentry">argument</format>
<family>CMIS</family>

View File

@@ -2,8 +2,17 @@
<shortname>Retrieve Parent Folder (getFolderParent)</shortname>
<description>
</description>
<!-- by object id -->
<url>/cmis/i/{id}/parent?filter={filter?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/cmis/s/{store}/i/{id}/parent?filter={filter?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<!-- by path -->
<url>/cmis/p{path}/parent?filter={filter?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/cmis/s/{store}/p{path}/parent?filter={filter?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<!-- alfresco style -->
<url>/api/node/{store_type}/{store_id}/{id}/parent?filter={filter?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/api/path/{store_type}/{store_id}/{id}/parent?filter={filter?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/api/path/{store_type}/{store_id}/{path}/parent?filter={filter?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<authentication>guest</authentication>
<transaction allow="readonly"/>
<format default="atomentry">argument</format>

View File

@@ -1,22 +1,20 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
script:
{
// locate node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
var node = cmis.findNode(pathSegments[2], reference);
if (node === null)
var object = getObjectFromUrl();
if (object.node == null)
{
status.code = 404;
status.message = "Repository " + pathSegments[2] + " " + reference.join("/") + " not found";
status.redirect = true;
break script;
}
var node = object.node;
// locate parent
if (node.id == cmis.defaultRootFolder.id)
{
status.code = 404;
status.message = "Repository " + pathSegments[2] + " " + reference.join("/") + " parent not found";
status.message = "Object " + object.ref + " parent not found";
status.redirect = true;
break script;
}

View File

@@ -23,8 +23,17 @@ If “includeAllowableActions” is TRUE, the repository will return the allowab
"IncludeRelationships" indicates whether relationships are also returned for each returned object. If it is set to "source" or "target", relationships for which the returned object is a source, or respectively a target, will also be returned. If it is set to "both", relationships for which the returned object is either a source or a target will be returned. If it is set to "none", relationships are not returned.<br>
]]>
</description>
<!-- by object id -->
<url>/cmis/i/{id}/parents?filter={filter?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/cmis/s/{store}/i/{id}/parents?filter={filter?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<!-- by path -->
<url>/cmis/p{path}/parents?filter={filter?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/cmis/s/{store}/p{path}/parents?filter={filter?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<!-- alfresco style -->
<url>/api/node/{store_type}/{store_id}/{id}/parents?filter={filter?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/api/path/{store_type}/{store_id}/{id}/parents?filter={filter?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/api/path/{store_type}/{store_id}/{path}/parents?filter={filter?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<authentication>guest</authentication>
<transaction allow="readonly"/>
<format default="atomfeed">argument</format>

View File

@@ -1,20 +1,15 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
script:
{
// locate node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
var node = cmis.findNode(pathSegments[2], reference);
if (node === null)
// locate node and parent
var object = getObjectFromUrl();
if (object.node == null)
{
status.code = 404;
status.message = "Repository " + pathSegments[2] + " " + reference.join("/") + " not found";
status.redirect = true;
break script;
}
// locate parent
model.node = node;
model.parent = node.parent;
model.node = object.node;
model.parent = model.node.parent;
// property filter
model.filter = args[cmis.ARG_FILTER];

View File

@@ -14,7 +14,11 @@ It is repository specific on who can cancel a checkout (user, admin, larger grou
Throws OperationNotSupportedException if the object is not checked out<br>
]]>
</description>
<url>/api/pwc/{store_type}/{store_id}/{id}</url>
<!-- by object id -->
<url>/cmis/pwc/i/{id}</url>
<url>/cmis/pwc/s/{store}/i/{id}</url>
<authentication>user</authentication>
<format default="atomentry"/>
<family>CMIS</family>

View File

@@ -1,21 +1,18 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
script:
{
// locate node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
var node = cmis.findNode("node", reference);
if (node === null || !node.hasAspect("cm:workingcopy"))
var object = getObjectFromUrl();
if (object.node == null)
{
status.code = 404;
status.message = "Private working copy " + reference.join("/") + " not found";
status.redirect = true;
break script;
}
var node = object.node;
if (!node.hasPermission("CancelCheckOut"))
{
status.code = 403;
status.message = "Permission to cancel checkout is denied";
status.message = "Permission to cancel checkout of " + object.ref + " is denied";
status.redirect = true;
break script;
}

View File

@@ -1,7 +1,10 @@
<webscript>
<shortname>Retrieve properties of PWC</shortname>
<description>Retrieves the properties of a private working copy</description>
<url>/api/pwc/{store_type}/{store_id}/{id}?filter={filter?}</url>
<url>/cmis/pwc/i/{id}?filter={filter?}</url>
<url>/cmis/pwc/s/{store}/i/{id}?filter={filter?}</url>
<authentication>user</authentication>
<transaction allow="readonly"/>
<format default="atomentry">argument</format>

View File

@@ -1,16 +1,14 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
script:
{
// locate node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
model.node = cmis.findNode("node", reference);
if (model.node === null || !model.node.hasAspect("cm:workingcopy"))
var object = getObjectFromUrl();
if (object.node == null)
{
status.code = 404;
status.message = "Private working copy " + reference.join("/") + " not found";
status.redirect = true;
break script;
}
model.node = object.node;
// TODO: property filters

View File

@@ -1,26 +1,23 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/constants.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/atomentry.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/modify.lib.js">
script:
{
// locate node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
model.node = cmis.findNode("node", reference);
if (model.node === null || !model.node.hasAspect("cm:workingcopy"))
var object = getObjectFromUrl();
if (object.node == null)
{
status.code = 404;
status.message = "Private working copy " + reference.join("/") + " not found";
status.redirect = true;
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.message = "Permission to checkin " + object.ref + " is denied";
status.redirect = true;
break script;
}

View File

@@ -25,7 +25,10 @@ If Document is not checked out, throw OperationNotSupportedException.<br>
If the Document has “Content_Stream_Allowed” set to FALSE, and a call is made to checkIn that includes a content-stream, throw ConstraintViolationException.<br>
]]>
</description>
<url>/api/pwc/{store_type}/{store_id}/{id}?checkinComment={checkinComment?}&amp;major={major?}&amp;checkin={checkin?}</url>
<url>/cmis/pwc/i/{id}?checkinComment={checkinComment?}&amp;major={major?}&amp;checkin={checkin?}</url>
<url>/cmis/pwc/s/{store}/i/{id}?checkinComment={checkinComment?}&amp;major={major?}&amp;checkin={checkin?}</url>
<authentication>user</authentication>
<format default="atomentry"/>
<family>CMIS</family>

View File

@@ -1,19 +1,16 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/constants.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/atomentry.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/modify.lib.js">
script:
{
// locate node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
model.node = cmis.findNode("node", reference);
if (model.node === null || !model.node.hasAspect("cm:workingcopy"))
var object = getObjectFromUrl();
if (object.node === null || !object.node.hasAspect("cm:workingcopy"))
{
status.code = 404;
status.message = "Private working copy " + reference.join("/") + " not found";
status.redirect = true;
break script;
}
model.node = object.node;
// check permissions
model.checkin = args[cmis.ARG_CHECKIN] == "true" ? true : false;

View File

@@ -25,7 +25,10 @@ If Document is not checked out, throw OperationNotSupportedException.<br>
If the Document has “Content_Stream_Allowed” set to FALSE, and a call is made to checkIn that includes a content-stream, throw ConstraintViolationException.<br>
]]>
</description>
<url>/api/pwc/{store_type}/{store_id}/{id}?checkinComment={checkinComment?}&amp;major={major?}&amp;checkin={checkin?}</url>
<url>/cmis/pwc/i/{id}?checkinComment={checkinComment?}&amp;major={major?}&amp;checkin={checkin?}</url>
<url>/cmis/pwc/s/{store}/i/{id}?checkinComment={checkinComment?}&amp;major={major?}&amp;checkin={checkin?}</url>
<authentication>user</authentication>
<format default="atomentry"/>
<family>CMIS</family>

View File

@@ -2,7 +2,9 @@
<shortname>Delete relationship (deleteRelationship)</shortname>
<description>
</description>
<url>/api/rel/{store_type}/{store_id}/{id}/type/{rel_type}/target/{target_store_type}/{target_store_id}/{target_id}</url>
<url>/cmis/rel/s/{store}/i/{id}/type/{rel_type}/target/s/{target_store}/i/{target_id}</url>
<authentication>user</authentication>
<format default="atomentry"/>
<family>CMIS</family>

View File

@@ -1,32 +1,14 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/constants.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
script:
{
// relationship type
var relType = url.templateArgs.rel_type;
model.relTypeDef = cmis.queryType(relType);
if (model.relTypeDef === null)
var rel = getAssocFromUrl();
if (rel.assoc == null)
{
status.setCode(400, "Relationship type " + relType + " unknown");
break script;
}
if (model.relTypeDef.baseType.typeId != RELATIONSHIP_TYPE_ID)
{
status.setCode(400, "Type + " + relType + " is not a relationship type");
break script;
}
// source and target
var source = [url.templateArgs.store_type, url.templateArgs.store_id, url.templateArgs.id];
var target = [url.templateArgs.target_store_type, url.templateArgs.target_store_id, url.templateArgs.target_id];
// locate association
var assoc = cmis.findRelationship(model.relTypeDef, source, target);
if (assoc === null)
{
status.setCode(404, "Assoc " + source.join("/") + "/" + relType + "/" + target.join("/") + " not found");
break script;
}
var assoc = rel.assoc;
// TODO: check permission
// if (!assoc.source.hasPermission("DeleteAssociations"))

View File

@@ -2,7 +2,9 @@
<shortname>Retrieve relationship (getProperties)</shortname>
<description>
</description>
<url>/api/rel/{store_type}/{store_id}/{id}/type/{rel_type}/target/{target_store_type}/{target_store_id}/{target_id}?filter={filter?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/cmis/rel/s/{store}/i/{id}/type/{rel_type}/target/s/{target_store}/i/{target_id}?filter={filter?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<authentication>guest</authentication>
<transaction allow="readonly"/>
<format default="atomentry">argument</format>

View File

@@ -1,24 +1,15 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/constants.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
script:
{
// relationship type
var relType = url.templateArgs.rel_type;
model.relTypeDef = cmis.queryType(relType);
if (model.relTypeDef === null)
// locate association
var rel = getAssocFromUrl();
if (rel.assoc == null)
{
status.setCode(400, "Relationship type " + relType + " unknown");
break script;
}
if (model.relTypeDef.baseType.typeId != RELATIONSHIP_TYPE_ID)
{
status.setCode(400, "Type + " + relType + " is not a relationship type");
break script;
}
// source and target
var source = [url.templateArgs.store_type, url.templateArgs.store_id, url.templateArgs.id];
var target = [url.templateArgs.target_store_type, url.templateArgs.target_store_id, url.templateArgs.target_id];
model.assoc = rel.assoc;
// property filter
model.filter = args[cmis.ARG_FILTER];
@@ -30,12 +21,4 @@ script:
// include allowable actions
var includeAllowableActions = args[cmis.ARG_INCLUDE_ALLOWABLE_ACTIONS];
model.includeAllowableActions = (includeAllowableActions == "true" ? true : false);
// locate association
model.assoc = cmis.findRelationship(model.relTypeDef, source, target);
if (model.assoc === null)
{
status.setCode(404, "Assoc " + source.join("/") + "/" + relType + "/" + target.join("/") + " not found");
break script;
}
}

View File

@@ -2,6 +2,15 @@
<shortname>Retrieve list of relationships (getRelationships)</shortname>
<description>
</description>
<!-- by object id -->
<url>/cmis/i/{id}/rels?filter={filter?}&amp;relationshipType={relationshipType?}&amp;includeSubRelationshipTypes={includeSubRelationshipTypes?}&amp;direction={direction?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/cmis/s/{store}/i/{id}/rels?filter={filter?}&amp;relationshipType={relationshipType?}&amp;includeSubRelationshipTypes={includeSubRelationshipTypes?}&amp;direction={direction?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<!-- by path -->
<url>/cmis/p{path}/rels?filter={filter?}&amp;relationshipType={relationshipType?}&amp;includeSubRelationshipTypes={includeSubRelationshipTypes?}&amp;direction={direction?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/cmis/s/{store}/p{path}/rels?filter={filter?}&amp;relationshipType={relationshipType?}&amp;includeSubRelationshipTypes={includeSubRelationshipTypes?}&amp;direction={direction?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<!-- alfresco style -->
<url>/api/node/{store_type}/{store_id}/{id}/rels?filter={filter?}&amp;relationshipType={relationshipType?}&amp;includeSubRelationshipTypes={includeSubRelationshipTypes?}&amp;direction={direction?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/api/path/{store_type}/{store_id}/{id}/rels?filter={filter?}&amp;relationshipType={relationshipType?}&amp;includeSubRelationshipTypes={includeSubRelationshipTypes?}&amp;direction={direction?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<authentication>guest</authentication>

View File

@@ -1,16 +1,15 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/constants.lib.js">
script:
{
// locate node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
model.node = cmis.findNode(pathSegments[2], reference);
if (model.node === null)
var object = getObjectFromUrl();
if (object.node == null)
{
status.setCode(404, "Repository " + pathSegments[2] + " " + reference.join("/") + " not found");
break script;
}
model.node = object.node;
// property filter
model.filter = args[cmis.ARG_FILTER];

View File

@@ -1,5 +1,6 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/constants.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/atomentry.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/modify.lib.js">
script:
{
@@ -13,16 +14,12 @@ script:
}
// locate source node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
model.source = cmis.findNode(pathSegments[2], reference);
if (model.source === null)
var object = getObjectFromUrl();
if (object.node == null)
{
status.code = 404;
status.message = "Repository " + pathSegments[2] + " " + reference.join("/") + " not found";
status.redirect = true;
break script;
}
model.source = object.node;
// create
var assoc = createAssociation(model.source, entry);
@@ -36,6 +33,6 @@ script:
// TODO: set Content-Location
status.code = 201;
// TODO: complete url mapping
status.location = url.server + url.serviceContext + "/api/rel/" + model.source.nodeRef.storeRef.protocol + "/" + model.source.nodeRef.storeRef.identifier + "/" + model.source.nodeRef.id;
status.location = url.server + url.serviceContext + "/cmis/rel/" + model.source.nodeRef.storeRef.protocol + "/" + model.source.nodeRef.storeRef.identifier + "/" + model.source.nodeRef.id;
status.redirect = true;
}

View File

@@ -2,8 +2,18 @@
<shortname>Create relationship (createRelationship)</shortname>
<description>
</description>
<!-- by object id -->
<url>/cmis/i/{id}/rels</url>
<url>/cmis/s/{store}/i/{id}/rels</url>
<!-- by path -->
<url>/cmis/p{path}/rels</url>
<url>/cmis/s/{store}/p{path}/rels</url>
<!-- alfresco style -->
<url>/api/node/{store_type}/{store_id}/{id}/rels</url>
<url>/api/path/{store_type}/{store_id}/{id}/rels</url>
<authentication>guest</authentication>
<format default="atomentry">argument</format>
<family>CMIS</family>

View File

@@ -2,8 +2,17 @@
<shortname>Delete tree (deleteTree)</shortname>
<description>
</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>
<!-- 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>
<!-- alfresco style -->
<url>/api/node/{store_type}/{store_id}/{id}/tree?continueOnFailure={continueOnFailure?}&amp;unfileMultiFiledDocuments={unfileMultiFiledDocuments}</url>
<url>/api/path/{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>
<authentication>user</authentication>
<format default="atomfeed"/>
<family>CMIS</family>

View File

@@ -1,16 +1,14 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
script:
{
// locate node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
var node = cmis.findNode(pathSegments[2], reference);
if (node === null)
var object = getObjectFromUrl();
if (object.node == null)
{
status.code = 404;
status.message = "Repository " + pathSegments[2] + " " + reference.join("/") + " not found";
status.redirect = true;
break script;
}
var node = object.node;
// NOTE: Ignore continueOnDelete as complete tree is deleted in single transaction
// TODO: Throw error on invalid unfileMultiFiledDocuments error
@@ -28,7 +26,7 @@ script:
if (!node.remove())
{
status.code = 500;
status.message = "Failed to delete node " + pathSegments[2] + " " + reference.join("/");
status.message = "Failed to delete object " + object.ref;
status.redirect = true;
break script;
}

View File

@@ -2,8 +2,17 @@
<shortname>Retrieve folder tree (getFolderTree)</shortname>
<description>
</description>
<!-- by object id -->
<url>/cmis/i/{id}/tree?filter={filter?}&amp;depth={depth?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/cmis/s/{store}/i/{id}/tree?filter={filter?}&amp;depth={depth?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<!-- by path -->
<url>/cmis/p{path}/tree?filter={filter?}&amp;depth={depth?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/cmis/s/{store}/p{path}/tree?filter={filter?}&amp;depth={depth?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<!-- alfresco style -->
<url>/api/node/{store_type}/{store_id}/{id}/tree?filter={filter?}&amp;depth={depth?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/api/path/{store_type}/{store_id}/{id}/tree?filter={filter?}&amp;depth={depth?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<url>/api/path/{store_type}/{store_id}/{path}/tree?filter={filter?}&amp;depth={depth?}&amp;includeAllowableActions={includeAllowableActions?}</url>
<authentication>guest</authentication>
<transaction allow="readonly"/>
<format default="atomfeed">argument</format>

View File

@@ -1,21 +1,19 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
script:
{
// locate node
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
model.node = cmis.findNode(pathSegments[2], reference);
if (model.node === null)
var object = getObjectFromUrl();
if (object.node == null)
{
status.code = 404;
status.message = "Repository " + pathSegments[2] + " " + reference.join("/") + " not found";
status.redirect = true;
break script;
}
model.node = object.node;
if (model.node.isDocument)
{
status.code = 404;
status.message = "Repository " + pathSegments[2] + " " + reference.join("/") + " not a folder";
status.message = "Object " + object.ref + " is not a folder";
status.redirect = true;
break script;
}

View File

@@ -19,7 +19,7 @@ canCreateInstances if false, the user MUST NOT be able to create instances of th
When includeInheritedProperties is true, the repository SHOULD return all properties defined for the Object Type, including any properties inherited from its parent. If false, only Properties defined on the Object Type (but not its parent) SHOULD be returned.
]]>
</description>
<url>/api/type/{typeId}?includeInheritedProperties={includeInheritedProperties?}</url>
<url>/cmis/type/{typeId}?includeInheritedProperties={includeInheritedProperties?}</url>
<authentication>user</authentication>
<transaction allow="readonly"/>
<format default="atomentry"/>

View File

@@ -1,8 +1,8 @@
<webscript>
<shortname>Retrieve list of child Types</shortname>
<description>Retrieve list of all child Types</description>
<url>/api/type/{typeId}/children?includePropertyDefinitions={includePropertyDefinitions?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}</url>
<url>/api/types?typeId={typeId?}&amp;includePropertyDefinitions={includePropertyDefinitions?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}</url>
<url>/cmis/type/{typeId}/children?includePropertyDefinitions={includePropertyDefinitions?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}</url>
<url>/cmis/types?typeId={typeId?}&amp;includePropertyDefinitions={includePropertyDefinitions?}&amp;skipCount={skipCount?}&amp;maxItems={maxItems?}</url>
<authentication>user</authentication>
<transaction allow="readonly"/>
<format default="atomfeed"/>

View File

@@ -1,8 +1,8 @@
<webscript>
<shortname>Retrieve list of descendant Types</shortname>
<description>Retrieve list of all descendant Types</description>
<url>/api/type/{typeId}/descendants?includePropertyDefinitions={includePropertyDefinitions?}&amp;depth={depth?}</url>
<url>/api/types/descendants?typeId={typeId?}&amp;includePropertyDefinitions={includePropertyDefinitions?}&amp;depth={depth?}</url>
<url>/cmis/type/{typeId}/descendants?includePropertyDefinitions={includePropertyDefinitions?}&amp;depth={depth?}</url>
<url>/cmis/types/descendants?typeId={typeId?}&amp;includePropertyDefinitions={includePropertyDefinitions?}&amp;depth={depth?}</url>
<authentication>user</authentication>
<transaction allow="readonly"/>
<format default="atomfeed"/>

View File

@@ -1,7 +1,7 @@
<webscript>
<shortname>Unfiled Documents</shortname>
<description>Retrieve list of documents that are not in any folder</description>
<url>/api/unfiled</url>
<url>/cmis/unfiled</url>
<authentication>guest</authentication>
<transaction allow="readonly"/>
<format default="atomfeed"/>

View File

@@ -18,8 +18,17 @@ Notes:<br>
Returns all versions the user can access including checked-out version and private working copy.<br>
]]>
</description>
<!-- by object id -->
<url>/cmis/i/{id}/versions?filter={filter?}</url>
<url>/cmis/s/{store}/i/{id}/versions?filter={filter?}</url>
<!-- by path -->
<url>/cmis/p{path}/versions?filter={filter?}</url>
<url>/cmis/s/{store}/p{path}/versions?filter={filter?}</url>
<!-- alfresco style -->
<url>/api/node/{store_type}/{store_id}/{id}/versions?filter={filter?}</url>
<url>/api/path/{store_type}/{store_id}/{id}/versions?filter={filter?}</url>
<url>/api/path/{store_type}/{store_id}/{path}/versions?filter={filter?}</url>
<authentication>user</authentication>
<transaction allow="readonly"/>
<format default="atomfeed">argument</format>

View File

@@ -1,17 +1,15 @@
<import resource="classpath:alfresco/templates/webscripts/org/alfresco/cmis/read.lib.js">
script:
{
// locate version series
// NOTE: version series is identified by noderef (as this is constant during lifetime of node)
var pathSegments = url.match.split("/");
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
model.node = cmis.findNode(pathSegments[2], reference);
if (model.node === null || !model.node.isVersioned)
var object = getObjectFromUrl();
if (object.node == null || !object.node.isVersioned)
{
status.code = 404;
status.message = "Versions series " + pathSegments[2] + " " + reference.join("/") + " not found";
status.redirect = true;
status.message = "Versions series " + object.ref + " not found";
break script;
}
model.node = object.node;
// property filter
model.filter = args[cmis.ARG_FILTER];

View File

@@ -224,10 +224,10 @@
<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" />
<property name="repository" ref="repositoryHelper" />
<property name="CMISService" ref="CMISService" />
<property name="CMISDictionaryService" ref="CMISDictionaryService" />
<property name="CMISQueryService" ref="CMISQueryService" />
<property name="CMISReferenceFactory" ref="CMISReferenceFactory" />
<property name="paging" ref="webscripts.js.paging" />
</bean>
@@ -292,7 +292,7 @@
<!-- Content Retrieval -->
<bean id="webscript.org.alfresco.repository.store.content.get" class="org.alfresco.repo.web.scripts.content.ContentGet" parent="webscript">
<property name="repository" ref="repositoryHelper" />
<property name="referenceFactory" ref="CMISReferenceFactory" />
<property name="namespaceService" ref="NamespaceService" />
<property name="permissionService" ref="PermissionService" />
<property name="nodeService" ref="NodeService" />
@@ -309,13 +309,20 @@
<!-- Content Write -->
<bean id="webscript.org.alfresco.repository.store.content.put" class="org.alfresco.repo.web.scripts.content.ContentSet" parent="webscript">
<property name="repository" ref="repositoryHelper" />
<property name="referenceFactory" ref="CMISReferenceFactory" />
<property name="dictionaryService" ref="DictionaryService" />
<property name="namespaceService" ref="NamespaceService" />
<property name="contentService" ref="ContentService" />
<property name="mimetypeService" ref="MimetypeService" />
</bean>
<!-- Content Delete -->
<bean id="webscript.org.alfresco.repository.store.content.delete" class="org.alfresco.repo.web.scripts.content.ContentDelete" parent="webscript">
<property name="referenceFactory" ref="CMISReferenceFactory" />
<property name="namespaceService" ref="NamespaceService" />
<property name="nodeService" ref="NodeService" />
</bean>
<!-- Remote Store service - AVM -->
<bean id="webscript.org.alfresco.repository.store.remoteavm.get" class="org.alfresco.repo.web.scripts.bean.AVMRemoteStore" parent="webscript">
<property name="mimetypeService" ref="MimetypeService" />

View File

@@ -26,26 +26,29 @@ package org.alfresco.repo.cmis.rest;
import java.util.Collection;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Map;
import org.alfresco.cmis.CMISDictionaryService;
import org.alfresco.cmis.CMISJoinEnum;
import org.alfresco.cmis.CMISObjectReference;
import org.alfresco.cmis.CMISPropertyDefinition;
import org.alfresco.cmis.CMISQueryEnum;
import org.alfresco.cmis.CMISQueryOptions;
import org.alfresco.cmis.CMISQueryService;
import org.alfresco.cmis.CMISRelationshipDirectionEnum;
import org.alfresco.cmis.CMISRelationshipReference;
import org.alfresco.cmis.CMISRepositoryReference;
import org.alfresco.cmis.CMISResultSet;
import org.alfresco.cmis.CMISServices;
import org.alfresco.cmis.CMISTypeDefinition;
import org.alfresco.cmis.CMISTypesFilterEnum;
import org.alfresco.cmis.CMISQueryOptions.CMISQueryMode;
import org.alfresco.cmis.reference.NodeRefReference;
import org.alfresco.cmis.reference.ReferenceFactory;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.jscript.Association;
import org.alfresco.repo.jscript.BaseScopableProcessorExtension;
import org.alfresco.repo.jscript.ScriptNode;
import org.alfresco.repo.model.Repository;
import org.alfresco.repo.web.util.paging.Cursor;
import org.alfresco.repo.web.util.paging.Page;
import org.alfresco.repo.web.util.paging.PagedResults;
@@ -101,15 +104,11 @@ public class CMISScript extends BaseScopableProcessorExtension
// service dependencies
private ServiceRegistry services;
private Repository repository;
private CMISServices cmisService;
private CMISDictionaryService cmisDictionaryService;
private CMISQueryService cmisQueryService;
private Paging paging;
// versioned objectId pattern
// TODO: encapsulate elsewhere
private static final Pattern versionedObjectIdPattern = Pattern.compile(".+://.+/.+/.+");
private ReferenceFactory referenceFactory;
/**
@@ -122,16 +121,6 @@ public class CMISScript extends BaseScopableProcessorExtension
this.services = services;
}
/**
* Set the repository
*
* @param repository
*/
public void setRepository(Repository repository)
{
this.repository = repository;
}
/**
* Set the paging helper
*
@@ -172,6 +161,16 @@ public class CMISScript extends BaseScopableProcessorExtension
this.cmisQueryService = cmisQueryService;
}
/**
* Set the CMIS Reference Factory
*
* @param referenceFactory
*/
public void setCMISReferenceFactory(ReferenceFactory referenceFactory)
{
this.referenceFactory = referenceFactory;
}
/**
* Gets the supported CMIS Version
*
@@ -238,63 +237,83 @@ public class CMISScript extends BaseScopableProcessorExtension
}
/**
* Finds a Node given a repository reference
* Create CMIS Repository Reference from URL segments
*
* @param referenceType node, path
* @param reference node => id, path => path
* @return node (or null, if not found)
* @param args url arguments
* @param templateArgs url template arguments
* @return Repository Reference (or null, in case of bad url)
*/
public ScriptNode findNode(String referenceType, String[] reference)
public CMISRepositoryReference createRepoReferenceFromUrl(Map<String, String> args, Map<String, String> templateArgs)
{
ScriptNode node = null;
NodeRef nodeRef = repository.findNodeRef(referenceType, reference);
if (nodeRef != null)
{
node = new ScriptNode(nodeRef, services, getScope());
}
return node;
return referenceFactory.createRepoReferenceFromUrl(args, templateArgs);
}
/**
* Finds a Node given CMIS ObjectId
* Create CMIS Object Reference from URL segments
*
* @param objectId
* @return node (or null, if not found)
* @param args url arguments
* @param templateArgs url template arguments
* @return Repository Reference (or null, in case of bad url)
*/
public ScriptNode findNode(String objectId)
public CMISObjectReference createObjectReferenceFromUrl(Map<String, String> args, Map<String, String> templateArgs)
{
NodeRef nodeRef;
Matcher matcher = versionedObjectIdPattern.matcher(objectId);
if (matcher.matches())
{
// TODO: handle version id
nodeRef = new NodeRef(objectId.substring(0, objectId.lastIndexOf("/")));
}
else
{
nodeRef = new NodeRef(objectId);
}
String[] reference = new String[] {nodeRef.getStoreRef().getProtocol(), nodeRef.getStoreRef().getIdentifier(), nodeRef.getId()};
return findNode("node", reference);
return referenceFactory.createObjectReferenceFromUrl(args, templateArgs);
}
/**
* Finds an Association
* Create CMIS Relationship Reference from URL segments
*
* @param sourceType
* @param source
* @param relDef
* @param targetType
* @param target
*
* @return
* @param args url arguments
* @param templateArgs url template arguments
* @return Repository Reference (or null, in case of bad url)
*/
public Association findRelationship(CMISTypeDefinition relDef, String[] sourceRef, String[] targetRef)
public CMISRelationshipReference createRelationshipReferenceFromUrl(Map<String, String> args, Map<String, String> templateArgs)
{
NodeRef source = new NodeRef(sourceRef[0], sourceRef[1], sourceRef[2]);
NodeRef target = new NodeRef(targetRef[0], targetRef[1], targetRef[2]);
AssociationRef assocRef = cmisService.getRelationship(relDef, source, target);
return (assocRef == null) ? null : new Association(services, assocRef);
return referenceFactory.createRelationshipReferenceFromUrl(args, templateArgs);
}
/**
* Create Object Reference
*
* @param repo repository reference
* @param object id object id (NodeRef.toString() format)
* @return object id reference
*/
public CMISObjectReference createObjectIdReference(String objectId)
{
return new NodeRefReference(cmisService, objectId);
}
/**
* Get Node from Object Reference
*
* @param ref object reference
* @return node
*/
public ScriptNode getNode(CMISObjectReference ref)
{
NodeRef nodeRef = ref.getNodeRef();
if (nodeRef == null)
{
return null;
}
return new ScriptNode(nodeRef, services, getScope());
}
/**
* Get Association from Relationship Reference
*
* @param ref relationship reference
* @return association
*/
public Association getAssociation(CMISRelationshipReference ref)
{
AssociationRef assocRef = ref.getAssocRef();
if (assocRef == null)
{
return null;
}
return new Association(services, assocRef);
}
/**
@@ -424,35 +443,6 @@ public class CMISScript extends BaseScopableProcessorExtension
return results;
}
/**
* Query for all Type Definitions in a type hierarchy
*
* @param page
* @return paged result set of types
*/
// public PagedResults queryTypeHierarchy(CMISTypeDefinition typeDef, boolean descendants, Page page)
// {
// Collection<CMISTypeDefinition> subTypes = typeDef.getSubTypes(descendants);
// Cursor cursor = paging.createCursor(subTypes.size(), page);
//
// // skip
// Iterator<CMISTypeDefinition> iterSubTypes = subTypes.iterator();
// for (int i = 0; i < cursor.getStartRow(); i++)
// {
// iterSubTypes.next();
// }
//
// // get types for page
// CMISTypeDefinition[] types = new CMISTypeDefinition[cursor.getRowCount()];
// for (int i = cursor.getStartRow(); i <= cursor.getEndRow(); i++)
// {
// types[i - cursor.getStartRow()] = iterSubTypes.next();
// }
//
// PagedResults results = paging.createPagedResults(types, cursor);
// return results;
// }
/**
* Query for a Type Definition given a CMIS Type Id
*

View File

@@ -782,8 +782,6 @@ public class RepositoryContainer extends AbstractRuntimeContainer implements Ten
{
try
{
if (logger.isDebugEnabled())
logger.debug("Writing Transactional response: size=" + outputStream.size());
if (outputWriter != null)
{
@@ -792,6 +790,9 @@ public class RepositoryContainer extends AbstractRuntimeContainer implements Ten
}
else if (outputStream != null)
{
if (logger.isDebugEnabled())
logger.debug("Writing Transactional response: size=" + outputStream.size());
outputStream.flush();
outputStream.writeTo(res.getOutputStream());
}

View File

@@ -0,0 +1,138 @@
/*
* 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.web.scripts.content;
import java.io.IOException;
import java.util.HashMap;
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.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.scripts.AbstractWebScript;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptResponse;
/**
* Content Delete Service
*
* Delete content stream from the Repository.
*
* @author davidc
*/
public class ContentDelete extends AbstractWebScript
{
// Component dependencies
private ReferenceFactory referenceFactory;
private NamespaceService namespaceService;
private NodeService nodeService;
/**
* @param reference factory
*/
public void setReferenceFactory(ReferenceFactory referenceFactory)
{
this.referenceFactory = referenceFactory;
}
/**
* @param namespaceService
*/
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
/**
* @param nodeService
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @see org.alfresco.web.scripts.WebScript#execute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
public void execute(WebScriptRequest req, WebScriptResponse res)
throws IOException
{
// create map of args
String[] names = req.getParameterNames();
Map<String, String> args = new HashMap<String, String>(names.length, 1.0f);
for (String name : names)
{
args.put(name, req.getParameter(name));
}
// create map of template vars
Map<String, String> templateVars = req.getServiceMatch().getTemplateVars();
// create object reference from url
CMISObjectReference reference = referenceFactory.createObjectReferenceFromUrl(args, templateVars);
NodeRef nodeRef = reference.getNodeRef();
if (nodeRef == null)
{
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find " + reference.toString());
}
// determine content property
QName propertyQName = ContentModel.PROP_CONTENT;
String contentPart = templateVars.get("property");
if (contentPart.length() > 0 && contentPart.charAt(0) == ';')
{
if (contentPart.length() < 2)
{
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Content property malformed");
}
String propertyName = contentPart.substring(1);
if (propertyName.length() > 0)
{
propertyQName = QName.createQName(propertyName, namespaceService);
}
}
// retrieve content property
ContentData contentData = (ContentData)nodeService.getProperty(nodeRef, propertyQName);
if (contentData != null)
{
contentData = new ContentData(null, null, 0, null);
nodeService.setProperty(nodeRef, propertyQName, contentData);
}
// no content returned
res.setStatus(204);
}
}

View File

@@ -25,13 +25,14 @@
package org.alfresco.repo.web.scripts.content;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
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.model.Repository;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
@@ -56,15 +57,15 @@ public class ContentGet extends StreamContent
private static final Log logger = LogFactory.getLog(ContentGet.class);
// Component dependencies
private Repository repository;
private ReferenceFactory referenceFactory;
private NamespaceService namespaceService;
/**
* @param repository
* @param reference factory
*/
public void setRepository(Repository repository)
public void setReferenceFactory(ReferenceFactory referenceFactory)
{
this.repository = repository;
this.referenceFactory = referenceFactory;
}
/**
@@ -81,19 +82,23 @@ public class ContentGet extends StreamContent
public void execute(WebScriptRequest req, WebScriptResponse res)
throws IOException
{
// convert web script URL to node reference in Repository
String match = req.getServiceMatch().getPath();
String[] matchParts = match.split("/");
// create map of args
String[] names = req.getParameterNames();
Map<String, String> args = new HashMap<String, String>(names.length, 1.0f);
for (String name : names)
{
args.put(name, req.getParameter(name));
}
// create map of template vars
Map<String, String> templateVars = req.getServiceMatch().getTemplateVars();
String[] id = templateVars.get("id").split("/");
String[] path = new String[id.length + 2];
path[0] = templateVars.get("store_type");
path[1] = templateVars.get("store_id");
System.arraycopy(id, 0, path, 2, id.length);
NodeRef nodeRef = repository.findNodeRef(matchParts[2], path);
// create object reference from url
CMISObjectReference reference = referenceFactory.createObjectReferenceFromUrl(args, templateVars);
NodeRef nodeRef = reference.getNodeRef();
if (nodeRef == null)
{
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find " + matchParts[2] + " reference " + Arrays.toString(path));
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find " + reference.toString());
}
// determine content property

View File

@@ -28,14 +28,16 @@ import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.cmis.CMISObjectReference;
import org.alfresco.cmis.reference.ObjectPathReference;
import org.alfresco.cmis.reference.ReferenceFactory;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.encoding.ContentCharsetFinder;
import org.alfresco.repo.model.Repository;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
@@ -68,18 +70,18 @@ public class ContentSet extends AbstractWebScript
private static final Log logger = LogFactory.getLog(ContentSet.class);
// Component dependencies
private Repository repository;
private ReferenceFactory referenceFactory;
private DictionaryService dictionaryService;
private NamespaceService namespaceService;
private ContentService contentService;
private MimetypeService mimetypeService;
/**
* @param repository
* @param reference factory
*/
public void setRepository(Repository repository)
public void setReferenceFactory(ReferenceFactory referenceFactory)
{
this.repository = repository;
this.referenceFactory = referenceFactory;
}
/**
@@ -120,19 +122,23 @@ public class ContentSet extends AbstractWebScript
public void execute(WebScriptRequest req, WebScriptResponse res)
throws IOException
{
// convert web script URL to node reference in Repository
String match = req.getServiceMatch().getPath();
String[] matchParts = match.split("/");
// create map of args
String[] names = req.getParameterNames();
Map<String, String> args = new HashMap<String, String>(names.length, 1.0f);
for (String name : names)
{
args.put(name, req.getParameter(name));
}
// create map of template vars
Map<String, String> templateVars = req.getServiceMatch().getTemplateVars();
String[] id = templateVars.get("id").split("/");
String[] path = new String[id.length + 2];
path[0] = templateVars.get("store_type");
path[1] = templateVars.get("store_id");
System.arraycopy(id, 0, path, 2, id.length);
NodeRef nodeRef = repository.findNodeRef(matchParts[2], path);
// create object reference from url
CMISObjectReference reference = referenceFactory.createObjectReferenceFromUrl(args, templateVars);
NodeRef nodeRef = reference.getNodeRef();
if (nodeRef == null)
{
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find " + matchParts[2] + " reference " + Arrays.toString(path));
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find " + reference.toString());
}
// determine content property
@@ -153,7 +159,7 @@ public class ContentSet extends AbstractWebScript
PropertyDefinition propertyDef = dictionaryService.getProperty(propertyQName);
if (propertyDef == null)
{
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find " + matchParts[2] + " reference " + Arrays.toString(path) + " content property " + propertyQName);
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find content property " + propertyQName + " of " + reference.toString());
}
if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))
{
@@ -180,9 +186,9 @@ public class ContentSet extends AbstractWebScript
String mimetype = req.getContentType();
if (mimetype == null)
{
if (matchParts[2].equals("path") || matchParts[2].equals("avmpath"))
if (reference instanceof ObjectPathReference)
{
mimetype = mimetypeService.guessMimetype(templateVars.get("id"));
mimetype = mimetypeService.guessMimetype(((ObjectPathReference)reference).getPath());
}
}
if (mimetype != null)

View File

@@ -1,14 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<bean id="cmis.test.dictionaryBootstrap" parent="dictionaryModelBootstrap" depends-on="dictionaryBootstrap">
<property name="models">
<list>
<value>cmis/cmisCustomModel.xml</value>
</list>
</property>
</bean>
</beans>

View File

@@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<model name="cmiscustom:model" xmlns="http://www.alfresco.org/model/dictionary/1.0">
<description>CMIS Custom Model</description>
<author>Alfresco</author>
<version>1.0</version>
<imports>
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
<import uri="http://www.alfresco.org/model/system/1.0" prefix="sys"/>
</imports>
<namespaces>
<namespace uri="http://www.alfresco.org/model/cmis/custom" prefix="cmiscustom"/>
</namespaces>
<types>
<type name="cmiscustom:folder">
<title>Custom Folder</title>
<parent>cm:folder</parent>
<properties>
<property name="cmiscustom:folderprop_string">
<title>Custom Folder Property (string)</title>
<type>d:text</type>
</property>
</properties>
</type>
<type name="cmiscustom:document">
<title>Custom Document</title>
<parent>cm:content</parent>
<properties>
<property name="cmiscustom:docprop_string">
<title>Custom Document Property (string)</title>
<type>d:text</type>
</property>
<property name="cmiscustom:docprop_boolean_multi">
<title>Custom Document Property (multi-valued boolean)</title>
<type>d:boolean</type>
<multiple>true</multiple>
</property>
</properties>
<associations>
<association name="cmiscustom:assoc">
<source>
<mandatory>false</mandatory>
<many>false</many>
</source>
<target>
<class>cm:content</class>
<mandatory>false</mandatory>
<many>true</many>
</target>
</association>
</associations>
</type>
</types>
</model>