You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by an...@apache.org on 2015/10/06 18:27:37 UTC

svn commit: r1707085 [1/2] - in /jackrabbit/oak/trunk: oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/ oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/...

Author: angela
Date: Tue Oct  6 16:27:36 2015
New Revision: 1707085

URL: http://svn.apache.org/viewvc?rev=1707085&view=rev
Log:
OAK-1268 :  Add support for composite authorization setup (WIP)

Added:
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/AbstractCompositeProviderTest.java
      - copied, changed from r1704492, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProviderTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderAllReverseTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderAllTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderEmptyReverseTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderEmptyTest.java
      - copied, changed from r1704492, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProviderTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderLimitedReverseTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderLimitedTest.java
      - copied, changed from r1705991, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProviderTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderNoScopeReverseTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderNoScopeTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderScopeReverseTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderScopeTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/TestPermissionProvider.java
Removed:
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProviderTest.java
Modified:
    jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManager.java
    jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProvider.java
    jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugEvaluationTest.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAccessControlManager.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/AggregatedPermissionProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/package-info.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProvider.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAccessControlManagerTest.java

Modified: jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManager.java?rev=1707085&r1=1707084&r2=1707085&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManager.java (original)
+++ jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugAccessControlManager.java Tue Oct  6 16:27:36 2015
@@ -178,17 +178,17 @@ class CugAccessControlManager extends Ab
     //-------------------------------------< JackrabbitAccessControlManager >---
 
     public JackrabbitAccessControlPolicy[] getApplicablePolicies(Principal principal) throws RepositoryException {
-        // TODO
+        // editing by 'principal' is not supported
         return new JackrabbitAccessControlPolicy[0];
     }
 
     public JackrabbitAccessControlPolicy[] getPolicies(Principal principal) throws RepositoryException {
-        // TODO
+        // editing by 'principal' is not supported
         return new JackrabbitAccessControlPolicy[0];
     }
 
     public AccessControlPolicy[] getEffectivePolicies(Set<Principal> principals) throws RepositoryException {
-        // TODO
+        // editing by 'principal' is not supported
         return new AccessControlPolicy[0];
     }
 

Modified: jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProvider.java?rev=1707085&r1=1707084&r2=1707085&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProvider.java (original)
+++ jackrabbit/oak/trunk/oak-authorization-cug/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProvider.java Tue Oct  6 16:27:36 2015
@@ -162,6 +162,7 @@ class CugPermissionProvider implements A
     }
 
     //---------------------------------------< AggregatedPermissionProvider >---
+    @Nonnull
     @Override
     public PrivilegeBits supportedPrivileges(@Nullable Tree tree, @Nullable PrivilegeBits privilegeBits) {
         if (tree == null) {

Modified: jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugEvaluationTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugEvaluationTest.java?rev=1707085&r1=1707084&r2=1707085&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugEvaluationTest.java (original)
+++ jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugEvaluationTest.java Tue Oct  6 16:27:36 2015
@@ -61,6 +61,11 @@ public class CugEvaluationTest extends A
     private Root testRoot;
     private Principal testGroupPrincipal;
 
+    private Tree content;
+    private Tree content2;
+    private Tree a;
+    private Tree c;
+
     @Before
     @Override
     public void before() throws Exception {
@@ -79,6 +84,10 @@ public class CugEvaluationTest extends A
         n.addChild("aa", NT_OAK_UNSTRUCTURED).addChild("bb", NT_OAK_UNSTRUCTURED).addChild("cc", NT_OAK_UNSTRUCTURED);
 
         // create cugs
+        // - /content/a     : allow testGroup, deny everyone
+        // - /content/aa/bb : allow testGroup, deny everyone
+        // - /content/a/b/c : allow everyone,  deny testGroup (isolated)
+        // - /content2      : allow everyone,  deny testGroup (isolated)
         createCug("/content/a", testGroupPrincipal);
         createCug("/content/aa/bb", testGroupPrincipal);
         createCug("/content/a/b/c", EveryonePrincipal.getInstance());
@@ -98,6 +107,11 @@ public class CugEvaluationTest extends A
 
         root.commit();
 
+        content = root.getTree("/content");
+        content2 = root.getTree("/content2");
+        a = root.getTree("/content/a");
+        c = root.getTree("/content/a/b/c");
+
         testSession = createTestSession();
         testRoot = testSession.getLatestRoot();
     }
@@ -130,6 +144,10 @@ public class CugEvaluationTest extends A
         return getSecurityProvider().getConfiguration(AuthorizationConfiguration.class).getPermissionProvider(root, adminSession.getWorkspaceName(), principals);
     }
 
+    private PermissionProvider createPermissionProvider(Principal... principals) {
+        return getSecurityProvider().getConfiguration(AuthorizationConfiguration.class).getPermissionProvider(root, adminSession.getWorkspaceName(), ImmutableSet.copyOf(principals));
+    }
+
     @Test
     public void testRead() throws Exception {
         List<String> noAccess = ImmutableList.of(
@@ -261,14 +279,9 @@ public class CugEvaluationTest extends A
     }
 
     @Test
-    public void testIsGranted() throws Exception {
-        Tree content = root.getTree("/content");
-        Tree a = root.getTree("/content/a");
-        Tree c = root.getTree("/content/a/b/c");
-
+    public void testIsGrantedTestGroup() throws Exception {
         // testGroup
-        Set<Principal> principals = ImmutableSet.of(testGroupPrincipal);
-        PermissionProvider pp = createPermissionProvider(principals);
+        PermissionProvider pp = createPermissionProvider(testGroupPrincipal);
 
         assertTrue(pp.isGranted(content, null, Permissions.READ));
         assertTrue(pp.isGranted(a, null, Permissions.READ));
@@ -277,22 +290,28 @@ public class CugEvaluationTest extends A
         assertTrue(pp.isGranted(content, null, Permissions.READ_ACCESS_CONTROL));
         assertTrue(pp.isGranted(a, null, Permissions.READ_ACCESS_CONTROL));
         assertTrue(pp.isGranted(c, null, Permissions.READ_ACCESS_CONTROL));
+    }
 
+    @Test
+    public void testIsGrantedEveryone() throws Exception {
         // everyone
-        principals = ImmutableSet.<Principal>of(EveryonePrincipal.getInstance());
-        pp = createPermissionProvider(principals);
+        PermissionProvider pp = createPermissionProvider(EveryonePrincipal.getInstance());
 
         assertFalse(pp.isGranted(content, null, Permissions.READ));
+        assertFalse(pp.isGranted(content2, null, Permissions.READ));
         assertFalse(pp.isGranted(a, null, Permissions.READ));
         assertFalse(pp.isGranted(c, null, Permissions.READ));
 
         assertFalse(pp.isGranted(content, null, Permissions.READ_ACCESS_CONTROL));
+        assertFalse(pp.isGranted(content2, null, Permissions.READ_ACCESS_CONTROL));
         assertFalse(pp.isGranted(a, null, Permissions.READ_ACCESS_CONTROL));
         assertFalse(pp.isGranted(c, null, Permissions.READ_ACCESS_CONTROL));
+    }
 
+    @Test
+    public void testIsGrantedTestGroupEveryone() throws Exception {
         // testGroup + everyone
-        principals = ImmutableSet.of(testGroupPrincipal, EveryonePrincipal.getInstance());
-        pp = createPermissionProvider(principals);
+        PermissionProvider pp = createPermissionProvider(testGroupPrincipal, EveryonePrincipal.getInstance());
 
         assertTrue(pp.isGranted(content, null, Permissions.READ));
         assertTrue(pp.isGranted(a, null, Permissions.READ));
@@ -301,10 +320,12 @@ public class CugEvaluationTest extends A
         assertTrue(pp.isGranted(content, null, Permissions.READ_ACCESS_CONTROL));
         assertTrue(pp.isGranted(a, null, Permissions.READ_ACCESS_CONTROL));
         assertTrue(pp.isGranted(c, null, Permissions.READ_ACCESS_CONTROL));
+    }
 
+    @Test
+    public void testIsGrantedTestUserEveryone() throws Exception {
         // testUser + everyone
-        principals = ImmutableSet.of(getTestUser().getPrincipal(), EveryonePrincipal.getInstance());
-        pp = createPermissionProvider(principals);
+        PermissionProvider pp = createPermissionProvider(getTestUser().getPrincipal(), EveryonePrincipal.getInstance());
 
         assertTrue(pp.isGranted(content, null, Permissions.READ));
         assertFalse(pp.isGranted(a, null, Permissions.READ));
@@ -316,14 +337,9 @@ public class CugEvaluationTest extends A
     }
 
     @Test
-    public void testHasPrivileges() throws Exception {
-        Tree content = root.getTree("/content");
-        Tree a = root.getTree("/content/a");
-        Tree c = root.getTree("/content/a/b/c");
-
+    public void testHasPrivilegesTestGroup() throws Exception {
         // testGroup
-        Set<Principal> principals = ImmutableSet.of(testGroupPrincipal);
-        PermissionProvider pp = createPermissionProvider(principals);
+        PermissionProvider pp = createPermissionProvider(testGroupPrincipal);
 
         assertTrue(pp.hasPrivileges(content, PrivilegeConstants.JCR_READ));
         assertTrue(pp.hasPrivileges(a, PrivilegeConstants.JCR_READ));
@@ -332,22 +348,28 @@ public class CugEvaluationTest extends A
         assertTrue(pp.hasPrivileges(content, PrivilegeConstants.REP_WRITE, PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
         assertTrue(pp.hasPrivileges(a, PrivilegeConstants.REP_WRITE, PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
         assertTrue(pp.hasPrivileges(c, PrivilegeConstants.REP_WRITE, PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+    }
 
+    @Test
+    public void testHasPrivilegesEveryone() throws Exception {
         // everyone
-        principals = ImmutableSet.<Principal>of(EveryonePrincipal.getInstance());
-        pp = createPermissionProvider(principals);
+        PermissionProvider pp = createPermissionProvider(EveryonePrincipal.getInstance());
 
         assertFalse(pp.hasPrivileges(content, PrivilegeConstants.JCR_READ));
+        assertFalse(pp.hasPrivileges(content2, PrivilegeConstants.JCR_READ));
         assertFalse(pp.hasPrivileges(a, PrivilegeConstants.JCR_READ));
         assertFalse(pp.hasPrivileges(c, PrivilegeConstants.JCR_READ));
 
         assertFalse(pp.hasPrivileges(content, PrivilegeConstants.REP_WRITE, PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+        assertFalse(pp.hasPrivileges(content2, PrivilegeConstants.REP_WRITE, PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
         assertFalse(pp.hasPrivileges(a, PrivilegeConstants.REP_WRITE, PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
         assertFalse(pp.hasPrivileges(c, PrivilegeConstants.REP_WRITE, PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+    }
 
+    @Test
+    public void testHasPrivilegesTestGroupEveryone() throws Exception {
         // testGroup + everyone
-        principals = ImmutableSet.of(testGroupPrincipal, EveryonePrincipal.getInstance());
-        pp = createPermissionProvider(principals);
+        PermissionProvider pp = createPermissionProvider(testGroupPrincipal, EveryonePrincipal.getInstance());
 
         assertTrue(pp.hasPrivileges(content, PrivilegeConstants.JCR_READ));
         assertTrue(pp.hasPrivileges(a, PrivilegeConstants.JCR_READ));
@@ -356,10 +378,12 @@ public class CugEvaluationTest extends A
         assertTrue(pp.hasPrivileges(content, PrivilegeConstants.REP_WRITE, PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
         assertTrue(pp.hasPrivileges(a, PrivilegeConstants.REP_WRITE, PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
         assertTrue(pp.hasPrivileges(c, PrivilegeConstants.REP_WRITE, PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
+    }
 
+    @Test
+    public void testHasPrivilegesTestUserEveryone() throws Exception {
         // testUser + everyone
-        principals = ImmutableSet.of(getTestUser().getPrincipal(), EveryonePrincipal.getInstance());
-        pp = createPermissionProvider(principals);
+        PermissionProvider pp = createPermissionProvider(getTestUser().getPrincipal(), EveryonePrincipal.getInstance());
 
         assertTrue(pp.hasPrivileges(content, PrivilegeConstants.JCR_READ));
         assertFalse(pp.hasPrivileges(a, PrivilegeConstants.JCR_READ));
@@ -376,9 +400,9 @@ public class CugEvaluationTest extends A
         Set<Principal> principals = ImmutableSet.of(testGroupPrincipal);
         PermissionProvider pp = createPermissionProvider(principals);
 
-        assertFalse(pp.hasPrivileges(root.getTree("/content"), PrivilegeConstants.JCR_ALL));
-        assertFalse(pp.hasPrivileges(root.getTree("/content/a"), PrivilegeConstants.JCR_ALL));
-        assertFalse(pp.hasPrivileges(root.getTree("/content/b/c"), PrivilegeConstants.JCR_ALL));
+        assertFalse(pp.hasPrivileges(content, PrivilegeConstants.JCR_ALL));
+        assertFalse(pp.hasPrivileges(a, PrivilegeConstants.JCR_ALL));
+        assertFalse(pp.hasPrivileges(c, PrivilegeConstants.JCR_ALL));
     }
 
     @Test
@@ -390,8 +414,7 @@ public class CugEvaluationTest extends A
         root.commit();
 
         // testGroup
-        Set<Principal> principals = ImmutableSet.of(testGroupPrincipal);
-        PermissionProvider pp = createPermissionProvider(principals);
+        PermissionProvider pp = createPermissionProvider(testGroupPrincipal);
 
         assertFalse(pp.hasPrivileges(root.getTree("/content"), PrivilegeConstants.JCR_ALL));
         assertTrue(pp.hasPrivileges(root.getTree("/content/a"), PrivilegeConstants.JCR_ALL));
@@ -400,61 +423,64 @@ public class CugEvaluationTest extends A
     }
 
     @Test
-    public void testHasAllPrivileges3() throws Exception {
+    public void testHasAllPrivilegesAdmin() throws Exception {
         // admin principal
         Set<Principal> principals = adminSession.getAuthInfo().getPrincipals();
         PermissionProvider pp = createPermissionProvider(principals);
 
-        assertTrue(pp.hasPrivileges(root.getTree("/content"), PrivilegeConstants.JCR_ALL));
-        assertTrue(pp.hasPrivileges(root.getTree("/content/a"), PrivilegeConstants.JCR_ALL));
-        assertTrue(pp.hasPrivileges(root.getTree("/content/a/b/c"), PrivilegeConstants.JCR_ALL));
+        assertTrue(pp.hasPrivileges(content, PrivilegeConstants.JCR_ALL));
+        assertTrue(pp.hasPrivileges(a, PrivilegeConstants.JCR_ALL));
+        assertTrue(pp.hasPrivileges(c, PrivilegeConstants.JCR_ALL));
     }
 
     @Test
-    public void testGetPrivileges() throws Exception {
-        Tree content = root.getTree("/content");
-        Tree content2 = root.getTree("/content2");
-        Tree a = root.getTree("/content/a");
-        Tree c = root.getTree("/content/a/b/c");
-
-        Set<String> r = ImmutableSet.of(PrivilegeConstants.JCR_READ);
+    public void testGetPrivilegesTestGroup() throws Exception {
         Set<String> w_rac = ImmutableSet.of(PrivilegeConstants.REP_WRITE, PrivilegeConstants.JCR_READ_ACCESS_CONTROL);
         Set<String> r_w_rac = ImmutableSet.of(PrivilegeConstants.JCR_READ, PrivilegeConstants.REP_WRITE, PrivilegeConstants.JCR_READ_ACCESS_CONTROL);
 
         // testGroup
-        Set<Principal> principals = ImmutableSet.of(testGroupPrincipal);
-        PermissionProvider pp = createPermissionProvider(principals);
+        PermissionProvider pp = createPermissionProvider(testGroupPrincipal);
 
         assertEquals(r_w_rac, pp.getPrivileges(content));
         assertEquals(r_w_rac, pp.getPrivileges(a));
         assertEquals(w_rac, pp.getPrivileges(c));
         assertTrue(pp.getPrivileges(content2).isEmpty());
+    }
 
+    @Test
+    public void testGetPrivilegesEveryone() throws Exception {
         // everyone
-        principals = ImmutableSet.<Principal>of(EveryonePrincipal.getInstance());
-        pp = createPermissionProvider(principals);
+        PermissionProvider pp = createPermissionProvider(EveryonePrincipal.getInstance());
 
         assertTrue(pp.getPrivileges(content).isEmpty());
+        assertTrue(pp.getPrivileges(content2).isEmpty());
         assertTrue(pp.getPrivileges(a).isEmpty());
-        assertEquals(r, pp.getPrivileges(c));
-        assertEquals(r, pp.getPrivileges(content2));
+        assertTrue(pp.getPrivileges(c).isEmpty());
+    }
+
+    @Test
+    public void testGetPrivilegesTestGroupEveryone() throws Exception {
+        Set<String> r_w_rac = ImmutableSet.of(PrivilegeConstants.JCR_READ, PrivilegeConstants.REP_WRITE, PrivilegeConstants.JCR_READ_ACCESS_CONTROL);
 
         // testGroup + everyone
-        principals = ImmutableSet.of(testGroupPrincipal, EveryonePrincipal.getInstance());
-        pp = createPermissionProvider(principals);
+        PermissionProvider pp = createPermissionProvider(testGroupPrincipal, EveryonePrincipal.getInstance());
 
         assertEquals(r_w_rac, pp.getPrivileges(content));
         assertEquals(r_w_rac, pp.getPrivileges(a));
         assertEquals(r_w_rac, pp.getPrivileges(c));
-        assertEquals(r, pp.getPrivileges(content2));
+        assertTrue(pp.getPrivileges(content2).isEmpty());
+    }
 
+    @Test
+    public void testGetPrivilegesTestUserEveryone() throws Exception {
         // testUser + everyone
-        principals = ImmutableSet.of(getTestUser().getPrincipal(), EveryonePrincipal.getInstance());
-        pp = createPermissionProvider(principals);
+        PermissionProvider pp = createPermissionProvider(getTestUser().getPrincipal(), EveryonePrincipal.getInstance());
 
+        Set<String> r = ImmutableSet.of(PrivilegeConstants.JCR_READ);
         assertEquals(r, pp.getPrivileges(content));
-        assertTrue(pp.getPrivileges(a).isEmpty());
         assertEquals(r, pp.getPrivileges(c));
-        assertEquals(r, pp.getPrivileges(content2));
+
+        assertTrue(pp.getPrivileges(a).isEmpty());
+        assertTrue(pp.getPrivileges(content2).isEmpty());
     }
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAccessControlManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAccessControlManager.java?rev=1707085&r1=1707084&r2=1707085&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAccessControlManager.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAccessControlManager.java Tue Oct  6 16:27:36 2015
@@ -28,6 +28,7 @@ import javax.jcr.security.AccessControlP
 import javax.jcr.security.Privilege;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterators;
 import com.google.common.collect.Lists;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
@@ -62,12 +63,12 @@ class CompositeAccessControlManager exte
     @Nonnull
     @Override
     public Privilege[] getSupportedPrivileges(String absPath) throws RepositoryException {
-        ImmutableList.Builder<Privilege> privs = ImmutableList.builder();
+        ImmutableSet.Builder<Privilege> privs = ImmutableSet.builder();
         for (AccessControlManager acMgr : acMgrs) {
             privs.add(acMgr.getSupportedPrivileges(absPath));
         }
-        List<Privilege> l = privs.build();
-        return l.toArray(new Privilege[l.size()]);
+        Set<Privilege> s = privs.build();
+        return s.toArray(new Privilege[s.size()]);
     }
 
     @Override

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProvider.java?rev=1707085&r1=1707084&r2=1707085&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProvider.java Tue Oct  6 16:27:36 2015
@@ -93,17 +93,19 @@ class CompositePermissionProvider implem
             PrivilegeBits supported = aggregatedPermissionProvider.supportedPrivileges(immutableTree, null).modifiable();
             if (doEvaluate(supported)) {
                 PrivilegeBits granted = privilegeBitsProvider.getBits(aggregatedPermissionProvider.getPrivileges(immutableTree));
-                // make sure privs denied by a previous provider are substracted
-                if (!denied.isEmpty()) {
-                    result.add(granted.modifiable().diff(denied));
-                } else {
+                // add the granted privileges to the result
+                if (!granted.isEmpty()) {
                     result.add(granted);
                 }
                 // update the set of denied privs by comparing the granted privs
-                // the complete set of supported privileges.
+                // with the complete set of supported privileges
                 denied.add(supported.diff(granted));
             }
         }
+        // subtract all denied privileges from the result
+        if (!denied.isEmpty()) {
+            result.diff(denied);
+        }
         return privilegeBitsProvider.getPrivilegeNames(result);
     }
 
@@ -111,6 +113,9 @@ class CompositePermissionProvider implem
     public boolean hasPrivileges(@Nullable Tree tree, @Nonnull String... privilegeNames) {
         Tree immutableTree = PermissionUtil.getImmutableTree(tree, immutableRoot);
         PrivilegeBits privilegeBits = privilegeBitsProvider.getBits(privilegeNames);
+        if (privilegeBits.isEmpty()) {
+            return true;
+        }
 
         boolean hasPrivileges = false;
         PrivilegeBits coveredPrivs = PrivilegeBits.getInstance();
@@ -120,7 +125,7 @@ class CompositePermissionProvider implem
             if (doEvaluate(supported)) {
                 Set<String> supportedNames = privilegeBitsProvider.getPrivilegeNames(supported);
                 hasPrivileges = aggregatedPermissionProvider.hasPrivileges(immutableTree, supportedNames.toArray(new String[supportedNames.size()]));
-                coveredPrivs.add(supported);;
+                coveredPrivs.add(supported);
 
                 if (!hasPrivileges) {
                     break;
@@ -218,26 +223,21 @@ class CompositePermissionProvider implem
     private final class CompositeTreePermission implements TreePermission {
 
         private final ImmutableTree tree;
-        private final CompositeTreePermission parentPermission;
-
         private final Map<AggregatedPermissionProvider, TreePermission> map;
 
         private Boolean canRead;
 
         private CompositeTreePermission() {
             tree = null;
-            parentPermission = null;
-
             map = ImmutableMap.of();
         }
 
         private CompositeTreePermission(@Nonnull final ImmutableTree tree, @Nonnull CompositeTreePermission parentPermission) {
             this.tree = tree;
-            this.parentPermission = parentPermission;
-
             map = new LinkedHashMap<AggregatedPermissionProvider, TreePermission>(pps.size());
             for (AggregatedPermissionProvider provider : pps) {
-                TreePermission tp = provider.getTreePermission(tree, getParentPermission(provider));
+                // TODO: stop aggregation for providers that don't support evaluation within this path
+                TreePermission tp = provider.getTreePermission(tree, getParentPermission(parentPermission, provider));
                 map.put(provider, tp);
             }
         }
@@ -324,11 +324,9 @@ class CompositePermissionProvider implem
         }
 
         @Nonnull
-        private TreePermission getParentPermission(AggregatedPermissionProvider provider) {
-            TreePermission parent = null;
-            if (parentPermission != null) {
-                parent = parentPermission.map.get(provider);
-            }
+        private TreePermission getParentPermission(@Nonnull CompositeTreePermission compositeParent,
+                                                   @Nonnull AggregatedPermissionProvider provider) {
+            TreePermission parent = compositeParent.map.get(provider);
             return (parent == null) ? TreePermission.EMPTY : parent;
         }
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java?rev=1707085&r1=1707084&r2=1707085&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/permission/PermissionProviderImpl.java Tue Oct  6 16:27:36 2015
@@ -116,6 +116,7 @@ public class PermissionProviderImpl impl
     }
 
     //---------------------------------------< AggregatedPermissionProvider >---
+    @Nonnull
     @Override
     public PrivilegeBits supportedPrivileges(@Nullable Tree tree, @Nullable PrivilegeBits privilegeBits) {
         return (privilegeBits != null) ? privilegeBits : new PrivilegeBitsProvider(immutableRoot).getBits(PrivilegeConstants.JCR_ALL);

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/AggregatedPermissionProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/AggregatedPermissionProvider.java?rev=1707085&r1=1707084&r2=1707085&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/AggregatedPermissionProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/AggregatedPermissionProvider.java Tue Oct  6 16:27:36 2015
@@ -32,6 +32,29 @@ import org.apache.jackrabbit.oak.spi.sec
  */
 public interface AggregatedPermissionProvider extends PermissionProvider {
 
+    /**
+     * Allows to determined the set or subset of privileges evaluated by the
+     * implementing permission provider at the specified path or at the repository
+     * level in case the specified {@code tree} is {@code null}.
+     *
+     * If the given {@code privilegeBits} is {@code null} an implementation returns
+     * the complete set that is covered by the provider; otherwise the supported
+     * subset of the specified {@code privilegeBits} is returned.
+     *
+     * Returning {@link PrivilegeBits#EMPTY} indicates that this implementation
+     * is not in charge of evaluating the specified privileges and thus will
+     * be ignored while computing the composite result of
+     * {@link PermissionProvider#getPrivileges(org.apache.jackrabbit.oak.api.Tree)}
+     * or {@link PermissionProvider#hasPrivileges(org.apache.jackrabbit.oak.api.Tree, String...)}.
+     *
+     * @param tree The tree for which the privileges will be evaluated or {@code null}
+     * for repository level privileges.
+     * @param privilegeBits The privilege(s) to be tested or {@code null}
+     * @return The set of privileges or the subset of the given {@code privilegeBits}
+     * that are supported and evaluated by the the implementation at the given {@code tree}
+     * represented as {@code PrivilegeBits}.
+     */
+    @Nonnull
     PrivilegeBits supportedPrivileges(@Nullable Tree tree, @Nullable PrivilegeBits privilegeBits);
 
     long supportedPermissions(@Nullable Tree tree, @Nullable PropertyState property, long permissions);

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/package-info.java?rev=1707085&r1=1707084&r2=1707085&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/package-info.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/package-info.java Tue Oct  6 16:27:36 2015
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("2.0.1")
+@Version("2.0.2")
 @Export(optional = "provide:=true")
 package org.apache.jackrabbit.oak.spi.security.authorization.permission;
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProvider.java?rev=1707085&r1=1707084&r2=1707085&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/PrivilegeBitsProvider.java Tue Oct  6 16:27:36 2015
@@ -28,10 +28,12 @@ import javax.jcr.RepositoryException;
 import javax.jcr.security.Privilege;
 
 import com.google.common.base.Function;
+import com.google.common.base.Predicates;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
+import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.Type;
@@ -88,21 +90,26 @@ public final class PrivilegeBitsProvider
      */
     @Nonnull
     public PrivilegeBits getBits(@Nonnull Iterable<String> privilegeNames) {
-        if (!privilegeNames.iterator().hasNext()) {
+        if (Iterables.isEmpty(privilegeNames)) {
             return PrivilegeBits.EMPTY;
         }
 
-        Tree privilegesTree = getPrivilegesTree();
-        if (!privilegesTree.exists()) {
-            return PrivilegeBits.EMPTY;
-        }
+        Tree privilegesTree = null;
         PrivilegeBits bits = PrivilegeBits.getInstance();
         for (String privilegeName : privilegeNames) {
-            if (privilegesTree.hasChild(privilegeName)) {
-                Tree defTree = privilegesTree.getChild(privilegeName);
-                bits.add(PrivilegeBits.getInstance(defTree));
+            PrivilegeBits builtIn = PrivilegeBits.BUILT_IN.get(privilegeName);
+            if (builtIn != null) {
+                bits.add(builtIn);
             } else {
-                log.debug("Ignoring privilege name " + privilegeName);
+                if (privilegesTree == null) {
+                    privilegesTree = getPrivilegesTree();
+                }
+                if (privilegesTree.exists() && privilegesTree.hasChild(privilegeName)) {
+                    Tree defTree = privilegesTree.getChild(privilegeName);
+                    bits.add(PrivilegeBits.getInstance(defTree));
+                } else {
+                    log.debug("Ignoring privilege name " + privilegeName);
+                }
             }
         }
         return bits.unmodifiable();
@@ -117,7 +124,7 @@ public final class PrivilegeBitsProvider
      */
     @Nonnull
     public PrivilegeBits getBits(@Nonnull Privilege[] privileges, final @Nonnull NameMapper nameMapper) {
-        return getBits(Iterables.transform(Arrays.asList(privileges), new Function<Privilege, String>() {
+        return getBits(Iterables.filter(Iterables.transform(Arrays.asList(privileges), new Function<Privilege, String>() {
 
             @Override
             public String apply(@Nullable Privilege privilege) {
@@ -131,7 +138,7 @@ public final class PrivilegeBitsProvider
                 // null privilege or failed to resolve the privilege name
                 return null;
             }
-        }));
+        }), Predicates.notNull()));
     }
 
     /**
@@ -247,8 +254,9 @@ public final class PrivilegeBitsProvider
             if (!privTree.exists()) {
                 return;
             }
-            if (privTree.hasProperty(REP_AGGREGATES)) {
-                for (String name : privTree.getProperty(REP_AGGREGATES).getValue(Type.NAMES)) {
+            PropertyState aggregates = privTree.getProperty(REP_AGGREGATES);
+            if (aggregates != null) {
+                for (String name : aggregates.getValue(Type.NAMES)) {
                     if (NON_AGGREGATE_PRIVILEGES.contains(name)) {
                         aggSet.add(name);
                     } else if (aggregation.containsKey(name)) {

Copied: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/AbstractCompositeProviderTest.java (from r1704492, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProviderTest.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/AbstractCompositeProviderTest.java?p2=jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/AbstractCompositeProviderTest.java&p1=jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProviderTest.java&r1=1704492&r2=1707085&rev=1707085&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProviderTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/AbstractCompositeProviderTest.java Tue Oct  6 16:27:36 2015
@@ -16,9 +16,250 @@
  */
 package org.apache.jackrabbit.oak.security.authorization.composite;
 
+import java.security.Principal;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.jcr.security.AccessControlManager;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
 import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
+import org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.RepositoryPermission;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission;
+import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.apache.jackrabbit.oak.util.NodeUtil;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public abstract class AbstractCompositeProviderTest extends AbstractSecurityTest implements NodeTypeConstants {
+
+    static final String ROOT_PATH = "/";
+    static final String TEST_PATH = "/test";
+    static final String TEST_CHILD_PATH = "/test/child";
+    static final String TEST_A_PATH = "/test/a";
+    static final String TEST_A_B_PATH = "/test/a/b";
+    static final String TEST_A_B_C_PATH = "/test/a/b/c";
+    static final String TEST_A_B2_PATH = "/test/a/b2";
+
+    static final String TEST_PATH_2 = "/test2";
+
+    static final String PROP_NAME = "propName";
+
+    static final List<String> NODE_PATHS = ImmutableList.of("/", TEST_PATH, TEST_PATH_2, TEST_CHILD_PATH, TEST_A_PATH, TEST_A_B_PATH, TEST_A_B_C_PATH, TEST_A_B2_PATH);
+
+    Map<String, Long> defPermissions;
+    Map<String, Set<String>> defPrivileges;
+
+
+    @Override
+    public void before() throws Exception {
+        super.before();
+
+        NodeUtil rootNode = new NodeUtil(root.getTree("/"));
+
+        NodeUtil test = rootNode.addChild("test", NT_OAK_UNSTRUCTURED);
+        test.setString(PROP_NAME, "strValue");
+        test.addChild("child", NT_OAK_UNSTRUCTURED).setString(PROP_NAME, "strVal");
+        NodeUtil a = test.addChild("a", NT_OAK_UNSTRUCTURED);
+        a.addChild("b2", NT_OAK_UNSTRUCTURED);
+        a.addChild("b", NT_OAK_UNSTRUCTURED).addChild("c", NT_OAK_UNSTRUCTURED).setString(PROP_NAME, "strVal");
+
+        rootNode.addChild("test2", NT_OAK_UNSTRUCTURED);
+
+        AccessControlManager acMgr = getAccessControlManager(root);
+        Principal everyone = EveryonePrincipal.getInstance();
+
+        allow(acMgr, everyone, null, PrivilegeConstants.JCR_NAMESPACE_MANAGEMENT, PrivilegeConstants.JCR_NODE_TYPE_DEFINITION_MANAGEMENT);
+        allow(acMgr, everyone, TEST_PATH, PrivilegeConstants.JCR_READ);
+        allow(acMgr, everyone, TEST_CHILD_PATH, PrivilegeConstants.JCR_READ_ACCESS_CONTROL);
+
+        allow(acMgr, everyone, TEST_A_PATH, PrivilegeConstants.JCR_WRITE);
+        deny(acMgr, everyone, TEST_A_B_PATH, PrivilegeConstants.REP_REMOVE_PROPERTIES, PrivilegeConstants.JCR_REMOVE_NODE);
+        deny(acMgr, everyone, TEST_A_B_C_PATH, PrivilegeConstants.REP_READ_NODES);
+
+        root.commit();
+
+        defPermissions = ImmutableMap.<String, Long>builder().
+                put(TEST_PATH, Permissions.READ).
+                put(TEST_CHILD_PATH, Permissions.READ | Permissions.READ_ACCESS_CONTROL).
+                put(TEST_A_PATH, Permissions.READ | Permissions.SET_PROPERTY | Permissions.MODIFY_CHILD_NODE_COLLECTION).
+                put(TEST_A_B2_PATH, Permissions.READ | Permissions.WRITE | Permissions.MODIFY_CHILD_NODE_COLLECTION).
+                put(TEST_A_B_PATH, Permissions.READ | Permissions.ADD_NODE | Permissions.ADD_PROPERTY | Permissions.MODIFY_PROPERTY | Permissions.MODIFY_CHILD_NODE_COLLECTION).
+                put(TEST_A_B_C_PATH, Permissions.READ_PROPERTY | Permissions.ADD_NODE | Permissions.ADD_PROPERTY | Permissions.MODIFY_PROPERTY | Permissions.MODIFY_CHILD_NODE_COLLECTION).
+                build();
+        defPrivileges = ImmutableMap.<String, Set<String>>builder().
+                put(ROOT_PATH, ImmutableSet.<String>of()).
+                put(TEST_PATH_2, ImmutableSet.<String>of()).
+                put(TEST_PATH, ImmutableSet.of(PrivilegeConstants.JCR_READ)).
+                put(TEST_CHILD_PATH, ImmutableSet.of(PrivilegeConstants.JCR_READ, PrivilegeConstants.JCR_READ_ACCESS_CONTROL)).
+                put(TEST_A_PATH, ImmutableSet.of(PrivilegeConstants.JCR_READ, PrivilegeConstants.JCR_WRITE)).
+                put(TEST_A_B2_PATH, ImmutableSet.of(PrivilegeConstants.JCR_READ, PrivilegeConstants.JCR_WRITE)).
+                put(TEST_A_B_PATH, ImmutableSet.of(PrivilegeConstants.JCR_READ, PrivilegeConstants.JCR_ADD_CHILD_NODES, PrivilegeConstants.JCR_REMOVE_CHILD_NODES, PrivilegeConstants.REP_ADD_PROPERTIES, PrivilegeConstants.REP_ALTER_PROPERTIES)).
+                put(TEST_A_B_C_PATH, ImmutableSet.of(PrivilegeConstants.REP_READ_PROPERTIES, PrivilegeConstants.JCR_ADD_CHILD_NODES, PrivilegeConstants.JCR_REMOVE_CHILD_NODES, PrivilegeConstants.REP_ADD_PROPERTIES, PrivilegeConstants.REP_ALTER_PROPERTIES)).
+                build();
+    }
+
+    @Override
+    public void after() throws Exception {
+        try {
+            root.refresh();
+            root.getTree(TEST_PATH).remove();
+            root.commit();
+        } finally {
+            super.after();
+        }
+    }
+
+    private static void allow(@Nonnull AccessControlManager acMgr,
+                      @Nonnull Principal principal,
+                      @Nullable String path,
+                      @Nonnull String... privilegeNames) throws Exception {
+        JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(acMgr, path);
+        acl.addEntry(principal, AccessControlUtils.privilegesFromNames(acMgr, privilegeNames), true);
+        acMgr.setPolicy(acl.getPath(), acl);
+    }
+
+    private static void deny(@Nonnull AccessControlManager acMgr,
+                     @Nonnull Principal principal,
+                     @Nullable String path,
+                     @Nonnull String... privilegeNames) throws Exception {
+        JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList(acMgr, path);
+        acl.addEntry(principal, AccessControlUtils.privilegesFromNames(acMgr, privilegeNames), false);
+        acMgr.setPolicy(acl.getPath(), acl);
+    }
+
+    abstract AggregatedPermissionProvider getTestPermissionProvider();
+
+    boolean reverseOrder() {
+        return false;
+    }
+
+    private List<AggregatedPermissionProvider> getAggregatedProviders(@Nonnull String workspaceName,
+                                                                      @Nonnull AuthorizationConfiguration config,
+                                                                      @Nonnull Set<Principal> principals) {
+        if (reverseOrder()) {
+            return ImmutableList.of(
+                    (AggregatedPermissionProvider) config.getPermissionProvider(root, workspaceName, principals),
+                    getTestPermissionProvider());
+        } else {
+            return ImmutableList.of(
+                    (AggregatedPermissionProvider) config.getPermissionProvider(root, workspaceName, principals),
+                    getTestPermissionProvider());
+        }
+    }
+
+
+    CompositePermissionProvider createPermissionProvider(Principal... principals) {
+        return createPermissionProvider(ImmutableSet.copyOf(principals));
+    }
+
+    CompositePermissionProvider createPermissionProvider(Set<Principal> principals) {
+        String workspaceName = root.getContentSession().getWorkspaceName();
+        AuthorizationConfiguration config = getConfig(AuthorizationConfiguration.class);
+        return new CompositePermissionProvider(root, getAggregatedProviders(workspaceName, config, principals), config.getContext());
+    }
+
+    @Test
+    public void testHasPrivilegesJcrAll() throws Exception {
+        PermissionProvider pp = createPermissionProvider();
+        for (String p : NODE_PATHS) {
+            Tree tree = root.getTree(p);
+
+            assertFalse(p, pp.hasPrivileges(tree, PrivilegeConstants.JCR_ALL));
+        }
+    }
+
+    @Test
+    public void testHasPrivilegesNone() throws Exception {
+        PermissionProvider pp = createPermissionProvider();
+        for (String p : NODE_PATHS) {
+            Tree tree = root.getTree(p);
+
+            assertTrue(p, pp.hasPrivileges(tree));
+        }
+    }
+
+    @Test
+    public void testHasPrivilegesOnRepoJcrAll() throws Exception {
+        PermissionProvider pp = createPermissionProvider();
+        assertFalse(pp.hasPrivileges(null, PrivilegeConstants.JCR_ALL));
+    }
+
+    @Test
+    public void testHasPrivilegesOnRepoNone() throws Exception {
+        PermissionProvider pp = createPermissionProvider();
+        assertTrue(pp.hasPrivileges(null));
+    }
+
+    @Test
+    public void testIsGrantedAll() throws Exception {
+        PermissionProvider pp = createPermissionProvider();
+
+        for (String p : NODE_PATHS) {
+            Tree tree = root.getTree(p);
+            PropertyState ps = tree.getProperty(JcrConstants.JCR_PRIMARYTYPE);
+
+            assertFalse(p, pp.isGranted(tree, null, Permissions.ALL));
+            assertFalse(PathUtils.concat(p, JcrConstants.JCR_PRIMARYTYPE), pp.isGranted(tree, ps, Permissions.ALL));
+        }
+    }
+
+    @Test
+    public void testIsGrantedNone() throws Exception {
+        PermissionProvider pp = createPermissionProvider();
+
+        for (String p : NODE_PATHS) {
+            Tree tree = root.getTree(p);
+            PropertyState ps = tree.getProperty(JcrConstants.JCR_PRIMARYTYPE);
+
+            assertFalse(p, pp.isGranted(tree, null, Permissions.NO_PERMISSION));
+            assertFalse(PathUtils.concat(p, JcrConstants.JCR_PRIMARYTYPE), pp.isGranted(tree, ps, Permissions.NO_PERMISSION));
+        }
+    }
+
+    @Test
+    public void testGetTreePermissionInstance() throws Exception {
+        TreePermission parentPermission = TreePermission.EMPTY;
+
+        List<String> paths = ImmutableList.of("/", TEST_PATH, TEST_CHILD_PATH, TEST_CHILD_PATH + "/nonexisting");
+        for (String path : paths) {
+            TreePermission tp = createPermissionProvider().getTreePermission(root.getTree(path), parentPermission);
+            assertTrue(tp.getClass().getName().endsWith("CompositeTreePermission"));
+            parentPermission = tp;
+        }
+    }
 
-public class CompositePermissionProviderTest extends AbstractSecurityTest {
+    @Test
+    public void testGetRepositoryPermissionInstance() throws Exception {
+        RepositoryPermission rp = createPermissionProvider().getRepositoryPermission();
+        assertTrue(rp.getClass().getName().endsWith("CompositeRepositoryPermission"));
+    }
 
-    // TODO
+    @Test
+    public void testRepositoryPermissionIsNotGranted() throws Exception {
+        RepositoryPermission rp = createPermissionProvider().getRepositoryPermission();
+        assertFalse(rp.isGranted(Permissions.PRIVILEGE_MANAGEMENT));
+        assertFalse(rp.isGranted(Permissions.NAMESPACE_MANAGEMENT|Permissions.PRIVILEGE_MANAGEMENT));
+        assertFalse(rp.isGranted(Permissions.WORKSPACE_MANAGEMENT));
+        assertFalse(rp.isGranted(Permissions.ALL));
+        assertFalse(rp.isGranted(Permissions.NO_PERMISSION));
+    }
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAccessControlManagerTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAccessControlManagerTest.java?rev=1707085&r1=1707084&r2=1707085&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAccessControlManagerTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAccessControlManagerTest.java Tue Oct  6 16:27:36 2015
@@ -16,7 +16,6 @@
  */
 package org.apache.jackrabbit.oak.security.authorization.composite;
 
-
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
@@ -29,8 +28,12 @@ import javax.jcr.security.Privilege;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
 import org.apache.jackrabbit.commons.iterator.AccessControlPolicyIteratorAdapter;
 import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
 import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.PolicyOwner;
@@ -57,12 +60,14 @@ public class CompositeAccessControlManag
 
         NodeUtil node = new NodeUtil(root.getTree("/"));
         node.addChild("test", NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+
         root.commit();
     }
 
     @Override
     public void after() throws Exception {
         try {
+            root.refresh();
             root.getTree(TEST_PATH).remove();
             root.commit();
         } finally {
@@ -73,13 +78,12 @@ public class CompositeAccessControlManag
     @Test
     public void testGetSupportedPrivileges() throws Exception {
         Set<Privilege> expected = ImmutableSet.copyOf(getPrivilegeManager(root).getRegisteredPrivileges());
-        Set<Privilege> result = ImmutableSet.copyOf(acMgr.getSupportedPrivileges(TEST_PATH));
+        Set<Privilege> result = ImmutableSet.copyOf(acMgr.getSupportedPrivileges("/"));
         assertEquals(expected, result);
-    }
 
-    @Test
-    public void testPrivilegeFromName() {
-        // TODO
+        result = Sets.newHashSet(acMgr.getSupportedPrivileges(TEST_PATH));
+        assertTrue(result.containsAll(expected));
+        assertTrue(result.contains(TestPrivilege.INSTANCE));
     }
 
     @Test
@@ -91,12 +95,9 @@ public class CompositeAccessControlManag
             }
         }
 
-        boolean found = false;
-        it = acMgr.getApplicablePolicies(TEST_PATH);
-        while (!found && it.hasNext()) {
-            found = (it.nextAccessControlPolicy() == TestPolicy.INSTANCE);
-        }
-        assertTrue(found);
+        Set<AccessControlPolicy> applicable = ImmutableSet.copyOf(acMgr.getApplicablePolicies(TEST_PATH));
+        assertEquals(2, applicable.size());
+        assertTrue(applicable.contains(TestPolicy.INSTANCE));
     }
 
     @Test
@@ -131,18 +132,67 @@ public class CompositeAccessControlManag
     }
 
     @Test
-    public void testGetEffectivePolicies() {
-        // TODO
+    public void testGetEffectivePolicies() throws Exception {
+        AccessControlPolicy[] effective = acMgr.getEffectivePolicies(TEST_PATH);
+        assertEquals(0, effective.length);
+
+        AccessControlPolicyIterator it = acMgr.getApplicablePolicies(TEST_PATH);
+        while (it.hasNext()) {
+            AccessControlPolicy plc = it.nextAccessControlPolicy();
+            acMgr.setPolicy(TEST_PATH, plc);
+        }
+        root.commit();
+        assertEquals(2, acMgr.getEffectivePolicies(TEST_PATH).length);
+
+        Tree child = root.getTree(TEST_PATH).addChild("child");
+        child.setProperty(JcrConstants.JCR_PRIMARYTYPE, NodeTypeConstants.NT_OAK_UNSTRUCTURED);
+
+        assertEquals(1, acMgr.getEffectivePolicies(child.getPath()).length);
     }
 
     @Test
-    public void testSetPolicy() {
-        // TODO
+    public void testSetPolicyAtRoot() throws Exception {
+        AccessControlPolicyIterator it = acMgr.getApplicablePolicies("/");
+        int cnt = 0;
+        while (it.hasNext()) {
+            AccessControlPolicy plc = it.nextAccessControlPolicy();
+            assertTrue(plc instanceof JackrabbitAccessControlList);
+            acMgr.setPolicy("/", plc);
+            cnt++;
+        }
+        assertEquals(1, cnt);
     }
 
     @Test
-    public void testRemovePolicy() {
-        // TODO
+    public void testSetPolicyAtTestPath() throws Exception {
+        AccessControlPolicyIterator it = acMgr.getApplicablePolicies(TEST_PATH);
+        int cnt = 0;
+        while (it.hasNext()) {
+            AccessControlPolicy plc = it.nextAccessControlPolicy();
+            acMgr.setPolicy(TEST_PATH, plc);
+            cnt++;
+        }
+        assertEquals(2, cnt);
+    }
+
+    @Test
+    public void testRemovePolicy() throws Exception {
+        AccessControlPolicyIterator it = acMgr.getApplicablePolicies(TEST_PATH);
+        while (it.hasNext()) {
+            AccessControlPolicy plc = it.nextAccessControlPolicy();
+            acMgr.setPolicy(TEST_PATH, plc);
+        }
+        root.commit();
+
+        acMgr.removePolicy(TEST_PATH, TestPolicy.INSTANCE);
+        root.commit();
+
+        assertEquals(1, acMgr.getPolicies(TEST_PATH).length);
+
+        acMgr.removePolicy(TEST_PATH, acMgr.getPolicies(TEST_PATH)[0]);
+        root.commit();
+
+        assertEquals(0, acMgr.getPolicies(TEST_PATH).length);
     }
 
 
@@ -150,9 +200,19 @@ public class CompositeAccessControlManag
 
         private boolean hasPolicy = false;
 
+        private final Privilege[] supported;
+
+        private TestAcMgr() {
+            this.supported = new Privilege[] {TestPrivilege.INSTANCE};
+        }
+
         @Override
         public Privilege[] getSupportedPrivileges(String absPath) {
-            return new Privilege[0];
+            if (TEST_PATH.equals(absPath)) {
+                return supported;
+            } else {
+                return new Privilege[0];
+            }
         }
 
         @Override
@@ -173,7 +233,7 @@ public class CompositeAccessControlManag
         @Override
         public AccessControlPolicy[] getPolicies(String absPath) {
             if (TEST_PATH.equals(absPath) && hasPolicy) {
-                return new AccessControlPolicy[] {TestPolicy.INSTANCE};
+                return TestPolicy.asPolicyArray();
             } else {
                 return new AccessControlPolicy[0];
             }
@@ -182,7 +242,7 @@ public class CompositeAccessControlManag
         @Override
         public AccessControlPolicy[] getEffectivePolicies(String absPath) {
             if (TEST_PATH.equals(absPath) && hasPolicy) {
-                return new AccessControlPolicy[] {TestPolicy.INSTANCE};
+                return TestPolicy.asPolicyArray();
             } else {
                 return new AccessControlPolicy[0];
             }
@@ -224,6 +284,41 @@ public class CompositeAccessControlManag
 
     private static final class TestPolicy implements AccessControlPolicy {
 
-        private static final TestPolicy INSTANCE = new TestPolicy();
+        static final TestPolicy INSTANCE = new TestPolicy();
+
+        static AccessControlPolicy[] asPolicyArray() {
+            return new AccessControlPolicy[] {INSTANCE};
+        }
+    }
+
+    private static final class TestPrivilege implements Privilege {
+
+        static final String NAME = TestPrivilege.class.getName() + "-privilege";
+        static final Privilege INSTANCE = new TestPrivilege();
+
+        @Override
+        public String getName() {
+            return NAME;
+        }
+
+        @Override
+        public boolean isAbstract() {
+            return false;
+        }
+
+        @Override
+        public boolean isAggregate() {
+            return false;
+        }
+
+        @Override
+        public Privilege[] getDeclaredAggregatePrivileges() {
+            return new Privilege[0];
+        }
+
+        @Override
+        public Privilege[] getAggregatePrivileges() {
+            return new Privilege[0];
+        }
     }
 }
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderAllReverseTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderAllReverseTest.java?rev=1707085&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderAllReverseTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderAllReverseTest.java Tue Oct  6 16:27:36 2015
@@ -0,0 +1,29 @@
+/*
+ * 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.jackrabbit.oak.security.authorization.composite;
+
+/**
+ * Same as {@link CompositeProviderAllTest}
+ * with reverse order of the aggregated providers.
+ */
+public class CompositeProviderAllReverseTest extends CompositeProviderAllTest {
+
+    @Override
+    boolean reverseOrder() {
+        return true;
+    }
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderAllTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderAllTest.java?rev=1707085&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderAllTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderAllTest.java Tue Oct  6 16:27:36 2015
@@ -0,0 +1,217 @@
+/*
+ * 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.jackrabbit.oak.security.authorization.composite;
+
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import com.google.common.collect.ImmutableSet;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.plugins.tree.TreeLocation;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.OpenPermissionProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.RepositoryPermission;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission;
+import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBitsProvider;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test the effect of the combination of
+ *
+ * - default permission provider (which a limited permission setup)
+ * - custom provider that always grants full access and supports all permissions.
+ *
+ * for the {@link #getTestUser()}.
+ *
+ * The expected result is only the subset of permissions granted by the default
+ * provider. The test user must never have full access anywhere.
+ */
+public class CompositeProviderAllTest extends AbstractCompositeProviderTest {
+
+    private CompositePermissionProvider cpp;
+
+
+    @Override
+    public void before() throws Exception {
+        super.before();
+
+        cpp = createPermissionProvider(getTestUser().getPrincipal(), EveryonePrincipal.getInstance());
+    }
+
+    @Override
+    protected AggregatedPermissionProvider getTestPermissionProvider() {
+        return new OpenAggregateProvider(root);
+    }
+
+    @Test
+    public void testGetPrivileges() throws Exception {
+        for (String p : defPrivileges.keySet()) {
+            Set<String> expected = defPrivileges.get(p);
+            Tree tree = root.getTree(p);
+
+            assertEquals(p, expected, cpp.getPrivileges(tree));
+        }
+    }
+
+    @Test
+    public void testGetPrivilegesOnRepo() throws Exception {
+        Set<String> privilegeNames = cpp.getPrivileges(null);
+        assertEquals(ImmutableSet.of(PrivilegeConstants.JCR_NAMESPACE_MANAGEMENT, PrivilegeConstants.JCR_NODE_TYPE_DEFINITION_MANAGEMENT), privilegeNames);
+    }
+
+
+    @Test
+    public void testHasPrivileges() throws Exception {
+        for (String p : defPrivileges.keySet()) {
+            Set<String> expected = defPrivileges.get(p);
+            Tree tree = root.getTree(p);
+
+            assertTrue(p, cpp.hasPrivileges(tree, expected.toArray(new String[expected.size()])));
+        }
+    }
+
+
+    @Test
+    public void testHasPrivilegesOnRepo() throws Exception {
+        assertTrue(cpp.hasPrivileges(null, PrivilegeConstants.JCR_NAMESPACE_MANAGEMENT, PrivilegeConstants.JCR_NODE_TYPE_DEFINITION_MANAGEMENT));
+    }
+
+
+    @Test
+    public void testIsGranted() throws Exception {
+        for (String p : defPermissions.keySet()) {
+            long expected = defPermissions.get(p);
+            Tree tree = root.getTree(p);
+
+            assertTrue(p, cpp.isGranted(tree, null, expected));
+        }
+    }
+
+    @Test
+    public void testIsGrantedProperty() throws Exception {
+        // TODO
+    }
+
+    @Test
+    public void testIsGrantedAction() throws Exception {
+        // TODO
+    }
+
+    @Test
+    public void testRepositoryPermissionsIsGranted() throws Exception {
+        RepositoryPermission rp = cpp.getRepositoryPermission();
+        assertTrue(rp.isGranted(Permissions.NAMESPACE_MANAGEMENT));
+        assertTrue(rp.isGranted(Permissions.NODE_TYPE_DEFINITION_MANAGEMENT));
+        assertTrue(rp.isGranted(Permissions.NAMESPACE_MANAGEMENT | Permissions.NODE_TYPE_DEFINITION_MANAGEMENT));
+    }
+
+    @Test
+    public void testGetTreePermission() throws Exception {
+        // TODO
+    }
+
+    /**
+     * Custom permission provider that supports all permissions and grants
+     * full access for everyone.
+     */
+    private static final class OpenAggregateProvider implements AggregatedPermissionProvider {
+
+        private static final PermissionProvider BASE = OpenPermissionProvider.getInstance();
+        private final Root root;
+
+        private OpenAggregateProvider(@Nonnull Root root) {
+            this.root = root;
+        }
+
+        @Nonnull
+        @Override
+        public PrivilegeBits supportedPrivileges(@Nullable Tree tree, @Nullable PrivilegeBits privilegeBits) {
+            return new PrivilegeBitsProvider(root).getBits(PrivilegeConstants.JCR_ALL);
+        }
+
+        //-----------------------------------< AggregatedPermissionProvider >---
+        @Override
+        public long supportedPermissions(@Nullable Tree tree, @Nullable PropertyState property, long permissions) {
+            return permissions;
+        }
+
+        @Override
+        public long supportedPermissions(@Nonnull TreeLocation location, long permissions) {
+            return permissions;
+        }
+
+        @Override
+        public long supportedPermissions(@Nonnull TreePermission treePermission, long permissions) {
+            return permissions;
+        }
+
+        @Override
+        public boolean isGranted(@Nonnull TreeLocation location, long permissions) {
+            return true;
+        }
+
+        //---------------------------------------------< PermissionProvider >---
+        @Override
+        public void refresh() {
+            root.refresh();
+        }
+
+        @Nonnull
+        @Override
+        public Set<String> getPrivileges(@Nullable Tree tree) {
+            return BASE.getPrivileges(tree);
+        }
+
+        @Override
+        public boolean hasPrivileges(@Nullable Tree tree, @Nonnull String... privilegeNames) {
+            return BASE.hasPrivileges(tree, privilegeNames);
+        }
+
+        @Nonnull
+        @Override
+        public RepositoryPermission getRepositoryPermission() {
+            return BASE.getRepositoryPermission();
+        }
+
+        @Nonnull
+        @Override
+        public TreePermission getTreePermission(@Nonnull Tree tree, @Nonnull TreePermission parentPermission) {
+            return BASE.getTreePermission(tree, parentPermission);
+        }
+
+        @Override
+        public boolean isGranted(@Nonnull Tree tree, @Nullable PropertyState property, long permissions) {
+            return BASE.isGranted(tree, property, permissions);
+        }
+
+        @Override
+        public boolean isGranted(@Nonnull String oakPath, @Nonnull String jcrActions) {
+            return BASE.isGranted(oakPath, jcrActions);
+        }
+    };
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderEmptyReverseTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderEmptyReverseTest.java?rev=1707085&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderEmptyReverseTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderEmptyReverseTest.java Tue Oct  6 16:27:36 2015
@@ -0,0 +1,29 @@
+/*
+ * 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.jackrabbit.oak.security.authorization.composite;
+
+/**
+ * Same as {@link CompositeProviderEmptyTest}
+ * with reverse order of the aggregated providers.
+ */
+public class CompositeProviderEmptyReverseTest extends CompositeProviderEmptyTest {
+
+    @Override
+    boolean reverseOrder() {
+        return true;
+    }
+}
\ No newline at end of file

Copied: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderEmptyTest.java (from r1704492, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProviderTest.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderEmptyTest.java?p2=jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderEmptyTest.java&p1=jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProviderTest.java&r1=1704492&r2=1707085&rev=1707085&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositePermissionProviderTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderEmptyTest.java Tue Oct  6 16:27:36 2015
@@ -16,9 +16,240 @@
  */
 package org.apache.jackrabbit.oak.security.authorization.composite;
 
-import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.jcr.Session;
 
-public class CompositePermissionProviderTest extends AbstractSecurityTest {
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.tree.TreeLocation;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.EmptyPermissionProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.PermissionProvider;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.RepositoryPermission;
+import org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBitsProvider;
+import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
+import org.apache.jackrabbit.util.Text;
+import org.junit.Test;
 
-    // TODO
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test the effect of the combination of
+ *
+ * - default permission provider, which always grants full access to an administrative session.
+ * - custom provider that prevents all access but supports all permissions and
+ *   thus is always called during composite evaluation.
+ *
+ * The tests are executed with the set of principals associated with the admin session,
+ * which in the default permission provider is granted full access.
+ *
+ * The expected outcome is that despite the default provider granting full access,
+ * the combination effectively prevents any access.
+ */
+public class CompositeProviderEmptyTest extends AbstractCompositeProviderTest {
+
+    private CompositePermissionProvider cpp;
+
+    @Override
+    public void before() throws Exception {
+        super.before();
+        cpp = createPermissionProvider(root.getContentSession().getAuthInfo().getPrincipals());
+    }
+
+    @Override
+    protected AggregatedPermissionProvider getTestPermissionProvider() {
+        return new EmptyAggregatedProvider(root);
+    }
+
+    @Test
+    public void testGetPrivileges() throws Exception {
+        for (String p : NODE_PATHS) {
+            assertTrue(cpp.getPrivileges(root.getTree(p)).isEmpty());
+        }
+    }
+
+    @Test
+    public void testGetPrivilegesOnRepo() throws Exception {
+        assertTrue(cpp.getPrivileges(null).isEmpty());
+    }
+
+    @Test
+    public void testHasPrivileges() throws Exception {
+        for (String p : NODE_PATHS) {
+            Tree tree = root.getTree(p);
+
+            assertFalse(cpp.hasPrivileges(tree, PrivilegeConstants.JCR_READ));
+            assertFalse(cpp.hasPrivileges(tree, PrivilegeConstants.JCR_WRITE));
+            assertFalse(cpp.hasPrivileges(tree, PrivilegeConstants.REP_READ_NODES));
+        }
+    }
+
+    @Test
+    public void testHasPrivilegesOnRepo() throws Exception {
+        assertFalse(cpp.hasPrivileges(null, PrivilegeConstants.JCR_NAMESPACE_MANAGEMENT));
+    }
+
+
+    @Test
+    public void testIsGranted() throws Exception {
+        for (String p : NODE_PATHS) {
+            Tree tree = root.getTree(p);
+            PropertyState ps = tree.getProperty(JcrConstants.JCR_PRIMARYTYPE);
+
+            assertFalse(cpp.isGranted(tree, null, Permissions.READ_NODE));
+            assertFalse(cpp.isGranted(tree, ps, Permissions.READ_PROPERTY));
+
+            assertFalse(cpp.isGranted(tree, null, Permissions.READ_NODE | Permissions.MODIFY_CHILD_NODE_COLLECTION));
+            assertFalse(cpp.isGranted(tree, ps, Permissions.MODIFY_PROPERTY));
+
+            assertFalse(cpp.isGranted(tree, null, Permissions.READ_ACCESS_CONTROL | Permissions.MODIFY_ACCESS_CONTROL));
+            assertFalse(cpp.isGranted(tree, ps, Permissions.READ_ACCESS_CONTROL | Permissions.MODIFY_ACCESS_CONTROL));
+        }
+    }
+
+    @Test
+    public void testIsGrantedProperty() throws Exception {
+        // TODO
+    }
+
+    @Test
+    public void testIsGrantedAction() throws Exception {
+        for (String nodePath : NODE_PATHS) {
+            String propPath = PathUtils.concat(nodePath, JcrConstants.JCR_PRIMARYTYPE);
+            String nonExisting = PathUtils.concat(nodePath, "nonExisting");
+
+            assertFalse(cpp.isGranted(nodePath, Session.ACTION_REMOVE));
+            assertFalse(cpp.isGranted(propPath, JackrabbitSession.ACTION_MODIFY_PROPERTY));
+
+            assertFalse(cpp.isGranted(nodePath, Text.implode(new String[] {JackrabbitSession.ACTION_MODIFY_ACCESS_CONTROL, JackrabbitSession.ACTION_READ_ACCESS_CONTROL}, ",")));
+            assertFalse(cpp.isGranted(nonExisting, JackrabbitSession.ACTION_ADD_PROPERTY));
+            assertFalse(cpp.isGranted(nonExisting, Session.ACTION_ADD_NODE));
+        }
+    }
+
+    @Test
+    public void testRepositoryPermissionsIsGranted() throws Exception {
+        RepositoryPermission rp = cpp.getRepositoryPermission();
+        assertFalse(rp.isGranted(Permissions.NAMESPACE_MANAGEMENT));
+        assertFalse(rp.isGranted(Permissions.NODE_TYPE_DEFINITION_MANAGEMENT));
+    }
+
+    @Test
+    public void testGetTreePermission() throws Exception {
+        TreePermission rootPermission = assertTreePermission(root.getTree("/"), TreePermission.EMPTY);
+        TreePermission testPermission = assertTreePermission(root.getTree(TEST_PATH), rootPermission);
+        assertTreePermission(root.getTree(TEST_CHILD_PATH), testPermission);
+    }
+
+    private TreePermission assertTreePermission(@Nonnull Tree tree, @Nonnull TreePermission parentPermission) {
+        PropertyState ps = tree.getProperty(JcrConstants.JCR_PRIMARYTYPE);
+        assertNotNull(ps);
+
+        TreePermission treePermission = cpp.getTreePermission(tree, parentPermission);
+
+        assertFalse(treePermission.isGranted(Permissions.ALL));
+        assertFalse(treePermission.isGranted(Permissions.READ_NODE));
+        assertFalse(treePermission.isGranted(Permissions.REMOVE_NODE));
+        assertFalse(treePermission.isGranted(Permissions.REMOVE_NODE));
+
+        assertFalse(treePermission.isGranted(Permissions.READ_PROPERTY, ps));
+        assertFalse(treePermission.isGranted(Permissions.REMOVE_PROPERTY, ps));
+
+        assertFalse(treePermission.canRead());
+        assertFalse(treePermission.canRead(ps));
+        assertFalse(treePermission.canReadAll());
+        assertFalse(treePermission.canReadProperties());
+
+        return treePermission;
+    }
+
+    /**
+     * {@code AggregatedPermissionProvider} that doesn't grant any access.
+     */
+    private static final class EmptyAggregatedProvider implements AggregatedPermissionProvider {
+
+        private static final PermissionProvider BASE = EmptyPermissionProvider.getInstance();
+        private final Root root;
+
+        private EmptyAggregatedProvider(@Nonnull Root root) {
+            this.root = root;
+        }
+
+        //---------------------------------------------< PermissionProvider >---
+        @Override
+        public void refresh() {
+            root.refresh();
+        }
+
+        @Nonnull
+        @Override
+        public Set<String> getPrivileges(@Nullable Tree tree) {
+            return BASE.getPrivileges(tree);
+        }
+
+        @Override
+        public boolean hasPrivileges(@Nullable Tree tree, @Nonnull String... privilegeNames) {
+            return BASE.hasPrivileges(tree, privilegeNames);
+        }
+
+        @Nonnull
+        @Override
+        public RepositoryPermission getRepositoryPermission() {
+            return BASE.getRepositoryPermission();
+        }
+
+        @Nonnull
+        @Override
+        public TreePermission getTreePermission(@Nonnull Tree tree, @Nonnull TreePermission parentPermission) {
+            return BASE.getTreePermission(tree, parentPermission);
+        }
+
+        @Override
+        public boolean isGranted(@Nonnull Tree tree, @Nullable PropertyState property, long permissions) {
+            return BASE.isGranted(tree, property, permissions);
+        }
+
+        @Override
+        public boolean isGranted(@Nonnull String oakPath, @Nonnull String jcrActions) {
+            return BASE.isGranted(oakPath, jcrActions);
+        }
+
+        //-----------------------------------< AggregatedPermissionProvider >---
+        @Nonnull
+        @Override
+        public PrivilegeBits supportedPrivileges(@Nullable Tree tree, @Nullable PrivilegeBits privilegeBits) {
+            return (privilegeBits == null) ? new PrivilegeBitsProvider(root).getBits(PrivilegeConstants.JCR_ALL) : privilegeBits;
+        }
+
+        @Override
+        public long supportedPermissions(@Nullable Tree tree, @Nullable PropertyState property, long permissions) {
+            return permissions;
+        }
+
+        @Override
+        public long supportedPermissions(@Nonnull TreeLocation location, long permissions) {
+            return permissions;
+        }
+
+        @Override
+        public long supportedPermissions(@Nonnull TreePermission treePermission, long permissions) {
+            return permissions;
+        }
+
+        @Override
+        public boolean isGranted(@Nonnull TreeLocation location, long permissions) {
+            return false;
+        }
+    };
 }
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderLimitedReverseTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderLimitedReverseTest.java?rev=1707085&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderLimitedReverseTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderLimitedReverseTest.java Tue Oct  6 16:27:36 2015
@@ -0,0 +1,29 @@
+/*
+ * 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.jackrabbit.oak.security.authorization.composite;
+
+/**
+ * Same as {@link CompositeProviderLimitedTest}
+ * with reverse order of the aggregated providers.
+ */
+public class CompositeProviderLimitedReverseTest extends CompositeProviderLimitedTest {
+
+    @Override
+    boolean reverseOrder() {
+        return true;
+    }
+}
\ No newline at end of file