jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ang...@apache.org
Subject svn commit: r1092723 [1/2] - in /jackrabbit/trunk/jackrabbit-core/src: main/java/org/apache/jackrabbit/core/security/authorization/ main/java/org/apache/jackrabbit/core/security/authorization/acl/ main/java/org/apache/jackrabbit/core/security/authoriza...
Date Fri, 15 Apr 2011 14:34:46 GMT
Author: angela
Date: Fri Apr 15 14:34:45 2011
New Revision: 1092723

URL: http://svn.apache.org/viewvc?rev=1092723&view=rev
Log:
JCR-2887 : Split PrivilegeRegistry in a per-session manager instance and a repository level registry [work in progress]

Added:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeBits.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/PrivilegeBitsTest.java   (with props)
Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractCompiledPermissions.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeManagerImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeRegistry.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CompiledPermissionsImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLProvider.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplateTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEntryTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/CustomPrivilegeTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/JackrabbitAccessControlListTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/PrivilegeManagerImplTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/PrivilegeRegistryTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/TestAll.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplateTest.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java?rev=1092723&r1=1092722&r2=1092723&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java Fri Apr 15 14:34:45 2011
@@ -36,7 +36,6 @@ import org.apache.jackrabbit.core.securi
 import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
-import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
 
 /**
  * <code>AbstractAccessControlProvider</code>...
@@ -61,7 +60,7 @@ public abstract class AbstractAccessCont
      */
     protected SessionImpl session;
     protected ObservationManager observationMgr;
-    protected NamePathResolver resolver;
+    protected PrivilegeManagerImpl privilegeManager;
 
     private boolean initialized;
 
@@ -83,7 +82,7 @@ public abstract class AbstractAccessCont
      * @throws RepositoryException
      */
     protected PrivilegeManagerImpl getPrivilegeManagerImpl() throws RepositoryException {
-        return (PrivilegeManagerImpl) ((JackrabbitWorkspace) session.getWorkspace()).getPrivilegeManager();
+        return privilegeManager;
     }
 
     /**
@@ -105,7 +104,7 @@ public abstract class AbstractAccessCont
                 return true;
             }
             public int getPrivileges(Path absPath) throws RepositoryException {
-                return getPrivilegeManagerImpl().getBits(getAllPrivilege());
+                return PrivilegeRegistry.getBits(new Privilege[] {getAllPrivilege()});
             }
             public boolean hasPrivileges(Path absPath, Privilege... privileges) {
                 return true;
@@ -150,7 +149,7 @@ public abstract class AbstractAccessCont
                 if (isAcItem(absPath)) {
                     return PrivilegeRegistry.NO_PRIVILEGE;
                 } else {
-                    return getPrivilegeManagerImpl().getBits(getReadPrivilege());
+                    return PrivilegeRegistry.getBits(new Privilege[] {getReadPrivilege()});
                 }
             }
             public boolean hasPrivileges(Path absPath, Privilege... privileges) throws RepositoryException {
@@ -254,7 +253,7 @@ public abstract class AbstractAccessCont
         }
         session = (SessionImpl) systemSession;
         observationMgr = systemSession.getWorkspace().getObservationManager();
-        resolver = (NamePathResolver) systemSession;
+        privilegeManager = (PrivilegeManagerImpl) ((JackrabbitWorkspace) session.getWorkspace()).getPrivilegeManager();
 
         initialized = true;
     }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractCompiledPermissions.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractCompiledPermissions.java?rev=1092723&r1=1092722&r2=1092723&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractCompiledPermissions.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractCompiledPermissions.java Fri Apr 15 14:34:45 2011
@@ -20,10 +20,9 @@ import org.apache.commons.collections.ma
 import org.apache.jackrabbit.spi.Path;
 
 import javax.jcr.RepositoryException;
+import javax.jcr.security.AccessControlException;
 import javax.jcr.security.Privilege;
 import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
@@ -82,23 +81,6 @@ public abstract class AbstractCompiledPe
         }
     }
 
-    /**
-     * Adds the given <code>privileges</code> to the specified
-     * <code>target</code> set if they are not present in the specified
-     * <code>complement</code> set.
-     * 
-     * @param privileges
-     * @param target
-     * @param complement
-     */
-    protected static void updatePrivileges(Collection<Privilege> privileges, Set<Privilege> target, Set<Privilege> complement) {
-        for (Privilege p : privileges) {
-            if (!complement.contains(p)) {
-                target.add(p);
-            }
-        }
-    }
-
     //------------------------------------------------< CompiledPermissions >---
     /**
      * @see CompiledPermissions#close()
@@ -118,7 +100,8 @@ public abstract class AbstractCompiledPe
      * @see CompiledPermissions#getPrivileges(Path)
      */
     public int getPrivileges(Path absPath) throws RepositoryException {
-        return getResult(absPath).getPrivileges();
+        Set<Privilege> pvs = getPrivilegeSet(absPath);
+        return PrivilegeRegistry.getBits(pvs.toArray(new Privilege[pvs.size()]));
     }
 
     /**
@@ -126,32 +109,9 @@ public abstract class AbstractCompiledPe
      */
     public boolean hasPrivileges(Path absPath, Privilege... privileges) throws RepositoryException {
         Result result = getResult(absPath);
-        int builtin = getPrivilegeManagerImpl().getBits(privileges);
 
-        if ((result.allowPrivileges | ~builtin) == -1) {
-            // in addition check all custom privileges
-            for (Privilege p : privileges) {
-                if (getPrivilegeManagerImpl().isCustomPrivilege(p)) {
-                    if (!result.customAllow.contains(p)) {
-                        if (p.isAggregate()) {
-                            // test if aggregated privs were granted individually.
-                            for (Privilege aggr : p.getAggregatePrivileges()) {
-                                if (!aggr.isAggregate() && !result.customAllow.contains(aggr)) {
-                                    // an aggregated custom priv is not allowed -> return false
-                                    return false;
-                                }
-                            }
-                        } else {
-                            // simple custom allow not allowed -> return false
-                            return false;
-                        }
-                    } // else: custom privilege allowed -> continue.
-                } // else: not a custom priv -> already covered.
-            }
-            return true;
-        } else {
-            return false;
-        }
+        PrivilegeBits bits = getPrivilegeManagerImpl().getBits(privileges);
+        return result.allowPrivileges.includes(bits);
     }
 
     /**
@@ -159,10 +119,7 @@ public abstract class AbstractCompiledPe
      */
     public Set<Privilege> getPrivilegeSet(Path absPath) throws RepositoryException {
         Result result = getResult(absPath);
-        Set<Privilege> privileges = new HashSet<Privilege>();
-        privileges.addAll(getPrivilegeManagerImpl().getPrivileges(result.getPrivileges()));
-        privileges.addAll(result.customAllow);
-        return privileges;
+        return getPrivilegeManagerImpl().getPrivileges(result.allowPrivileges);
     }
 
     /**
@@ -178,55 +135,54 @@ public abstract class AbstractCompiledPe
      */
     public static class Result {
 
-        public static final Result EMPTY = new Result(Permission.NONE, Permission.NONE, PrivilegeRegistry.NO_PRIVILEGE, PrivilegeRegistry.NO_PRIVILEGE);
+        public static final Result EMPTY = new Result(Permission.NONE, Permission.NONE, PrivilegeBits.EMPTY, PrivilegeBits.EMPTY);
 
         private final int allows;
         private final int denies;
-        private final int allowPrivileges;
-        private final int denyPrivileges;
-
-        private final Set<Privilege> customAllow;
-        private final Set<Privilege> customDeny;
+        private final PrivilegeBits allowPrivileges;
+        private final PrivilegeBits denyPrivileges;
 
         private int hashCode = -1;
 
+        /**
+         * @deprecated
+         */
         public Result(int allows, int denies, int allowPrivileges, int denyPrivileges) {
-            this(allows, denies, allowPrivileges, denyPrivileges, Collections.<Privilege>emptySet(), Collections.<Privilege>emptySet());
+            this(allows, denies, PrivilegeBits.getInstance(allowPrivileges), PrivilegeBits.getInstance(denyPrivileges));
         }
 
-        public Result(int allows, int denies, int allowPrivileges, int denyPrivileges,
-                      Set<Privilege> customAllow, Set<Privilege> customDeny) {
+        public Result(int allows, int denies, PrivilegeBits allowPrivileges, PrivilegeBits denyPrivileges) {
             this.allows = allows;
             this.denies = denies;
             this.allowPrivileges = allowPrivileges;
             this.denyPrivileges = denyPrivileges;
-
-            this.customAllow = customAllow;
-            this.customDeny = customDeny;
         }
 
         public boolean grants(int permissions) {
             return (this.allows | ~permissions) == -1;
         }
 
+        /**
+         * @deprecated jackrabbit 2.3 (throws UnsupportedOperationException, use getPrivilegeBits instead)
+         */
         public int getPrivileges() {
+            throw new UnsupportedOperationException("use #getPrivilegeBits instead.");
+        }
+
+        public PrivilegeBits getPrivilegeBits() {
             return allowPrivileges;
         }
 
         public Result combine(Result other) {
             int cAllows =  allows | Permission.diff(other.allows, denies);
             int cDenies = denies | Permission.diff(other.denies, allows);
-            int cAPrivs = allowPrivileges | Permission.diff(other.allowPrivileges, denyPrivileges);
-            int cDPrivs = denyPrivileges | Permission.diff(other.denyPrivileges, allowPrivileges);
 
-            Set<Privilege> combinedAllow = new HashSet<Privilege>();
-            combinedAllow.addAll(customAllow);
-            updatePrivileges(other.customAllow, combinedAllow, customDeny);
-
-            Set<Privilege> combinedDeny = new HashSet<Privilege>();
-            combinedDeny.addAll(customDeny);
-            updatePrivileges(other.customDeny, combinedDeny, customAllow);
-            return new Result(cAllows, cDenies, cAPrivs, cDPrivs, customAllow, customDeny);
+            PrivilegeBits cAPrivs = PrivilegeBits.getInstance(allowPrivileges);
+            cAPrivs.addDifference(other.allowPrivileges, denyPrivileges);
+            PrivilegeBits cdPrivs = PrivilegeBits.getInstance(denyPrivileges);
+            cdPrivs.addDifference(other.denyPrivileges, allowPrivileges);
+
+            return new Result(cAllows, cDenies, allowPrivileges, denyPrivileges);
         }
 
         /**
@@ -238,10 +194,8 @@ public abstract class AbstractCompiledPe
                 int h = 17;
                 h = 37 * h + allows;
                 h = 37 * h + denies;
-                h = 37 * h + allowPrivileges;
-                h = 37 * h + denyPrivileges;
-                h = 37 * h + customAllow.hashCode();
-                h = 37 * h + customDeny.hashCode();
+                h = 37 * h + allowPrivileges.hashCode();
+                h = 37 * h + denyPrivileges.hashCode();
                 hashCode = h;
             }
             return hashCode;
@@ -259,10 +213,8 @@ public abstract class AbstractCompiledPe
                 Result other = (Result) object;
                 return allows == other.allows &&
                        denies == other.denies &&
-                       allowPrivileges == other.allowPrivileges &&
-                       denyPrivileges == other.denyPrivileges &&
-                       customAllow.equals(other.customAllow) &&
-                       customDeny.equals(other.customDeny);
+                       allowPrivileges.equals(other.allowPrivileges) &&
+                       denyPrivileges.equals(other.denyPrivileges);
             }
             return false;
         }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryImpl.java?rev=1092723&r1=1092722&r2=1092723&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryImpl.java Fri Apr 15 14:34:45 2011
@@ -49,7 +49,7 @@ public abstract class AccessControlEntry
     /**
      * PrivilegeBits calculated from built-in privileges
      */
-    private final int privilegeBits;
+    private final PrivilegeBits privilegeBits;
 
     /**
      * the Principal of this entry
@@ -74,12 +74,6 @@ public abstract class AccessControlEntry
     private int hashCode = -1;
 
     /**
-     * Calculated set of non-aggregate custom privileges (see also privilegeBits
-     * above for the built-in privileges) used upon ac evaluation.
-     */
-    private Set<Privilege> customPrivs;
-
-    /**
      * Construct an access control entry for the given principal and privileges.
      *
      * @param principal Principal for this access control entry.
@@ -157,40 +151,11 @@ public abstract class AccessControlEntry
     /**
      * @return the permission bits that correspond to the privileges defined by this entry.
      */
-    public int getPrivilegeBits() {
+    public PrivilegeBits getPrivilegeBits() {
         return privilegeBits;
     }
 
     /**
-     * @return A collection of all non-aggregate custom privileges defined by
-     * this entry including those contained in the aggregated custom privileges.
-     */
-    public Set<Privilege> getCustomPrivileges() {
-        if (customPrivs == null) {
-            customPrivs = new HashSet<Privilege>();
-            for (Privilege p : privileges) {
-                try {
-                    if (getPrivilegeManager().isCustomPrivilege(p)) {
-                        if (p.isAggregate()) {
-                            for (Privilege aggr : p.getAggregatePrivileges()) {
-                                if (!aggr.isAggregate()) {
-                                    customPrivs.add(p);
-                                }
-                            }
-                        } else {
-                            customPrivs.add(p);
-
-                        }
-                    }
-                } catch (AccessControlException e) {
-                    // ignore.
-                }
-            }
-        }
-        return customPrivs;
-    }
-
-    /**
      * Returns <code>true</code> if this ACE defines any restriction.
      *
      * @return <code>true</code> if this ACE defines any restriction;
@@ -315,17 +280,10 @@ public abstract class AccessControlEntry
         if (obj instanceof AccessControlEntryImpl) {
             AccessControlEntryImpl other = (AccessControlEntryImpl) obj;
             return principal.getName().equals(other.principal.getName()) &&
-                   privilegeBits == other.privilegeBits &&
+                   privilegeBits.equals(other.privilegeBits) &&
                    allow == other.allow &&
-                   restrictions.equals(other.restrictions) &&
-                   equalCustomPrivileges(other);
+                   restrictions.equals(other.restrictions);
         }
         return false;
     }
-
-    private boolean equalCustomPrivileges(AccessControlEntryImpl other) {
-        Set<Privilege> a1 = getCustomPrivileges();
-        Set<Privilege> a2 = other.getCustomPrivileges();
-        return a1.size() == a2.size() && a1.containsAll(a2);
-    }
 }
\ No newline at end of file

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeBits.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeBits.java?rev=1092723&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeBits.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeBits.java Fri Apr 15 14:34:45 2011
@@ -0,0 +1,555 @@
+/*
+ * 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.core.security.authorization;
+
+import java.math.BigInteger;
+
+/**
+ * <code>PrivilegeBits</code> 
+ */
+public class PrivilegeBits {
+
+    public static final PrivilegeBits EMPTY = new PrivilegeBits(SimpleData.EMPTY);
+
+    private static final long READ = 1; // PrivilegeRegistry.READ
+
+    private final Data d;
+
+    /**
+     * Private constructor.
+     *
+     * @param d
+     */
+    private PrivilegeBits(Data d) {
+        this.d = d;
+    }
+
+    /**
+     * Package private method used by <code>PrivilegeRegistry</code> to handle
+     * built-in privileges and calculate internal permissions.
+     * 
+     * @return long representation of this instance.
+     * @see PrivilegeRegistry#calculatePermissions(PrivilegeBits, PrivilegeBits, boolean, boolean)
+     */
+    long longValue() {
+        return d.longValue();
+    }
+
+    /**
+     * Package private method used by <code>PrivilegeRegistry</code> to calculate
+     * the privilege bits associated with a given built-in or custom privilege
+     * definition.
+     *
+     * @return an instance of <code>PrivilegeBits</code>
+     */
+    PrivilegeBits nextBits() {
+        if (this == EMPTY) {
+            return EMPTY;
+        } else {
+            return new PrivilegeBits(d.next());
+        }
+    }
+        
+    /**
+     * Returns an unmodifiable instance.
+     *
+     * @return an unmodifiable <code>PrivilegeBits</code> instance.
+     */
+    PrivilegeBits unmodifiable() {
+        if (d instanceof ModifiableData) {
+            return (d.isSimple()) ? getInstance(d.longValue()) : new PrivilegeBits(new BigIntegerData(d.getBigInteger()));
+        } else {
+            return this;
+        }
+    }
+
+    /**
+     * Package private method used by <code>PrivilegeRegistry</code> to create
+     * an instance of privilege bits for the specified long value.
+     *
+     * @param bits
+     * @return an instance of <code>PrivilegeBits</code>
+     */
+    static PrivilegeBits getInstance(long bits) {
+        if (bits == PrivilegeRegistry.NO_PRIVILEGE) {
+            return EMPTY;
+        } else if (bits < PrivilegeRegistry.NO_PRIVILEGE) {
+            throw new IllegalArgumentException();
+        } else {
+            return new PrivilegeBits(new SimpleData(bits));
+        }
+    }
+
+    /**
+     * Creates a mutable instance of privilege bits.
+     *
+     * @return a new instance of privilege bits.
+     */
+    public static PrivilegeBits getInstance() {
+        return new PrivilegeBits(new ModifiableData());
+    }
+
+    /**
+     * Creates a mutable instance of privilege bits.
+     *
+     * @param base
+     * @return a new instance of privilege bits.
+     */
+    public static PrivilegeBits getInstance(PrivilegeBits base) {
+        return new PrivilegeBits(new ModifiableData(base.d));
+    }
+
+    /**
+     * Returns <code>true</code> if this privilege bits includes no privileges
+     * at all.
+     *
+     * @return <code>true</code> if this privilege bits includes no privileges
+     * at all; <code>false</code> otherwise.
+     * @see PrivilegeRegistry#NO_PRIVILEGE
+     */
+    public boolean isEmpty() {
+        return d.isEmpty();
+    }
+
+    /**
+     * Returns <code>true</code> if this instance includes the jcr:read
+     * privilege. Shortcut for calling {@link PrivilegeBits#includes(PrivilegeBits)}
+     * where the other bits represented the jcr:read privilege.
+     *
+     * @return <code>true</code> if this instance includes the jcr:read
+     * privilege; <code>false</code> otherwise.
+     */
+    public boolean includesRead() {
+        if (this == EMPTY) {
+            return false;
+        } else if (d.isSimple()) {
+            return (d.longValue() & READ) == READ;
+        } else {
+            return d.getBigInteger().testBit(0);
+        }
+    }
+
+    /**
+     * Returns <code>true</code> if all privileges defined by the specified
+     * <code>otherBits</code> are present in this instance.
+     *
+     * @param otherBits
+     * @return <code>true</code> if all privileges defined by the specified
+     * <code>otherBits</code> are included in this instance; <code>false</code>
+     * otherwise.
+     */
+    public boolean includes(PrivilegeBits otherBits) {
+        return d.includes(otherBits.d);
+    }
+
+    /**
+     * Adds the other privilege bits to this instance.
+     *
+     * @param other The other privilege bits to be added.
+     * @throws UnsupportedOperationException if this instance is immutable.
+     */
+    public void add(PrivilegeBits other) {
+        if (d instanceof ModifiableData) {
+            ((ModifiableData) d).add(other.d);
+        } else {
+            throw new UnsupportedOperationException("immutable privilege bits");
+        }
+    }
+
+    /**
+     * Subtracts the other PrivilegeBits from the this.<br>
+     * If the specified bits do not intersect with this, it isn't modified.<br>
+     * If <code>this</code> is included in <code>other</code> {@link #EMPTY empty}
+     * privilege bits is returned.
+     *
+     * @param other The other privilege bits to be substracted from this instance.
+     * @throws UnsupportedOperationException if this instance is immutable.
+     */
+    public void diff(PrivilegeBits other) {
+        if (d instanceof ModifiableData) {
+            ((ModifiableData) d).diff(other.d);
+        } else {
+            throw new UnsupportedOperationException("immutable privilege bits");
+        }
+    }
+
+    /**
+     * Subtracts the <code>b</code> from <code>a</code> and adds the result (diff)
+     * to this instance.
+     *
+     * @param a An instance of privilege bits.
+     * @param b An instance of privilege bits.
+     * @throws UnsupportedOperationException if this instance is immutable.
+     */
+    public void addDifference(PrivilegeBits a, PrivilegeBits b) {
+        if (d instanceof ModifiableData) {
+            ((ModifiableData) d).addDifference(a.d, b.d);
+        } else {
+            throw new UnsupportedOperationException("immutable privilege bits");
+        }
+    }
+
+    //-------------------------------------------------------------< Object >---
+    @Override
+    public int hashCode() {
+        return d.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        } else if (o instanceof PrivilegeBits) {
+            return d.equals(((PrivilegeBits) o).d);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("PrivilegeBits: ");
+        if (d.isSimple()) {
+            sb.append(d.longValue());
+        } else {
+            sb.append(d.getBigInteger().toString());
+        }
+        return sb.toString();
+    }
+
+    //------------------------------------------------------< inner classes >---
+    /**
+     * Base class for the internal privilege bits representation and handling.
+     */
+    private static abstract class Data {
+
+        private static final BigInteger MINUS_ONE = BigInteger.valueOf(-1);
+
+        abstract boolean isEmpty();
+        
+        abstract long longValue();
+
+        /**
+         * TODO: FIXME (see also BigIntegerData)
+         */
+        abstract BigInteger getBigInteger();
+
+        abstract boolean isSimple();
+
+        abstract Data next();
+
+        abstract boolean includes(Data other);
+
+        static boolean includes(long bits, long otherBits) {
+            return (bits | ~otherBits) == -1;
+        }
+
+        static boolean includes(BigInteger bits, BigInteger otherBits) {
+            if (bits.equals(otherBits)) {
+                return true;
+            } else {
+                return MINUS_ONE.equals(bits.or(otherBits.not()));
+            }
+        }
+    }
+
+    /**
+     * Unmodifiable instance of the Data base class.
+     */
+    private static class SimpleData extends Data {
+
+        private static final long MAX = Long.MAX_VALUE / 2;
+        private static final SimpleData EMPTY = new SimpleData(PrivilegeRegistry.NO_PRIVILEGE);
+
+        private final long bits;
+
+        private SimpleData(long bits) {
+            this.bits = bits;
+        }
+
+        @Override
+        boolean isEmpty() {
+            return this == EMPTY;
+        }
+
+        @Override
+        long longValue() {
+            return bits;
+        }
+
+        @Override
+        BigInteger getBigInteger() {
+            return (isEmpty()) ? BigInteger.ZERO : BigInteger.valueOf(bits);
+        }
+
+        @Override
+        boolean isSimple() {
+            return true;
+        }
+
+        @Override
+        Data next() {
+            if (this == EMPTY) {
+                return EMPTY;
+            } else if (bits < MAX) {
+                long b = bits << 1;
+                return new SimpleData(b);
+            } else {
+                return new BigIntegerData(BigInteger.valueOf(bits)).next();
+            }
+        }
+
+        @Override
+        boolean includes(Data other) {
+            if (other.isSimple()) {
+                return includes(bits, other.longValue());
+            } else {
+                return false;
+            }
+        }
+
+        //---------------------------------------------------------< Object >---
+        @Override
+        public int hashCode() {
+            return new Long(bits).hashCode();
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o == this) {
+                return true;
+            } else if (o instanceof Data) {
+                Data d = (Data) o;
+                return d.isSimple() && bits == d.longValue(); 
+            } else {
+                return false;
+            }
+        }
+    }
+
+    /**
+     * Unmodifiable instance of the Data base class.
+     * TODO: FIXME replace with performing impl without biginteger
+     */
+    private static class BigIntegerData extends Data {
+
+        private static final long ZERO = 0;
+        private final BigInteger bits;
+
+        private BigIntegerData(BigInteger bits) {
+            this.bits = bits;
+        }
+
+        @Override
+        boolean isEmpty() {
+            return false;
+        }
+
+        @Override
+        long longValue() {
+            return ZERO;
+        }
+
+        @Override
+        BigInteger getBigInteger() {
+            return bits;
+        }
+
+        @Override
+        Data next() {
+            return new BigIntegerData(bits.shiftLeft(1));
+        }
+
+        @Override
+        boolean includes(Data other) {
+            return includes(bits, other.getBigInteger());
+        }
+
+        @Override
+        boolean isSimple() {
+            return false;
+        }
+
+        //---------------------------------------------------------< Object >---
+        @Override
+        public int hashCode() {
+            return bits.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o == this) {
+                return true;
+            } else if (o instanceof Data) {
+                Data d = (Data) o;
+                return !d.isSimple() && bits.equals(d.getBigInteger());
+            } else {
+                return false;
+            }
+        }
+    }
+
+    /**
+     * Mutable implementation of the Data base class.
+     */
+    private static class ModifiableData extends Data {
+
+        private long l;
+        private BigInteger bi;
+
+        private ModifiableData() {
+            l = PrivilegeRegistry.NO_PRIVILEGE;
+        }
+        
+        private ModifiableData(Data base) {
+            if (base instanceof SimpleData) {
+                l = ((SimpleData) base).bits;
+            } else if (base instanceof BigIntegerData) {
+                bi = ((BigIntegerData) base).bits;
+            } else {
+                ModifiableData b = (ModifiableData) base;
+                l = b.l;
+                bi = b.bi;
+            }
+        }
+
+        private void reset() {
+            l = PrivilegeRegistry.NO_PRIVILEGE;
+            bi = null;
+        }
+
+        private void writeBackResult(BigInteger result) {
+            if (BigInteger.ZERO.equals(result)) {
+                reset();
+            } else {
+                long dl = result.longValue();
+                if (dl > 0) {
+                    l = dl;
+                    bi = null;
+                } else {
+                    bi = result;
+                }
+            }
+        }
+
+        @Override
+        boolean isEmpty() {
+            return l == PrivilegeRegistry.NO_PRIVILEGE && bi == null;
+        }
+
+        @Override
+        long longValue() {
+            return (bi == null) ? l : BigIntegerData.ZERO;
+        }
+
+        @Override
+        BigInteger getBigInteger() {
+            return (bi == null) ? BigInteger.valueOf(l) : bi;
+        }
+
+        @Override
+        boolean isSimple() {
+            return bi == null;
+        }
+
+        @Override
+        Data next() {
+            throw new UnsupportedOperationException("Not implemented.");
+        }
+
+        @Override
+        boolean includes(Data other) {
+            if (bi == null) {
+                return (other.isSimple()) ? includes(l, other.longValue()) : false;
+            } else {
+                return this.equals(other) ? true : includes(bi, other.getBigInteger());
+            }
+        }
+               
+        public void add(Data other) {
+            if (other != this) {
+                if (bi == null && other.isSimple()) {
+                    l |= other.longValue();
+                } else {
+                    if (!this.equals(other)) {
+                        bi = getBigInteger().or(other.getBigInteger());
+                    } // else: equals -> nothing to do.
+                }
+            }
+        }
+
+        private void diff(Data other) {
+            if (bi == null && other.isSimple()) {
+                l = l & ~other.longValue();
+            } else {
+                if (this.equals(other)) {
+                    reset();
+                } else {
+                    BigInteger big = getBigInteger();
+                    BigInteger diff = big.andNot(other.getBigInteger());
+                    if (!big.equals(diff)) {
+                        writeBackResult(diff);
+                    } // else: no change
+                }
+            }
+        }
+
+        private void addDifference(Data a, Data b) {
+            BigInteger diff = null;
+            long diffL = 0;
+            
+            if (a.isSimple() && b.isSimple()) {
+                diffL = a.longValue() & ~b.longValue();
+                if (bi != null) {
+                    diff = BigInteger.valueOf(diffL);
+                }
+            } else {
+                diff = a.getBigInteger().andNot(b.getBigInteger());
+            }
+
+            if (diff != null) {
+                BigInteger big = getBigInteger();
+                BigInteger res = big.or(diff);
+                if (!big.equals(res)) {
+                    writeBackResult(res);
+                } // else: no change
+            } else {
+                l |= diffL;
+            }
+        }
+
+        //---------------------------------------------------------< Object >---       
+        @Override
+        public int hashCode() {
+            // NOTE: mutable object. hashcode not implemented.
+            return 0;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o == this) {
+                return true;
+            } else if (o instanceof Data) {
+                Data other = (Data) o;
+                if (isSimple() == other.isSimple()) {
+                    return (isSimple()) ? l == other.longValue() : bi.equals(other.getBigInteger());
+                }
+            }
+            return false;
+        }
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeBits.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeBits.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeManagerImpl.java?rev=1092723&r1=1092722&r2=1092723&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeManagerImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeManagerImpl.java Fri Apr 15 14:34:45 2011
@@ -112,7 +112,7 @@ public final class PrivilegeManagerImpl 
      * <li>the namespace URI must be a valid, registered namespace excluding
      * those namespaces marked as being reserved</li>
      * <li>an aggregate custom privilege is valid if all declared aggregate
-     * names can be resolved to registered custom privileges and if there exists
+     * names can be resolved to registered privileges and if there exists
      * no registered privilege with the same aggregated privileges.</li>
      * </ul>
      *
@@ -162,46 +162,26 @@ public final class PrivilegeManagerImpl 
 
     //-----------------------------< implementation specific public methods >---       
     /**
-     * Returns <code>true</code> if the specified privilege is a custom
-     * privilege that has been
-     * {@link #registerPrivilege(String, boolean, String[]) registered} before.
-     *
-     * @param privilege
-     * @return <code>true</code> if the specified privilege is a custom
-     * privilege; <code>false</code> otherwise.
-     * @throws AccessControlException If the specified privilege is
-     * <code>null</code> or unknown to this manager.
-     */
-    public boolean isCustomPrivilege(Privilege privilege) throws AccessControlException {
-        if (privilege instanceof PrivilegeImpl) {
-            return ((PrivilegeImpl) privilege).definition.isCustom();
-        } else {
-            throw new AccessControlException("Invalid privilege instance.");
-        }
-    }
-
-    /**
      * @param privileges An array of privileges.
-     * @return The bits of the built-in privileges contained in the specified
+     * @return The bits of the privileges contained in the specified
      * array.
      * @throws AccessControlException If the specified array is null, empty
      * or if it contains an unregistered privilege.
      */
-    public int getBits(Privilege... privileges) throws AccessControlException {
+    public PrivilegeBits getBits(Privilege... privileges) throws AccessControlException {
         if (privileges == null || privileges.length == 0) {
             throw new AccessControlException("Privilege array is empty or null.");
         }
-        PrivilegeRegistry.Definition[] defs = new PrivilegeRegistry.Definition[privileges.length];
-        for (int i = 0; i < privileges.length; i++) {
-            Privilege priv = privileges[i];
+        PrivilegeBits bits = PrivilegeBits.getInstance();
+        for (Privilege priv : privileges) {
             if (priv instanceof PrivilegeImpl) {
-                defs[i] = ((PrivilegeImpl) priv).definition;
+                bits.add(((PrivilegeImpl) priv).definition.getBits());
             } else {
                 String name = (priv == null) ? "null" : priv.getName();
                 throw new AccessControlException("Unknown privilege '" + name + "'.");
             }
         }
-        return registry.getBits(defs);
+        return bits;
     }
 
     /**
@@ -218,7 +198,7 @@ public final class PrivilegeManagerImpl 
      * resolved to registered <code>Privilege</code>s.
      * @see #getBits(Privilege...)
      */
-    public Set<Privilege> getPrivileges(int bits) {
+    public Set<Privilege> getPrivileges(PrivilegeBits bits) {
         Name[] names = registry.getNames(bits);
         if (names.length == 0) {
             return Collections.emptySet();

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeRegistry.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeRegistry.java?rev=1092723&r1=1092722&r2=1092723&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeRegistry.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeRegistry.java Fri Apr 15 14:34:45 2011
@@ -29,7 +29,6 @@ import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.NameFactory;
 import org.apache.jackrabbit.spi.commons.conversion.DefaultNamePathResolver;
 import org.apache.jackrabbit.spi.commons.conversion.NameResolver;
-import org.apache.jackrabbit.spi.commons.iterator.Iterators;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
 import org.apache.jackrabbit.util.Text;
@@ -72,12 +71,7 @@ public final class PrivilegeRegistry {
     public static final Name REP_WRITE_NAME = NAME_FACTORY.create(REP_WRITE);
 
     /**
-     * A custom privilege for which bits were not calculated
-     */
-    private static final int UNDEFINED = -1;
-
-    /**
-     * No privileges 
+     * No privileges
      */
     public static final int NO_PRIVILEGE = 0;
 
@@ -118,7 +112,7 @@ public final class PrivilegeRegistry {
 
     
     private final Map<Name, Definition> registeredPrivileges = new HashMap<Name, Definition>();
-    private final Map<Integer, Set<Name>> bitsToNames = new HashMap<Integer, Set<Name>>();
+    private final Map<PrivilegeBits, Set<Name>> bitsToNames = new HashMap<PrivilegeBits, Set<Name>>();
 
     @SuppressWarnings("unchecked")    
     private final Map<Listener, Listener> listeners = Collections.synchronizedMap(new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.WEAK));
@@ -128,6 +122,8 @@ public final class PrivilegeRegistry {
 
     private final NameResolver resolver;
 
+    private PrivilegeBits nextBits = PrivilegeBits.getInstance(RETENTION_MNGMT).nextBits();
+
     public PrivilegeRegistry(NamespaceRegistry namespaceRegistry, FileSystem fs)
             throws RepositoryException {
 
@@ -197,17 +193,17 @@ public final class PrivilegeRegistry {
 
     /**
      * Creates a new <code>PrivilegeManager</code> from the specified resolver
-     * and calls {@link PrivilegeManagerImpl#getPrivileges(int)}.
+     * and calls {@link PrivilegeManagerImpl#getPrivileges(PrivilegeBits)}.
      *
      * @param bits Privilege bits as obtained from {@link #getBits(Privilege[])}.
      * @return Array of <code>Privilege</code>s that are presented by the given it
      * or an empty array if <code>bits</code> is lower than {@link #READ} or
      * cannot be resolved to registered <code>Privilege</code>s.
      * @see #getBits(Privilege[])
-     * @deprecated Use {@link PrivilegeManagerImpl#getPrivileges(int)} instead.
+     * @deprecated Use {@link PrivilegeManagerImpl#getPrivileges(PrivilegeBits)} instead.
      */
     public Privilege[] getPrivileges(int bits) {
-        Set<Privilege> prvs = new PrivilegeManagerImpl(this, resolver).getPrivileges(bits);
+        Set<Privilege> prvs = new PrivilegeManagerImpl(this, resolver).getPrivileges(PrivilegeBits.getInstance(bits));
         return prvs.toArray(new Privilege[prvs.size()]);
     }
 
@@ -239,10 +235,10 @@ public final class PrivilegeRegistry {
                 if (PRIVILEGE_NAMES.containsKey(n)) {
                     bits |= PRIVILEGE_NAMES.get(n);
                 } else if (NameConstants.JCR_WRITE.equals(n)) {
-                    bits |= createJcrWriteDefinition().bits;
+                    bits |= createJcrWriteDefinition().bits.longValue();
                 } else if (REP_WRITE_NAME.equals(n)) {
                     Definition jcrWrite = createJcrWriteDefinition();
-                    bits |= createRepWriteDefinition(jcrWrite.bits).bits;
+                    bits |= createRepWriteDefinition(jcrWrite).bits.longValue();
                 } else if (NameConstants.JCR_ALL.equals(n)) {
                     for (Name pn : PRIVILEGE_NAMES.keySet()) {
                         bits |= PRIVILEGE_NAMES.get(pn);
@@ -273,7 +269,32 @@ public final class PrivilegeRegistry {
      * defines access control related information.
      * @return the permissions granted evaluating the given privileges.
      */
+    public static int calculatePermissions(PrivilegeBits privs, PrivilegeBits parentPrivs, boolean isAllow, boolean protectsPolicy) {
+        return calculatePermissions(privs.longValue(), parentPrivs.longValue(), isAllow, protectsPolicy);
+    }
+
+    /**
+     * Build the permissions granted by evaluating the given privileges. Note,
+     * that only built-in privileges can be mapped to permissions. Any other
+     * privileges will be ignored.
+     *
+     * @param privs The privileges granted on the Node itself (for properties
+     * the ACL of the direct ancestor).
+     * @param parentPrivs The privileges granted on the parent of the Node. Not
+     * relevant for properties since it only is used to determine permissions
+     * on a Node (add_child_nodes, remove_child_nodes).
+     * @param isAllow <code>true</code> if the privileges are granted; <code>false</code>
+     * otherwise.
+     * @param protectsPolicy If <code>true</code> the affected item itself
+     * defines access control related information.
+     * @return the permissions granted evaluating the given privileges.
+     * @deprecated Use {@link #calculatePermissions(PrivilegeBits, PrivilegeBits, boolean, boolean)} instead.
+     */
     public static int calculatePermissions(int privs, int parentPrivs, boolean isAllow, boolean protectsPolicy) {
+        return calculatePermissions((long) privs, (long) parentPrivs, isAllow, protectsPolicy);
+    }
+
+    private static int calculatePermissions(long privs, long parentPrivs, boolean isAllow, boolean protectsPolicy) {
         int perm = Permission.NONE;
         if (protectsPolicy) {
             if ((parentPrivs & READ_AC) == READ_AC) {
@@ -420,44 +441,29 @@ public final class PrivilegeRegistry {
     }
 
     /**
-     * Calculates the bits of the specified definitions. Note, that custom
-     * privileges don't have a integer representation as they are not used
-     * for permission calculation.
-     *
-     * @param defs
-     * @return
-     */
-    int getBits(Definition[] defs) {
-        int bits = NO_PRIVILEGE;
-        for (Definition def : defs) {
-            bits |= def.bits;
-        }
-        return bits;
-    }
-
-    /**
      * Returns the names of the privileges identified by the specified bits.
      * Note, that custom privileges don't have a integer representation as they
      * are not used for permission calculation.
      * 
-     * @param bits The privilege bits.
+     * @param privilegeBits The privilege bits.
      * @return Privilege names that corresponds to the given bits.
      */
-    Name[] getNames(int bits) {
-        if (bits <= NO_PRIVILEGE) {
+    Name[] getNames(PrivilegeBits privilegeBits) {
+        if (privilegeBits == null || privilegeBits.isEmpty()) {
             return Name.EMPTY_ARRAY;
-        } else if (bitsToNames.containsKey(bits)) {
+        } else if (bitsToNames.containsKey(privilegeBits)) {
             // matches all built-in aggregates and single built-in privileges
-            Set<Name> ips = bitsToNames.get(bits);
+            Set<Name> ips = bitsToNames.get(privilegeBits);
             return ips.toArray(new Name[ips.size()]);
         } else {
             // bits are a combination of built-in privileges.
             Set<Name> names = new HashSet<Name>();
+            long bits = privilegeBits.longValue();
             if ((bits & READ) == READ) {
                 names.add(NameConstants.JCR_READ);
             }
-            int repWrite = registeredPrivileges.get(REP_WRITE_NAME).bits;
-            int jcrWrite = registeredPrivileges.get(NameConstants.JCR_WRITE).bits;
+            long repWrite = registeredPrivileges.get(REP_WRITE_NAME).bits.longValue();
+            long jcrWrite = registeredPrivileges.get(NameConstants.JCR_WRITE).bits.longValue();
             if ((bits & repWrite) == repWrite) {
                 names.add(REP_WRITE_NAME);
             } else if ((bits & jcrWrite) == jcrWrite) {
@@ -498,8 +504,26 @@ public final class PrivilegeRegistry {
                 names.add(NameConstants.JCR_RETENTION_MANAGEMENT);
             }
 
+            // include matching custom privilege names
+            Set<Name> customNames = new HashSet<Name>();
+            Set<Definition> aggr = new HashSet<Definition>();
+            for (Definition def : registeredPrivileges.values()) {
+                if (def.isCustom && privilegeBits.includes(def.bits)) {
+                    customNames.add(def.name);
+                    if (!def.declaredAggregateNames.isEmpty()) {
+                        aggr.add(def);
+                    }
+                }
+            }
+            // avoid redundant entries in case of aggregate privileges.
+            for (Definition aggregate : aggr) {
+                customNames.removeAll(aggregate.declaredAggregateNames);
+            }
+            names.addAll(customNames);
+
+            // remember this resolution.
             if (!names.isEmpty()) {
-                bitsToNames.put(bits, names);
+                bitsToNames.put(privilegeBits, names);
             }
             return names.toArray(new Name[names.size()]);
         }
@@ -519,21 +543,25 @@ public final class PrivilegeRegistry {
     private void registerDefinitions(Map<Name, Definition> definitions) {
         registeredPrivileges.putAll(definitions);
         for (Definition def : definitions.values()) {
-            if (def.bits > NO_PRIVILEGE) {
-                bitsToNames.put(def.bits, Collections.singleton(def.name));
-            }
+            bitsToNames.put(def.bits, Collections.singleton(def.name));
         }
 
         if (!definitions.containsKey(NameConstants.JCR_ALL)) {
             // redefine the jcr:all privilege definition
             Definition all = registeredPrivileges.get(NameConstants.JCR_ALL);
-
+            bitsToNames.remove(all.bits);
+            
             Set<Name> allAggrNames = all.declaredAggregateNames;
             allAggrNames.addAll(definitions.keySet());
 
-            all = new Definition(NameConstants.JCR_ALL, false, allAggrNames, all.bits);
-            registeredPrivileges.put(NameConstants.JCR_ALL, all);
-            bitsToNames.put(all.bits, Collections.singleton(NameConstants.JCR_ALL));
+            PrivilegeBits allbits = PrivilegeBits.getInstance(all.bits);
+            for (Definition d : definitions.values()) {
+                allbits.add(d.bits);
+            }
+
+            Definition newAll = new Definition(NameConstants.JCR_ALL, false, allAggrNames, allbits.unmodifiable(), false);
+            registeredPrivileges.put(NameConstants.JCR_ALL, newAll);
+            bitsToNames.put(newAll.bits, Collections.singleton(NameConstants.JCR_ALL));
         }
     }
    
@@ -559,7 +587,7 @@ public final class PrivilegeRegistry {
         defs.put(jcrWrite.name, jcrWrite);
 
         // rep:write
-        Definition repWrite = createRepWriteDefinition(jcrWrite.bits);
+        Definition repWrite = createRepWriteDefinition(jcrWrite);
         defs.put(repWrite.name, repWrite);
 
         // jcr:all
@@ -615,7 +643,7 @@ public final class PrivilegeRegistry {
             // validate aggregates
             if (stub.declaredAggregateNames.isEmpty()) {
                 // not an aggregate priv definition.
-                definitions.put(name, new Definition(stub, NO_PRIVILEGE));
+                definitions.put(name, new Definition(stub, nextBits()));
             } else {
                 for (Name declaredAggregateName : stub.declaredAggregateNames) {
                     if (name.equals(declaredAggregateName)) {
@@ -646,37 +674,24 @@ public final class PrivilegeRegistry {
             // look for those definitions whose declared aggregates have all been processed.
             for (Iterator<DefinitionStub> itr = aggregates.iterator(); itr.hasNext();) {
                 DefinitionStub stub = itr.next();
-
-                int bts = NO_PRIVILEGE;
-                for (Name n : stub.declaredAggregateNames) {
-                    Definition aggr = null;
-                    if (registeredPrivileges.containsKey(n)) {
-                        aggr = registeredPrivileges.get(n);
-                    } else if (definitions.containsKey(n)) {
-                        aggr = definitions.get(n);
+                PrivilegeBits bts = getAggregateBits(stub.declaredAggregateNames, definitions);
+                if (!bts.isEmpty()) {
+                    // make sure the same aggregation is not yet covered by an
+                    // already registered privilege
+                    if (bitsToNames.containsKey(bts) && bitsToNames.get(bts).size() == 1) {
+                        Name existingName = bitsToNames.get(bts).iterator().next();
+                        throw new RepositoryException("Custom aggregate privilege '" + stub.name + "' is already covered by '" + existingName.toString() + "'");
                     }
-
-                    if (aggr == null) {
-                        // unknown dependency
-                        bts = UNDEFINED;
-                        break;
-                    } else if (!aggr.isCustom()) {
-                        throw new RepositoryException("Custom privileges may only aggregate custom privileges.");
-                    } // else: a known custom privilege -> try next.
-                }
-
-                if (bts == NO_PRIVILEGE) {
-                    Definition def = new Definition(stub, bts);
-
-                    // final validation if a custom aggregated has not yet been defined.
-                    Iterator<Definition> it = Iterators.iteratorChain(registeredPrivileges.values().iterator(), definitions.values().iterator());
-                    while (it.hasNext()) {
-                        Definition d = it.next();
-                        if (isEquivalentAggregate(d, def, definitions)) {
-                            throw new RepositoryException("Custom aggregate privilege '" + def.name + "' is already defined by '"+ d.name+"'");
+                    // ... nor is present within the set of definitions that have
+                    // been created before for registration.
+                    for (Definition d : definitions.values()) {
+                        if (bts.equals(d.bits)) {
+                            throw new RepositoryException("Custom aggregate privilege '" + stub.name + "' is already defined by '"+ d.name+"'");
                         }
                     }
 
+                    // now its save to create the new definition
+                    Definition def = new Definition(stub, bts);
                     definitions.put(def.name, def);
                     itr.remove();
                 } // unresolvable bts -> postpone to next iterator.
@@ -691,33 +706,36 @@ public final class PrivilegeRegistry {
         return definitions;
     }
 
-    private boolean isEquivalentAggregate(Definition d, Definition otherDef,
-                                          Map<Name, Definition> unregistered) {
-        // either of the definitions isn't an aggregate.
-        if (d.declaredAggregateNames.isEmpty() || otherDef.declaredAggregateNames.isEmpty()) {
-            return false;
-        }
-        // two aggregates that defined the same declared aggregate names
-        if (d.declaredAggregateNames.equals(otherDef.declaredAggregateNames)) {
-            return true;
-        }
-        // two aggregates that defined the same aggregation of simple definitions.
-        Set<Name> aggrNames = getAggrNames(d, unregistered);
-        Set<Name> otherAggrNames = getAggrNames(otherDef, unregistered);
-        return aggrNames.size() == otherAggrNames.size() && aggrNames.containsAll(otherAggrNames);
-    }
-
-    private Set<Name> getAggrNames(Definition def, Map<Name, Definition> unregistered) {
-        Set<Name> names = new HashSet<Name>();
-        for (Name n : def.declaredAggregateNames) {
-            Definition a = (unregistered.containsKey(n)) ? unregistered.get(n) : registeredPrivileges.get(n);
-            if (a.declaredAggregateNames.isEmpty()) {
-                names.add(a.name);
+    /**
+     *
+     * @return
+     */
+    private PrivilegeBits nextBits() {
+        PrivilegeBits b = nextBits;
+        nextBits = nextBits.nextBits();
+        return b;
+    }
+
+    /**
+     *
+     * @param declaredAggregateNames
+     * @param toRegister
+     * @return
+     */
+    private PrivilegeBits getAggregateBits(Set<Name> declaredAggregateNames, Map<Name, Definition> toRegister) {
+        PrivilegeBits bts = PrivilegeBits.getInstance();
+        for (Name n : declaredAggregateNames) {
+            if (registeredPrivileges.containsKey(n)) {
+                bts.add(registeredPrivileges.get(n).bits);
+            } else if (toRegister.containsKey(n)) {
+                Definition def = toRegister.get(n);
+                bts.add(def.bits);
             } else {
-                names.addAll(getAggrNames(a, unregistered));
+                // unknown dependency (should not get here) -> return the empty set.
+                return PrivilegeBits.EMPTY;
             }
         }
-        return names;
+        return bts.unmodifiable();
     }
 
     /**
@@ -762,12 +780,12 @@ public final class PrivilegeRegistry {
         return new Definition(NameConstants.JCR_WRITE, false, jcrWriteAggregates, jcrWriteBits);
     }
 
-    private static Definition createRepWriteDefinition(int jcrWriteBits) {
+    private static Definition createRepWriteDefinition(Definition jcrWrite) {
         Set<Name> repWriteAggregates = new HashSet<Name>(2);
         repWriteAggregates.add(NameConstants.JCR_WRITE);
         repWriteAggregates.add(NameConstants.JCR_NODE_TYPE_MANAGEMENT);
 
-        int repWriteBits = jcrWriteBits | PRIVILEGE_NAMES.get(NameConstants.JCR_NODE_TYPE_MANAGEMENT);
+        long repWriteBits = jcrWrite.bits.longValue() | PRIVILEGE_NAMES.get(NameConstants.JCR_NODE_TYPE_MANAGEMENT);
         return new Definition(REP_WRITE_NAME, false, repWriteAggregates, repWriteBits);
     }
 
@@ -842,29 +860,41 @@ public final class PrivilegeRegistry {
      */
     static class Definition extends DefinitionStub {
 
-        private final int bits;
+        private final PrivilegeBits bits;
+        private final boolean isCustom;
 
-        private Definition(DefinitionStub stub, int bits) {
-            this(stub.name, stub.isAbstract, stub.declaredAggregateNames, bits);
+        private int hashCode;
+
+        private Definition(DefinitionStub stub, PrivilegeBits bits) {
+            this(stub.name, stub.isAbstract, stub.declaredAggregateNames, bits, true);
         }
 
-        private Definition(Name name, boolean isAbstract, int bits) {
-            this(name, isAbstract, Collections.<Name>emptySet(), bits);
+        private Definition(Name name, boolean isAbstract, long bits) {
+            this(name, isAbstract, Collections.<Name>emptySet(), PrivilegeBits.getInstance(bits), false);
         }
 
-        private Definition(Name name, boolean isAbstract, Set<Name> declaredAggregateNames, int bits) {
+        private Definition(Name name, boolean isAbstract, Set<Name> declaredAggregateNames, long bits) {
+            this(name, isAbstract, declaredAggregateNames, PrivilegeBits.getInstance(bits), false);
+        }
+
+        private Definition(Name name, boolean isAbstract, Set<Name> declaredAggregateNames, PrivilegeBits bits, boolean isCustom) {
             super(name, isAbstract, declaredAggregateNames);
-            if (bits < NO_PRIVILEGE) {
-                throw new IllegalArgumentException("Failed to build int representation of PrivilegeDefinition.");
+            if (bits == null || bits.isEmpty()) {
+                throw new IllegalArgumentException("Failed to build bit representation of PrivilegeDefinition.");
             } else {
                 this.bits = bits;
             }
+            this.isCustom = isCustom;
         }
 
         Name getName() {
             return name;
         }
 
+        PrivilegeBits getBits() {
+            return bits;
+        }
+
         boolean isAbstract() {
             return isAbstract;
         }
@@ -877,8 +907,31 @@ public final class PrivilegeRegistry {
             }
         }
 
-        boolean isCustom() {
-            return bits == NO_PRIVILEGE;
+        //---------------------------------------------------------< Object >---
+        @Override
+        public int hashCode() {
+            if (hashCode == 0) {
+                int h = 17;
+                h = 37 * h + name.hashCode();
+                h = 37 * h + Boolean.valueOf(isAbstract).hashCode();
+                h = 37 * h + bits.hashCode();
+                hashCode = h;
+            }
+            return hashCode;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj == this) {
+                return true;
+            }
+            if (obj instanceof Definition) {
+                Definition other = (Definition) obj;
+                return name.equals(other.name)
+                        && isAbstract==other.isAbstract
+                        && bits.equals(other.bits);
+            }
+            return false;
         }
     }
 

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java?rev=1092723&r1=1092722&r2=1092723&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java Fri Apr 15 14:34:45 2011
@@ -44,10 +44,9 @@ import org.apache.jackrabbit.core.id.Nod
 import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
 import org.apache.jackrabbit.core.security.authorization.AbstractACLTemplate;
 import org.apache.jackrabbit.core.security.authorization.AccessControlEntryImpl;
-import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.core.security.authorization.PrivilegeBits;
 import org.apache.jackrabbit.core.security.authorization.PrivilegeManagerImpl;
 import org.apache.jackrabbit.core.security.authorization.GlobPattern;
-import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
 import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
 import org.apache.jackrabbit.core.security.principal.UnknownPrincipal;
 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
@@ -225,15 +224,11 @@ class ACLTemplate extends AbstractACLTem
             int updateIndex = -1;
             Entry complementEntry = null;
 
-            Set<Privilege> otherCustom = entry.getCustomPrivileges();
             for (Entry e : entriesPerPrincipal) {
                 if (equalRestriction(entry, e)) {
                     if (entry.isAllow() == e.isAllow()) {
                         // need to update an existing entry
-                        int existingPrivs = e.getPrivilegeBits();
-                        Set<Privilege> existingCustom = e.getCustomPrivileges();
-                        if ((existingPrivs | ~entry.getPrivilegeBits()) == -1 &&
-                                existingCustom.containsAll(otherCustom)) {
+                        if (e.getPrivilegeBits().includes(entry.getPrivilegeBits())) {
                             // all privileges to be granted/denied are already present
                             // in the existing entry -> not modified
                             return false;
@@ -246,10 +241,10 @@ class ACLTemplate extends AbstractACLTem
                         // includes both the new privileges and the existing ones.
                         entries.remove(e);
 
-                        int mergedBits = e.getPrivilegeBits() | entry.getPrivilegeBits();
+                        PrivilegeBits mergedBits = PrivilegeBits.getInstance(e.getPrivilegeBits());
+                        mergedBits.add(entry.getPrivilegeBits());
+                        
                         Set<Privilege> mergedPrivs = privilegeMgr.getPrivileges(mergedBits);
-                        mergedPrivs.addAll(existingCustom);
-                        mergedPrivs.addAll(otherCustom);
                         // omit validation check.
                         entry = createEntry(entry, mergedPrivs.toArray(new Privilege[mergedPrivs.size()]), entry.isAllow());
                     } else {
@@ -263,25 +258,23 @@ class ACLTemplate extends AbstractACLTem
             // denied/granted.
             if (complementEntry != null) {
 
-                int complPrivs = complementEntry.getPrivilegeBits();
-                int diff = Permission.diff(complPrivs, entry.getPrivilegeBits());
-
-                Set<Privilege> result = complementEntry.getCustomPrivileges();
-                boolean customMod = result.removeAll(otherCustom);
+                PrivilegeBits complPrivs = complementEntry.getPrivilegeBits();
+                PrivilegeBits diff = PrivilegeBits.getInstance(complPrivs);
+                diff.diff(entry.getPrivilegeBits());
                 
-                if (diff == PrivilegeRegistry.NO_PRIVILEGE && result.isEmpty()) {
+                if (diff.isEmpty()) {
                     // remove the complement entry as the new entry covers
                     // all privileges granted by the existing entry.
                     entries.remove(complementEntry);
                     updateIndex--;
 
-                } else if (diff != complPrivs || customMod) {
+                } else if (!diff.equals(complPrivs)) {
                     // replace the existing entry having the privileges adjusted
                     int index = entries.indexOf(complementEntry);
                     entries.remove(complementEntry);
 
                     // combine set of new builtin and custom privileges
-                    result.addAll(privilegeMgr.getPrivileges(diff));
+                    Set<Privilege> result = privilegeMgr.getPrivileges(diff);
                     // and create a new entry.
                     Entry tmpl = createEntry(entry,
                             result.toArray(new Privilege[result.size()]),

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CompiledPermissionsImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CompiledPermissionsImpl.java?rev=1092723&r1=1092722&r2=1092723&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CompiledPermissionsImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CompiledPermissionsImpl.java Fri Apr 15 14:34:45 2011
@@ -30,6 +30,7 @@ import org.apache.jackrabbit.core.securi
 import org.apache.jackrabbit.core.security.authorization.AccessControlModifications;
 import org.apache.jackrabbit.core.security.authorization.AccessControlUtils;
 import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.core.security.authorization.PrivilegeBits;
 import org.apache.jackrabbit.core.security.authorization.PrivilegeManagerImpl;
 import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
 import org.apache.jackrabbit.spi.Name;
@@ -39,10 +40,8 @@ import org.apache.jackrabbit.util.Text;
 import javax.jcr.ItemNotFoundException;
 import javax.jcr.RepositoryException;
 import javax.jcr.security.AccessControlEntry;
-import javax.jcr.security.Privilege;
 import java.security.Principal;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -103,13 +102,10 @@ class CompiledPermissionsImpl extends Ab
         int allows = Permission.NONE;
         int denies = Permission.NONE;
 
-        int allowBits = PrivilegeRegistry.NO_PRIVILEGE;
-        int denyBits = PrivilegeRegistry.NO_PRIVILEGE;
-        int parentAllowBits = PrivilegeRegistry.NO_PRIVILEGE;
-        int parentDenyBits = PrivilegeRegistry.NO_PRIVILEGE;
-
-        Set<Privilege> customAllow = new HashSet<Privilege>();
-        Set<Privilege> customDeny = new HashSet<Privilege>();
+        PrivilegeBits allowBits = PrivilegeBits.getInstance();
+        PrivilegeBits denyBits = PrivilegeBits.getInstance();
+        PrivilegeBits parentAllowBits = PrivilegeBits.getInstance();
+        PrivilegeBits parentDenyBits = PrivilegeBits.getInstance();
 
         String parentPath = Text.getRelativeParent(filter.getPath(), 1);
 
@@ -123,32 +119,28 @@ class CompiledPermissionsImpl extends Ab
             parent. For inherited ACEs determine if the ACE matches the
             parent path.
             */
-            int entryBits = ace.getPrivilegeBits();
+            PrivilegeBits entryBits = ace.getPrivilegeBits();
             boolean isLocal = isExistingNode && ace.isLocal(node.getNodeId());
             boolean matchesParent = (!isLocal && ace.matches(parentPath));
             if (matchesParent) {
                 if (ace.isAllow()) {
-                    parentAllowBits |= Permission.diff(entryBits, parentDenyBits);
+                    parentAllowBits.addDifference(entryBits, parentDenyBits);
                 } else {
-                    parentDenyBits |= Permission.diff(entryBits, parentAllowBits);
+                    parentDenyBits.addDifference(entryBits, parentAllowBits);
                 }
             }
             if (ace.isAllow()) {
-                allowBits |= Permission.diff(entryBits, denyBits);
+                allowBits.addDifference(entryBits, denyBits);
                 int permissions = PrivilegeRegistry.calculatePermissions(allowBits, parentAllowBits, true, isAcItem);
                 allows |= Permission.diff(permissions, denies);
-
-                updatePrivileges(ace.getCustomPrivileges(), customAllow, customDeny);
             } else {
-                denyBits |= Permission.diff(entryBits, allowBits);
+                denyBits.addDifference(entryBits, allowBits);
                 int permissions = PrivilegeRegistry.calculatePermissions(denyBits, parentDenyBits, false, isAcItem);
                 denies |= Permission.diff(permissions, allows);
-
-                updatePrivileges(ace.getCustomPrivileges(), customDeny, customAllow);
             }
         }
 
-        return new Result(allows, denies, allowBits, denyBits, customAllow, customDeny);
+        return new Result(allows, denies, allowBits, denyBits);
     }
 
     //------------------------------------< AbstractCompiledPermissions >---
@@ -264,8 +256,7 @@ class CompiledPermissionsImpl extends Ab
                      */
                     for (AccessControlEntry accessControlEntry : entryCollector.collectEntries(node, filter)) {
                         ACLTemplate.Entry ace = (ACLTemplate.Entry) accessControlEntry;
-                        int entryBits = ace.getPrivilegeBits();
-                        if ((entryBits & Permission.READ) == Permission.READ) {
+                        if (ace.getPrivilegeBits().includesRead()) {
                             canRead = ace.isAllow();
                             break;
                         }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLProvider.java?rev=1092723&r1=1092722&r2=1092723&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLProvider.java Fri Apr 15 14:34:45 2011
@@ -31,6 +31,7 @@ import org.apache.jackrabbit.core.securi
 import org.apache.jackrabbit.core.security.authorization.AccessControlModifications;
 import org.apache.jackrabbit.core.security.authorization.CompiledPermissions;
 import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.core.security.authorization.PrivilegeBits;
 import org.apache.jackrabbit.core.security.authorization.PrivilegeManagerImpl;
 import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
 import org.apache.jackrabbit.core.security.authorization.UnmodifiableAccessControlList;
@@ -68,7 +69,7 @@ import java.util.Map;
 import java.util.Set;
 
 /**
- * <code>CombinedProvider</code>...
+ * <code>ACLProvider</code>...
  */
 public class ACLProvider extends AbstractAccessControlProvider implements AccessControlConstants {
 
@@ -78,7 +79,6 @@ public class ACLProvider extends Abstrac
     private ACLEditor editor;
 
     private EntriesCache entriesCache;
-    private int readBits;
 
     //----------------------------------------------< AccessControlProvider >---
     /**
@@ -98,10 +98,8 @@ public class ACLProvider extends Abstrac
             acRoot = root.addNode(N_ACCESSCONTROL, NT_REP_ACCESS_CONTROL, null);
         }
 
-        editor = new ACLEditor(session, resolver.getQPath(acRoot.getPath()));
+        editor = new ACLEditor(session, session.getQPath(acRoot.getPath()));
         entriesCache = new EntriesCache(session, editor, acRoot.getPath());
-        PrivilegeManagerImpl pm = getPrivilegeManagerImpl();
-        readBits = pm.getBits(pm.getPrivilege(Privilege.JCR_READ));
 
         // TODO: replace by configurable default policy (see JCR-2331)
         if (!configuration.containsKey(PARAM_OMIT_DEFAULT_PERMISSIONS)) {
@@ -362,7 +360,7 @@ public class ACLProvider extends Abstrac
             if (canReadAll) {
                 for (AccessControlEntry entry : entries) {
                     AccessControlEntryImpl ace = (AccessControlEntryImpl) entry;
-                    if (!ace.isAllow() && ((ace.getPrivilegeBits() & readBits) == readBits)) {
+                    if (!ace.isAllow() && ace.getPrivilegeBits().includesRead()) {
                         // found an ace that defines read deny for a sub tree
                         // -> canReadAll is false.
                         canReadAll = false;
@@ -412,13 +410,10 @@ public class ACLProvider extends Abstrac
             int allows = Permission.NONE;
             int denies = Permission.NONE;
 
-            int allowBits = PrivilegeRegistry.NO_PRIVILEGE;
-            int denyBits = PrivilegeRegistry.NO_PRIVILEGE;
-            int parentAllowBits = PrivilegeRegistry.NO_PRIVILEGE;
-            int parentDenyBits = PrivilegeRegistry.NO_PRIVILEGE;
-
-            Set<Privilege> customAllow = new HashSet<Privilege>();
-            Set<Privilege> customDeny = new HashSet<Privilege>();
+            PrivilegeBits allowBits = PrivilegeBits.getInstance();
+            PrivilegeBits denyBits = PrivilegeBits.getInstance();
+            PrivilegeBits parentAllowBits = PrivilegeBits.getInstance();
+            PrivilegeBits parentDenyBits = PrivilegeBits.getInstance();
 
             String parentPath = Text.getRelativeParent(targetPath, 1);
             for (AccessControlEntry entry : entries) {
@@ -427,35 +422,31 @@ public class ACLProvider extends Abstrac
                     continue;
                 }
                 ACLTemplate.Entry entr = (ACLTemplate.Entry) entry;
-                int privs = entr.getPrivilegeBits();
+                PrivilegeBits privs = entr.getPrivilegeBits();
 
                 if (!"".equals(parentPath) && entr.matches(parentPath)) {
                     if (entr.isAllow()) {
-                        parentAllowBits |= Permission.diff(privs, parentDenyBits);
+                        parentAllowBits.addDifference(privs, parentDenyBits);
                     } else {
-                        parentDenyBits |= Permission.diff(privs, parentAllowBits);
+                        parentDenyBits.addDifference(privs, parentAllowBits);
                     }
                 }
 
                 boolean matches = entr.matches(targetPath);
                 if (matches) {
                     if (entr.isAllow()) {
-                        allowBits |= Permission.diff(privs, denyBits);
+                        allowBits.addDifference(privs, denyBits);
                         int permissions = PrivilegeRegistry.calculatePermissions(allowBits, parentAllowBits, true, isAcItem);
                         allows |= Permission.diff(permissions, denies);
-
-                        updatePrivileges(entr.getCustomPrivileges(), customAllow, customDeny);
                     } else {
-                        denyBits |= Permission.diff(privs, allowBits);
+                        denyBits.addDifference(privs, allowBits);
                         int permissions = PrivilegeRegistry.calculatePermissions(denyBits, parentDenyBits, false, isAcItem);
                         denies |= Permission.diff(permissions, allows);
-
-                        updatePrivileges(entr.getCustomPrivileges(), customDeny, customAllow);
                     }
                 }
             }
 
-            return new Result(allows, denies, allowBits, denyBits, customAllow, customDeny);
+            return new Result(allows, denies, allowBits, denyBits);
         }
 
         //--------------------------------------------< CompiledPermissions >---

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java?rev=1092723&r1=1092722&r2=1092723&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java Fri Apr 15 14:34:45 2011
@@ -34,6 +34,7 @@ import org.apache.jackrabbit.core.securi
 import org.apache.jackrabbit.core.security.authorization.CompiledPermissions;
 import org.apache.jackrabbit.core.security.authorization.NamedAccessControlPolicyImpl;
 import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.core.security.authorization.PrivilegeBits;
 import org.apache.jackrabbit.core.security.authorization.PrivilegeManagerImpl;
 import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
 import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
@@ -53,8 +54,6 @@ import javax.jcr.security.Privilege;
 
 import java.security.Principal;
 import java.security.acl.Group;
-import java.util.Collections;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
@@ -298,7 +297,7 @@ public class UserAccessControlProvider e
     }
 
     private Node getExistingNode(Path path) throws RepositoryException {
-        String absPath = resolver.getJCRPath(path.getNormalizedPath());
+        String absPath = session.getJCRPath(path.getNormalizedPath());
         if (session.nodeExists(absPath)) {
             return session.getNode(absPath);
         } else if (session.propertyExists(absPath)) {
@@ -377,9 +376,13 @@ public class UserAccessControlProvider e
             observationMgr.addEventListener(this, events, groupsPath, true, null, null, false);
         }
 
-        private int getPrivilegeBits(String privName) throws RepositoryException {
+        private PrivilegeBits getPrivilegeBits(String... privNames) throws RepositoryException {
             PrivilegeManagerImpl impl = getPrivilegeManagerImpl();
-            return impl.getBits(impl.getPrivilege(privName));
+            Privilege[] privs = new Privilege[privNames.length];
+            for (int i = 0; i < privNames.length; i++) {
+                privs[i] = impl.getPrivilege(privNames[i]);
+            }
+            return impl.getBits(privs);
         }
 
         //------------------------------------< AbstractCompiledPermissions >---
@@ -408,15 +411,15 @@ public class UserAccessControlProvider e
             int denies = Permission.NONE;
             // default allow permission and default privileges
             int allows = Permission.READ;
-            int privs;
+            PrivilegeBits privs;
             // Determine if for path, the set of privileges must be calculated:
             // Generally, privileges can only be determined for existing nodes.
-            String jcrPath = resolver.getJCRPath(path.getNormalizedPath());
+            String jcrPath = session.getJCRPath(path.getNormalizedPath());
             boolean calcPrivs = session.nodeExists(jcrPath);
             if (calcPrivs) {
                 privs = getPrivilegeBits(Privilege.JCR_READ);
             } else {
-                privs = PrivilegeRegistry.NO_PRIVILEGE;
+                privs = PrivilegeBits.EMPTY;
             }
 
             if (Text.isDescendant(usersPath, jcrPath)) {
@@ -437,7 +440,7 @@ public class UserAccessControlProvider e
                         if (calcPrivs) {
                             // grant WRITE privilege
                             // note: ac-read/modification is not included
-                            privs |= getPrivilegeBits(PrivilegeRegistry.REP_WRITE);
+                            privs.add(getPrivilegeBits(PrivilegeRegistry.REP_WRITE));
                         }
                     }
                 } else {
@@ -449,14 +452,14 @@ public class UserAccessControlProvider e
                         // user can only read && write his own props
                         allows |= (Permission.SET_PROPERTY | Permission.REMOVE_PROPERTY);
                         if (calcPrivs) {
-                            privs |= getPrivilegeBits(Privilege.JCR_MODIFY_PROPERTIES);
+                            privs.add(getPrivilegeBits(Privilege.JCR_MODIFY_PROPERTIES));
                         }
                     } else if (isUserAdmin) {
                         allows |= (Permission.ADD_NODE | Permission.REMOVE_NODE | Permission.SET_PROPERTY | Permission.REMOVE_PROPERTY | Permission.NODE_TYPE_MNGMT);
                         if (calcPrivs) {
                             // grant WRITE privilege
                             // note: ac-read/modification is not included
-                            privs |= getPrivilegeBits(PrivilegeRegistry.REP_WRITE);
+                            privs.add(getPrivilegeBits(PrivilegeRegistry.REP_WRITE));
                         }
                     } // else: normal user that isn't allowed to modify another user.
                 }
@@ -475,20 +478,19 @@ public class UserAccessControlProvider e
                             // no remove perm on group-admin node
                             allows |= (Permission.ADD_NODE | Permission.SET_PROPERTY | Permission.REMOVE_PROPERTY | Permission.NODE_TYPE_MNGMT);
                             if (calcPrivs) {
-                                privs |= getPrivilegeBits(PrivilegeRegistry.REP_WRITE);
-                                privs ^= getPrivilegeBits(Privilege.JCR_REMOVE_NODE);
+                                privs.add(getPrivilegeBits(Privilege.JCR_ADD_CHILD_NODES, Privilege.JCR_MODIFY_PROPERTIES, Privilege.JCR_NODE_TYPE_MANAGEMENT));
                             }
                         } else {
                             // complete write
                             allows |= (Permission.ADD_NODE | Permission.REMOVE_NODE | Permission.SET_PROPERTY | Permission.REMOVE_PROPERTY | Permission.NODE_TYPE_MNGMT);
                             if (calcPrivs) {
-                                privs |= getPrivilegeBits(PrivilegeRegistry.REP_WRITE);
+                                privs.add(getPrivilegeBits(PrivilegeRegistry.REP_WRITE));
                             }
                         }
                     }
                 }
             } // else outside of user/group tree -> read only.
-            return new Result(allows, denies, privs, PrivilegeRegistry.NO_PRIVILEGE);
+            return new Result(allows, denies, privs, PrivilegeBits.EMPTY);
         }
 
         @Override



Mime
View raw message