You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by je...@apache.org on 2011/10/02 22:35:13 UTC

svn commit: r1178250 [2/3] - in /chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src: main/java/org/apache/chemistry/opencmis/inmemory/ main/java/org/apache/chemistry/opencmis/inmemory/query/ main/java/org/apache/c...

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/ObjectStoreImpl.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/ObjectStoreImpl.java?rev=1178250&r1=1178249&r2=1178250&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/ObjectStoreImpl.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/ObjectStoreImpl.java Sun Oct  2 20:35:12 2011
@@ -26,14 +26,17 @@ import java.util.concurrent.ConcurrentHa
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
+import org.apache.chemistry.opencmis.commons.data.Ace;
 import org.apache.chemistry.opencmis.commons.data.Acl;
 import org.apache.chemistry.opencmis.commons.data.ContentStream;
 import org.apache.chemistry.opencmis.commons.data.PropertyData;
+import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
 import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
 import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
 import org.apache.chemistry.opencmis.commons.enums.VersioningState;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException;
 import org.apache.chemistry.opencmis.inmemory.storedobj.api.Document;
 import org.apache.chemistry.opencmis.inmemory.storedobj.api.DocumentVersion;
 import org.apache.chemistry.opencmis.inmemory.storedobj.api.Folder;
@@ -70,6 +73,12 @@ import org.apache.chemistry.opencmis.inm
  */
 public class ObjectStoreImpl implements ObjectStore {
 
+    
+    /**
+     * user id for administrator always having all rights
+     */
+    public static final String ADMIN_PRINCIPAL_ID = "Admin";
+    
     /**
      * Simple id generator that uses just an integer
      */
@@ -80,6 +89,13 @@ public class ObjectStoreImpl implements 
      */
     private final Map<String, StoredObject> fStoredObjectMap = new ConcurrentHashMap<String, StoredObject>();
 
+    /**
+     * a concurrent HashMap to hold all Acls in the repository
+     */
+    private static int NEXT_UNUSED_ACL_ID = 1;
+    
+    private final List<InMemoryAcl> fAcls = new ArrayList<InMemoryAcl>();
+
     private final Lock fLock = new ReentrantLock();
 
     final String fRepositoryId;
@@ -94,7 +110,11 @@ public class ObjectStoreImpl implements 
         return NEXT_UNUSED_ID++;
     }
 
-    public void lock() {
+    private static synchronized Integer getNextAclId() {
+        return NEXT_UNUSED_ACL_ID++;
+    }
+    
+   public void lock() {
       fLock.lock();
     }
 
@@ -232,6 +252,8 @@ public class ObjectStoreImpl implements 
         if (null != folder) {
             ((FolderImpl)folder).addChildDocument(doc); // add document to folder and
         }
+        int aclId = getAclId(((FolderImpl)folder), addACEs, removeACEs);
+        doc.setAclId(aclId);
         return doc;
     }
 
@@ -249,6 +271,8 @@ public class ObjectStoreImpl implements 
         }
         version.createSystemBasePropertiesWhenCreated(propMap, user);
         version.setCustomProperties(propMap);
+        int aclId = getAclId(((FolderImpl)folder), addACEs, removeACEs);
+        doc.setAclId(aclId);
         doc.persist();
         return version;
     }
@@ -266,6 +290,10 @@ public class ObjectStoreImpl implements 
         if (null != parent) {
         	((FolderImpl)parent).addChildFolder(folder); // add document to folder and set
         }
+
+        int aclId = getAclId(((FolderImpl)parent), addACEs, removeACEs);
+        folder.setAclId(aclId);
+        
         return folder;
     }
 
@@ -282,8 +310,8 @@ public class ObjectStoreImpl implements 
         for (StoredObject so : fStoredObjectMap.values()) {
             if (so instanceof VersionedDocument) {
                 VersionedDocument verDoc = (VersionedDocument) so;
-                if (verDoc.isCheckedOut()) {
-                    res.add(verDoc);
+                if (verDoc.isCheckedOut() && hasReadAccess(user, verDoc)) {
+                    res.add(verDoc.getPwc());
                 }
             }
         }
@@ -291,6 +319,81 @@ public class ObjectStoreImpl implements 
         return res;
     }
 
+	public StoredObject createRelationship(StoredObject sourceObject,
+			StoredObject targetObject, Map<String, PropertyData<?>> propMap,
+			String user, Acl addACEs, Acl removeACEs) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+    public Acl applyAcl(StoredObject so, Acl addAces, Acl removeAces, AclPropagation aclPropagation, String principalId) {
+        if (aclPropagation==AclPropagation.OBJECTONLY || !(so instanceof Folder)) {
+            return applyAcl(so, addAces, removeAces);
+        } else {
+            return applyAclRecursive(((Folder)so), addAces, removeAces, principalId);            
+        }
+    }
+    
+    public Acl applyAcl(StoredObject so, Acl acl, AclPropagation aclPropagation, String principalId) {
+        if (aclPropagation==AclPropagation.OBJECTONLY || !(so instanceof Folder)) {
+            return applyAcl(so, acl);
+        } else {
+            return applyAclRecursive(((Folder)so), acl, principalId);
+        }
+    }
+
+    public List<Integer> getAllAclsForUser(String principalId, Permission permission) {
+        List<Integer> acls = new ArrayList<Integer>();
+        acls.add(0); // ACL with id 0 means no ACL set granting all users any access rights
+        for (InMemoryAcl acl: fAcls) {
+            if (acl.hasPermission(principalId, permission))
+                acls.add(acl.getId());
+        }
+        return acls;
+    }
+    
+    public Acl getAcl(int aclId) {
+        InMemoryAcl acl = getInMemoryAcl(aclId);
+        return acl==null ? null : acl.toCommonsAcl();
+    }
+    
+    public int getAclId(StoredObjectImpl so, Acl addACEs, Acl removeACEs) {
+        InMemoryAcl newAcl;
+        
+        if (so == null) {
+            newAcl = new InMemoryAcl();
+        } else {
+            newAcl = getInMemoryAcl(so.getAclId());
+            if (null == newAcl)
+                newAcl = new InMemoryAcl();
+            else
+                // copy list so that we can safely change it without effecting the original
+                newAcl = new InMemoryAcl(newAcl.getAces()); 
+        }
+
+        if (newAcl.size() == 0 && addACEs == null && removeACEs == null)
+            return 0;
+
+        // add ACEs
+        if (null != addACEs)
+            for (Ace ace: addACEs.getAces()) {
+                InMemoryAce inMemAce = new InMemoryAce(ace);
+                newAcl.addAce(inMemAce);
+            }
+        
+        // remove ACEs
+        if (null != removeACEs)
+            for (Ace ace: removeACEs.getAces()) {
+                InMemoryAce inMemAce = new InMemoryAce(ace);
+                newAcl.removeAce(inMemAce);
+            }
+
+        if (newAcl.size() > 0)
+            return addAcl(newAcl);
+        else
+            return 0;
+    }
+    
     private void deleteFolder(String folderId, String user) {
         StoredObject folder = fStoredObjectMap.get(folderId);
         if (folder == null) {
@@ -311,11 +414,162 @@ public class ObjectStoreImpl implements 
         fStoredObjectMap.remove(folderId);
     }
 
-	public StoredObject createRelationship(StoredObject sourceObject,
-			StoredObject targetObject, Map<String, PropertyData<?>> propMap,
-			String user, Acl addACEs, Acl removeACEs) {
-		// TODO Auto-generated method stub
-		return null;
+    public boolean hasReadAccess(String principalId, StoredObject so) {       
+        return hasAccess(principalId, so, Permission.READ);
+    }
+    /*
+    public boolean hasReadAccess(String principalId, StoredObject so) {       
+        int aclId = ((StoredObjectImpl)so).getAclId();
+        if (0 == aclId || null == principalId) 
+            return true; // no ACL set or user is admin user
+        List<Integer> aclIds = getAllAclsForUser(principalId, Permission.READ);
+        return hasAccess(principalId, so, Permission.READ);
+    }
+    */
+    public boolean hasWriteAccess(String principalId, StoredObject so) {       
+        return hasAccess(principalId, so, Permission.WRITE);
+    }
+
+    public boolean hasAllAccess(String principalId, StoredObject so) {       
+        return hasAccess(principalId, so, Permission.ALL);
+    }
+    
+
+    public void checkReadAccess(String principalId, StoredObject so) {
+        checkAccess(principalId, so, Permission.READ);
+    }
+    
+    public void checkWriteAccess(String principalId, StoredObject so) {
+        checkAccess(principalId, so, Permission.WRITE);
+    }
+    
+    public void checkAllAccess(String principalId, StoredObject so) {
+        checkAccess(principalId, so, Permission.ALL);
+    }
+ 
+    private void checkAccess(String principalId, StoredObject so, Permission permission) {
+        if (!hasAccess(principalId, so, permission))
+            throw new CmisPermissionDeniedException("Object with id " + so.getId() + " and name " + so.getName()
+                    + " does not grant " + permission.toString() + " access to principal " + principalId);
+    }
+
+    private boolean hasAccess(String principalId, StoredObject so, Permission permission) {
+        if (null != principalId && principalId.equals(ADMIN_PRINCIPAL_ID))
+            return true;
+        List<Integer> aclIds = getAllAclsForUser(principalId, permission);        
+        return aclIds.contains(((StoredObjectImpl)so).getAclId());
+    }
+
+    private InMemoryAcl getInMemoryAcl(int aclId) {
+        if (0 == aclId)
+            return null;
+        
+        for (InMemoryAcl acl : fAcls) {
+            if (aclId == acl.getId())
+                return acl;
+        }
+        return null;
+    }
+
+    private int setAcl(StoredObjectImpl so, Acl acl) {
+        int aclId;
+        if (null == acl || acl.getAces().isEmpty())
+            aclId = 0;
+        else {
+            aclId = getAclId(null, acl, null);
+        }
+        so.setAclId(aclId);
+        return aclId;
+    }
+    
+	/**
+	 * check if an Acl is already known
+	 * @param acl
+	 *     acl to be checked
+	 * @return
+	 *     0 if Acl is not known, id of Acl otherwise
+	 */
+	private int hasAcl(InMemoryAcl acl) {
+	    for (InMemoryAcl acl2: fAcls) {
+	        if (acl2.equals(acl))
+	            return acl2.getId();
+	    }
+	    return 0;
 	}
 
+    private int addAcl(InMemoryAcl acl) {
+        int aclId = 0;
+        
+        if (null == acl)
+            return 0;
+        
+        lock();
+        try {
+            aclId = hasAcl(acl);
+            if (0 == aclId) {
+                aclId = getNextAclId();
+                acl.setId(aclId);
+                fAcls.add(acl);
+            }
+        } finally {
+            unlock();
+        }
+        return aclId;
+    }
+    
+    private Acl applyAcl(StoredObject so, Acl acl) {
+        int aclId = setAcl((StoredObjectImpl) so, acl);
+        return getAcl(aclId);
+    }
+
+    private Acl applyAcl(StoredObject so, Acl addAces, Acl removeAces) {
+        int aclId = getAclId((StoredObjectImpl) so, addAces, removeAces);
+        ((StoredObjectImpl) so).setAclId(aclId);
+        return getAcl(aclId);
+    }
+
+    private Acl applyAclRecursive(Folder folder, Acl addAces, Acl removeAces, String principalId) {
+        List<StoredObject> children = folder.getChildren(-1, -1, ADMIN_PRINCIPAL_ID);
+        
+        Acl result = applyAcl(folder, addAces, removeAces);  
+
+        if (null == children) {
+            return result;
+        }
+        
+        for (StoredObject child : children) {
+            if (hasAllAccess(principalId, child)) {
+                if (child instanceof Folder) {
+                    applyAclRecursive((Folder) child, addAces, removeAces, principalId);                
+                } else {
+                    applyAcl(child, addAces, removeAces);               
+                }
+            }
+        }
+        
+        return result;
+    }
+    
+    private Acl applyAclRecursive(Folder folder, Acl acl, String principalId) {
+        List<StoredObject> children = folder.getChildren(-1, -1, ADMIN_PRINCIPAL_ID);
+
+        Acl result = applyAcl(folder, acl);  
+
+        if (null == children) {
+            return result;
+        }
+
+        for (StoredObject child : children) {
+            if (hasAllAccess(principalId, child)) {
+                if (child instanceof Folder) {
+                    applyAclRecursive((Folder) child, acl, principalId);                
+                } else {
+                    applyAcl(child, acl);               
+                }
+            }
+        }
+        
+        return result;
+    }
+
 }

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/Permission.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/Permission.java?rev=1178250&r1=1178249&r2=1178250&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/Permission.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/Permission.java Sun Oct  2 20:35:12 2011
@@ -18,6 +18,8 @@
  */
 package org.apache.chemistry.opencmis.inmemory.storedobj.impl;
 
+import org.apache.chemistry.opencmis.commons.impl.jaxb.EnumBasicPermissions;
+
 
 public enum Permission {
     NONE("none"),
@@ -46,15 +48,25 @@ public enum Permission {
     
     public static Permission fromCmisString(String strPerm) {
         Permission permission;
-        if (strPerm.equals("cmis:read")) 
+        if (strPerm.equals(EnumBasicPermissions.CMIS_READ.value())) 
             permission = Permission.READ;
-        else if (strPerm.equals("cmis:write")) 
+        else if (strPerm.equals(EnumBasicPermissions.CMIS_WRITE.value())) 
             permission = Permission.WRITE;
-        else if (strPerm.equals("cmis:all")) 
+        else if (strPerm.equals(EnumBasicPermissions.CMIS_ALL.value())) 
             permission = Permission.ALL;
         else
             throw new IllegalArgumentException("InMemory only supports CMIS basic permissions read, write, all.");
         return permission;
      }
 
+    public String toCmisString() {
+        if (this.equals(READ)) 
+            return EnumBasicPermissions.CMIS_READ.value();
+        else if (this.equals(WRITE)) 
+            return EnumBasicPermissions.CMIS_WRITE.value();
+        else if (this.equals(ALL)) 
+            return EnumBasicPermissions.CMIS_ALL.value();
+        else
+            return "";
+    }
 }

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/StoreManagerImpl.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/StoreManagerImpl.java?rev=1178250&r1=1178249&r2=1178250&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/StoreManagerImpl.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/StoreManagerImpl.java Sun Oct  2 20:35:12 2011
@@ -118,7 +118,7 @@ public class StoreManagerImpl implements
     }
 
     public CmisServiceValidator getServiceValidator() {
-        return new BaseServiceValidatorImpl(this);
+        return new InMemoryServiceValidatorImpl(this);
     }
 
     public BindingsObjectFactory getObjectFactory() {
@@ -390,7 +390,7 @@ public class StoreManagerImpl implements
         TypeManager tm = getTypeManager(repositoryId);
         ObjectStore objectStore = getObjectStore(repositoryId);
 
-        InMemoryQueryProcessor queryProcessor = new InMemoryQueryProcessor();
+        InMemoryQueryProcessor queryProcessor = new InMemoryQueryProcessor(getStore(repositoryId));
         ObjectList objList = queryProcessor.query(tm, objectStore, user, repositoryId, statement, searchAllVersions,
                 includeAllowableActions, includeRelationships, renditionFilter, maxItems, skipCount);
 

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/StoredObjectImpl.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/StoredObjectImpl.java?rev=1178250&r1=1178249&r2=1178250&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/StoredObjectImpl.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/StoredObjectImpl.java Sun Oct  2 20:35:12 2011
@@ -57,6 +57,7 @@ public class StoredObjectImpl implements
     protected String fRepositoryId;
     protected Map<String, PropertyData<?>> fProperties;
     protected final ObjectStoreImpl fObjStore;
+    protected int fAclId;
 
     StoredObjectImpl(ObjectStoreImpl objStore) { // visibility should be package
         GregorianCalendar now = getNow();
@@ -377,10 +378,20 @@ public class StoredObjectImpl implements
     }
 
 	public Acl getAcl() {
-		// TODO Auto-generated method stub
-		return null;
+		if (0 == getAclId())
+		    return null;
+		else
+		    return fObjStore.getAcl(fAclId);
 	}
 
+	public int getAclId() {
+	    return fAclId;
+	}
+	
+	public void setAclId(int aclId) {
+	    fAclId = aclId;
+	}
+	
 	public ObjectList getObjectRelationships(
 			Boolean includeSubRelationshipTypes,
 			RelationshipDirection relationshipDirection, String typeId,

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/VersionedDocumentImpl.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/VersionedDocumentImpl.java?rev=1178250&r1=1178249&r2=1178250&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/VersionedDocumentImpl.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/storedobj/impl/VersionedDocumentImpl.java Sun Oct  2 20:35:12 2011
@@ -26,17 +26,13 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.commons.data.ContentStream;
 import org.apache.chemistry.opencmis.commons.data.Properties;
 import org.apache.chemistry.opencmis.commons.data.PropertyData;
-import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
 import org.apache.chemistry.opencmis.commons.enums.VersioningState;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
-import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertiesImpl;
 import org.apache.chemistry.opencmis.commons.spi.BindingsObjectFactory;
 import org.apache.chemistry.opencmis.inmemory.FilterParser;
 import org.apache.chemistry.opencmis.inmemory.storedobj.api.DocumentVersion;
-import org.apache.chemistry.opencmis.inmemory.storedobj.api.Filing;
 import org.apache.chemistry.opencmis.inmemory.storedobj.api.VersionedDocument;
-import org.apache.chemistry.opencmis.inmemory.types.PropertyCreationHelper;
 
 public class VersionedDocumentImpl extends AbstractMultiFilingImpl implements VersionedDocument {
 
@@ -56,15 +52,16 @@ public class VersionedDocumentImpl exten
             throw new CmisConstraintException("Cannot add a version to document, document is checked out.");
         }
 
-        Map<String, PropertyData<?>> existingProps = fVersions.size() == 0 ? fProperties : getLatestVersion(false)
-                .getProperties();
-        
         DocumentVersionImpl ver = new DocumentVersionImpl(fRepositoryId, this, content, verState, fObjStore);
-        PropertiesImpl newProps = PropertyCreationHelper.copyProperties(existingProps, null);
-        fProperties = newProps.getProperties();
-        
         ver.setSystemBasePropertiesWhenCreatedDirect(getName(), getTypeId(), user); // copy
-        // name and type id from version series.
+        // name
+        // and
+        // type
+        // id
+        // from
+        // version
+        // series
+        // .
         ver.persist();
         fVersions.add(ver);
         if (verState == VersioningState.CHECKEDOUT) {
@@ -95,8 +92,7 @@ public class VersionedDocumentImpl exten
         fCheckedOutUser = null;
     }
 
-    public void checkIn(boolean isMajor, Properties properties, ContentStream content, String checkinComment,
-            String user, TypeDefinition typeDef) {
+    public void checkIn(boolean isMajor, Properties properties, ContentStream content, String checkinComment, String user) {
         if (fIsCheckedOut) {
             if (fCheckedOutUser.equals(user)) {
                 fIsCheckedOut = false;
@@ -111,22 +107,13 @@ public class VersionedDocumentImpl exten
         }
 
         DocumentVersion pwc = getPwc();
-
-        if (properties != null) {
-            // we do not allow a rename on check-in
-            PropertyData<?> pd = properties.getProperties().get(PropertyIds.NAME);
-            if (pd != null) {
-                throw new CmisInvalidArgumentException("Error: Name can't be changed during a check-in (Document " + getId()
-                        + ").");
-            }
-
-            PropertyCreationHelper.updateProperties(pwc.getProperties(), properties.getProperties(), typeDef, true);
-        }
-
         
         if (null != content)
             pwc.setContent(content, false);
 
+        if (null != properties && null != properties.getProperties())
+            ((DocumentVersionImpl)pwc).setCustomProperties(properties.getProperties());
+
         pwc.setCheckinComment(checkinComment);
         pwc.commit(isMajor);
     }

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/InMemoryDocumentTypeDefinition.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/InMemoryDocumentTypeDefinition.java?rev=1178250&r1=1178249&r2=1178250&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/InMemoryDocumentTypeDefinition.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/InMemoryDocumentTypeDefinition.java Sun Oct  2 20:35:12 2011
@@ -100,7 +100,7 @@ public class InMemoryDocumentTypeDefinit
         setLocalName(id);
         setLocalNamespace("local");
         setQueryName(id);
-        setIsControllableAcl(false);
+        setIsControllableAcl(true);
         setIsControllablePolicy(false);
         setIsCreatable(true);
         setIsFileable(true);

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/InMemoryFolderTypeDefinition.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/InMemoryFolderTypeDefinition.java?rev=1178250&r1=1178249&r2=1178250&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/InMemoryFolderTypeDefinition.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/InMemoryFolderTypeDefinition.java Sun Oct  2 20:35:12 2011
@@ -90,7 +90,7 @@ public class InMemoryFolderTypeDefinitio
         setLocalName(id);
         setLocalNamespace("local");
         setQueryName(id);
-        setIsControllableAcl(false);
+        setIsControllableAcl(true);
         setIsControllablePolicy(false);
         setIsCreatable(true);
         setIsFileable(true);

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/PropertyCreationHelper.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/PropertyCreationHelper.java?rev=1178250&r1=1178249&r2=1178250&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/PropertyCreationHelper.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/main/java/org/apache/chemistry/opencmis/inmemory/types/PropertyCreationHelper.java Sun Oct  2 20:35:12 2011
@@ -27,6 +27,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 
 import org.apache.chemistry.opencmis.commons.PropertyIds;
+import org.apache.chemistry.opencmis.commons.data.Acl;
 import org.apache.chemistry.opencmis.commons.data.AllowableActions;
 import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
 import org.apache.chemistry.opencmis.commons.data.ObjectData;
@@ -40,7 +41,6 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
 import org.apache.chemistry.opencmis.commons.enums.PropertyType;
 import org.apache.chemistry.opencmis.commons.enums.Updatability;
-import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.AbstractPropertyData;
@@ -61,6 +61,7 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.inmemory.DataObjectCreator;
 import org.apache.chemistry.opencmis.inmemory.FilterParser;
 import org.apache.chemistry.opencmis.inmemory.NameValidator;
+import org.apache.chemistry.opencmis.inmemory.storedobj.api.DocumentVersion;
 import org.apache.chemistry.opencmis.inmemory.storedobj.api.StoredObject;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -297,7 +298,8 @@ public class PropertyCreationHelper {
         }
         
         if (null != includeACL && includeACL) {
-            od.setAcl(so.getAcl());
+            Acl acl = so instanceof DocumentVersion ? ((DocumentVersion) so).getParentDocument().getAcl() : so.getAcl();
+            od.setAcl(acl);
         }
         od.setIsExactAcl(true);
 
@@ -351,62 +353,6 @@ public class PropertyCreationHelper {
         return od;
     }
 
-    public static PropertiesImpl copyProperties(Map<String, PropertyData<?>> existingProps, Map<String, PropertyData<?>> newProps) {
-        
-        PropertiesImpl newPD = new PropertiesImpl();
-        // copy all existing properties
-        for (PropertyData<?> prop : existingProps.values()) {
-            newPD.addProperty(prop);
-        }
-        
-        // overwrite all new properties
-        if (newProps != null)
-            for (PropertyData<?> prop : newProps.values()) {
-                newPD.addProperty(prop);
-            }
-        
-        return newPD;
-    }
-    
-    public static boolean updateProperties(Map<String, PropertyData<?>> properties,
-            Map<String, PropertyData<?>> newProps, TypeDefinition typeDef, boolean isCheckedOut) {
-        boolean hasUpdated = false;
-
-        for (String key : newProps.keySet()) {
-            if (key.equals(PropertyIds.NAME))
-             {
-                continue; // ignore here
-            }
-
-            PropertyData<?> value = newProps.get(key);
-            PropertyDefinition<?> propDef = typeDef.getPropertyDefinitions().get(key);
-            if (value.getValues() == null || value.getFirstValue() == null) {
-                // delete property
-                // check if a required a property
-                if (propDef.isRequired()) {
-                    throw new CmisConstraintException(
-                            "updateProperties failed, following property can't be deleted, because it is required: "
-                                    + key);
-                }
-                properties.remove(key);
-                hasUpdated = true;
-            } else {
-                if (propDef.getUpdatability().equals(Updatability.WHENCHECKEDOUT) && !isCheckedOut) {
-                    throw new CmisConstraintException(
-                            "updateProperties failed, following property can't be updated, because it is not checked-out: "
-                                    + key);
-                } else if (!propDef.getUpdatability().equals(Updatability.READWRITE)) {
-                    throw new CmisConstraintException(
-                            "updateProperties failed, following property can't be updated, because it is not writable: "
-                                    + key);
-                }
-                properties.put(key, value);
-                hasUpdated = true;
-            }
-        }
-        return hasUpdated;
-    }
-
     // internal helpers
     private static void createStandardDefinition(AbstractPropertyDefinition<?> prop, String id, PropertyType propType,
             String displayName, Cardinality card) {

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/AbstractServiceTest.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/AbstractServiceTest.java?rev=1178250&r1=1178249&r2=1178250&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/AbstractServiceTest.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/AbstractServiceTest.java Sun Oct  2 20:35:12 2011
@@ -49,6 +49,7 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.commons.enums.VersioningState;
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.BindingsObjectFactoryImpl;
 import org.apache.chemistry.opencmis.commons.server.CallContext;
+import org.apache.chemistry.opencmis.commons.spi.AclService;
 import org.apache.chemistry.opencmis.commons.spi.BindingsObjectFactory;
 import org.apache.chemistry.opencmis.commons.spi.CmisBinding;
 import org.apache.chemistry.opencmis.commons.spi.DiscoveryService;
@@ -77,6 +78,7 @@ public class AbstractServiceTest {
     protected VersioningService fVerSvc;
     protected MultiFilingService fMultiSvc;
     protected DiscoveryService fDiscSvc;
+    protected AclService fAclSvc;
     protected CallContext fTestCallContext;
     private String fTypeCreatorClassName;
 
@@ -162,17 +164,25 @@ public class AbstractServiceTest {
     }
 
     protected String createFolderNoCatch(String folderName, String parentFolderId, String typeId) {
+        return createFolderNoCatch(folderName, parentFolderId, typeId, null, null);
+    }
+
+    protected String createFolderNoCatch(String folderName, String parentFolderId, String typeId, Acl addACEs,
+            Acl removeACEs) {
         Properties props = createFolderProperties(folderName, typeId);
-        String id = fObjSvc.createFolder(fRepositoryId, props, parentFolderId, null, null, null, null);
+        String id = fObjSvc.createFolder(fRepositoryId, props, parentFolderId, null, addACEs, removeACEs, null);
         return id;
     }
 
-    protected String createDocumentNoCatch(String name, String folderId, String typeId, VersioningState versioningState,
-            boolean withContent) {
+    protected String createDocumentNoCatch(String name, String folderId, String typeId,
+            VersioningState versioningState, boolean withContent) {
+        return createDocumentNoCatch(name, folderId, typeId, versioningState, withContent, null, null);
+    }
+
+    protected String createDocumentNoCatch(String name, String folderId, String typeId,
+            VersioningState versioningState, boolean withContent, Acl addACEs, Acl removeACEs) {
         ContentStream contentStream = null;
         List<String> policies = null;
-        Acl addACEs = null;
-        Acl removeACEs = null;
         ExtensionsData extension = null;
 
         Properties props = createDocumentProperties(name, typeId);
@@ -395,6 +405,7 @@ public class AbstractServiceTest {
         fVerSvc = binding.getVersioningService();
         fMultiSvc = binding.getMultiFilingService();
         fDiscSvc = binding.getDiscoveryService();
+        fAclSvc = binding.getAclService();
     }
 
     protected String getStringProperty(ObjectData objData, String propertyKey) {

Added: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/AclPermissionsTest.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/AclPermissionsTest.java?rev=1178250&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/AclPermissionsTest.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-inmemory/src/test/java/org/apache/chemistry/opencmis/inmemory/AclPermissionsTest.java Sun Oct  2 20:35:12 2011
@@ -0,0 +1,1265 @@
+package org.apache.chemistry.opencmis.inmemory;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.Assert;
+
+import org.apache.chemistry.opencmis.commons.PropertyIds;
+import org.apache.chemistry.opencmis.commons.data.Ace;
+import org.apache.chemistry.opencmis.commons.data.Acl;
+import org.apache.chemistry.opencmis.commons.data.ContentStream;
+import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
+import org.apache.chemistry.opencmis.commons.data.ObjectData;
+import org.apache.chemistry.opencmis.commons.data.ObjectInFolderContainer;
+import org.apache.chemistry.opencmis.commons.data.ObjectInFolderData;
+import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList;
+import org.apache.chemistry.opencmis.commons.data.ObjectList;
+import org.apache.chemistry.opencmis.commons.data.ObjectParentData;
+import org.apache.chemistry.opencmis.commons.data.Properties;
+import org.apache.chemistry.opencmis.commons.data.PropertyData;
+import org.apache.chemistry.opencmis.commons.data.RenditionData;
+import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
+import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
+import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
+import org.apache.chemistry.opencmis.commons.enums.VersioningState;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException;
+import org.apache.chemistry.opencmis.commons.impl.jaxb.EnumBaseObjectTypeIds;
+import org.apache.chemistry.opencmis.commons.impl.jaxb.EnumBasicPermissions;
+import org.apache.chemistry.opencmis.commons.server.CallContext;
+import org.apache.chemistry.opencmis.commons.spi.Holder;
+import org.apache.chemistry.opencmis.inmemory.storedobj.api.ObjectStore;
+import org.apache.chemistry.opencmis.server.support.query.CalendarHelper;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class AclPermissionsTest extends AbstractServiceTest  {
+
+	private static Log LOG = LogFactory.getLog(AclPermissionsTest.class);
+	private static final BigInteger MINUS_ONE = BigInteger.valueOf(-1L);
+	
+    protected ObjectCreator fCreator;
+	protected ObjectStore objectStore = null;
+	protected List<Ace> addACEs = null;
+	protected Acl addAcl = null;
+	protected List<Ace> standardACEs = null;
+	protected Acl standardAcl = null;
+	protected List<Ace> noReadACEs = null;
+	protected Acl noReadAcl = null;
+	protected List<Ace>readACEs = null;
+	protected Acl readAcl = null;
+	protected List<Ace>readWriteACEs = null;
+	protected Acl readWriteAcl = null;
+	protected List<Ace> writerReadACEs = null;
+	protected Acl writerReadAcl = null;
+	protected List<Ace> adminACEs = null;
+	protected Acl adminAcl = null;
+	protected List<Ace> testUserACEs = null;
+	protected Acl testUserAcl = null;
+	
+	protected static Map<String, String> idMap = new HashMap<String, String>();
+	
+    @Override
+    @After
+    public void tearDown() {
+        super.tearDown();
+    }
+
+    @Override
+    @Before
+    public void setUp() {
+        super.setTypeCreatorClass(UnitTestTypeSystemCreator.class.getName());
+        super.setUp();
+        fCreator = new ObjectCreator(fFactory, fObjSvc, fRepositoryId);
+		 List<String> principalIds = new ArrayList<String>(3);
+		 principalIds.add("TestAdmin");
+		 principalIds.add("Writer");
+		 principalIds.add("Reader");
+		 principalIds.add("TestUser");
+		addACEs = new ArrayList<Ace>(4);
+		addACEs.add(createAce("TestAdmin", EnumBasicPermissions.CMIS_ALL));
+		addACEs.add(createAce("Writer", EnumBasicPermissions.CMIS_WRITE));
+		addACEs.add(createAce("TestUser", EnumBasicPermissions.CMIS_WRITE));
+		addACEs.add(createAce("Reader", EnumBasicPermissions.CMIS_READ));
+		addAcl = fFactory.createAccessControlList(addACEs);
+		
+		standardACEs = new ArrayList<Ace>(3);
+		standardACEs.add(createAce("TestAdmin", EnumBasicPermissions.CMIS_ALL));
+		standardACEs.add(createAce("Writer", EnumBasicPermissions.CMIS_WRITE));
+		standardACEs.add(createAce("Reader", EnumBasicPermissions.CMIS_READ));
+		standardAcl = fFactory.createAccessControlList(standardACEs);	
+		
+		noReadACEs = new ArrayList<Ace>(2);
+		noReadACEs.add(createAce("TestAdmin", EnumBasicPermissions.CMIS_ALL));
+		noReadACEs.add(createAce("Writer", EnumBasicPermissions.CMIS_WRITE));
+		noReadAcl = fFactory.createAccessControlList(noReadACEs);	
+		
+		readACEs = new ArrayList<Ace>(1);
+		readACEs.add(createAce("Reader", EnumBasicPermissions.CMIS_READ));
+		readAcl = fFactory.createAccessControlList(readACEs);	
+		
+		readWriteACEs = new ArrayList<Ace>(2);
+		readWriteACEs.add(createAce("Reader", EnumBasicPermissions.CMIS_READ));
+		readWriteACEs.add(createAce("Writer", EnumBasicPermissions.CMIS_WRITE));
+		readWriteAcl = fFactory.createAccessControlList(readWriteACEs);	
+		
+		testUserACEs = new ArrayList<Ace>(1);
+		testUserACEs.add(createAce("TestUser", EnumBasicPermissions.CMIS_WRITE));
+		testUserAcl = fFactory.createAccessControlList(testUserACEs);	
+		
+		writerReadACEs = new ArrayList<Ace>(1);
+		writerReadACEs.add(createAce("Writer", EnumBasicPermissions.CMIS_READ));
+		writerReadAcl = fFactory.createAccessControlList(writerReadACEs);	
+		
+		adminACEs = new ArrayList<Ace>(1);
+		adminACEs.add(createAce("TestAdmin", EnumBasicPermissions.CMIS_ALL));
+		adminAcl = fFactory.createAccessControlList(adminACEs);	
+	}
+
+	@Test
+	public void testCreateObjectsWithAcl()
+	{
+		// create a document with initial ACL
+		String docId = createDocumentWithAcls("complexDocument",  fRootFolderId, UnitTestTypeSystemCreator.COMPLEX_TYPE,
+				addAcl, null);
+		Acl acl1 = fAclSvc.getAcl(fRepositoryId, docId, true, null);
+		assertTrue(aclEquals(addAcl, acl1));
+		
+		// create a folder with initial ACL
+		String folderId = createFolderWithAcls("folderWithAcl", fRootFolderId, BaseTypeId.CMIS_FOLDER.value(),
+				addAcl, null);
+		Acl acl2 = fAclSvc.getAcl(fRepositoryId, folderId, true, null);
+		assertTrue(aclEquals(addAcl, acl2));
+		
+		// add acl later
+		String docId2 = createVersionedDocument("complexDocument2",  fRootFolderId);
+        Acl acl = fAclSvc.applyAcl(fRepositoryId, docId2, addAcl, null, AclPropagation.OBJECTONLY, null);
+		assertTrue(aclEquals(addAcl, acl));
+		
+		String folderId2 = createFolder("folder2", fRootFolderId, "cmis:folder");
+		acl2 = fAclSvc.applyAcl(fRepositoryId, folderId2, addAcl, null, AclPropagation.OBJECTONLY, null);
+		assertTrue(aclEquals(addAcl, acl2));
+		
+		// add a subfolder
+		String subFolderId = createFolder("subFolder", folderId,  BaseTypeId.CMIS_FOLDER.value());
+		// folder should inherit acl
+		Acl subAcl = fAclSvc.getAcl(fRepositoryId, subFolderId, true, null);
+		assertTrue(aclEquals(addAcl, subAcl));
+		
+		// add a document
+		String subDocId = createVersionedDocument("subDoc", subFolderId);
+		// document should inherit acl
+		Acl subAclDoc = fAclSvc.getAcl(fRepositoryId, subDocId, true, null);
+		assertTrue(aclEquals(addAcl, subAclDoc));
+		
+		// remove an ace, no permission is left for TestUser
+		Acl removeAcl = createAcl("TestUser", EnumBasicPermissions.CMIS_WRITE);
+		Acl acl3 = fAclSvc.applyAcl(fRepositoryId, docId2, null, removeAcl, AclPropagation.OBJECTONLY, null);
+		
+		List<Ace> compareRemoveACEs = new ArrayList<Ace>(3);
+		compareRemoveACEs.add(createAce("TestAdmin", EnumBasicPermissions.CMIS_ALL));
+		compareRemoveACEs.add(createAce("Writer", EnumBasicPermissions.CMIS_WRITE));
+		compareRemoveACEs.add(createAce("Reader", EnumBasicPermissions.CMIS_READ));
+		Acl compareRemoveAcl = fFactory.createAccessControlList(compareRemoveACEs);
+		
+		assertTrue(aclEquals(compareRemoveAcl, acl3));
+		
+		// addACE not propagated
+		Acl addPropAcl = createAcl("TestUser", EnumBasicPermissions.CMIS_WRITE);
+		
+		Acl acl4 = fAclSvc.applyAcl(fRepositoryId, subFolderId, addPropAcl, null, AclPropagation.OBJECTONLY, null);
+		Acl subAclDoc2 = fAclSvc.getAcl(fRepositoryId, subDocId, true, null);
+		assertTrue(aclEquals(addAcl, subAclDoc2));  // acl of doc did not change
+		
+		List<Ace> compareRemoveACEs2 = new ArrayList<Ace>(4);
+		compareRemoveACEs2.add(createAce("TestAdmin", EnumBasicPermissions.CMIS_ALL));
+		compareRemoveACEs2.add(createAce("Writer", EnumBasicPermissions.CMIS_WRITE));
+		compareRemoveACEs2.add(createAce("TestUser", EnumBasicPermissions.CMIS_ALL));
+		compareRemoveACEs2.add(createAce("Reader", EnumBasicPermissions.CMIS_READ));
+		Acl compareRemoveAcl2 = fFactory.createAccessControlList(compareRemoveACEs2);
+		assertTrue(aclEquals(compareRemoveAcl2, acl4)); 
+		
+		// addACE propagated
+		Acl acl5 = fAclSvc.applyAcl(fRepositoryId, subFolderId, addPropAcl, null, AclPropagation.PROPAGATE, null);
+		Acl subAclDoc3 = fAclSvc.getAcl(fRepositoryId, subDocId, true, null);
+		assertTrue(aclEquals(compareRemoveAcl2, subAclDoc3));  // acl of doc did change
+		assertTrue(aclEquals(compareRemoveAcl2, acl5)); 
+	}
+		
+	
+	@Test
+	public void checkNavigationServiceGeneralAccess()
+	{
+		// starts with call context TestUser
+		switchCallContext("TestAdmin");
+		String docId = createDocumentWithAcls("doc",  fRootFolderId, "ComplexType",
+				standardAcl, null);
+		String folderId = createFolderWithAcls("folder", fRootFolderId, "cmis:folder", standardAcl, null);
+//		fTestCallContext = new DummyCallContext("Writer");
+		String subFolderId = createFolderWithAcls("subFolder", folderId, "cmis:folder", standardAcl, null);
+		
+		
+		// TestUser has no permission at all
+		switchCallContext("TestUser");
+		boolean exceptionThrown = false;
+		try
+		{
+			ObjectInFolderList list = fNavSvc.getChildren(fRepositoryId, folderId, null, null, false, IncludeRelationships.NONE, null, null, 
+					BigInteger.ZERO , BigInteger.ZERO, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permissions)");
+		
+		switchCallContext("Reader");
+		ObjectInFolderList list = fNavSvc.getChildren(fRepositoryId, folderId, null, null, false, IncludeRelationships.NONE, null, null,
+				BigInteger.ZERO , BigInteger.ZERO, null);
+		
+		
+		switchCallContext("TestUser");
+		exceptionThrown = false;
+		try
+		{
+			List<ObjectInFolderContainer> list2 = fNavSvc.getDescendants(fRepositoryId, folderId, MINUS_ONE, null, null, null, null, null, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permissions)");
+		
+		switchCallContext("Reader");
+		List<ObjectInFolderContainer> list2 = fNavSvc.getDescendants(fRepositoryId, folderId, MINUS_ONE, null, null, null, null, null, null);
+		
+		
+		switchCallContext("TestUser");
+		exceptionThrown = false;
+		try
+		{
+			List<ObjectInFolderContainer> list3 = fNavSvc.getFolderTree(fRepositoryId, folderId, BigInteger.ONE, null, null, null, null, null, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permissions)");
+		
+		switchCallContext("Reader");
+		List<ObjectInFolderContainer> list3 = fNavSvc.getFolderTree(fRepositoryId, folderId, BigInteger.ONE, null, null, null, null, null, null);
+		
+		switchCallContext("TestUser");
+		exceptionThrown = false;
+		try
+		{
+			List<ObjectParentData> list4 = fNavSvc.getObjectParents(fRepositoryId, folderId, null, null, null, null, null, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permissions)");
+		
+		switchCallContext("Reader");
+		List<ObjectParentData> list4 = fNavSvc.getObjectParents(fRepositoryId, folderId, null, null, null, null, null, null);
+		
+		switchCallContext("TestUser");
+		exceptionThrown = false;
+		try
+		{
+			ObjectData list5 = fNavSvc.getFolderParent(fRepositoryId, folderId, null, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permissions)");
+		
+		switchCallContext("Reader");
+		ObjectData list5 = fNavSvc.getFolderParent(fRepositoryId, folderId, null, null);
+	
+		switchCallContext("TestUser");
+		exceptionThrown = false;
+		try
+		{
+			ObjectList list6 = fNavSvc.getCheckedOutDocs(fRepositoryId, folderId, null, null, null, IncludeRelationships.NONE, 
+					null, MINUS_ONE, MINUS_ONE, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permissions)");
+		
+		switchCallContext("Reader");
+		ObjectList list6 = fNavSvc.getCheckedOutDocs(fRepositoryId, folderId, null, null, null, IncludeRelationships.NONE, 
+				null, MINUS_ONE, MINUS_ONE, null);
+	}
+	
+	@Test
+	public void checkAclServiceGeneralAccess()
+	{
+	    List<Ace> initialACEs = new ArrayList<Ace>(4);
+	    initialACEs.addAll(standardACEs);
+	    initialACEs.add(createAce("Admin2", EnumBasicPermissions.CMIS_ALL));
+        Acl initialAcl = fFactory.createAccessControlList(initialACEs);   
+        
+        List<Ace> expectedACEs = new ArrayList<Ace>(5);
+        expectedACEs.addAll(initialACEs);
+        expectedACEs.addAll(testUserACEs);
+        Acl expectedAcl = fFactory.createAccessControlList(expectedACEs);   
+        
+	    List<Ace> removeACEs = new ArrayList<Ace>(1);
+        removeACEs.add(createAce("TestAdmin", EnumBasicPermissions.CMIS_ALL));
+		Acl removeAcl = fFactory.createAccessControlList(removeACEs);
+		
+		List<Ace> removeACEs2 = new ArrayList<Ace>(2);
+		removeACEs2.add(createAce("TestAdmin", EnumBasicPermissions.CMIS_ALL));
+		removeACEs2.add(createAce("Reader", EnumBasicPermissions.CMIS_READ));
+		Acl removeAcl2 = fFactory.createAccessControlList(removeACEs2);
+		
+		List<Ace> testUserACEs = new ArrayList<Ace>(1);
+		testUserACEs.add(createAce("TestUser", EnumBasicPermissions.CMIS_WRITE));
+		Acl testUserAcl = fFactory.createAccessControlList(testUserACEs);
+		
+		switchCallContext("TestAdmin");
+		String docId = createDocumentWithAcls("doc",  fRootFolderId, "ComplexType",
+		        initialAcl, null);
+		String folderId = createFolderWithAcls("folder", fRootFolderId, "cmis:folder", initialAcl, null);
+		String subFolderId = createFolderWithAcls("subFolder", folderId, "cmis:folder", initialAcl, null);
+		
+		// getAcl of a folder
+		switchCallContext("TestUser");
+		boolean exceptionThrown = false;
+		try
+		{
+			Acl acl = fAclSvc.getAcl(fRepositoryId, folderId, null, null); 
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permissions to get acl of folder");
+		
+		switchCallContext("Reader");
+		Acl acl = fAclSvc.getAcl(fRepositoryId, folderId, null, null);
+		
+		// getAcl of a document
+		switchCallContext("TestUser");
+		exceptionThrown = false;
+		try
+		{
+			Acl docAcl = fAclSvc.getAcl(fRepositoryId, docId, true, null); 
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permissions to get acl of doc)");
+		
+		switchCallContext("Reader");
+		Acl docAcl = fAclSvc.getAcl(fRepositoryId, docId, true, null);
+		
+		// applyAcl
+		switchCallContext("Reader");
+		exceptionThrown = false;
+		try
+		{
+			Acl docAcl2 = fAclSvc.applyAcl(fRepositoryId, docId, initialAcl, null, AclPropagation.OBJECTONLY, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permissions)");
+		
+//		switchCallContext("Writer");
+        switchCallContext("TestAdmin");
+		Acl docAcl2 = fAclSvc.applyAcl(fRepositoryId, docId, initialAcl, null, AclPropagation.OBJECTONLY, null);
+		
+		// applyAcl when not allowed to subItem
+		switchCallContext("TestAdmin");
+		Acl docAcl4 = fAclSvc.applyAcl(fRepositoryId, subFolderId, null, removeAcl, AclPropagation.OBJECTONLY, null);
+		
+//        switchCallContext("Writer");
+        switchCallContext("TestAdmin");
+        // apply an ACL where the current user has permission to modify ACL on folder but not on sub-folder:
+		Acl docAcl5 = fAclSvc.applyAcl(fRepositoryId, folderId, testUserAcl, null, AclPropagation.PROPAGATE, null);
+		switchCallContext("Admin");
+		Acl docAcl6 = fAclSvc.getAcl(fRepositoryId, folderId, true, null);
+		assertTrue(aclEquals(expectedAcl, docAcl6)); 
+		Acl docAcl7 = fAclSvc.getAcl(fRepositoryId, subFolderId, true, null);
+		assertTrue(aclEquals(standardAcl, docAcl7)); 
+	}
+	
+	@Test
+	public void checkObjectServiceGeneralAccess()
+	{
+			
+		// starts with call context TestUser
+		switchCallContext("TestAdmin");
+		String docId = createDocumentWithAcls("doc",  fRootFolderId, "ComplexType",
+				standardAcl, null);
+		String folderId = createFolderWithAcls("folder", fRootFolderId, "cmis:folder", standardAcl, null);
+//		fTestCallContext = new DummyCallContext("Writer");
+		String subFolderId = createFolderWithAcls("subFolder", folderId, "cmis:folder", standardAcl, null);
+		String noReadFolderId = createFolderWithAcls("noReadFolder", folderId, "cmis:folder", null, readAcl);
+		String adminFolderId = createFolderWithAcls("adminFolder", folderId, "cmis:folder", null, readWriteAcl);
+		
+		// TestUser has no permission at all
+		switchCallContext("TestUser");
+		boolean exceptionThrown = false;
+		try
+		{
+			Properties properties = createDocumentProperties("doc", "ComplexType");
+			String id = fObjSvc.createDocument(fRepositoryId, properties, folderId, null, null, null, null,
+					null, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permissions to create a document");
+		
+		exceptionThrown = false;
+		try
+		{
+			String id = fObjSvc.createFolder(fRepositoryId, null, folderId, null, null, null, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permissions to create a folder");
+		
+		/*
+		exceptionThrown = false;
+		try
+		{
+			Properties properties = createRelationshipProperties(folderId, fRootFolderId);
+			String id1 = fObjSvc.createRelationship(fRepositoryId, properties, null, null, null, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permissions to create a relationship: missing read permission for source id");
+		
+		exceptionThrown = false;
+		Properties properties = createRelationshipProperties( fRootFolderId, folderId);
+		try
+		{
+			String id2 = fObjSvc.createRelationship(fRepositoryId, properties, null, null, null, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permissions to create a relationship: missing read permission for destination");
+		*/
+		
+		exceptionThrown = false;
+		try
+		{
+			Properties props = fObjSvc.getProperties(fRepositoryId,  folderId, null, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permissions to get properties of the folder");
+		
+		exceptionThrown = false;
+		try
+		{
+			Properties props = fObjSvc.getProperties(fRepositoryId,  docId, null, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permissions to get properties of the document");
+		
+		exceptionThrown = false;
+		try
+		{
+			List<RenditionData> renditions = fObjSvc.getRenditions(fRepositoryId,  docId, null, BigInteger.valueOf(-1),
+					BigInteger.valueOf(-1), null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permissions to get renditions of the document");
+		
+		exceptionThrown = false;
+		try
+		{
+			ContentStream contentStream =  fObjSvc.getContentStream(fRepositoryId,  docId, null, BigInteger.valueOf(-1),
+					BigInteger.valueOf(-1), null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permissions to get contentStream of the document");
+		
+		switchCallContext("Reader");
+		exceptionThrown = false;
+		Properties properties = createDocumentProperties( "name", "typeId");
+		try
+		{	
+			fObjSvc.updateProperties(fRepositoryId,
+					new Holder<String>(docId), new Holder<String>("changeToken"), properties, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("Reader has no permissions to update properties of the document");
+		
+		exceptionThrown = false;
+		properties = createDocumentProperties( "name", "typeId");
+		try
+		{	
+			fObjSvc.updateProperties(fRepositoryId,
+					new Holder<String>(docId), new Holder<String>("changeToken"), properties, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("Reader has no permissions to update properties of the document");
+		
+		exceptionThrown = false;
+		try
+		{	
+			fObjSvc.moveObject(fRepositoryId, new Holder<String>(docId), subFolderId,
+					fRootFolderId, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("Reader has no permissions to move document");
+		
+		switchCallContext("Writer");
+		exceptionThrown = false;
+		try
+		{	
+			fObjSvc.moveObject(fRepositoryId,new Holder<String>(docId), adminFolderId,
+					fRootFolderId, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("Writer has no permissions to move document to admin folder");
+		
+		switchCallContext("Reader");
+		exceptionThrown = false;
+		try
+		{	
+			fObjSvc.deleteObject(fRepositoryId, docId, true, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("Reader has no permissions to delete document ");
+		
+		exceptionThrown = false;
+		try
+		{	
+			fObjSvc.deleteObject(fRepositoryId, adminFolderId, true, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("Reader has no permissions to delete admin folder ");
+		
+		exceptionThrown = false;
+		try
+		{	
+			fObjSvc.setContentStream(fRepositoryId, new Holder<String> (docId), true,
+					new Holder<String>("changeToken"), null, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("Reader has no permissions to set content ");
+		
+		exceptionThrown = false;
+		try
+		{	
+			fObjSvc.deleteContentStream(fRepositoryId, new Holder<String> (docId), 
+					new Holder<String>("changeToken"), null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("Reader has no permissions to delete content ");
+		
+		exceptionThrown = false;
+		try
+		{	
+			fObjSvc.deleteTree(fRepositoryId, folderId, true,
+					 null, false, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("Reader has no permissions to delete tree ");
+	}
+	
+	@Test
+	public void checkMultiFilingServiceGeneralAccess()
+	{
+		// starts with call context TestUser
+		switchCallContext("TestAdmin");
+		String docId = createDocumentWithAcls("doc",  fRootFolderId, "ComplexType",
+				standardAcl, null);
+		String folderId = createFolderWithAcls("folder", fRootFolderId, "cmis:folder", 
+				addAcl, null);
+		String noReadFolderId = createFolderWithAcls("noReadFolder", folderId, "cmis:folder", 
+				null, readAcl);
+		
+		// TestUser has no permission at the document
+		switchCallContext("TestUser");
+		boolean exceptionThrown = false;
+		try
+		{
+			
+			fMultiSvc.addObjectToFolder(fRepositoryId, docId, folderId, true, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permissions at the document to add a parent");
+		
+		exceptionThrown = false;
+		switchCallContext("Reader");  // has no permission at the folder
+		try
+		{
+			
+			fMultiSvc.addObjectToFolder(fRepositoryId, docId, noReadFolderId, true, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("Reader has no permission at the folder to add a parent");
+		
+		switchCallContext("TestAdmin");
+		fMultiSvc.addObjectToFolder(fRepositoryId, docId, noReadFolderId, true, null);
+		fMultiSvc.addObjectToFolder(fRepositoryId, docId, folderId, true, null);
+		
+		switchCallContext("Reader");  
+		try
+		{
+			
+			fMultiSvc.removeObjectFromFolder(fRepositoryId, docId, noReadFolderId, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("Reader has no permission at the folder to remove a parent");
+		
+		switchCallContext("TestUser"); 
+		try
+		{
+			
+			fMultiSvc.removeObjectFromFolder(fRepositoryId, docId, folderId, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permission at the object to remove a parent");
+	}
+	
+	@Test
+	public void checkVersioningServiceGeneralAccess()
+	{
+		// starts with call context TestUser
+		switchCallContext("TestAdmin");
+		String docId = createDocumentWithAcls("doc",  fRootFolderId, UnitTestTypeSystemCreator.VERSION_DOCUMENT_TYPE_ID,
+		        VersioningState.MAJOR, standardAcl, null);
+	
+		// TestUser has no permission at all
+		switchCallContext("TestUser");
+		boolean exceptionThrown = false;
+		try
+		{
+			Holder<String> docIdHolder = new Holder<String>(docId);
+			fVerSvc.checkOut(fRepositoryId, docIdHolder, null, 
+					new Holder<Boolean>(false));
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permission to checkout)");
+		
+		// Reader has only read permission
+		switchCallContext("Reader");
+		exceptionThrown = false;
+		try
+		{
+			fVerSvc.checkOut(fRepositoryId, new Holder<String>(docId), null, 
+					new Holder<Boolean>(false));
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("Reader has not enough permission to checkout)");
+		
+		// checkout
+		switchCallContext("TestAdmin");
+		fAclSvc.applyAcl(fRepositoryId, docId, testUserAcl, null, AclPropagation.OBJECTONLY, null);
+		switchCallContext("TestUser");
+		Holder<String> docIdHolder = new Holder<String>(docId);
+		fVerSvc.checkOut(fRepositoryId, docIdHolder, null, 
+				new Holder<Boolean>(false));
+	
+        switchCallContext("TestAdmin");
+		fAclSvc.applyAcl(fRepositoryId, docId, null, testUserAcl, AclPropagation.OBJECTONLY, null);
+		
+		// TestUser has no permission at all, only checkout user can checkin
+		switchCallContext("TestUser");
+		exceptionThrown = false;
+		try
+		{
+			fVerSvc.cancelCheckOut(fRepositoryId, docId, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permission to cancelCheckOut)");
+		switchCallContext("TestAdmin");
+		fAclSvc.applyAcl(fRepositoryId, docId, testUserAcl, null, AclPropagation.OBJECTONLY, null);
+		switchCallContext("TestUser");
+		fVerSvc.cancelCheckOut(fRepositoryId, docId, null);
+		
+		// writer looses write permission
+		switchCallContext("Writer");
+		fVerSvc.checkOut(fRepositoryId, new Holder<String>(docId), null, 
+				new Holder<Boolean>(false));
+
+		switchCallContext("TestAdmin");
+		fAclSvc.applyAcl(fRepositoryId, docId, null, readWriteAcl, AclPropagation.OBJECTONLY, null);
+	
+		switchCallContext("Writer");
+        exceptionThrown = false;
+		try
+		{
+			fVerSvc.cancelCheckOut(fRepositoryId, docId, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("Reader has not enough permission to cancelCheckOut)");
+		switchCallContext("TestAdmin");
+		fAclSvc.applyAcl(fRepositoryId, docId, readWriteAcl, null, AclPropagation.OBJECTONLY, null);
+		switchCallContext("Writer");
+		fVerSvc.cancelCheckOut(fRepositoryId, docId, null);
+		
+		
+		// TestUser has no permission at all
+		switchCallContext("TestAdmin");
+		fAclSvc.applyAcl(fRepositoryId, docId, testUserAcl, null, AclPropagation.OBJECTONLY, null);
+		switchCallContext("TestUser");
+		fVerSvc.checkOut(fRepositoryId, new Holder<String>(docId), null, 
+				new Holder<Boolean>(false));
+
+		switchCallContext("TestAdmin");
+		fAclSvc.applyAcl(fRepositoryId, docId, null, testUserAcl, AclPropagation.OBJECTONLY, null);
+	
+		switchCallContext("TestUser");
+		exceptionThrown = false;
+		try
+		{
+			fVerSvc.checkIn(fRepositoryId, new Holder<String>(docId), true,  null, null, null, null,
+					null, null, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has no permission to checkIn)");
+		switchCallContext("TestAdmin");
+		fAclSvc.applyAcl(fRepositoryId, docId, testUserAcl, null, AclPropagation.OBJECTONLY, null);
+		switchCallContext("TestUser");
+		fVerSvc.checkIn(fRepositoryId, new Holder<String>(docId), true,  null, null, null, null,
+				null, null, null);
+
+		switchCallContext("TestAdmin");
+		fAclSvc.applyAcl(fRepositoryId, docId, null, testUserAcl, AclPropagation.OBJECTONLY, null);
+		
+		// writer looses write permission
+		switchCallContext("Writer");
+		fVerSvc.checkOut(fRepositoryId, new Holder<String>(docId), null, 
+				new Holder<Boolean>(false));
+        
+		switchCallContext("TestAdmin");
+		fAclSvc.applyAcl(fRepositoryId, docId, null, readWriteAcl, AclPropagation.OBJECTONLY, null);
+
+		switchCallContext("Writer");	
+		exceptionThrown = false;
+		try
+		{
+			fVerSvc.checkIn(fRepositoryId, new Holder<String>(docId), true,  null, null, null, null,
+					null, null, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("Writer has not enough permission to checkIn)");
+		switchCallContext("TestAdmin");
+		fAclSvc.applyAcl(fRepositoryId, docId, readWriteAcl, null, AclPropagation.OBJECTONLY, null);
+		switchCallContext("Writer");
+		fVerSvc.checkIn(fRepositoryId, new Holder<String>(docId), true,  null, null, null, null,
+				null, null, null);
+		
+		// TestUser has no permission at all
+		switchCallContext("TestUser");
+		exceptionThrown = false;
+		try
+		{
+			ObjectData objectData = fVerSvc.getObjectOfLatestVersion(fRepositoryId, docId, null, true,
+	            null, false, IncludeRelationships.NONE,
+	            null, false, false, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has not enough permission to getObjectOfLatestVersion)");
+		
+		exceptionThrown = false;
+		try
+		{
+			 List<ObjectData> objectDataList = fVerSvc.getAllVersions(fRepositoryId, docId, docId, null,
+	            false, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has not enough permission to getAllVersions)");
+
+
+		exceptionThrown = false;
+		try
+		{
+			Properties properties = fVerSvc.getPropertiesOfLatestVersion(fRepositoryId, docId, null, 
+					false, null, null);
+		}
+		catch (CmisPermissionDeniedException e)
+		{
+			exceptionThrown = true;
+		}
+		if (!exceptionThrown)
+			Assert.fail("TestUser has not enough permission to getAllVersions)");
+	}
+	
+		
+	@Test
+	public void checkVisibleObjects()
+	{
+        LOG.debug("start test checkVisibleObjects()...");
+		switchCallContext("TestAdmin");
+		String docId = createDocumentWithAcls("doc",  fRootFolderId, UnitTestTypeSystemCreator.VERSION_DOCUMENT_TYPE_ID,
+				VersioningState.MAJOR, standardAcl, null);
+		String docId2 = createDocumentWithAcls("doc2",  fRootFolderId, UnitTestTypeSystemCreator.VERSION_DOCUMENT_TYPE_ID,
+		        VersioningState.MAJOR, addAcl, null);
+		String folderId = createFolderWithAcls("folder", fRootFolderId, "cmis:folder", 
+				standardAcl, null);
+		String folderId2 = createFolderWithAcls("folder2", fRootFolderId, "cmis:folder", 
+				addAcl, null);
+		LOG.debug("checkVisibleObjects(): folderId2 is: " + folderId2);
+		String subFolderId = createFolderWithAcls("subFolder", folderId2, "cmis:folder", 
+				null, testUserAcl);
+        LOG.debug("checkVisibleObjects(): subFolderId is: " + subFolderId);
+		String subFolderId2 = createFolderWithAcls("subFolder2", folderId2, "cmis:folder", 
+				addAcl, null);
+        LOG.debug("checkVisibleObjects(): subFolderId2 is: " + subFolderId2);
+		String subDocId = createDocumentWithAcls("subDoc",  folderId2, UnitTestTypeSystemCreator.VERSION_DOCUMENT_TYPE_ID,
+		        VersioningState.MAJOR, null, testUserAcl);
+        LOG.debug("checkVisibleObjects(): subDocId is: " + subDocId);
+		String subDocId2 = createDocumentWithAcls("subDoc2", folderId2, UnitTestTypeSystemCreator.VERSION_DOCUMENT_TYPE_ID,
+		        VersioningState.MAJOR, addAcl, null);
+        LOG.debug("checkVisibleObjects(): subDocId2 is: " + subDocId2);
+		String noAclDocId2 = createDocumentWithAcls("noAclDoc2", fRootFolderId, "ComplexType",
+				null, null);
+        LOG.debug("checkVisibleObjects(): noAclDocId2 is: " + noAclDocId2);
+		
+		// TestUser has no permission in standardAcl
+		switchCallContext("TestUser");
+		
+		ObjectInFolderList list = fNavSvc.getChildren(fRepositoryId, folderId2, null, null, false, IncludeRelationships.NONE, null, null, 
+					null, null, null);
+		List<ObjectInFolderData> objects = list.getObjects();
+		assertObjectDataListIds(objects, subDocId2);
+        assertObjectDataListIds(objects, subFolderId2);
+		
+		list = fNavSvc.getChildren(fRepositoryId, fRootFolderId, null, null, false, IncludeRelationships.NONE, null, null, 
+				null, null, null);
+		objects = list.getObjects();
+		assertObjectDataListIds(objects, docId2);
+        assertObjectDataListIds(objects, folderId2);
+        assertObjectDataListIds(objects, noAclDocId2);
+		
+		List<ObjectInFolderContainer> descList = fNavSvc.getDescendants(fRepositoryId, fRootFolderId, MINUS_ONE,
+				null, false, IncludeRelationships.NONE, null, false, null);
+		assertObjectInFolderContainerIds(descList, docId2);
+        assertObjectInFolderContainerIds(descList, folderId2);
+        assertObjectInFolderContainerIds(descList, noAclDocId2);
+		
+		List<ObjectInFolderContainer> folderList = fNavSvc.getFolderTree(fRepositoryId, fRootFolderId, MINUS_ONE,
+				null, false, IncludeRelationships.NONE, null, false, null);
+        assertObjectInFolderContainerIds(folderList, folderId2);
+        assertObjectInFolderContainerIds(folderList, subFolderId2);
+		
+		// check out
+		switchCallContext("TestAdmin");
+		Holder<String> holderDocId = new Holder<String>(docId);
+		Holder<String> holderDocId2 = new Holder<String>(docId2);
+		Holder<String> holderSubDocId = new Holder<String>(subDocId);
+		Holder<String> holderSubDocId2 = new Holder<String>(subDocId2);
+		fVerSvc.checkOut(fRepositoryId, holderDocId, null, null);
+		fVerSvc.checkOut(fRepositoryId, holderDocId2, null, null);
+		fVerSvc.checkOut(fRepositoryId, holderSubDocId, null, null);
+		fVerSvc.checkOut(fRepositoryId, holderSubDocId2, null, null);
+		
+		switchCallContext("TestUser");
+		ObjectList objectList = fNavSvc.getCheckedOutDocs(fRepositoryId, null, null, null, false,
+				IncludeRelationships.NONE, null, MINUS_ONE, MINUS_ONE, null);
+		assertObjectInObjectListIds(objectList, holderDocId2.getValue());
+        assertObjectInObjectListIds(objectList, holderSubDocId2.getValue());
+		
+		// only direct children are returned
+		ObjectList objectList2 = fNavSvc.getCheckedOutDocs(fRepositoryId, fRootFolderId, null, null, false,
+				IncludeRelationships.NONE, null, MINUS_ONE, MINUS_ONE, null);
+		List<String> docIds2 = new ArrayList<String>(1);
+		docIds2.add(docId2);
+		Assert.assertEquals(BigInteger.valueOf(1L), objectList2.getNumItems());
+		
+		// multi filing, get object parents
+		switchCallContext("TestAdmin");
+		String secFolderId = createFolderWithAcls("secondFolder", fRootFolderId, "cmis:folder", 
+				standardAcl, null);  	
+		String docId3 = createDocumentWithAcls("thirdDoc", folderId2, "ComplexType",
+				addAcl, null);
+		fMultiSvc.addObjectToFolder(fRepositoryId, docId3, secFolderId, true, null);
+		
+		switchCallContext("TestUser");  // second parent is not visible
+		List<ObjectParentData> objectParentData = fNavSvc.getObjectParents(fRepositoryId, docId3, null, null, null, null, true, null);
+		Assert.assertEquals(1, objectParentData.size());
+		Assert.assertEquals(folderId2, objectParentData.get(0).getObject().getId());
+        LOG.debug("...stop test checkVisibleObjects()");
+	}
+		
+	@Test
+	public void checkQueryAccess()
+	{
+		createCustomPropertyDocuments();
+		
+		String queryStatement;
+		List<ObjectData> objectDataList;
+		ObjectList objectList;
+		ObjectData first;
+		
+		switchCallContext("TestUser"); // Testuser has no permissions to view a document
+		queryStatement = "select * from cmis:document";
+		objectList = fDiscSvc.query(fRepositoryId, queryStatement, null, null, null,
+				null, MINUS_ONE, MINUS_ONE, null);
+		assertTrue ( 0L == objectList.getNumItems().longValue());
+		
+		// add a permission for a document
+		switchCallContext("TestAdmin"); 
+		String docId20 = idMap.get("customDocId20");
+		fAclSvc.applyAcl(fRepositoryId, idMap.get("customDocId20"), testUserAcl, null, AclPropagation.OBJECTONLY, null);
+		
+		switchCallContext("TestUser"); // Testuser has has only permissions for customDocId20
+		queryStatement = "select * from ComplexType where IntProp <= 20";
+		
+		objectList = fDiscSvc.query(fRepositoryId, queryStatement, null, null, null,
+				null, MINUS_ONE, MINUS_ONE, null); 
+		assertTrue ( 1L == objectList.getNumItems().longValue());
+		objectDataList = objectList.getObjects();
+		first = objectDataList.get(0);
+		assertTrue(first.getBaseTypeId().equals(BaseTypeId.CMIS_DOCUMENT ));
+	}
+	
+	protected String createDocumentWithAcls(String name, String folderId, String typeId, 
+			Acl addACEs, Acl removeACEs)
+	{
+		return createDocumentWithAcls(name, folderId, typeId, VersioningState.NONE, addACEs, removeACEs);
+	}
+	
+    protected String createDocumentWithAcls(String name, String folderId, String typeId, VersioningState versioningState,
+            Acl addACEs, Acl removeACEs)
+    {
+        ContentStream contentStream = null;
+        List<String> policies = null;
+        ExtensionsData extension = null;
+
+        Properties props = createDocumentProperties(name, typeId);
+
+        String id = fObjSvc.createDocument(fRepositoryId, props, folderId, contentStream, versioningState , policies,
+                addACEs, removeACEs, extension);
+        return id;
+    }
+	
+	protected String createFolderWithAcls(String name, String folderId, String typeId, 
+			Acl addACEs, Acl removeACEs)
+	{
+		List<String> policies = null;
+		ExtensionsData extension = null;
+
+		Properties props = createFolderProperties(name, typeId);
+
+	
+		String id = fObjSvc.createFolder(fRepositoryId, props, folderId, policies,
+				addACEs, removeACEs, extension);
+		return id;
+	}
+	
+	 protected Properties createRelationshipProperties(String sourceId, String targetId) {
+	        List<PropertyData<?>> properties = new ArrayList<PropertyData<?>>();
+	        properties.add(fFactory.createPropertyIdData(PropertyIds.SOURCE_ID, sourceId));
+	        properties.add(fFactory.createPropertyIdData(PropertyIds.TARGET_ID, targetId));
+	        properties.add(fFactory.createPropertyIdData(PropertyIds.OBJECT_TYPE_ID, 
+	        		EnumBaseObjectTypeIds.CMIS_RELATIONSHIP.value()));
+	        Properties props = fFactory.createPropertiesData(properties);
+	        return props;
+	 }
+	 
+	 private void switchCallContext(String user) {
+	     ((DummyCallContext) fTestCallContext).put(CallContext.USERNAME, user);
+	 }
+	
+	protected void createCustomPropertyDocuments()
+	{
+		switchCallContext("TestAdmin"); 
+		// create folder
+		String folderId = createFolderWithAcls("customFolder", fRootFolderId, "cmis:folder", standardAcl, null);
+		idMap.put("customFolder", folderId);
+
+		// create documents
+		List<PropertyData<?>> properties10 = new ArrayList<PropertyData<?>>();
+		properties10.add(fFactory.createPropertyIntegerData("IntProp", BigInteger.valueOf(10)));
+		properties10.add(fFactory.createPropertyStringData("StringProp", "10 string"));
+		properties10.add(fFactory.createPropertyBooleanData("BooleanProp", true));
+		GregorianCalendar gregorianCalendar = CalendarHelper.fromString("2010-07-10T12:00:00.000-01:00");
+		properties10.add(fFactory.createPropertyDateTimeData("DateTimeProp", gregorianCalendar));
+		String customDocId10 = createDocumentWithProperties("customDocument10", folderId, "ComplexType",
+				properties10, false);
+		idMap.put("customDocId10", customDocId10);
+
+		List<PropertyData<?>>  properties20 = new ArrayList<PropertyData<?>>();
+		properties20.add(fFactory.createPropertyIntegerData("IntProp", BigInteger.valueOf(20)));
+		properties20.add(fFactory.createPropertyStringData("StringProp", "20 string"));
+		properties20.add(fFactory.createPropertyBooleanData("BooleanProp", false));
+		gregorianCalendar = CalendarHelper.fromString("2010-07-20T12:00:00.000-01:00");
+		properties20.add(fFactory.createPropertyDateTimeData("DateTimeProp", gregorianCalendar));
+		String customDocId20 = createDocumentWithProperties("customDocument20", folderId, "ComplexType", 
+				properties20,false);
+		idMap.put("customDocId20", customDocId20);
+
+		List<PropertyData<?>>  properties30 = new ArrayList<PropertyData<?>>();
+		properties30.add(fFactory.createPropertyIntegerData("IntProp", BigInteger.valueOf(30)));
+		properties30.add(fFactory.createPropertyStringData("StringProp", "30 string"));
+		properties30.add(fFactory.createPropertyBooleanData("BooleanProp", true));
+		gregorianCalendar = CalendarHelper.fromString("2010-07-30T12:00:00.000-01:00");
+		properties30.add(fFactory.createPropertyDateTimeData("DateTimeProp", gregorianCalendar));
+		String customDocId30 = createDocumentWithProperties("customDocument30", folderId, "ComplexType",
+				properties30, false);
+		idMap.put("customDocId30", customDocId30);
+	
+	}
+	
+	  protected String createDocumentWithProperties(String name, String folderId, String typeId, List<PropertyData<?>> properties,
+	            boolean withContent) {
+	        ContentStream contentStream = null;
+	        
+	        // add document properties
+	        properties.add(fFactory.createPropertyIdData(PropertyIds.NAME, name));
+	        properties.add(fFactory.createPropertyIdData(PropertyIds.OBJECT_TYPE_ID, typeId));
+	        Properties props = fFactory.createPropertiesData(properties);
+
+	        if (withContent)
+	            contentStream = createContent();
+
+	        String id = null;
+	        try {
+	            id = fObjSvc.createDocument(fRepositoryId, props, folderId, contentStream, VersioningState.NONE, null,
+	                    null, null, null);
+	            if (null == id)
+	                fail("createDocument failed.");
+	        } catch (Exception e) {
+	            fail("createDocument() failed with exception: " + e);
+	        }
+	        return id;
+
+	    }
+
+	    private Acl createAcl(String principalId, EnumBasicPermissions permission) {
+	        List<Ace> acesAdd = Arrays.asList(new Ace[] { 
+	                createAce(principalId, permission),
+	                });
+	       return fFactory.createAccessControlList(acesAdd);                
+	    }
+
+	    private Ace createAce(String principalId, EnumBasicPermissions permission) {
+	        return  fFactory.createAccessControlEntry(principalId, Collections.singletonList( permission.value() ));
+	    }
+
+	    private static boolean aclEquals(Acl acl1, Acl acl2) {
+	        if (acl1 == acl2)
+	            return true;
+	        if (acl1 == null || acl2 == null)
+	            return false;
+	        if (acl1.getClass() != acl2.getClass())
+	            return false;
+            if (acl1.getAces().size() != acl2.getAces().size())
+                return false;
+	        for (int i=0; i<acl1.getAces().size(); i++) {
+	            aclHasAce(acl1.getAces(), acl2.getAces().get(i));
+	        }
+	        return true;
+	    }
+
+	    private static boolean aclHasAce( List<Ace> aces, Ace ace) {
+	        for (Ace ace2 : aces) {
+                if (!ace.getPrincipalId().equals(ace2.getPrincipalId()))
+                    continue;
+                if (ace.getPermissions().size() != ace2.getPermissions().size())
+                    continue;
+                for (int i=0; i<ace2.getPermissions().size(); i++)
+                    if (!aceHasPermission(ace.getPermissions(), ace2.getPermissions().get(i)))
+                        continue;
+
+                return true;
+	        }
+	        return false;
+	    }
+
+	   private static boolean aceHasPermission( List<String> permissions, String permission) {
+	      for (String permission2 : permissions)
+	          if (permission2.equals(permission))
+	              return true;
+	      return false;
+	   }
+
+	    private String createVersionedDocument(String name, String folderId) {
+
+	        VersioningState versioningState = VersioningState.MAJOR;
+	        String id = null;
+	        Map<String, String> properties = new HashMap<String, String>();
+	        id = fCreator.createDocument(name, UnitTestTypeSystemCreator.VERSION_DOCUMENT_TYPE_ID, folderId,
+	                versioningState, properties);
+
+	        return id;
+	    }
+	    
+	    private void assertObjectDataListIds(List<ObjectInFolderData> folderData, String id) {
+	        boolean found = false;
+	        for (ObjectInFolderData folder : folderData) {
+	            LOG.info("   found folder id " + folder.getObject().getId());
+	            if (id.equals(folder.getObject().getId()))
+	                found = true;
+	        }
+            assertTrue("Failed to find folder id " + id, found);          
+	    }
+	    
+	    private void assertObjectInFolderContainerIds(List<ObjectInFolderContainer> folderList, String id) {
+            boolean found = objectInFolderContainerHasId(folderList, id);
+            assertTrue("Failed to find folder id " + id, found);                  
+	    }
+	    
+        private boolean objectInFolderContainerHasId(List<ObjectInFolderContainer> folderList, String id) {
+            for (ObjectInFolderContainer fc : folderList) {
+                if (id.equals(fc.getObject().getObject().getId()))
+                    return true;
+                List<ObjectInFolderContainer> children = fc.getChildren();
+                if (children != null && objectInFolderContainerHasId(children, id))
+                    return true;
+            }
+            return false;                  
+        }
+
+	    private void assertObjectInObjectListIds(ObjectList objList, String id) {
+            boolean found = false;
+            for (ObjectData od : objList.getObjects()) {
+                LOG.info("   found object id " + od.getId());
+                if (id.equals(od.getId()))
+                    found = true;
+
+            }
+            assertTrue("Failed to find object id " + id, found);                  
+        }
+
+}