Author: angela
Date: Wed Oct 14 09:02:49 2015
New Revision: 1708563

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

Added:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeTreePermission.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderCoverageTest.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderFullScopeReverseTest.java
      - copied, changed from r1708292, 
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/CompositeProviderFullScopeTest.java
      - copied, changed from r1708292, 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderLimitedTest.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeTreePermissionTest.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/FullScopeProvider.java
      - copied, changed from r1708074, 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/TestPermissionProvider.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/LimitedScopeProvider.java
      - copied, changed from r1708074, 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/TestPermissionProvider.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/NoScopeProvider.java
Removed:
    
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
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/TestPermissionProvider.java
Modified:
    
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/CugPermissionProviderTest.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/TreePermission.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/test/java/org/apache/jackrabbit/oak/security/authorization/composite/AbstractCompositeProviderTest.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfigurationTest.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/CompositeProviderEmptyTest.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/CompositeProviderScopeTest.java

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=1708563&r1=1708562&r2=1708563&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
 Wed Oct 14 09:02:49 2015
@@ -24,6 +24,7 @@ import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
@@ -32,6 +33,7 @@ import org.apache.jackrabbit.oak.api.Roo
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.tree.RootFactory;
 import org.apache.jackrabbit.oak.plugins.tree.TreeLocation;
 import org.apache.jackrabbit.oak.spi.security.Context;
 import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider;
@@ -40,15 +42,10 @@ import org.apache.jackrabbit.oak.spi.sec
 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.PrivilegeConstants;
-import org.apache.jackrabbit.oak.plugins.tree.RootFactory;
 import org.apache.jackrabbit.oak.util.TreeUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 class CugPermissionProvider implements AggregatedPermissionProvider, 
CugConstants {
 
-    private static final Logger log = 
LoggerFactory.getLogger(CugPermissionProvider.class);
-
     private static final Set<String> READ_PRIVILEGE_NAMES = ImmutableSet.of(
             PrivilegeConstants.JCR_READ,
             PrivilegeConstants.REP_READ_NODES,
@@ -119,17 +116,13 @@ class CugPermissionProvider implements A
     @Override
     public TreePermission getTreePermission(@Nonnull Tree tree, @Nonnull 
TreePermission parentPermission) {
         Tree immutableTree = getImmutableTree(tree);
-        if (parentPermission == TreePermission.EMPTY && 
!immutableTree.isRoot() || isAcContent(immutableTree, true)) {
+        if (((TreePermission.EMPTY == parentPermission) && 
!immutableTree.isRoot()) || isAcContent(immutableTree, true)) {
             return TreePermission.EMPTY;
         }
 
         TreePermission tp;
         if (parentPermission instanceof CugTreePermission) {
-            tp =  new CugTreePermission(immutableTree, ((CugTreePermission) 
parentPermission));
-            if (hasCug(immutableTree)) {
-                // a new (nested) cug starts off here
-                tp = createCugPermission(immutableTree, tp);
-            }
+            tp = createCugPermission(immutableTree, (CugTreePermission) 
parentPermission);
         } else {
             String path = immutableTree.getPath();
             if (supportedPaths.includes(path)) {
@@ -210,7 +203,7 @@ class CugPermissionProvider implements A
     }
 
     @Override
-    public long supportedPermissions(@Nonnull TreePermission treePermission, 
long permissions) {
+    public long supportedPermissions(@Nonnull TreePermission treePermission, 
@Nullable PropertyState propertyState, long permissions) {
         long supported = permissions & Permissions.READ;
         if (supported != Permissions.NO_PERMISSION && (treePermission 
instanceof CugTreePermission)) {
             return supported;
@@ -311,23 +304,27 @@ class CugPermissionProvider implements A
     }
 
     @Nonnull
-    private TreePermission createCugPermission(@Nonnull Tree tree, @Nullable 
TreePermission fallback) {
+    private TreePermission createCugPermission(@Nonnull Tree tree, @Nullable 
CugTreePermission parent) {
+        TreePermission tp;
+
         Tree cugTree = tree.getChild(REP_CUG_POLICY);
-        if (CugUtil.definesCug(cugTree)) {
-            PropertyState princNamesState = 
cugTree.getProperty(REP_PRINCIPAL_NAMES);
-            if (princNamesState != null) {
-                boolean allow = false;
-                for (String pName : princNamesState.getValue(Type.STRINGS)) {
-                    if (principalNames.contains(pName)) {
-                        allow = true;
-                        break;
-                    }
+        PropertyState princNamesState = 
cugTree.getProperty(REP_PRINCIPAL_NAMES);
+
+        if (CugUtil.definesCug(cugTree) && princNamesState != null) {
+            // a new (possibly nested) cug starts off here
+            boolean allow = 
Iterables.any(princNamesState.getValue(Type.STRINGS), new Predicate<String>() {
+                @Override
+                public boolean apply(@Nullable String principalName) {
+                    return (principalName != null) && 
principalNames.contains(principalName);
                 }
-                return new CugTreePermission(tree, allow, this);
-            } else {
-                log.warn("Tree at {0} doesn't represent a valid CUG.", 
cugTree.getPath());
-            }
+            });
+            tp = new CugTreePermission(tree, allow, this);
+        } else if (parent != null) {
+            // still within the parents CUG
+            tp = new CugTreePermission(tree, parent);
+        } else {
+            tp = new EmptyCugTreePermission(tree, this);
         }
-        return (fallback == null) ? new EmptyCugTreePermission(tree, this) : 
fallback;
+        return tp;
     }
 }
\ No newline at end of file

Modified: 
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProviderTest.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/CugPermissionProviderTest.java?rev=1708563&r1=1708562&r2=1708563&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProviderTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-authorization-cug/src/test/java/org/apache/jackrabbit/oak/spi/security/authorization/cug/impl/CugPermissionProviderTest.java
 Wed Oct 14 09:02:49 2015
@@ -235,16 +235,16 @@ public class CugPermissionProviderTest e
      */
     @Test
     public void testSupportedPermissionsByNullTree() {
-        assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(null, null, Permissions.READ));
-        assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(null, null, Permissions.READ_NODE));
-        assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(null, null, Permissions.READ_PROPERTY));
-
-        assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(null, null, Permissions.ALL));
-        assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(null, null, Permissions.READ_NODE | 
Permissions.READ_ACCESS_CONTROL));
-
-        assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(null, null, Permissions.WRITE));
-        assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(null, null, 
Permissions.ADD_NODE|Permissions.REMOVE));
-        assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(null, null, 
Permissions.READ_ACCESS_CONTROL));
+        assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions((Tree) null, null, Permissions.READ));
+        assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions((Tree) null, null, Permissions.READ_NODE));
+        assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions((Tree) null, null, 
Permissions.READ_PROPERTY));
+
+        assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions((Tree) null, null, Permissions.ALL));
+        assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions((Tree) null, null, Permissions.READ_NODE | 
Permissions.READ_ACCESS_CONTROL));
+
+        assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions((Tree) null, null, Permissions.WRITE));
+        assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions((Tree) null, null, 
Permissions.ADD_NODE|Permissions.REMOVE));
+        assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions((Tree) null, null, 
Permissions.READ_ACCESS_CONTROL));
     }
 
     /**
@@ -280,7 +280,7 @@ public class CugPermissionProviderTest e
     }
 
     /**
-     * @see 
org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider#supportedPermissions(org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission,
 long)
+     * @see 
org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider#supportedPermissions(org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission,
 org.apache.jackrabbit.oak.api.PropertyState, long)
      */
     @Test
     public void testSupportedPermissionsByTreePermission() {
@@ -314,19 +314,19 @@ public class CugPermissionProviderTest e
             boolean isInCug = tpMap.get(tp);
 
             if (isInCug) {
-                assertEquals(Permissions.READ, 
cugPermProvider.supportedPermissions(tp, Permissions.READ));
-                assertEquals(Permissions.READ_NODE, 
cugPermProvider.supportedPermissions(tp, Permissions.READ_NODE));
-                assertEquals(Permissions.READ_PROPERTY, 
cugPermProvider.supportedPermissions(tp, Permissions.READ_PROPERTY));
-                assertEquals(Permissions.READ, 
cugPermProvider.supportedPermissions(tp, Permissions.ALL));
-                assertEquals(Permissions.READ_NODE, 
cugPermProvider.supportedPermissions(tp, Permissions.READ_NODE | 
Permissions.READ_ACCESS_CONTROL));
+                assertEquals(Permissions.READ, 
cugPermProvider.supportedPermissions(tp, null, Permissions.READ));
+                assertEquals(Permissions.READ_NODE, 
cugPermProvider.supportedPermissions(tp, null, Permissions.READ_NODE));
+                assertEquals(Permissions.READ_PROPERTY, 
cugPermProvider.supportedPermissions(tp, null, Permissions.READ_PROPERTY));
+                assertEquals(Permissions.READ, 
cugPermProvider.supportedPermissions(tp, null, Permissions.ALL));
+                assertEquals(Permissions.READ_NODE, 
cugPermProvider.supportedPermissions(tp, null, Permissions.READ_NODE | 
Permissions.READ_ACCESS_CONTROL));
             } else {
-                assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(tp, Permissions.READ));
-                assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(tp, Permissions.READ_NODE));
-                assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(tp, Permissions.READ_PROPERTY));
-                assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(tp, Permissions.ALL));
-                assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(tp, Permissions.READ_NODE | 
Permissions.READ_ACCESS_CONTROL));
+                assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(tp, null, Permissions.READ));
+                assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(tp, null, Permissions.READ_NODE));
+                assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(tp, null, Permissions.READ_PROPERTY));
+                assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(tp, null, Permissions.ALL));
+                assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(tp, null, Permissions.READ_NODE | 
Permissions.READ_ACCESS_CONTROL));
             }
-            assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(tp, Permissions.ADD_NODE | 
Permissions.REMOVE));
+            assertEquals(Permissions.NO_PERMISSION, 
cugPermProvider.supportedPermissions(tp, null, Permissions.ADD_NODE | 
Permissions.REMOVE));
         }
     }
 

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=1708563&r1=1708562&r2=1708563&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
 Wed Oct 14 09:02:49 2015
@@ -16,14 +16,11 @@
  */
 package org.apache.jackrabbit.oak.security.authorization.composite;
 
-import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import com.google.common.collect.ImmutableMap;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.api.Tree;
@@ -39,7 +36,6 @@ import org.apache.jackrabbit.oak.spi.sec
 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.state.NodeState;
 
 /**
  * Permission provider implementation that aggregates a list of different
@@ -55,7 +51,7 @@ class CompositePermissionProvider implem
     private final List<AggregatedPermissionProvider> pps;
     private final Context ctx;
 
-    private final CompositeRepositoryPermission repositoryPermission;
+    private final RepositoryPermission repositoryPermission;
 
     private Root immutableRoot;
     private PrivilegeBitsProvider privilegeBitsProvider;
@@ -146,7 +142,7 @@ class CompositePermissionProvider implem
     public TreePermission getTreePermission(@Nonnull Tree tree, @Nonnull 
TreePermission parentPermission) {
         ImmutableTree immutableTree = (ImmutableTree) 
PermissionUtil.getImmutableTree(tree, immutableRoot);
         if (tree.isRoot()) {
-            return new CompositeTreePermission(immutableTree, new 
CompositeTreePermission());
+            return new CompositeTreePermission(immutableTree, new 
CompositeTreePermission(pps));
         } else {
             if (!(parentPermission instanceof CompositeTreePermission)) {
                 throw new IllegalArgumentException("Illegal parent permission 
instance. Expected CompositeTreePermission.");
@@ -208,7 +204,8 @@ class CompositePermissionProvider implem
     }
 
     //------------------------------------------------------------< private 
>---
-    private static boolean doEvaluate(long supportedPermissions) {
+
+    static boolean doEvaluate(long supportedPermissions) {
         return supportedPermissions != Permissions.NO_PERMISSION;
     }
 
@@ -216,121 +213,6 @@ class CompositePermissionProvider implem
         return !supportedPrivileges.isEmpty();
     }
 
-    //-----------------------------------------------------< TreePermission 
>---
-    /**
-     * {@code TreePermission} implementation that wraps multiple 
implementations.
-     */
-    private final class CompositeTreePermission implements TreePermission {
-
-        private final ImmutableTree tree;
-        private final Map<AggregatedPermissionProvider, TreePermission> map;
-
-        private Boolean canRead;
-
-        private CompositeTreePermission() {
-            tree = null;
-            map = ImmutableMap.of();
-        }
-
-        private CompositeTreePermission(@Nonnull final ImmutableTree tree, 
@Nonnull CompositeTreePermission parentPermission) {
-            this.tree = tree;
-            map = new LinkedHashMap<AggregatedPermissionProvider, 
TreePermission>(pps.size());
-            for (AggregatedPermissionProvider provider : pps) {
-                // 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);
-            }
-        }
-
-        @Nonnull
-        @Override
-        public TreePermission getChildPermission(@Nonnull String childName, 
@Nonnull NodeState childState) {
-            ImmutableTree childTree = new ImmutableTree(tree, childName, 
childState);
-            return new CompositeTreePermission(childTree, this);
-        }
-
-        @Override
-        public boolean canRead() {
-            if (canRead == null) {
-                boolean readable = false;
-                for (Map.Entry<AggregatedPermissionProvider, TreePermission> 
entry : map.entrySet()) {
-                    TreePermission tp = entry.getValue();
-                    long supported = entry.getKey().supportedPermissions(tp, 
Permissions.READ_NODE);
-                    if (doEvaluate(supported)) {
-                        readable = tp.canRead();
-                        if (!readable) {
-                            break;
-                        }
-                    }
-                }
-                canRead = readable;
-            }
-            return canRead;
-        }
-
-        @Override
-        public boolean canRead(@Nonnull PropertyState property) {
-            boolean canReadProperty = false;
-            for (Map.Entry<AggregatedPermissionProvider, TreePermission> entry 
: map.entrySet()) {
-                TreePermission tp = entry.getValue();
-                long supported = entry.getKey().supportedPermissions(tp, 
Permissions.READ_PROPERTY);
-                if (doEvaluate(supported)) {
-                    canReadProperty = tp.canRead(property);
-                    if (!canReadProperty) {
-                        break;
-                    }
-                }
-            }
-            return canReadProperty;
-        }
-
-        @Override
-        public boolean canReadAll() {
-            return false;
-        }
-
-        @Override
-        public boolean canReadProperties() {
-            return false;
-        }
-
-        @Override
-        public boolean isGranted(long permissions) {
-            return grantsPermission(permissions, null);
-        }
-
-        @Override
-        public boolean isGranted(long permissions, @Nonnull PropertyState 
property) {
-            return grantsPermission(permissions, property);
-        }
-
-        private boolean grantsPermission(long permissions, @Nullable 
PropertyState property) {
-            boolean isGranted = false;
-            long coveredPermissions = Permissions.NO_PERMISSION;
-
-            for (Map.Entry<AggregatedPermissionProvider, TreePermission> entry 
: map.entrySet()) {
-                long supportedPermissions = 
entry.getKey().supportedPermissions(tree, property, permissions);
-                if (doEvaluate(supportedPermissions)) {
-                    TreePermission tp = entry.getValue();
-                    isGranted = (property == null) ? 
tp.isGranted(supportedPermissions) : tp.isGranted(supportedPermissions, 
property);
-                    coveredPermissions |= supportedPermissions;
-
-                    if (!isGranted) {
-                        return false;
-                    }
-                }
-            }
-            return isGranted && coveredPermissions == permissions;
-        }
-
-        @Nonnull
-        private TreePermission getParentPermission(@Nonnull 
CompositeTreePermission compositeParent,
-                                                   @Nonnull 
AggregatedPermissionProvider provider) {
-            TreePermission parent = compositeParent.map.get(provider);
-            return (parent == null) ? TreePermission.EMPTY : parent;
-        }
-    }
-
     //-----------------------------------------------< RepositoryPermission 
>---
     /**
      * {@code RepositoryPermission} implementation that wraps multiple 
implementations.
@@ -343,7 +225,7 @@ class CompositePermissionProvider implem
             long coveredPermissions = Permissions.NO_PERMISSION;
 
             for (AggregatedPermissionProvider aggregatedPermissionProvider : 
pps) {
-                long supportedPermissions = 
aggregatedPermissionProvider.supportedPermissions(null, null, 
repositoryPermissions);
+                long supportedPermissions = 
aggregatedPermissionProvider.supportedPermissions((Tree) null, null, 
repositoryPermissions);
                 if (doEvaluate(supportedPermissions)) {
                     isGranted = 
aggregatedPermissionProvider.getRepositoryPermission().isGranted(supportedPermissions);
                     coveredPermissions |= supportedPermissions;

Added: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeTreePermission.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeTreePermission.java?rev=1708563&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeTreePermission.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeTreePermission.java
 Wed Oct 14 09:02:49 2015
@@ -0,0 +1,174 @@
+/*
+ * 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.LinkedHashMap;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.plugins.tree.impl.ImmutableTree;
+import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.AggregatedPermissionProvider;
+import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.Permissions;
+import 
org.apache.jackrabbit.oak.spi.security.authorization.permission.TreePermission;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+/**
+ * {@code TreePermission} implementation that combines multiple {@code 
TreePermission}
+ * implementations.
+ */
+final class CompositeTreePermission implements TreePermission {
+
+    private final ImmutableTree tree;
+    private final Map<AggregatedPermissionProvider, TreePermission> map;
+
+    private Boolean canRead;
+
+    CompositeTreePermission(@Nonnull Iterable<AggregatedPermissionProvider> 
providers) {
+        tree = null;
+        ImmutableMap.Builder<AggregatedPermissionProvider, TreePermission> 
builder = ImmutableMap.builder();
+        for (AggregatedPermissionProvider app : providers) {
+            builder.put(app, TreePermission.EMPTY);
+        }
+        map = builder.build();
+    }
+
+    CompositeTreePermission(@Nonnull final ImmutableTree tree, @Nonnull 
CompositeTreePermission parentPermission) {
+        this.tree = tree;
+
+        TreePermission parent;
+        AggregatedPermissionProvider provider;
+
+        int size = parentPermission.map.size();
+        switch (size) {
+            case 0:
+                map = ImmutableMap.of();
+                break;
+            case 1:
+                provider = parentPermission.map.keySet().iterator().next();
+                parent = getParentPermission(parentPermission, provider);
+                if (NO_RECOURSE != parent) {
+                    map = ImmutableMap.of(provider, 
provider.getTreePermission(tree, parent));
+                } else {
+                    map = ImmutableMap.of();
+                }
+                break;
+            default:
+                map = new LinkedHashMap<AggregatedPermissionProvider, 
TreePermission>(size);
+                for (AggregatedPermissionProvider app : 
parentPermission.map.keySet()) {
+                    parent = getParentPermission(parentPermission, app);
+                    if (NO_RECOURSE != parent) {
+                        TreePermission tp = app.getTreePermission(tree, 
parent);
+                        map.put(app, tp);
+                    }
+                }
+        }
+    }
+
+    //-----------------------------------------------------< TreePermission 
>---
+    @Nonnull
+    @Override
+    public TreePermission getChildPermission(@Nonnull String childName, 
@Nonnull NodeState childState) {
+        if (tree == null) {
+            throw new IllegalStateException();
+        }
+        ImmutableTree childTree = new ImmutableTree(tree, childName, 
childState);
+        return new CompositeTreePermission(childTree, this);
+    }
+
+    @Override
+    public boolean canRead() {
+        if (canRead == null) {
+            canRead = grantsRead(null);
+        }
+        return canRead;
+    }
+
+    @Override
+    public boolean canRead(@Nonnull PropertyState property) {
+        return grantsRead(property);
+    }
+
+    @Override
+    public boolean canReadAll() {
+        return false;
+    }
+
+    @Override
+    public boolean canReadProperties() {
+        return false;
+    }
+
+    @Override
+    public boolean isGranted(long permissions) {
+        return grantsPermission(permissions, null);
+    }
+
+    @Override
+    public boolean isGranted(long permissions, @Nonnull PropertyState 
property) {
+        return grantsPermission(permissions, property);
+    }
+
+    //------------------------------------------------------------< private 
>---
+
+    private boolean grantsPermission(long permissions, @Nullable PropertyState 
property) {
+        boolean isGranted = false;
+        long coveredPermissions = Permissions.NO_PERMISSION;
+
+        for (Map.Entry<AggregatedPermissionProvider, TreePermission> entry : 
map.entrySet()) {
+            TreePermission tp = entry.getValue();
+            long supported = entry.getKey().supportedPermissions(tp, property, 
permissions);
+            if (doEvaluate(supported)) {
+                isGranted = (property == null) ? tp.isGranted(supported) : 
tp.isGranted(supported, property);
+                coveredPermissions |= supported;
+
+                if (!isGranted) {
+                    return false;
+                }
+            }
+        }
+        return isGranted && coveredPermissions == permissions;
+    }
+
+    private boolean grantsRead(@Nullable PropertyState property) {
+        boolean readable = false;
+        for (Map.Entry<AggregatedPermissionProvider, TreePermission> entry : 
map.entrySet()) {
+            TreePermission tp = entry.getValue();
+            long supported = entry.getKey().supportedPermissions(tp, property, 
(property == null) ? Permissions.READ_NODE : Permissions.READ_PROPERTY);
+            if (doEvaluate(supported)) {
+                readable = (property == null) ? tp.canRead() : 
tp.canRead(property);
+                if (!readable) {
+                    break;
+                }
+            }
+        }
+        return readable;
+    }
+
+    private static boolean doEvaluate(long supportedPermissions) {
+        return CompositePermissionProvider.doEvaluate(supportedPermissions);
+    }
+
+    @Nonnull
+    private static TreePermission getParentPermission(@Nonnull 
CompositeTreePermission compositeParent,
+                                                      @Nonnull 
AggregatedPermissionProvider provider) {
+        TreePermission parent = compositeParent.map.get(provider);
+        return (parent == null) ? TreePermission.EMPTY : parent;
+    }
+}
\ No newline at end of file

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=1708563&r1=1708562&r2=1708563&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
 Wed Oct 14 09:02:49 2015
@@ -133,7 +133,7 @@ public class PermissionProviderImpl impl
     }
 
     @Override
-    public long supportedPermissions(@Nonnull TreePermission treePermission, 
long permissions) {
+    public long supportedPermissions(@Nonnull TreePermission treePermission, 
@Nullable PropertyState propertyState, long permissions) {
         return permissions;
     }
 

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=1708563&r1=1708562&r2=1708563&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
 Wed Oct 14 09:02:49 2015
@@ -61,7 +61,7 @@ public interface AggregatedPermissionPro
 
     long supportedPermissions(@Nonnull TreeLocation location, long 
permissions);
 
-    long supportedPermissions(@Nonnull TreePermission treePermission, long 
permissions);
+    long supportedPermissions(@Nonnull TreePermission treePermission, 
@Nullable PropertyState propertyState, long permissions);
 
     /**
      * Test if the specified permissions are granted for the set of {@code 
Principal}s

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/TreePermission.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/TreePermission.java?rev=1708563&r1=1708562&r2=1708563&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/TreePermission.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/permission/TreePermission.java
 Wed Oct 14 09:02:49 2015
@@ -188,4 +188,43 @@ public interface TreePermission {
             return true;
         }
     };
+
+    TreePermission NO_RECOURSE = new TreePermission() {
+
+        @Nonnull
+        @Override
+        public TreePermission getChildPermission(@Nonnull String childName, 
@Nonnull NodeState childState) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean canRead() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean canRead(@Nonnull PropertyState property) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean canReadAll() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean canReadProperties() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isGranted(long permissions) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isGranted(long permissions, @Nonnull PropertyState 
property) {
+            throw new UnsupportedOperationException();
+        }
+    };
 }
\ No newline at end of file

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=1708563&r1=1708562&r2=1708563&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
 Wed Oct 14 09:02:49 2015
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("2.0.2")
+@Version("3.0.0")
 @Export(optional = "provide:=true")
 package org.apache.jackrabbit.oak.spi.security.authorization.permission;
 

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/AbstractCompositeProviderTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/AbstractCompositeProviderTest.java?rev=1708563&r1=1708562&r2=1708563&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/AbstractCompositeProviderTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/AbstractCompositeProviderTest.java
 Wed Oct 14 09:02:49 2015
@@ -22,19 +22,24 @@ import java.util.Map;
 import java.util.Set;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
+import javax.jcr.Session;
 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.JackrabbitSession;
 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.memory.PropertyStates;
 import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
+import org.apache.jackrabbit.oak.plugins.tree.RootFactory;
+import org.apache.jackrabbit.oak.plugins.tree.impl.ImmutableTree;
 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;
@@ -43,13 +48,15 @@ import org.apache.jackrabbit.oak.spi.sec
 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.spi.state.NodeState;
 import org.apache.jackrabbit.oak.util.NodeUtil;
+import org.apache.jackrabbit.util.Text;
 import org.junit.Test;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-public abstract class AbstractCompositeProviderTest extends 
AbstractSecurityTest implements NodeTypeConstants {
+public abstract class AbstractCompositeProviderTest extends 
AbstractSecurityTest implements NodeTypeConstants, PrivilegeConstants {
 
     static final String ROOT_PATH = "/";
     static final String TEST_PATH = "/test";
@@ -61,13 +68,31 @@ public abstract class AbstractCompositeP
 
     static final String TEST_PATH_2 = "/test2";
 
-    static final String PROP_NAME = "propName";
+    static final List<String> NODE_PATHS = ImmutableList.of(ROOT_PATH, 
TEST_PATH, TEST_PATH_2, TEST_CHILD_PATH, TEST_A_PATH, TEST_A_B_PATH, 
TEST_A_B_C_PATH, TEST_A_B2_PATH);
+    static final List<String> TP_PATHS = ImmutableList.of(ROOT_PATH, 
TEST_PATH, TEST_A_PATH, TEST_A_B_PATH, TEST_A_B_C_PATH, TEST_A_B_C_PATH + 
"/nonexisting");
 
-    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);
+    static final PropertyState PROPERTY_STATE = 
PropertyStates.createProperty("propName", "val");
+
+    static final String[] ALL_ACTIONS = new String[] {
+            Session.ACTION_READ,
+            Session.ACTION_ADD_NODE,
+            JackrabbitSession.ACTION_REMOVE_NODE,
+            Session.ACTION_SET_PROPERTY,
+            JackrabbitSession.ACTION_ADD_PROPERTY,
+            JackrabbitSession.ACTION_MODIFY_PROPERTY,
+            JackrabbitSession.ACTION_REMOVE_PROPERTY,
+            Session.ACTION_REMOVE,
+            JackrabbitSession.ACTION_READ_ACCESS_CONTROL,
+            JackrabbitSession.ACTION_MODIFY_ACCESS_CONTROL,
+            JackrabbitSession.ACTION_LOCKING,
+            JackrabbitSession.ACTION_NODE_TYPE_MANAGEMENT,
+            JackrabbitSession.ACTION_VERSIONING,
+            JackrabbitSession.ACTION_USER_MANAGEMENT
+    };
 
     Map<String, Long> defPermissions;
     Map<String, Set<String>> defPrivileges;
-
+    Map<String, String[]> defActionsGranted;
 
     @Override
     public void before() throws Exception {
@@ -76,44 +101,79 @@ public abstract class AbstractCompositeP
         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");
+        test.addChild("child", NT_OAK_UNSTRUCTURED);
         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");
+        a.addChild("b", NT_OAK_UNSTRUCTURED).addChild("c", 
NT_OAK_UNSTRUCTURED);
 
         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);
+        allow(acMgr, everyone, null, JCR_NAMESPACE_MANAGEMENT, 
JCR_NODE_TYPE_DEFINITION_MANAGEMENT);
+        allow(acMgr, everyone, TEST_PATH, JCR_READ);
+        allow(acMgr, everyone, TEST_CHILD_PATH, JCR_READ_ACCESS_CONTROL);
+
+        allow(acMgr, everyone, TEST_A_PATH, JCR_WRITE, JCR_VERSION_MANAGEMENT);
+        deny(acMgr, everyone, TEST_A_B_PATH, REP_REMOVE_PROPERTIES, 
JCR_REMOVE_NODE);
+        deny(acMgr, everyone, TEST_A_B_C_PATH, 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).
+                put(TEST_CHILD_PATH,
+                        Permissions.READ |
+                        Permissions.READ_ACCESS_CONTROL).
+                put(TEST_A_PATH,
+                        Permissions.READ |
+                        Permissions.SET_PROPERTY |
+                        Permissions.MODIFY_CHILD_NODE_COLLECTION |
+                        Permissions.VERSION_MANAGEMENT).
+                put(TEST_A_B2_PATH,
+                        Permissions.READ |
+                        Permissions.WRITE |
+                        Permissions.MODIFY_CHILD_NODE_COLLECTION |
+                        Permissions.VERSION_MANAGEMENT).
+                put(TEST_A_B_PATH,
+                        Permissions.READ |
+                        Permissions.ADD_NODE |
+                        Permissions.ADD_PROPERTY |
+                        Permissions.MODIFY_PROPERTY |
+                        Permissions.MODIFY_CHILD_NODE_COLLECTION |
+                        Permissions.VERSION_MANAGEMENT).
+                put(TEST_A_B_C_PATH,
+                        Permissions.READ_PROPERTY |
+                        Permissions.ADD_NODE |
+                        Permissions.ADD_PROPERTY |
+                        Permissions.MODIFY_PROPERTY |
+                        Permissions.MODIFY_CHILD_NODE_COLLECTION |
+                        Permissions.VERSION_MANAGEMENT).
                 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)).
+                put(TEST_PATH, ImmutableSet.of(JCR_READ)).
+                put(TEST_CHILD_PATH, ImmutableSet.of(JCR_READ, 
JCR_READ_ACCESS_CONTROL)).
+                put(TEST_A_PATH, ImmutableSet.of(JCR_READ, JCR_WRITE, 
JCR_VERSION_MANAGEMENT)).
+                put(TEST_A_B2_PATH, ImmutableSet.of(JCR_READ, JCR_WRITE, 
JCR_VERSION_MANAGEMENT)).
+                put(TEST_A_B_PATH, ImmutableSet.of(JCR_READ, 
JCR_ADD_CHILD_NODES, JCR_REMOVE_CHILD_NODES, REP_ADD_PROPERTIES, 
REP_ALTER_PROPERTIES, JCR_VERSION_MANAGEMENT)).
+                put(TEST_A_B_C_PATH, ImmutableSet.of(REP_READ_PROPERTIES, 
JCR_ADD_CHILD_NODES, JCR_REMOVE_CHILD_NODES, REP_ADD_PROPERTIES, 
REP_ALTER_PROPERTIES, JCR_VERSION_MANAGEMENT)).
+                build();
+
+        defActionsGranted = ImmutableMap.<String, String[]>builder().
+                put(TEST_PATH, new String[] {Session.ACTION_READ}).
+                put(TEST_CHILD_PATH, new String[] {Session.ACTION_READ, 
JackrabbitSession.ACTION_READ_ACCESS_CONTROL}).
+                put(TEST_A_PATH, new String[] {Session.ACTION_READ, 
Session.ACTION_SET_PROPERTY, JackrabbitSession.ACTION_VERSIONING}).
+                put(TEST_A_PATH + "/jcr:primaryType", new String[] 
{Session.ACTION_SET_PROPERTY, JackrabbitSession.ACTION_VERSIONING}).
+                put(TEST_A_PATH + "/propName", new String[] 
{JackrabbitSession.ACTION_ADD_PROPERTY, 
JackrabbitSession.ACTION_MODIFY_PROPERTY, 
JackrabbitSession.ACTION_REMOVE_PROPERTY, JackrabbitSession.ACTION_VERSIONING}).
+                put(TEST_A_PATH + "/nodeName", new String[] 
{Session.ACTION_ADD_NODE, JackrabbitSession.ACTION_VERSIONING}).
+                put(TEST_A_B2_PATH, new String[] {Session.ACTION_READ, 
Session.ACTION_ADD_NODE, JackrabbitSession.ACTION_REMOVE_NODE, 
Session.ACTION_REMOVE, Session.ACTION_SET_PROPERTY, 
JackrabbitSession.ACTION_VERSIONING}).
+                put(TEST_A_B_PATH, new String[] {Session.ACTION_READ, 
Session.ACTION_ADD_NODE, JackrabbitSession.ACTION_ADD_PROPERTY, 
JackrabbitSession.ACTION_MODIFY_PROPERTY, JackrabbitSession.ACTION_VERSIONING}).
+                put(TEST_A_B_PATH + "/nonExisting", new String[] 
{Session.ACTION_READ, Session.ACTION_ADD_NODE, 
JackrabbitSession.ACTION_ADD_PROPERTY, 
JackrabbitSession.ACTION_MODIFY_PROPERTY, JackrabbitSession.ACTION_VERSIONING}).
+                put(TEST_A_B_C_PATH + "/jcr:primaryType",  new String[] 
{Session.ACTION_READ, JackrabbitSession.ACTION_VERSIONING}).
+                put(TEST_A_B_C_PATH,  new String[] {Session.ACTION_ADD_NODE, 
JackrabbitSession.ACTION_ADD_PROPERTY, JackrabbitSession.ACTION_VERSIONING}).
                 build();
     }
 
@@ -146,15 +206,20 @@ public abstract class AbstractCompositeP
         acMgr.setPolicy(acl.getPath(), acl);
     }
 
+    @Nonnull
+    static String getActionString(@Nonnull String... actions) {
+        return Text.implode(actions, ",");
+    }
+
     abstract AggregatedPermissionProvider getTestPermissionProvider();
 
     boolean reverseOrder() {
         return false;
     }
 
-    private List<AggregatedPermissionProvider> getAggregatedProviders(@Nonnull 
String workspaceName,
-                                                                      @Nonnull 
AuthorizationConfiguration config,
-                                                                      @Nonnull 
Set<Principal> principals) {
+    List<AggregatedPermissionProvider> getAggregatedProviders(@Nonnull String 
workspaceName,
+                                                              @Nonnull 
AuthorizationConfiguration config,
+                                                              @Nonnull 
Set<Principal> principals) {
         if (reverseOrder()) {
             return ImmutableList.of(
                     (AggregatedPermissionProvider) 
config.getPermissionProvider(root, workspaceName, principals),
@@ -178,12 +243,18 @@ public abstract class AbstractCompositeP
     }
 
     @Test
+    public void testRefresh() throws Exception {
+        CompositePermissionProvider pp = createPermissionProvider();
+        pp.refresh();
+    }
+
+    @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));
+            assertFalse(p, pp.hasPrivileges(tree, JCR_ALL));
         }
     }
 
@@ -200,7 +271,7 @@ public abstract class AbstractCompositeP
     @Test
     public void testHasPrivilegesOnRepoJcrAll() throws Exception {
         PermissionProvider pp = createPermissionProvider();
-        assertFalse(pp.hasPrivileges(null, PrivilegeConstants.JCR_ALL));
+        assertFalse(pp.hasPrivileges(null, JCR_ALL));
     }
 
     @Test
@@ -236,17 +307,146 @@ public abstract class AbstractCompositeP
     }
 
     @Test
+    public void testIsNotGranted() 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.MODIFY_ACCESS_CONTROL));
+            assertFalse(PathUtils.concat(p, JcrConstants.JCR_PRIMARYTYPE), 
pp.isGranted(tree, ps, Permissions.MODIFY_ACCESS_CONTROL));
+        }
+    }
+
+    @Test
+    public void testIsGrantedActionNone() throws Exception {
+        PermissionProvider pp = createPermissionProvider();
+        String actions = "";
+
+        for (String nodePath : NODE_PATHS) {
+            assertFalse(nodePath, pp.isGranted(nodePath, actions));
+
+            String propPath = PathUtils.concat(nodePath, 
JcrConstants.JCR_PRIMARYTYPE);
+            assertFalse(propPath, pp.isGranted(propPath, actions));
+
+            String nonExPath = PathUtils.concat(nodePath, "nonExisting");
+            assertFalse(nonExPath, pp.isGranted(nonExPath, actions));
+        }
+    }
+
+    @Test
+    public void testIsNotGrantedAction() throws Exception {
+        PermissionProvider pp = createPermissionProvider();
+        String[] actions = new String[]{JackrabbitSession.ACTION_LOCKING, 
JackrabbitSession.ACTION_MODIFY_ACCESS_CONTROL};
+
+        for (String nodePath : NODE_PATHS) {
+            String actionStr = getActionString(actions);
+            assertFalse(nodePath, pp.isGranted(nodePath, actionStr));
+
+            String propPath = PathUtils.concat(nodePath, 
JcrConstants.JCR_PRIMARYTYPE);
+            assertFalse(propPath, pp.isGranted(propPath, actionStr));
+
+            String nonExPath = PathUtils.concat(nodePath, "nonExisting");
+            assertFalse(nonExPath, pp.isGranted(nonExPath, actionStr));
+        }
+    }
+
+    @Test
     public void testGetTreePermissionInstance() throws Exception {
+        PermissionProvider pp = createPermissionProvider();
         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);
+        for (String path : TP_PATHS) {
+            TreePermission tp = pp.getTreePermission(root.getTree(path), 
parentPermission);
             
assertTrue(tp.getClass().getName().endsWith("CompositeTreePermission"));
             parentPermission = tp;
         }
     }
 
+    @Test(expected = IllegalArgumentException.class)
+    public void testGetTreePermissionInvalidParent() throws Exception {
+        TreePermission tp = 
createPermissionProvider().getTreePermission(root.getTree(TEST_PATH), 
TreePermission.ALL);
+    }
+
+    @Test
+    public void testTreePermissionIsGrantedAll() throws Exception {
+        PermissionProvider pp = createPermissionProvider();
+        TreePermission parentPermission = TreePermission.EMPTY;
+
+        PropertyState ps = PropertyStates.createProperty("propName", "val");
+
+        for (String path : TP_PATHS) {
+            Tree t = root.getTree(path);
+            TreePermission tp = pp.getTreePermission(t, parentPermission);
+
+            assertFalse(tp.isGranted(Permissions.ALL));
+            assertFalse(tp.isGranted(Permissions.ALL, ps));
+
+            parentPermission = tp;
+        }
+    }
+
+    @Test
+    public void testTreePermissionIsNotGranted() throws Exception {
+        PermissionProvider pp = createPermissionProvider();
+        TreePermission parentPermission = TreePermission.EMPTY;
+
+        PropertyState ps = PropertyStates.createProperty("propName", "val");
+
+        for (String path : TP_PATHS) {
+            Tree t = root.getTree(path);
+            TreePermission tp = pp.getTreePermission(t, parentPermission);
+
+            assertFalse(tp.isGranted(Permissions.NO_PERMISSION));
+            assertFalse(tp.isGranted(Permissions.MODIFY_ACCESS_CONTROL));
+            assertFalse(tp.isGranted(Permissions.NO_PERMISSION, ps));
+            assertFalse(tp.isGranted(Permissions.MODIFY_ACCESS_CONTROL, ps));
+
+            parentPermission = tp;
+        }
+    }
+
+    @Test
+    public void testTreePermissionCanReadAll() throws Exception {
+        PermissionProvider pp = createPermissionProvider();
+        TreePermission parentPermission = TreePermission.EMPTY;
+
+        for (String path : TP_PATHS) {
+            TreePermission tp = pp.getTreePermission(root.getTree(path), 
parentPermission);
+            assertFalse(tp.canReadAll());
+
+            parentPermission = tp;
+        }
+    }
+
+    @Test
+    public void testTreePermissionCanReadProperties() throws Exception {
+        PermissionProvider pp = createPermissionProvider();
+        TreePermission parentPermission = TreePermission.EMPTY;
+
+        for (String path : TP_PATHS) {
+            TreePermission tp = pp.getTreePermission(root.getTree(path), 
parentPermission);
+            assertFalse(tp.canReadProperties());
+
+            parentPermission = tp;
+        }
+    }
+
+    @Test
+    public void testTreePermissionGetChild() throws Exception {
+        List<String> childNames = ImmutableList.of("test", "a", "b", "c", 
"nonexisting");
+
+        NodeState ns = ((ImmutableTree) 
RootFactory.createReadOnlyRoot(root).getTree(ROOT_PATH)).getNodeState();
+        TreePermission tp = 
createPermissionProvider().getTreePermission(root.getTree(ROOT_PATH), 
TreePermission.EMPTY);
+
+        for (String cName : childNames) {
+            ns = ns.getChildNode(cName);
+            tp = tp.getChildPermission(cName, ns);
+            
assertTrue(tp.getClass().getName().endsWith("CompositeTreePermission"));
+        }
+    }
+
     @Test
     public void testGetRepositoryPermissionInstance() throws Exception {
         RepositoryPermission rp = 
createPermissionProvider().getRepositoryPermission();

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfigurationTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfigurationTest.java?rev=1708563&r1=1708562&r2=1708563&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfigurationTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeAuthorizationConfigurationTest.java
 Wed Oct 14 09:02:49 2015
@@ -19,35 +19,121 @@ package org.apache.jackrabbit.oak.securi
 import java.security.Principal;
 import java.util.Collections;
 
+import javax.jcr.RepositoryException;
+import javax.jcr.security.AccessControlManager;
+
 import org.apache.jackrabbit.oak.AbstractSecurityTest;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import 
org.apache.jackrabbit.oak.security.authorization.AuthorizationConfigurationImpl;
+import 
org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
+import 
org.apache.jackrabbit.oak.spi.security.authorization.OpenAuthorizationConfiguration;
+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.restriction.CompositeRestrictionProvider;
 import 
org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
 import org.junit.Test;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
 
 public class CompositeAuthorizationConfigurationTest extends 
AbstractSecurityTest {
 
-    private CompositeAuthorizationConfiguration compositeConfiguration;
-
-    @Override
-    public void before() throws Exception {
-        super.before();
-        compositeConfiguration = new 
CompositeAuthorizationConfiguration(getSecurityProvider());
+    private CompositeAuthorizationConfiguration 
getCompositeConfiguration(AuthorizationConfiguration... entries) {
+        CompositeAuthorizationConfiguration compositeConfiguration = new 
CompositeAuthorizationConfiguration(getSecurityProvider());
+        for (AuthorizationConfiguration ac : entries) {
+            compositeConfiguration.addConfiguration(ac);
+        }
+        return compositeConfiguration;
     }
 
     @Test(expected = IllegalStateException.class)
     public void testEmptyGetAccessControlManager() {
-        compositeConfiguration.getAccessControlManager(root, 
NamePathMapper.DEFAULT);
+        getCompositeConfiguration().getAccessControlManager(root, 
NamePathMapper.DEFAULT);
     }
 
     @Test(expected = IllegalStateException.class)
     public void testEmptyGetPermissionProvider() {
-        compositeConfiguration.getPermissionProvider(root, 
adminSession.getWorkspaceName(), Collections.<Principal>emptySet());
+        getCompositeConfiguration().getPermissionProvider(root, 
adminSession.getWorkspaceName(), Collections.<Principal>emptySet());
     }
 
     @Test
     public void testEmptyGetRestrictionProvider() {
-        assertSame(RestrictionProvider.EMPTY, 
compositeConfiguration.getRestrictionProvider());
+        assertSame(RestrictionProvider.EMPTY, 
getCompositeConfiguration().getRestrictionProvider());
+    }
+
+    @Test
+    public void testSingleGetAccessControlManager() {
+        CompositeAuthorizationConfiguration cc = getCompositeConfiguration(new 
AuthorizationConfigurationImpl(getSecurityProvider()));
+
+        AccessControlManager accessControlManager = 
cc.getAccessControlManager(root, NamePathMapper.DEFAULT);
+        assertFalse(accessControlManager instanceof 
CompositeAccessControlManager);
+    }
+
+    @Test
+    public void testSingleGetPermissionProvider() {
+        CompositeAuthorizationConfiguration cc = getCompositeConfiguration(new 
AuthorizationConfigurationImpl(getSecurityProvider()));
+
+        PermissionProvider pp = cc.getPermissionProvider(root, 
root.getContentSession().getWorkspaceName(), Collections.<Principal>emptySet());
+        assertFalse(pp instanceof CompositePermissionProvider);
+    }
+
+    @Test
+    public void testSlingRestrictionProvider() {
+        CompositeAuthorizationConfiguration cc = getCompositeConfiguration(new 
AuthorizationConfigurationImpl(getSecurityProvider()));
+
+        RestrictionProvider rp = cc.getRestrictionProvider();
+        assertFalse(rp instanceof CompositeRestrictionProvider);
+    }
+
+    @Test
+    public void testMultipleGetAccessControlManager() throws 
RepositoryException {
+        CompositeAuthorizationConfiguration cc = getCompositeConfiguration(
+                new AuthorizationConfigurationImpl(getSecurityProvider()),
+                new AuthorizationConfigurationImpl(getSecurityProvider()));
+
+        AccessControlManager accessControlManager = 
cc.getAccessControlManager(root, NamePathMapper.DEFAULT);
+        assertTrue(accessControlManager instanceof 
CompositeAccessControlManager);
+    }
+
+    @Test
+    public void testMultipleGetPermissionProvider() {
+        CompositeAuthorizationConfiguration cc = getCompositeConfiguration(
+                new OpenAuthorizationConfiguration(),
+                new AuthorizationConfigurationImpl(getSecurityProvider()));
+
+        PermissionProvider pp = cc.getPermissionProvider(root, 
root.getContentSession().getWorkspaceName(), Collections.<Principal>emptySet());
+        assertFalse(pp instanceof CompositePermissionProvider);
+    }
+
+    @Test
+    public void testMultipleGetPermissionProvider2() {
+        CompositeAuthorizationConfiguration cc = getCompositeConfiguration(
+                new AuthorizationConfigurationImpl(getSecurityProvider()),
+                new AuthorizationConfigurationImpl(getSecurityProvider()));
+
+        PermissionProvider pp = cc.getPermissionProvider(root, 
root.getContentSession().getWorkspaceName(), Collections.<Principal>emptySet());
+        assertTrue(pp instanceof CompositePermissionProvider);
+    }
+
+    @Test
+    public void testMultipleGetPermissionProvider3() {
+        CompositeAuthorizationConfiguration cc = getCompositeConfiguration(
+                new OpenAuthorizationConfiguration(),
+                new OpenAuthorizationConfiguration());
+
+        PermissionProvider pp = cc.getPermissionProvider(root, 
root.getContentSession().getWorkspaceName(), Collections.<Principal>emptySet());
+        assertFalse(pp instanceof CompositePermissionProvider);
+        assertSame(EmptyPermissionProvider.getInstance(), pp);
+    }
+
+    @Test
+    public void testMultipleRestrictionProvider() {
+        CompositeAuthorizationConfiguration cc = getCompositeConfiguration(
+                new AuthorizationConfigurationImpl(getSecurityProvider()),
+                new AuthorizationConfigurationImpl(getSecurityProvider()));
+
+        RestrictionProvider rp = cc.getRestrictionProvider();
+        assertTrue(rp instanceof CompositeRestrictionProvider);
     }
 }
\ No newline at end of file

Modified: 
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=1708563&r1=1708562&r2=1708563&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderAllTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderAllTest.java
 Wed Oct 14 09:02:49 2015
@@ -16,14 +16,19 @@
  */
 package org.apache.jackrabbit.oak.security.authorization.composite;
 
+import java.util.Map;
 import java.util.Set;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
+import javax.jcr.Session;
 
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
+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.OpenPermissionProvider;
@@ -34,10 +39,10 @@ import org.apache.jackrabbit.oak.spi.sec
 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.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -81,7 +86,7 @@ public class CompositeProviderAllTest ex
     @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);
+        assertEquals(ImmutableSet.of(JCR_NAMESPACE_MANAGEMENT, 
JCR_NODE_TYPE_DEFINITION_MANAGEMENT), privilegeNames);
     }
 
 
@@ -98,7 +103,7 @@ public class CompositeProviderAllTest ex
 
     @Test
     public void testHasPrivilegesOnRepo() throws Exception {
-        assertTrue(cpp.hasPrivileges(null, 
PrivilegeConstants.JCR_NAMESPACE_MANAGEMENT, 
PrivilegeConstants.JCR_NODE_TYPE_DEFINITION_MANAGEMENT));
+        assertTrue(cpp.hasPrivileges(null, JCR_NAMESPACE_MANAGEMENT, 
JCR_NODE_TYPE_DEFINITION_MANAGEMENT));
     }
 
 
@@ -114,12 +119,37 @@ public class CompositeProviderAllTest ex
 
     @Test
     public void testIsGrantedProperty() throws Exception {
-        // TODO
+        for (String p : defPermissions.keySet()) {
+            long expected = defPermissions.get(p);
+            Tree tree = root.getTree(p);
+
+            assertTrue(p, cpp.isGranted(tree, PROPERTY_STATE, expected));
+        }
     }
 
     @Test
     public void testIsGrantedAction() throws Exception {
-        // TODO
+        for (String p : defActionsGranted.keySet()) {
+            String actionStr = getActionString(defActionsGranted.get(p));
+            assertTrue(p + " : " + actionStr, cpp.isGranted(p, actionStr));
+        }
+    }
+
+    @Test
+    public void testIsGrantedAction2() throws Exception {
+        Map<String, String[]> noAccess = ImmutableMap.<String, 
String[]>builder().
+                put(ROOT_PATH, new String[] {Session.ACTION_READ}).
+                put(ROOT_PATH + "jcr:primaryType", new String[] 
{Session.ACTION_READ, Session.ACTION_SET_PROPERTY}).
+                put("/nonexisting", new String[] {Session.ACTION_READ, 
Session.ACTION_ADD_NODE}).
+                put(TEST_PATH_2, new String[] {Session.ACTION_READ, 
Session.ACTION_REMOVE}).
+                put(TEST_PATH_2 + "/jcr:primaryType", new String[] 
{Session.ACTION_READ, Session.ACTION_SET_PROPERTY}).
+                put(TEST_A_B_C_PATH, new String[] {Session.ACTION_READ, 
Session.ACTION_REMOVE}).
+                put(TEST_A_B_C_PATH + "/noneExisting", new String[] 
{Session.ACTION_READ, JackrabbitSession.ACTION_REMOVE_NODE}).
+                put(TEST_A_B_C_PATH + "/jcr:primaryType", new String[] 
{JackrabbitSession.ACTION_REMOVE_PROPERTY}).build();
+
+        for (String p : noAccess.keySet()) {
+            assertFalse(p, cpp.isGranted(p, getActionString(noAccess.get(p))));
+        }
     }
 
     @Test
@@ -131,8 +161,80 @@ public class CompositeProviderAllTest ex
     }
 
     @Test
-    public void testGetTreePermission() throws Exception {
-        // TODO
+    public void testTreePermissionIsGranted() throws Exception {
+        TreePermission parentPermission = TreePermission.EMPTY;
+
+        for (String path : TP_PATHS) {
+            TreePermission tp = cpp.getTreePermission(root.getTree(path), 
parentPermission);
+            Long toTest = (defPermissions.containsKey(path)) ? 
defPermissions.get(path) : defPermissions.get(PathUtils.getAncestorPath(path, 
1));
+            if (toTest != null) {
+                assertTrue(tp.isGranted(toTest));
+            }
+            parentPermission = tp;
+        }
+    }
+
+    @Test
+    public void testTreePermissionIsGrantedProperty() throws Exception {
+        TreePermission parentPermission = TreePermission.EMPTY;
+
+        for (String path : TP_PATHS) {
+            TreePermission tp = cpp.getTreePermission(root.getTree(path), 
parentPermission);
+            Long toTest = (defPermissions.containsKey(path)) ? 
defPermissions.get(path) : defPermissions.get(PathUtils.getAncestorPath(path, 
1));
+            if (toTest != null) {
+                assertTrue(tp.isGranted(toTest, PROPERTY_STATE));
+            }
+            parentPermission = tp;
+        }
+    }
+
+    @Test
+    public void testTreePermissionCanRead() throws Exception {
+        Map<String, Boolean> readMap = ImmutableMap.<String, Boolean>builder().
+                put(ROOT_PATH, false).
+                put(TEST_PATH, true).
+                put(TEST_A_PATH, true).
+                put(TEST_A_B_PATH, true).
+                put(TEST_A_B_C_PATH, false).
+                put(TEST_A_B_C_PATH + "/nonexisting", false).
+                build();
+
+        TreePermission parentPermission = TreePermission.EMPTY;
+        TreePermission parentPermission2 = TreePermission.EMPTY;
+        for (String nodePath : readMap.keySet()) {
+            Tree tree = root.getTree(nodePath);
+            TreePermission tp = cpp.getTreePermission(tree, parentPermission);
+
+            boolean expectedResult = readMap.get(nodePath);
+            assertEquals(nodePath, expectedResult, tp.canRead());
+
+            parentPermission = tp;
+        }
+    }
+
+    @Test
+    public void testTreePermissionCanReadProperty() throws Exception {
+        Map<String, Boolean> readMap = ImmutableMap.<String, Boolean>builder().
+                put(ROOT_PATH, false).
+                put(TEST_PATH, true).
+                put(TEST_A_PATH, true).
+                put(TEST_A_B_PATH, true).
+                put(TEST_A_B_C_PATH, true).
+                put(TEST_A_B_C_PATH + "/nonexisting", true).
+                build();
+
+        TreePermission parentPermission = TreePermission.EMPTY;
+        TreePermission parentPermission2 = TreePermission.EMPTY;
+        for (String nodePath : readMap.keySet()) {
+            Tree tree = root.getTree(nodePath);
+
+            TreePermission tp = cpp.getTreePermission(tree, parentPermission);
+
+            boolean expectedResult = readMap.get(nodePath);
+            assertEquals(nodePath, expectedResult, tp.canRead(PROPERTY_STATE));
+
+            parentPermission = tp;
+        }
     }
 
     /**
@@ -151,7 +253,7 @@ public class CompositeProviderAllTest ex
         @Nonnull
         @Override
         public PrivilegeBits supportedPrivileges(@Nullable Tree tree, 
@Nullable PrivilegeBits privilegeBits) {
-            return new 
PrivilegeBitsProvider(root).getBits(PrivilegeConstants.JCR_ALL);
+            return new PrivilegeBitsProvider(root).getBits(JCR_ALL);
         }
 
         //-----------------------------------< AggregatedPermissionProvider 
>---
@@ -166,7 +268,7 @@ public class CompositeProviderAllTest ex
         }
 
         @Override
-        public long supportedPermissions(@Nonnull TreePermission 
treePermission, long permissions) {
+        public long supportedPermissions(@Nonnull TreePermission 
treePermission, @Nullable PropertyState propertyState, long permissions) {
             return permissions;
         }
 

Added: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderCoverageTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderCoverageTest.java?rev=1708563&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderCoverageTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/composite/CompositeProviderCoverageTest.java
 Wed Oct 14 09:02:49 2015
@@ -0,0 +1,299 @@
+/*
+ * 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.security.Principal;
+import java.util.List;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.jcr.Session;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.api.JackrabbitSession;
+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.tree.TreeLocation;
+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.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.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test the {@link 
org.apache.jackrabbit.oak.security.authorization.composite.CompositePermissionProvider}
+ * where permissions are granted but not all permissions/privileges have been
+ * covered by the call. This might be the case when combining different
+ * providers that don't cover the full set of permissions/privileges.
+ *
+ * For simplicity the test only lists a single provider which only supports a
+ * limited set of permissions|privileges.
+ *
+ * The expected result is:
+ * - testing for the supported privileges|permissions must reveal that it is 
granted
+ * - any other combination of permissions|privileges must be denied.
+ */
+public class CompositeProviderCoverageTest extends 
AbstractCompositeProviderTest {
+
+    private CompositePermissionProvider cpp;
+
+    @Override
+    public void before() throws Exception {
+        super.before();
+
+        cpp = createPermissionProvider();
+    }
+
+    @Override
+    AggregatedPermissionProvider getTestPermissionProvider() {
+        return new LimitCoverageProvider();
+    }
+
+    @Override
+    List<AggregatedPermissionProvider> getAggregatedProviders(@Nonnull String 
workspaceName, @Nonnull AuthorizationConfiguration config, @Nonnull 
Set<Principal> principals) {
+        return ImmutableList.of(getTestPermissionProvider());
+    }
+
+    @Test
+    public void testGetPrivileges() throws Exception {
+        for (String p : NODE_PATHS) {
+            assertEquals(ImmutableSet.of(REP_READ_NODES), 
cpp.getPrivileges(root.getTree(p)));
+        }
+    }
+
+    @Test
+    public void testGetPrivilegesOnRepo() throws Exception {
+        assertEquals(ImmutableSet.of(JCR_NAMESPACE_MANAGEMENT), 
cpp.getPrivileges(null));
+    }
+
+    @Test
+    public void testHasPrivileges() throws Exception {
+        for (String p : NODE_PATHS) {
+            Tree tree = root.getTree(p);
+
+            assertTrue(cpp.hasPrivileges(tree, REP_READ_NODES));
+            assertFalse(cpp.hasPrivileges(tree, JCR_READ));
+            assertFalse(cpp.hasPrivileges(tree, JCR_WRITE));
+            assertFalse(cpp.hasPrivileges(tree, JCR_ALL));
+        }
+    }
+
+    @Test
+    public void testHasPrivilegesOnRepo() throws Exception {
+        assertTrue(cpp.hasPrivileges(null, JCR_NAMESPACE_MANAGEMENT));
+        assertFalse(cpp.hasPrivileges(null, 
JCR_NODE_TYPE_DEFINITION_MANAGEMENT));
+        assertFalse(cpp.hasPrivileges(null, JCR_ALL));
+    }
+
+
+    @Test
+    public void testIsGranted() throws Exception {
+        for (String p : NODE_PATHS) {
+            Tree tree = root.getTree(p);
+
+            assertTrue(cpp.isGranted(tree, null, Permissions.READ_NODE));
+            assertFalse(cpp.isGranted(tree, null, 
Permissions.LOCK_MANAGEMENT));
+            assertFalse(cpp.isGranted(tree, null, Permissions.ALL));
+            assertFalse(cpp.isGranted(tree, null, Permissions.READ_NODE | 
Permissions.LOCK_MANAGEMENT));
+        }
+    }
+
+    @Test
+    public void testIsGrantedProperty() throws Exception {
+        for (String p : NODE_PATHS) {
+            Tree tree = root.getTree(p);
+
+            assertTrue(cpp.isGranted(tree, PROPERTY_STATE, 
Permissions.READ_NODE));
+            assertFalse(cpp.isGranted(tree, PROPERTY_STATE, 
Permissions.READ_PROPERTY));
+            assertFalse(cpp.isGranted(tree, PROPERTY_STATE, 
Permissions.LOCK_MANAGEMENT));
+            assertFalse(cpp.isGranted(tree, PROPERTY_STATE, Permissions.ALL));
+            assertFalse(cpp.isGranted(tree, PROPERTY_STATE, 
Permissions.READ_NODE | Permissions.LOCK_MANAGEMENT));
+        }
+    }
+
+    @Test
+    public void testIsGrantedAction() throws Exception {
+        for (String nodePath : NODE_PATHS) {
+            String propPath = PathUtils.concat(nodePath, 
JcrConstants.JCR_PRIMARYTYPE);
+
+            assertTrue(cpp.isGranted(nodePath, Session.ACTION_READ));
+            assertFalse(cpp.isGranted(propPath, Session.ACTION_READ));
+
+            assertFalse(cpp.isGranted(nodePath, Session.ACTION_REMOVE));
+            assertFalse(cpp.isGranted(propPath, 
JackrabbitSession.ACTION_MODIFY_PROPERTY));
+
+            assertFalse(cpp.isGranted(nodePath, 
getActionString(JackrabbitSession.ACTION_MODIFY_ACCESS_CONTROL, 
JackrabbitSession.ACTION_READ_ACCESS_CONTROL)));
+
+            String nonExisting = PathUtils.concat(nodePath, "nonExisting");
+            assertFalse(cpp.isGranted(nonExisting, Session.ACTION_READ));
+            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();
+        assertTrue(rp.isGranted(Permissions.NAMESPACE_MANAGEMENT));
+        assertFalse(rp.isGranted(Permissions.NODE_TYPE_DEFINITION_MANAGEMENT));
+        assertFalse(rp.isGranted(Permissions.ALL));
+    }
+
+    @Test
+    public void testTreePermissionIsGranted() throws Exception {
+        TreePermission parentPermission = TreePermission.EMPTY;
+        for (String path : TP_PATHS) {
+            TreePermission tp = cpp.getTreePermission(root.getTree(path), 
parentPermission);
+
+            assertTrue(tp.isGranted(Permissions.READ_NODE));
+            assertFalse(tp.isGranted(Permissions.REMOVE_NODE));
+            assertFalse(tp.isGranted(Permissions.READ));
+            assertFalse(tp.isGranted(Permissions.ALL));
+
+            parentPermission = tp;
+        }
+    }
+
+    @Test
+    public void testTreePermissionIsGrantedProperty() throws Exception {
+        TreePermission parentPermission = TreePermission.EMPTY;
+
+        for (String path : TP_PATHS) {
+            TreePermission tp = cpp.getTreePermission(root.getTree(path), 
parentPermission);
+
+            assertFalse(tp.isGranted(Permissions.READ_PROPERTY, 
PROPERTY_STATE));
+            assertFalse(tp.isGranted(Permissions.REMOVE_PROPERTY, 
PROPERTY_STATE));
+            assertFalse(tp.isGranted(Permissions.READ, PROPERTY_STATE));
+            assertFalse(tp.isGranted(Permissions.ALL, PROPERTY_STATE));
+
+            parentPermission = tp;
+        }
+    }
+
+    @Test
+    public void testTreePermissionCanRead() throws Exception {
+        TreePermission parentPermission = TreePermission.EMPTY;
+
+        for (String path : TP_PATHS) {
+            Tree t = root.getTree(path);
+            TreePermission tp = cpp.getTreePermission(t, parentPermission);
+
+            assertTrue(tp.canRead());
+
+            parentPermission = tp;
+        }
+    }
+
+    @Test
+    public void testTreePermissionCanReadProperty() throws Exception {
+        TreePermission parentPermission = TreePermission.EMPTY;
+
+        for (String path : TP_PATHS) {
+            Tree t = root.getTree(path);
+            TreePermission tp = cpp.getTreePermission(t, parentPermission);
+            assertFalse(tp.canRead(PROPERTY_STATE));
+
+            parentPermission = tp;
+        }
+    }
+
+    private static final class LimitCoverageProvider implements 
AggregatedPermissionProvider {
+
+        @Nonnull
+        @Override
+        public PrivilegeBits supportedPrivileges(@Nullable Tree tree, 
@Nullable PrivilegeBits privilegeBits) {
+            PrivilegeBits supported = PrivilegeBits.getInstance(
+                    PrivilegeBits.BUILT_IN.get(JCR_NAMESPACE_MANAGEMENT),
+                    PrivilegeBits.BUILT_IN.get(REP_READ_NODES));
+            if (privilegeBits != null) {
+                return 
PrivilegeBits.getInstance(privilegeBits).retain(supported);
+            } else {
+                return supported;
+            }
+        }
+
+        @Override
+        public long supportedPermissions(@Nullable Tree tree, @Nullable 
PropertyState property, long permissions) {
+            if (tree == null) {
+                return permissions & Permissions.NAMESPACE_MANAGEMENT;
+            } else {
+                return permissions & Permissions.READ_NODE;
+            }
+        }
+
+        @Override
+        public long supportedPermissions(@Nonnull TreeLocation location, long 
permissions) {
+            return permissions & Permissions.READ_NODE;
+        }
+
+        @Override
+        public long supportedPermissions(@Nonnull TreePermission 
treePermission, @Nullable PropertyState propertyState, long permissions) {
+            return permissions & Permissions.READ_NODE;
+        }
+
+        @Override
+        public boolean isGranted(@Nonnull TreeLocation location, long 
permissions) {
+            return true;
+        }
+
+        @Override
+        public void refresh() {
+        }
+
+        @Nonnull
+        @Override
+        public Set<String> getPrivileges(@Nullable Tree tree) {
+            return (tree == null) ? ImmutableSet.of(JCR_NAMESPACE_MANAGEMENT) 
: ImmutableSet.of(REP_READ_NODES);
+        }
+
+        @Override
+        public boolean hasPrivileges(@Nullable Tree tree, @Nonnull String... 
privilegeNames) {
+            return true;
+        }
+
+        @Nonnull
+        @Override
+        public RepositoryPermission getRepositoryPermission() {
+            return RepositoryPermission.ALL;
+        }
+
+        @Nonnull
+        @Override
+        public TreePermission getTreePermission(@Nonnull Tree tree, @Nonnull 
TreePermission parentPermission) {
+            return TreePermission.ALL;
+        }
+
+        @Override
+        public boolean isGranted(@Nonnull Tree tree, @Nullable PropertyState 
property, long permissions) {
+            return true;
+        }
+
+        @Override
+        public boolean isGranted(@Nonnull String oakPath, @Nonnull String 
jcrActions) {
+            return true;
+        }
+    }
+}
\ No newline at end of file



Reply via email to