You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by dc...@apache.org on 2010/02/02 16:08:29 UTC

svn commit: r905667 - in /incubator/chemistry/trunk/chemistry/chemistry-tck-atompub: ./ src/main/java/org/apache/chemistry/abdera/ext/ src/main/java/org/apache/chemistry/tck/atompub/ src/main/java/org/apache/chemistry/tck/atompub/client/ src/main/java/...

Author: dcaruana
Date: Tue Feb  2 15:08:19 2010
New Revision: 905667

URL: http://svn.apache.org/viewvc?rev=905667&view=rev
Log:
Add ACL tests to TCK.
- also includes updates to TCK Abdera extension to query and traverse ACL related info

Added:
    incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISACLCapability.java   (with props)
    incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISAccessControlEntry.java   (with props)
    incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISAccessControlList.java   (with props)
    incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/test/spec/AccessControlListTest.java   (with props)
Modified:
    incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/pom.xml
    incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISAllowableAction.java
    incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISCapabilities.java
    incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISConstants.java
    incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISExtensionFactory.java
    incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISRepositoryInfo.java
    incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISTypeDefinition.java
    incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/TCKTest.java
    incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/client/CMISClient.java
    incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/test/TCKTestSuite.java

Modified: incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/pom.xml
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/pom.xml?rev=905667&r1=905666&r2=905667&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/pom.xml (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/pom.xml Tue Feb  2 15:08:19 2010
@@ -76,6 +76,7 @@
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
           <redirectTestOutputToFile>true</redirectTestOutputToFile>
+          <argLine>-Xmx256M</argLine>
           <systemProperties>
             <property>
               <!-- NOTE: use recent xerces for validating CMIS schema -->

Added: incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISACLCapability.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISACLCapability.java?rev=905667&view=auto
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISACLCapability.java (added)
+++ incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISACLCapability.java Tue Feb  2 15:08:19 2010
@@ -0,0 +1,55 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Authors:
+ *     David Ward, Alfresco
+ */
+package org.apache.chemistry.abdera.ext;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.abdera.factory.Factory;
+import org.apache.abdera.model.Element;
+import org.apache.abdera.model.ExtensibleElementWrapper;
+
+/**
+ * CMIS Repository ACL Capability metadata for the Abdera ATOM library.
+ */
+public class CMISACLCapability extends ExtensibleElementWrapper {
+
+    public CMISACLCapability(Element internal) {
+        super(internal);
+    }
+
+    public CMISACLCapability(Factory factory) {
+        super(factory, CMISConstants.ACL_CAPABILITY);
+    }
+
+    public String getSupportedPermissions() {
+        return getFirstChild(CMISConstants.ACL_SUPPORTED_PERMISSIONS).getText();
+    }
+
+    public String getPropagation() {
+        return getFirstChild(CMISConstants.ACL_PROPAGATION).getText();
+    }
+
+    public Set<String> getRepositoryPermissions() {
+        Set<String> permissions = new HashSet<String>(51);
+        for (Element permission = getFirstChild(CMISConstants.ACL_PERMISSIONS); permission != null; permission = permission
+                .getNextSibling(CMISConstants.ACL_PERMISSIONS)) {
+            permissions.add(permission.getFirstChild(CMISConstants.ACL_PERMISSION).getText());
+        }
+        return permissions;
+    }
+}

Propchange: incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISACLCapability.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISAccessControlEntry.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISAccessControlEntry.java?rev=905667&view=auto
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISAccessControlEntry.java (added)
+++ incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISAccessControlEntry.java Tue Feb  2 15:08:19 2010
@@ -0,0 +1,83 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Authors:
+ *     David Ward, Alfresco
+ */
+package org.apache.chemistry.abdera.ext;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.abdera.factory.Factory;
+import org.apache.abdera.model.Element;
+import org.apache.abdera.model.ExtensibleElementWrapper;
+
+/**
+ * CMIS Access Control Entry for the Abdera ATOM library.
+ */
+public class CMISAccessControlEntry extends ExtensibleElementWrapper {
+
+    /**
+     * The Constructor.
+     * 
+     * @param internal
+     *            the internal element
+     */
+    public CMISAccessControlEntry(Element internal) {
+        super(internal);
+    }
+
+    /**
+     * The Constructor.
+     * 
+     * @param factory
+     *            the factory
+     */
+    public CMISAccessControlEntry(Factory factory) {
+        super(factory, CMISConstants.PERMISSION);
+    }
+
+    /**
+     * Gets the identifier of a principal, i.e. a user, group, or role.
+     * 
+     * @return the principal id
+     */
+    public String getPrincipalId() {
+        return getFirstChild(CMISConstants.PRINCIPAL).getFirstChild(CMISConstants.PRINCIPAL_ID).getText();
+    }
+
+    /**
+     * Gets the permission names.
+     * 
+     * @return the permission names
+     */
+    public List<String> getPermissions() {
+        List<String> permissions = new ArrayList<String>(5);
+        for (Element permission = getFirstChild(CMISConstants.PERMISSION); permission != null; permission = permission
+                .getNextSibling(CMISConstants.PERMISSION)) {
+            permissions.add(permission.getText());
+        }
+        return permissions;
+    }
+
+    /**
+     * Determines whether the ACE is directly assigned to its object.
+     * 
+     * @return <code>true</code> if the ACE is directly assigned to its object
+     *         or <code>false</code> if the ACE is somehow derived.
+     */
+    public boolean isDirect() {
+        return Boolean.parseBoolean(getFirstChild(CMISConstants.DIRECT).getText());
+    }
+}

Propchange: incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISAccessControlEntry.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISAccessControlList.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISAccessControlList.java?rev=905667&view=auto
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISAccessControlList.java (added)
+++ incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISAccessControlList.java Tue Feb  2 15:08:19 2010
@@ -0,0 +1,66 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Authors:
+ *     David Ward, Alfresco
+ */
+package org.apache.chemistry.abdera.ext;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.abdera.factory.Factory;
+import org.apache.abdera.model.Element;
+import org.apache.abdera.model.ExtensibleElementWrapper;
+
+/**
+ * CMIS Access Control List Element Wrapper for the Abdera ATOM library.
+ */
+public class CMISAccessControlList extends ExtensibleElementWrapper {
+
+    /**
+     * The Constructor.
+     * 
+     * @param internal
+     *            the internal elemeny
+     */
+    public CMISAccessControlList(Element internal) {
+        super(internal);
+    }
+
+    /**
+     * The Constructor.
+     * 
+     * @param factory
+     *            the factory
+     */
+    public CMISAccessControlList(Factory factory) {
+        super(factory, CMISConstants.ACCESS_CONTROL_LIST);
+    }
+
+    /**
+     * Gets all access control entries.
+     * 
+     * @return list of access control entries.
+     */
+    public List<CMISAccessControlEntry> getEntries() {
+        List<Element> children = getElements();
+        List<CMISAccessControlEntry> entries = new ArrayList<CMISAccessControlEntry>(children.size());
+        for (Element child : children) {
+            if (child instanceof CMISAccessControlEntry) {
+                entries.add((CMISAccessControlEntry) child);
+            }
+        }
+        return entries;
+    }
+}

Propchange: incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISAccessControlList.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISAllowableAction.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISAllowableAction.java?rev=905667&r1=905666&r2=905667&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISAllowableAction.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISAllowableAction.java Tue Feb  2 15:08:19 2010
@@ -26,7 +26,7 @@
 /**
  * CMIS Allowable Action for the Abdera ATOM library.
  */
-public abstract class CMISAllowableAction extends ElementWrapper {
+public class CMISAllowableAction extends ElementWrapper {
     
     /**
      * @param internal
@@ -58,7 +58,7 @@
      * @return
      */
     public boolean isAllowed() {
-        return Boolean.getBoolean(this.getText());
+        return Boolean.parseBoolean(this.getText());
     }
 
 }

Modified: incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISCapabilities.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISCapabilities.java?rev=905667&r1=905666&r2=905667&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISCapabilities.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISCapabilities.java Tue Feb  2 15:08:19 2010
@@ -83,4 +83,8 @@
         return child.getText();
     }
 
+    public String getACL() {
+        Element child = getFirstChild(CMISConstants.CAPABILITY_ACL);
+        return child.getText();
+    }
 }

Modified: incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISConstants.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISConstants.java?rev=905667&r1=905666&r2=905667&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISConstants.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISConstants.java Tue Feb  2 15:08:19 2010
@@ -39,6 +39,7 @@
     public static final String MIMETYPE_CMIS_ALLOWABLE_ACTIONS = "application/cmisallowableactions+xml";
     public static final String MIMETYPE_CMISATOM = "application/cmisatom+xml";
     public static final String MIMETYPE_CMISTREE = "application/cmistree+xml";
+    public static final String MIMETYPE_CMISACL = "application/cmisacl+xml";
 
     // CMIS Service Document
     public static final QName COLLECTION_TYPE = new QName(CMISRA_NS, "collectionType");
@@ -59,6 +60,8 @@
     public static final QName PRODUCT_VERSION = new QName(CMIS_NS, "productVersion");
     public static final QName ROOT_FOLDER_ID = new QName(CMIS_NS, "rootFolderId");
     public static final QName VERSION_SUPPORTED = new QName(CMIS_NS, "cmisVersionSupported");
+    public static final QName PRINCIPAL_ANONYMOUS = new QName(CMIS_NS, "principalAnonymous");
+    public static final QName PRINCIPAL_ANYONE = new QName(CMIS_NS, "principalAnyone");
 
     // CMIS URI Templates
     public static final QName URI_TEMPLATE = new QName(CMISRA_NS, "uritemplate");
@@ -82,7 +85,15 @@
     public static final QName CAPABILITY_QUERY = new QName(CMIS_NS, "capabilityQuery");
     public static final QName CAPABILITY_JOIN = new QName(CMIS_NS, "capabilityJoin");
     public static final QName CAPABILITY_RENDITIONS = new QName(CMIS_NS, "capabilityRenditions");
+    public static final QName CAPABILITY_ACL = new QName(CMIS_NS, "capabilityACL");
 
+    // ACL Capabilities
+    public static final QName ACL_CAPABILITY = new QName(CMIS_NS, "aclCapability");
+    public static final QName ACL_SUPPORTED_PERMISSIONS  = new QName(CMIS_NS, "supportedPermissions");
+    public static final QName ACL_PROPAGATION = new QName(CMIS_NS, "propagation");
+    public static final QName ACL_PERMISSIONS = new QName(CMIS_NS, "permissions");
+    public static final QName ACL_PERMISSION = new QName(CMIS_NS, "permission");
+    
     // CMIS Object
     public static final QName OBJECT = new QName(CMISRA_NS, "object");
     public static final QName PROPERTIES = new QName(CMIS_NS, "properties");
@@ -179,6 +190,7 @@
     public static final String REL_ALLOWABLE_ACTIONS = CMISLINK_NS + "allowableactions";
     public static final String REL_POLICIES = CMISLINK_NS + "policies";
     public static final String REL_RELATIONSHIPS = CMISLINK_NS + "relationships";
+    public static final String REL_ACL = CMISLINK_NS + "acl";
     public static final String REL_ASSOC_SOURCE = CMISLINK_NS + "source";
     public static final String REL_ASSOC_TARGET = CMISLINK_NS + "target";
 
@@ -197,34 +209,42 @@
 
     // CMIS Allowable Actions
     public static final QName ALLOWABLE_ACTIONS = new QName(CMIS_NS, "allowableActions");
-    public static final QName CAN_DELETE = new QName(CMIS_NS, "canDelete");
+    public static final QName CAN_DELETE_OBJECT = new QName(CMIS_NS, "canDeleteObject");
     public static final QName CAN_UPDATE_PROPERTIES = new QName(CMIS_NS, "canUpdateProperties");
+    public static final QName CAN_GET_FOLDER_TREE = new QName(CMIS_NS, "canGetFolderTree");
     public static final QName CAN_GET_PROPERTIES = new QName(CMIS_NS, "canGetProperties");
     public static final QName CAN_GET_OBJECT_RELATIONSHIPS = new QName(CMIS_NS, "canGetObjectRelationships");
-    public static final QName CAN_GET_PARENTS = new QName(CMIS_NS, "canGetParents");
+    public static final QName CAN_GET_OBJECT_PARENTS = new QName(CMIS_NS, "canGetObjectParents");
     public static final QName CAN_GET_FOLDER_PARENT = new QName(CMIS_NS, "canGetFolderParent");
     public static final QName CAN_GET_DESCENDANTS = new QName(CMIS_NS, "canGetDescendants");
-    public static final QName CAN_GET_FOLDER_TREE = new QName(CMIS_NS, "canGetFolderTree");
-    public static final QName CAN_MOVE = new QName(CMIS_NS, "canMove");
-    public static final QName CAN_DELETE_VERSION = new QName(CMIS_NS, "canDeleteVersion");
-    public static final QName CAN_DELETE_CONTENT = new QName(CMIS_NS, "canDeleteContent");
-    public static final QName CAN_CHECKOUT = new QName(CMIS_NS, "canCheckout");
-    public static final QName CAN_CANCEL_CHECKOUT = new QName(CMIS_NS, "canCancelCheckout");
-    public static final QName CAN_CHECKIN = new QName(CMIS_NS, "canCheckin");
-    public static final QName CAN_SET_CONTENT = new QName(CMIS_NS, "canSetContent");
+    public static final QName CAN_MOVE_OBJECT = new QName(CMIS_NS, "canMoveObject");
+    public static final QName CAN_DELETE_CONTENT_STREAM = new QName(CMIS_NS, "canDeleteContentStream");
+    public static final QName CAN_CHECK_OUT = new QName(CMIS_NS, "canCheckOut");
+    public static final QName CAN_CANCEL_CHECK_OUT = new QName(CMIS_NS, "canCancelCheckOut");
+    public static final QName CAN_CHECK_IN = new QName(CMIS_NS, "canCheckIn");
+    public static final QName CAN_SET_CONTENT_STREAM = new QName(CMIS_NS, "canSetContentStream");
     public static final QName CAN_GET_ALL_VERSIONS = new QName(CMIS_NS, "canGetAllVersions");
-    public static final QName CAN_ADD_TO_FOLDER = new QName(CMIS_NS, "canAddToFolder");
-    public static final QName CAN_REMOVE_FROM_FOLDER = new QName(CMIS_NS, "canRemoveFromFolder");
-    public static final QName CAN_VIEW_CONTENT = new QName(CMIS_NS, "canViewContent");
-    public static final QName CAN_ADD_POLICY = new QName(CMIS_NS, "canAddPolicy");
+    public static final QName CAN_ADD_OBJECT_TO_FOLDER = new QName(CMIS_NS, "canAddObjectToFolder");
+    public static final QName CAN_REMOVE_OBJECT_FROM_FOLDER = new QName(CMIS_NS, "canRemoveObjectFromFolder");
+    public static final QName CAN_GET_CONTENT_STREAM = new QName(CMIS_NS, "canGetContentStream");
+    public static final QName CAN_APPLY_POLICY = new QName(CMIS_NS, "canApplyPolicy");
     public static final QName CAN_GET_APPLIED_POLICIES = new QName(CMIS_NS, "canGetAppliedPolicies");
     public static final QName CAN_REMOVE_POLICY = new QName(CMIS_NS, "canRemovePolicy");
     public static final QName CAN_GET_CHILDREN = new QName(CMIS_NS, "canGetChildren");
     public static final QName CAN_CREATE_DOCUMENT = new QName(CMIS_NS, "canCreateDocument");
     public static final QName CAN_CREATE_FOLDER = new QName(CMIS_NS, "canCreateFolder");
     public static final QName CAN_CREATE_RELATIONSHIP = new QName(CMIS_NS, "canCreateRelationship");
-    public static final QName CAN_CREATE_POLICY = new QName(CMIS_NS, "canCreatePolicy");
     public static final QName CAN_DELETE_TREE = new QName(CMIS_NS, "canDeleteTree");
+    public static final QName CAN_GET_RENDITIONS = new QName(CMIS_NS, "canGetRenditions");
+    public static final QName CAN_GET_ACL = new QName(CMIS_NS, "canGetACL");
+    public static final QName CAN_APPLY_ACL = new QName(CMIS_NS, "canApplyACL");
+
+    // CMIS Access Control List
+    public static final QName ACCESS_CONTROL_LIST = new QName(CMIS_NS, "acl");
+    public static final QName PRINCIPAL = new QName(CMIS_NS, "principal");
+    public static final QName PRINCIPAL_ID = new QName(CMIS_NS, "principalId");
+    public static final QName PERMISSION = new QName(CMIS_NS, "permission");
+    public static final QName DIRECT = new QName(CMIS_NS, "direct");
 
     // CMIS Type Names
     public static final String TYPE_DOCUMENT = "cmis:document";

Modified: incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISExtensionFactory.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISExtensionFactory.java?rev=905667&r1=905666&r2=905667&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISExtensionFactory.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISExtensionFactory.java Tue Feb  2 15:08:19 2010
@@ -44,6 +44,7 @@
         super(CMIS_NS, CMISRA_NS);
         addImpl(REPOSITORY_INFO, CMISRepositoryInfo.class);
         addImpl(CAPABILITIES, CMISCapabilities.class);
+        addImpl(ACL_CAPABILITY, CMISACLCapability.class);
         addImpl(URI_TEMPLATE, CMISUriTemplate.class);
         addImpl(OBJECT, CMISObject.class);
         addImpl(CONTENT, CMISContent.class);
@@ -59,6 +60,8 @@
         addImpl(HTML_PROPERTY, CMISPropertyHtml.class);
         addImpl(PROPERTY_VALUE, CMISValue.class);
         addImpl(ALLOWABLE_ACTIONS, CMISAllowableActions.class);
+        addImpl(ACCESS_CONTROL_LIST, CMISAccessControlList.class);
+        addImpl(PERMISSION, CMISAccessControlEntry.class);
         addImpl(TYPE_DEFINITION, CMISTypeDefinition.class);
         addImpl(STRING_PROPERTY_DEFINITION, CMISPropertyStringDefinition.class);
         addImpl(DECIMAL_PROPERTY_DEFINITION, CMISPropertyDecimalDefinition.class);
@@ -68,33 +71,35 @@
         addImpl(URI_PROPERTY_DEFINITION, CMISPropertyUriDefinition.class);
         addImpl(ID_PROPERTY_DEFINITION, CMISPropertyIdDefinition.class);
         addImpl(HTML_PROPERTY_DEFINITION, CMISPropertyHtmlDefinition.class);
-        addImpl(CAN_DELETE, CMISAllowableAction.class);
+        addImpl(CAN_DELETE_OBJECT, CMISAllowableAction.class);
         addImpl(CAN_UPDATE_PROPERTIES, CMISAllowableAction.class);
+        addImpl(CAN_GET_FOLDER_TREE, CMISAllowableAction.class);
         addImpl(CAN_GET_PROPERTIES, CMISAllowableAction.class);
         addImpl(CAN_GET_OBJECT_RELATIONSHIPS, CMISAllowableAction.class);
-        addImpl(CAN_GET_PARENTS, CMISAllowableAction.class);
+        addImpl(CAN_GET_OBJECT_PARENTS, CMISAllowableAction.class);
         addImpl(CAN_GET_FOLDER_PARENT, CMISAllowableAction.class);
         addImpl(CAN_GET_DESCENDANTS, CMISAllowableAction.class);
-        addImpl(CAN_MOVE, CMISAllowableAction.class);
-        addImpl(CAN_DELETE_VERSION, CMISAllowableAction.class);
-        addImpl(CAN_DELETE_CONTENT, CMISAllowableAction.class);
-        addImpl(CAN_CHECKOUT, CMISAllowableAction.class);
-        addImpl(CAN_CANCEL_CHECKOUT, CMISAllowableAction.class);
-        addImpl(CAN_CHECKIN, CMISAllowableAction.class);
-        addImpl(CAN_SET_CONTENT, CMISAllowableAction.class);
+        addImpl(CAN_MOVE_OBJECT, CMISAllowableAction.class);
+        addImpl(CAN_DELETE_CONTENT_STREAM, CMISAllowableAction.class);
+        addImpl(CAN_CHECK_OUT, CMISAllowableAction.class);
+        addImpl(CAN_CANCEL_CHECK_OUT, CMISAllowableAction.class);
+        addImpl(CAN_CHECK_IN, CMISAllowableAction.class);
+        addImpl(CAN_SET_CONTENT_STREAM, CMISAllowableAction.class);
         addImpl(CAN_GET_ALL_VERSIONS, CMISAllowableAction.class);
-        addImpl(CAN_ADD_TO_FOLDER, CMISAllowableAction.class);
-        addImpl(CAN_REMOVE_FROM_FOLDER, CMISAllowableAction.class);
-        addImpl(CAN_VIEW_CONTENT, CMISAllowableAction.class);
-        addImpl(CAN_ADD_POLICY, CMISAllowableAction.class);
+        addImpl(CAN_ADD_OBJECT_TO_FOLDER, CMISAllowableAction.class);
+        addImpl(CAN_REMOVE_OBJECT_FROM_FOLDER, CMISAllowableAction.class);
+        addImpl(CAN_GET_CONTENT_STREAM, CMISAllowableAction.class);
+        addImpl(CAN_APPLY_POLICY, CMISAllowableAction.class);
         addImpl(CAN_GET_APPLIED_POLICIES, CMISAllowableAction.class);
         addImpl(CAN_REMOVE_POLICY, CMISAllowableAction.class);
         addImpl(CAN_GET_CHILDREN, CMISAllowableAction.class);
         addImpl(CAN_CREATE_DOCUMENT, CMISAllowableAction.class);
         addImpl(CAN_CREATE_FOLDER, CMISAllowableAction.class);
         addImpl(CAN_CREATE_RELATIONSHIP, CMISAllowableAction.class);
-        addImpl(CAN_CREATE_POLICY, CMISAllowableAction.class);
         addImpl(CAN_DELETE_TREE, CMISAllowableAction.class);
+        addImpl(CAN_GET_RENDITIONS, CMISAllowableAction.class);
+        addImpl(CAN_GET_ACL, CMISAllowableAction.class);
+        addImpl(CAN_APPLY_ACL, CMISAllowableAction.class);
         addImpl(CHILDREN, CMISChildren.class);
     }
 

Modified: incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISRepositoryInfo.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISRepositoryInfo.java?rev=905667&r1=905666&r2=905667&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISRepositoryInfo.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISRepositoryInfo.java Tue Feb  2 15:08:19 2010
@@ -116,4 +116,28 @@
         }
         return null;
     }
+
+    public CMISACLCapability getACLCapability() {
+        Element child = getFirstChild(CMISConstants.ACL_CAPABILITY);
+        if (child != null) {
+            return (CMISACLCapability) child;
+        }
+        return null;
+    }
+
+    public String getPrincipalAnonymous() {
+        Element child = getFirstChild(CMISConstants.PRINCIPAL_ANONYMOUS);
+        if (child != null) {
+            return child.getText();
+        }
+        return null;
+    }
+
+    public String getPrincipalAnyone() {
+        Element child = getFirstChild(CMISConstants.PRINCIPAL_ANYONE);
+        if (child != null) {
+            return child.getText();
+        }
+        return null;
+    }
 }

Modified: incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISTypeDefinition.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISTypeDefinition.java?rev=905667&r1=905666&r2=905667&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISTypeDefinition.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/abdera/ext/CMISTypeDefinition.java Tue Feb  2 15:08:19 2010
@@ -44,6 +44,16 @@
     }
 
     /**
+     * Determines whether objects of this type are controllable by ACLs.
+     * 
+     * @return <code>true</code> if objects of this type are controllable by
+     *         ACLs
+     */
+    public boolean getControllableACL() {
+        return Boolean.parseBoolean(getFirstChild(CMISConstants.TYPE_CONTROLLABLE_ACL).getText());
+    }
+
+    /**
      * Gets all Property Definitions for this CMIS Type
      * 
      * @return property definitions

Modified: incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/TCKTest.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/TCKTest.java?rev=905667&r1=905666&r2=905667&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/TCKTest.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/TCKTest.java Tue Feb  2 15:08:19 2010
@@ -76,7 +76,7 @@
         String url = options.getServiceUrl();
         if (url == null)
             fail("CMIS Service URL not specified");
-        client = new CMISClient(connection, url, messageWriter);
+        client = new CMISClient(user, connection, url, messageWriter);
         boolean validate = options.getValidate();
         client.setValidate(validate);
         boolean failOnValidationError = options.getFailOnValidationError();

Modified: incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/client/CMISClient.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/client/CMISClient.java?rev=905667&r1=905666&r2=905667&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/client/CMISClient.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/client/CMISClient.java Tue Feb  2 15:08:19 2010
@@ -39,6 +39,7 @@
 import org.apache.abdera.model.Link;
 import org.apache.abdera.model.Service;
 import org.apache.abdera.model.Workspace;
+import org.apache.chemistry.abdera.ext.CMISACLCapability;
 import org.apache.chemistry.abdera.ext.CMISCapabilities;
 import org.apache.chemistry.abdera.ext.CMISConstants;
 import org.apache.chemistry.abdera.ext.CMISObject;
@@ -65,6 +66,7 @@
 
     private TCKMessageWriter messageWriter;
 
+    private String userId;
     private Connection connection;
     private boolean traceConnection;
 
@@ -82,7 +84,8 @@
     private CMISRepositoryInfo cmisRepositoryInfo = null;
 
 
-    public CMISClient(Connection connection, String serviceUrl, TCKMessageWriter messageWriter) {
+    public CMISClient(String userId, Connection connection, String serviceUrl, TCKMessageWriter messageWriter) {
+        this.userId = userId;
         this.connection = connection;
         this.serviceUrl = serviceUrl;
         this.messageWriter = messageWriter;
@@ -99,6 +102,11 @@
     public void setTrace(boolean trace) {
         this.traceConnection = trace;
     }
+    
+    public String getUserId()
+    {
+        return this.userId;
+    }
 
     public Service getRepository() throws Exception {
         if (cmisService == null) {
@@ -128,6 +136,10 @@
         return getRepositoryInfo().getCapabilities();
     }
 
+    public CMISACLCapability getACLCapability() throws Exception {
+        return getRepositoryInfo().getACLCapability();
+    }
+
     public Workspace getWorkspace() throws Exception {
         return getRepository().getWorkspaces().get(0);
     }
@@ -493,7 +505,8 @@
                     if (contentType.startsWith(CMISConstants.MIMETYPE_ATOM)) {
                         mimetypeValidator = getAtomValidator();
                     }
-                    else if (contentType.startsWith(CMISConstants.MIMETYPE_APP)) {
+                    else if (contentType.startsWith(CMISConstants.MIMETYPE_APP)
+                            || contentType.startsWith(CMISConstants.MIMETYPE_CMISACL)) {
                         mimetypeValidator = getAppValidator();
                     }
                 } catch(SAXException e) {}

Modified: incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/test/TCKTestSuite.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/test/TCKTestSuite.java?rev=905667&r1=905666&r2=905667&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/test/TCKTestSuite.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/test/TCKTestSuite.java Tue Feb  2 15:08:19 2010
@@ -20,6 +20,7 @@
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
 
+import org.apache.chemistry.tck.atompub.test.spec.AccessControlListTest;
 import org.apache.chemistry.tck.atompub.test.spec.AllowableActionsTest;
 import org.apache.chemistry.tck.atompub.test.spec.ContentStreamTest;
 import org.apache.chemistry.tck.atompub.test.spec.CreateTest;
@@ -59,6 +60,7 @@
         suite.addTestSuite(QueryPagingTest.class);
         suite.addTestSuite(AllowableActionsTest.class);
         suite.addTestSuite(VersionsTest.class);
+        suite.addTestSuite(AccessControlListTest.class);
         
         // custom type tests
         // TODO: when mechanism for registering custom types is done

Added: incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/test/spec/AccessControlListTest.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/test/spec/AccessControlListTest.java?rev=905667&view=auto
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/test/spec/AccessControlListTest.java (added)
+++ incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/test/spec/AccessControlListTest.java Tue Feb  2 15:08:19 2010
@@ -0,0 +1,377 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Authors:
+ *     David Ward, Alfresco
+ */
+package org.apache.chemistry.tck.atompub.test.spec;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.abdera.i18n.iri.IRI;
+import org.apache.abdera.model.Element;
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.model.Link;
+import org.apache.chemistry.abdera.ext.CMISACLCapability;
+import org.apache.chemistry.abdera.ext.CMISAccessControlEntry;
+import org.apache.chemistry.abdera.ext.CMISAccessControlList;
+import org.apache.chemistry.abdera.ext.CMISAllowableActions;
+import org.apache.chemistry.abdera.ext.CMISConstants;
+import org.apache.chemistry.abdera.ext.CMISObject;
+import org.apache.chemistry.abdera.ext.CMISRepositoryInfo;
+import org.apache.chemistry.abdera.ext.CMISTypeDefinition;
+import org.apache.chemistry.abdera.ext.CMISUriTemplate;
+import org.apache.chemistry.tck.atompub.TCKSkipCapabilityException;
+import org.apache.chemistry.tck.atompub.TCKTest;
+import org.apache.chemistry.tck.atompub.http.GetRequest;
+import org.apache.chemistry.tck.atompub.http.PutRequest;
+import org.apache.chemistry.tck.atompub.http.Request;
+import org.apache.chemistry.tck.atompub.http.Response;
+import org.junit.Assert;
+
+/**
+ * CMIS Access Control List Tests.
+ */
+public class AccessControlListTest extends TCKTest {
+
+    /**
+     * Test folder access control list.
+     * 
+     * @throws Exception
+     *             on error
+     */
+    public void testFolderAccessControlList() throws Exception {
+        checkACLCapability(false);
+        Entry folder = fixture.createTestFolder("testAccessControlList");
+
+        Link accessControlListLink = folder.getLink(CMISConstants.REL_ACL);
+        Request req = new GetRequest(accessControlListLink.getHref().toString());
+        Response accessControlListRes = client.executeRequest(req, 200);
+        Assert.assertNotNull(accessControlListRes);
+        Element accessControlList = model.parse(new StringReader(accessControlListRes.getContentAsString()), null);
+        Assert.assertNotNull(accessControlList);
+        Assert.assertTrue(accessControlList instanceof CMISAccessControlList);
+        CMISObject childObject = folder.getExtension(CMISConstants.OBJECT);
+        Assert.assertNotNull(childObject);
+        String objectId = childObject.getObjectId().getStringValue();
+        Assert.assertNotNull(objectId);
+
+        // Fetch via ID, this time with ACL
+        CMISUriTemplate objectByIdTemplate = client.getObjectByIdUriTemplate(client.getWorkspace());
+        Map<String, Object> variables = new HashMap<String, Object>(5);
+        variables.put("id", objectId);
+        variables.put("includeACL", "true");
+        IRI objectByIdRequest = objectByIdTemplate.generateUri(variables);
+        folder = client.getEntry(objectByIdRequest);
+
+        Assert.assertNotNull(folder);
+        childObject = folder.getExtension(CMISConstants.OBJECT);
+        Assert.assertNotNull(childObject);
+        CMISAccessControlList objectAccessControlList = childObject.getExtension(CMISConstants.ACCESS_CONTROL_LIST);
+        Assert.assertNotNull(objectAccessControlList);
+        Assert.assertEquals(hashAccessControlList((CMISAccessControlList) accessControlList),
+                hashAccessControlList(objectAccessControlList));
+    }
+
+    /**
+     * Test document access control list.
+     * 
+     * @throws Exception
+     *             on error
+     */
+    public void testDocumentAccessControlList() throws Exception {
+        checkACLCapability(false);
+        Entry document = fixture.createTestDocument("testDocumentAccessControlList");
+
+        Link accessControlListLink = document.getLink(CMISConstants.REL_ACL);
+        Request req = new GetRequest(accessControlListLink.getHref().toString());
+        Response accessControlListRes = client.executeRequest(req, 200);
+        Assert.assertNotNull(accessControlListRes);
+        Element accessControlList = model.parse(new StringReader(accessControlListRes.getContentAsString()), null);
+        Assert.assertNotNull(accessControlList);
+        Assert.assertTrue(accessControlList instanceof CMISAccessControlList);
+        CMISObject childObject = document.getExtension(CMISConstants.OBJECT);
+        Assert.assertNotNull(childObject);
+        String objectId = childObject.getObjectId().getStringValue();
+        Assert.assertNotNull(objectId);
+
+        // Fetch via ID, this time with ACL
+        CMISUriTemplate objectByIdTemplate = client.getObjectByIdUriTemplate(client.getWorkspace());
+        Map<String, Object> variables = new HashMap<String, Object>(5);
+        variables.put("id", objectId);
+        variables.put("includeACL", "true");
+        IRI objectByIdRequest = objectByIdTemplate.generateUri(variables);
+        document = client.getEntry(objectByIdRequest);
+
+        Assert.assertNotNull(document);
+        childObject = document.getExtension(CMISConstants.OBJECT);
+        Assert.assertNotNull(childObject);
+        CMISAccessControlList objectAccessControlList = childObject.getExtension(CMISConstants.ACCESS_CONTROL_LIST);
+        Assert.assertNotNull(objectAccessControlList);
+        Assert.assertEquals(hashAccessControlList((CMISAccessControlList) accessControlList),
+                hashAccessControlList(objectAccessControlList));
+    }
+
+    /**
+     * Test manage access control list.
+     * 
+     * @throws Exception
+     *             on error
+     */
+    public void testManageAccessControlList() throws Exception {
+        checkACLCapability(true);
+        Entry document = fixture.createTestDocument("testManageAccessControlList");
+
+        Link accessControlListLink = document.getLink(CMISConstants.REL_ACL);
+        Request req = new GetRequest(accessControlListLink.getHref().toString());
+        Response accessControlListRes = client.executeRequest(req, 200);
+        Assert.assertNotNull(accessControlListRes);
+        Element accessControlList = model.parse(new StringReader(accessControlListRes.getContentAsString()), null);
+        Assert.assertNotNull(accessControlList);
+        Assert.assertTrue(accessControlList instanceof CMISAccessControlList);
+        CMISObject childObject = document.getExtension(CMISConstants.OBJECT);
+        Assert.assertNotNull(childObject);
+        String objectId = childObject.getObjectId().getStringValue();
+        Assert.assertNotNull(objectId);
+
+        // Check whether apply ACL is an allowable action
+        CMISAllowableActions objectAllowableActions = childObject.getExtension(CMISConstants.ALLOWABLE_ACTIONS);
+        Assert.assertNotNull(objectAllowableActions);
+        boolean canApplyACL = objectAllowableActions.isAllowed("canApplyACL");
+
+        // Check whether the typedef allows ACL management
+        Link typeLink = document.getLink(CMISConstants.REL_DESCRIBED_BY);
+        Assert.assertNotNull(typeLink);
+        Entry type = client.getEntry(typeLink.getHref());
+        Assert.assertNotNull(type);
+        CMISTypeDefinition docType = type.getExtension(CMISConstants.TYPE_DEFINITION);
+        Assert.assertNotNull(docType);
+        boolean controllableACL = docType.getControllableACL();
+        if (!controllableACL) {
+            Assert.assertFalse(canApplyACL);
+        }
+        // If we are not allowed to apply the ACL, we should expect an error
+        // status code
+        int expectedStatusMin = 200, expectedStatusMax = 200;
+        if (!canApplyACL) {
+            expectedStatusMin = 400;
+            expectedStatusMax = 499;
+        }
+
+        // Convert the ACL to an easy to use form
+        Set<List<Object>> hashedACL = hashAccessControlList((CMISAccessControlList) accessControlList);
+
+        // Take a back up for future reference
+        Set<List<Object>> originalACL = new HashSet<List<Object>>(hashedACL);
+
+        // Choose some permissions to add in to the ACL
+        CMISACLCapability aclCapability = client.getACLCapability();
+        Assert.assertNotNull(aclCapability);
+        Set<String> repositoryPermissions = new HashSet<String>(aclCapability.getRepositoryPermissions());
+        String supportedPermissions = aclCapability.getSupportedPermissions();
+        CMISRepositoryInfo info = client.getRepositoryInfo();
+
+        // Add some ACES with repository permissions if supported
+        if (!supportedPermissions.equals("basic")) {
+            chooseRepositoryPermission(repositoryPermissions, client.getUserId(), hashedACL);
+            chooseRepositoryPermission(repositoryPermissions, info.getPrincipalAnonymous(), hashedACL);
+            chooseRepositoryPermission(repositoryPermissions, info.getPrincipalAnyone(), hashedACL);
+        }
+
+        // Add some ACES with CMIS permissions if supported
+        if (!supportedPermissions.equals("repository")) {
+            addAce(client.getUserId(), hashedACL, "cmis:write");
+            addAce(info.getPrincipalAnonymous(), hashedACL, "cmis:read");
+            addAce(info.getPrincipalAnyone(), hashedACL, "cmis:read");
+        }
+
+        // Apply the ACL with the additions
+        accessControlList = applyACL(accessControlListLink, hashedACL, expectedStatusMin, expectedStatusMax);
+
+        // If we expected success, try removing the ACEs we added and restoring the ACL to its original state
+        if (accessControlList != null) {
+            applyACL(accessControlListLink, originalACL, expectedStatusMin, expectedStatusMax);
+        }
+    }
+
+    /**
+     * Check whether we have sufficient capability to read and/or manage acls.
+     * 
+     * @param manage
+     *            <code>true</code> if we require management capability or
+     *            <code>false</code> if read capability is sufficient.
+     * 
+     * @throws TCKSkipCapabilityException
+     *             if we don't have sufficient capability
+     * @throws Exception
+     *             on error
+     */
+    private void checkACLCapability(boolean manage) throws TCKSkipCapabilityException, Exception {
+        String aclCapability = client.getCapabilities().getACL();
+        if (manage) {
+            if (!aclCapability.equals("manage")) {
+                throw new TCKSkipCapabilityException("ACL", "manage", aclCapability);
+            }
+        } else {
+            if (aclCapability.equals("none")) {
+                throw new TCKSkipCapabilityException("ACL", "read", aclCapability);
+            }
+        }
+        // Ensure the ACL capability info has been supplied as required
+        assertNotNull(client.getACLCapability());
+    }
+
+    /**
+     * Flattens an access control list into a structure that is easy to compare:
+     * a set of triples containing the principal ID, the direct flag and the
+     * permission name.
+     * 
+     * @param accessControlList
+     *            the access control list
+     * 
+     * @return the set of triples
+     */
+    private static Set<List<Object>> hashAccessControlList(CMISAccessControlList accessControlList) {
+        List<CMISAccessControlEntry> entries = accessControlList.getEntries();
+        Set<List<Object>> hashSet = new HashSet<List<Object>>(entries.size() * 2);
+        for (CMISAccessControlEntry accessControlEntry : entries) {
+            String principalId = accessControlEntry.getPrincipalId();
+            Boolean direct = accessControlEntry.isDirect();
+            for (String permission : accessControlEntry.getPermissions()) {
+                List<Object> comparable = new ArrayList<Object>(3);
+                comparable.add(principalId);
+                comparable.add(direct);
+                comparable.add(permission);
+                hashSet.add(comparable);
+            }
+        }
+        return hashSet;
+    }
+
+    /**
+     * Chooses a repository permission to add to an ACL for a given principal.
+     * Tries to find one that would result in a new entry.
+     * 
+     * @param repositoryPermissions
+     *            the repository permissions. Permissions are removed as they
+     *            are used
+     * @param principalId
+     *            the principal id. If <code>null</code> the method returns
+     *            immediately.
+     * @param hashedACL
+     *            the current state of the ACL. Tries to avoid creating an ACE
+     *            that is already present. The ace with the chosen permission is
+     *            added to this set
+     * 
+     * @return an ACE with the chosen permission or <code>null</code> if it was
+     *         not possible to choose one< object>
+     */
+    private static List<Object> chooseRepositoryPermission(Set<String> repositoryPermissions, String principalId,
+            Set<List<Object>> hashedACL) {
+        if (principalId == null) {
+            return null;
+        }
+        List<Object> potential = new ArrayList<Object>(3);
+        potential.add(principalId);
+        potential.add(Boolean.TRUE);
+        for (String permission : repositoryPermissions) {
+            potential.add(permission);
+            if (hashedACL.add(potential)) {
+                repositoryPermissions.remove(permission);
+                return potential;
+            }
+            potential.remove(2);
+        }
+        return null;
+    }
+
+    /**
+     * Adds an ACE for the given principal and permission to the given ACL if it
+     * does not already exist.
+     * 
+     * @param principalId
+     *            the principal id. If <code>null</code> the method returns
+     *            immediately.
+     * @param hashedACL
+     *            the current state of the ACL. The ace with the chosen given is
+     *            added to this set
+     * @param permission
+     *            the permission
+     * 
+     * @return an ACE with the permission if it did not already exist in the ACL
+     *         or <code>null</code> otherwise
+     */
+    private static List<Object> addAce(String principalId, Set<List<Object>> hashedACL, String permission) {
+        if (principalId == null) {
+            return null;
+        }
+        List<Object> potential = new ArrayList<Object>(3);
+        potential.add(principalId);
+        potential.add(Boolean.TRUE);
+        potential.add(permission);
+        if (hashedACL.add(potential)) {
+            return potential;
+        }
+        return null;
+    }
+
+    /**
+     * Applies the given ACL using the CMIS API.
+     * 
+     * @param accessControlListLink
+     *            the access control list link
+     * @param hashedACL
+     *            the hashed ACL
+     * @param expectedStatusMin
+     *            Minimum expected result status code
+     * @param expectedStatusMax
+     *            Maximum expected result status code
+     * 
+     * @return the resulting access control list
+     * 
+     * @throws Exception
+     *             on error
+     */
+    private CMISAccessControlList applyACL(Link accessControlListLink, Set<List<Object>> hashedACL,
+            int expectedStatusMin, int expectedStatusMax) throws Exception {
+        StringBuilder buff = new StringBuilder(1024);
+        buff.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>").append(
+                "<cmis:acl xmlns:cmis=\"http://docs.oasis-open.org/ns/cmis/core/200908/\">");
+        for (List<Object> ace : hashedACL) {
+            buff.append("<cmis:permission><cmis:principal><cmis:principalId>").append(ace.get(0)).append(
+                    "</cmis:principalId></cmis:principal><cmis:permission>").append(ace.get(2)).append(
+                    "</cmis:permission><cmis:direct>").append(ace.get(1)).append("</cmis:direct></cmis:permission>");
+        }
+        buff.append("</cmis:acl>");
+        String req = buff.toString();
+        client.getAppValidator().validate(new StreamSource(new StringReader(req)));
+        Request putReq = new PutRequest(accessControlListLink.getHref().toString(), req, CMISConstants.MIMETYPE_CMISACL);
+        Response aclRes = client.executeRequest(putReq, expectedStatusMin, expectedStatusMax);
+        Assert.assertNotNull(aclRes);
+        if (aclRes.getStatus() == 200) {
+            Element accessControlList = model.parse(new StringReader(aclRes.getContentAsString()), null);
+            Assert.assertNotNull(accessControlList);
+            Assert.assertTrue(accessControlList instanceof CMISAccessControlList);
+            return (CMISAccessControlList) accessControlList;
+        }
+        return null;
+    }
+}

Propchange: incubator/chemistry/trunk/chemistry/chemistry-tck-atompub/src/main/java/org/apache/chemistry/tck/atompub/test/spec/AccessControlListTest.java
------------------------------------------------------------------------------
    svn:eol-style = native