content: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you 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.
   */
  package org.apache.chemistry.opencmis.inmemory;
  
  import static org.junit.Assert.assertEquals;
  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 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.inmemory.storedobj.impl.InMemoryAce;
  import org.apache.chemistry.opencmis.server.support.query.CalendarHelper;
  import org.junit.After;
  import org.junit.Before;
  import org.junit.Test;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  public class AclPermissionsTest extends AbstractServiceTest {
  
      private static Logger LOG = LoggerFactory.getLogger(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 Acl defaultAcl = 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);
  
          List<Ace> defaultACEs = new ArrayList<Ace>(1);
          defaultACEs.add(createAce(InMemoryAce.getAnyoneUser(), EnumBasicPermissions.CMIS_ALL));
          defaultAcl = fFactory.createAccessControlList(defaultACEs);
      }
  
      @Test
      public void testCreateObjectsWithAcl() {
          // create a document with initial ACL
          String docId = createDocumentWithAcls("complexDocument", fRootFolderId, UnitTestTypeSystemCreator.COMPLEX_TYPE,
                  addAcl, defaultAcl);
          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,
                  defaultAcl);
          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, defaultAcl, AclPropagation.OBJECTONLY, null);
          assertTrue(aclEquals(addAcl, acl));
  
          String folderId2 = createFolder("folder2", fRootFolderId, "cmis:folder");
          acl2 = fAclSvc.applyAcl(fRepositoryId, folderId2, addAcl, defaultAcl, 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, defaultAcl);
          String folderId = createFolderWithAcls("folder", fRootFolderId, "cmis:folder", standardAcl, defaultAcl);
          // 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) {
              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) {
              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) {
              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) {
              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) {
              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) {
              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 testAclServiceGeneralAccess() {
          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, defaultAcl);
          String folderId = createFolderWithAcls("folder", fRootFolderId, "cmis:folder", initialAcl, defaultAcl);
          String subFolderId = createFolderWithAcls("subFolder", folderId, "cmis:folder", initialAcl, defaultAcl);
  
          // 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) {
              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) {
              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) {
              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 testObjectServiceGeneralAccess() {
  
          // starts with call context TestUser
          switchCallContext("TestAdmin");
          String docId = createDocumentWithAcls("doc", fRootFolderId, "ComplexType", standardAcl, defaultAcl);
          String folderId = createFolderWithAcls("folder", fRootFolderId, "cmis:folder", standardAcl, defaultAcl);
          // 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) {
              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) {
              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) 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) 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) {
              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) {
              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) {
              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) {
              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) {
              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) {
              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) {
              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) {
              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) {
              fail("Reader has no permissions to delete document ");
          }
  
          exceptionThrown = false;
          try {
              fObjSvc.deleteObject(fRepositoryId, adminFolderId, true, null);
          } catch (CmisPermissionDeniedException e) {
              exceptionThrown = true;
          }
          if (!exceptionThrown) {
              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) {
              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) {
              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) {
              fail("Reader has no permissions to delete tree ");
          }
      }
  
      @Test
      public void testMultiFilingServiceGeneralAccess() {
          // starts with call context TestUser
          switchCallContext("TestAdmin");
          String docId = createDocumentWithAcls("doc", fRootFolderId, "ComplexType", standardAcl, defaultAcl);
          String folderId = createFolderWithAcls("folder", fRootFolderId, "cmis:folder", addAcl, defaultAcl);
          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) {
              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) {
              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) {
              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) {
              fail("TestUser has no permission at the object to remove a parent");
          }
      }
  
      @Test
      public void testVersioningServiceGeneralAccess() {
          // starts with call context TestUser
          switchCallContext("TestAdmin");
          String docId = createDocumentWithAcls("doc", fRootFolderId, UnitTestTypeSystemCreator.VERSIONED_TYPE,
                  VersioningState.MAJOR, standardAcl, defaultAcl);
  
          // 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) {
              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) {
              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) {
              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) {
              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");
          Holder<String> idHolder = new Holder<String>(docId);
          fVerSvc.checkOut(fRepositoryId, idHolder, null, new Holder<Boolean>(false));
  
          switchCallContext("TestAdmin");
          fAclSvc.applyAcl(fRepositoryId, docId, null, testUserAcl, AclPropagation.OBJECTONLY, null);
  
          switchCallContext("TestUser");
          exceptionThrown = false;
          try {
              fVerSvc.checkIn(fRepositoryId, idHolder, true, null, null, null, null, null, null, null);
          } catch (CmisPermissionDeniedException e) {
              exceptionThrown = true;
          }
          if (!exceptionThrown) {
              fail("TestUser has no permission to checkIn)");
          }
          switchCallContext("TestAdmin");
          fAclSvc.applyAcl(fRepositoryId, docId, testUserAcl, null, AclPropagation.OBJECTONLY, null);
          switchCallContext("TestUser");
          fVerSvc.checkIn(fRepositoryId, idHolder, 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, idHolder, null, new Holder<Boolean>(false));
  
          switchCallContext("TestAdmin");
          fAclSvc.applyAcl(fRepositoryId, docId, null, readWriteAcl, AclPropagation.OBJECTONLY, null);
  
          switchCallContext("Writer");
          exceptionThrown = false;
          try {
              fVerSvc.checkIn(fRepositoryId, idHolder, true, null, null, null, null, null, null, null);
          } catch (CmisPermissionDeniedException e) {
              exceptionThrown = true;
          }
          if (!exceptionThrown) {
              fail("Writer has not enough permission to checkIn)");
          }
          switchCallContext("TestAdmin");
          fAclSvc.applyAcl(fRepositoryId, docId, readWriteAcl, null, AclPropagation.OBJECTONLY, null);
          switchCallContext("Writer");
          fVerSvc.checkIn(fRepositoryId, idHolder, 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) {
              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) {
              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) {
              fail("TestUser has not enough permission to getAllVersions)");
          }
      }
  
      @Test
      public void testVisibleObjects() {
          LOG.debug("start test checkVisibleObjects()...");
          switchCallContext("TestAdmin");
          String docId = createDocumentWithAcls("doc", fRootFolderId, UnitTestTypeSystemCreator.VERSIONED_TYPE,
                  VersioningState.MAJOR, standardAcl, defaultAcl);
          String docId2 = createDocumentWithAcls("doc2", fRootFolderId, UnitTestTypeSystemCreator.VERSIONED_TYPE,
                  VersioningState.MAJOR, addAcl, defaultAcl);
          String folderId = createFolderWithAcls("folder", fRootFolderId, "cmis:folder", standardAcl, defaultAcl);
          String folderId2 = createFolderWithAcls("folder2", fRootFolderId, "cmis:folder", addAcl, defaultAcl);
          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.VERSIONED_TYPE,
                  VersioningState.MAJOR, null, testUserAcl);
          LOG.debug("checkVisibleObjects(): subDocId is: " + subDocId);
          String subDocId2 = createDocumentWithAcls("subDoc2", folderId2, UnitTestTypeSystemCreator.VERSIONED_TYPE,
                  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);
          assertEquals(BigInteger.valueOf(1L), objectList2.getNumItems());
  
          // multi filing, get object parents
          switchCallContext("TestAdmin");
          String secFolderId = createFolderWithAcls("secondFolder", fRootFolderId, "cmis:folder", standardAcl, defaultAcl);
          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);
          assertEquals(1, objectParentData.size());
          assertEquals(folderId2, objectParentData.get(0).getObject().getId());
          LOG.debug("...stop test checkVisibleObjects()");
      }
  
      @Test
      public void testQueryAccess() {
          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, defaultAcl);
          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.VERSIONED_TYPE, 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);
      }
  
  }
  