You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2011/07/22 16:22:17 UTC

svn commit: r1149613 - in /jackrabbit/trunk/jackrabbit-core/src: main/java/org/apache/jackrabbit/core/security/authorization/ test/java/org/apache/jackrabbit/core/security/authorization/

Author: angela
Date: Fri Jul 22 14:22:16 2011
New Revision: 1149613

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

Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeBits.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/PrivilegeBitsTest.java

Modified: 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=1149613&r1=1149612&r2=1149613&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeBits.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeBits.java Fri Jul 22 14:22:16 2011
@@ -16,14 +16,14 @@
  */
 package org.apache.jackrabbit.core.security.authorization;
 
-import java.math.BigInteger;
+import java.util.Arrays;
 
 /**
  * <code>PrivilegeBits</code> 
  */
 public class PrivilegeBits {
 
-    public static final PrivilegeBits EMPTY = new PrivilegeBits(SimpleData.EMPTY);
+    public static final PrivilegeBits EMPTY = new PrivilegeBits(UnmodifiableData.EMPTY);
 
     private static final long READ = 1; // PrivilegeRegistry.READ
 
@@ -71,7 +71,7 @@ public class PrivilegeBits {
      */
     PrivilegeBits unmodifiable() {
         if (d instanceof ModifiableData) {
-            return (d.isSimple()) ? getInstance(d.longValue()) : new PrivilegeBits(new BigIntegerData(d.getBigInteger()));
+            return (d.isSimple()) ? getInstance(d.longValue()) : getInstance(d.longValues());
         } else {
             return this;
         }
@@ -90,11 +90,23 @@ public class PrivilegeBits {
         } else if (bits < PrivilegeRegistry.NO_PRIVILEGE) {
             throw new IllegalArgumentException();
         } else {
-            return new PrivilegeBits(new SimpleData(bits));
+            return new PrivilegeBits(new UnmodifiableData(bits));
         }
     }
 
     /**
+     * Internal method to create a new instance of <code>PrivilegeBits</code>.
+     * 
+     * @param bits
+     * @return an instance of <code>PrivilegeBits</code>
+     */
+    private static PrivilegeBits getInstance(long[] bits) {
+        long[] bts = new long[bits.length];
+        System.arraycopy(bits, 0, bts, 0, bits.length);
+        return new PrivilegeBits(new UnmodifiableData(bts));
+    }
+
+    /**
      * Creates a mutable instance of privilege bits.
      *
      * @return a new instance of privilege bits.
@@ -139,7 +151,7 @@ public class PrivilegeBits {
         } else if (d.isSimple()) {
             return (d.longValue() & READ) == READ;
         } else {
-            return d.getBigInteger().testBit(0);
+            return (d.longValues()[0] & READ) == READ;
         }
     }
 
@@ -226,7 +238,7 @@ public class PrivilegeBits {
         if (d.isSimple()) {
             sb.append(d.longValue());
         } else {
-            sb.append(d.getBigInteger().toString());
+            sb.append(Arrays.toString(d.longValues()));
         }
         return sb.toString();
     }
@@ -237,16 +249,11 @@ public class PrivilegeBits {
      */
     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 long[] longValues();
 
         abstract boolean isSimple();
 
@@ -258,27 +265,65 @@ public class PrivilegeBits {
             return (bits | ~otherBits) == -1;
         }
 
-        static boolean includes(BigInteger bits, BigInteger otherBits) {
-            if (bits.equals(otherBits)) {
+        static boolean includes(long[] bits, long[] otherBits) {
+            if (otherBits.length <= bits.length) {
+                // test for each long if is included
+                for (int i = 0; i < otherBits.length; i++) {
+                    if ((bits[i] | ~otherBits[i]) != -1) {
+                        return false;
+                    }
+                }
                 return true;
             } else {
-                return MINUS_ONE.equals(bits.or(otherBits.not()));
+                // otherbits array is longer > cannot be included in bits
+                return false;
+            }
+        }
+
+        //---------------------------------------------------------< Object >---
+        @Override
+        public boolean equals(Object o) {
+            if (o == this) {
+                return true;
+            } else if (o instanceof Data) {
+                Data d = (Data) o;
+                if (isSimple() != d.isSimple()) {
+                    return false;
+                }
+                if (isSimple()) {
+                    return longValue() == d.longValue();
+                } else {
+                    return Arrays.equals(longValues(), d.longValues());
+                }
+            } else {
+                return false;
             }
         }
     }
 
     /**
-     * Unmodifiable instance of the Data base class.
+     * Immutable Data object
      */
-    private static class SimpleData extends Data {
+    private static class UnmodifiableData extends Data {
 
         private static final long MAX = Long.MAX_VALUE / 2;
-        private static final SimpleData EMPTY = new SimpleData(PrivilegeRegistry.NO_PRIVILEGE);
+
+        private static final UnmodifiableData EMPTY = new UnmodifiableData(PrivilegeRegistry.NO_PRIVILEGE);
 
         private final long bits;
+        private final long[] bitsArr;
+        private final boolean isSimple;
 
-        private SimpleData(long bits) {
+        private UnmodifiableData(long bits) {
             this.bits = bits;
+            bitsArr = new long[] {bits};
+            isSimple = true;
+        }
+
+        private UnmodifiableData(long[] bitsArr) {
+            bits = PrivilegeRegistry.NO_PRIVILEGE;            
+            this.bitsArr = bitsArr;
+            isSimple = false;
         }
 
         @Override
@@ -292,114 +337,54 @@ public class PrivilegeBits {
         }
 
         @Override
-        BigInteger getBigInteger() {
-            return (isEmpty()) ? BigInteger.ZERO : BigInteger.valueOf(bits);
+        long[] longValues() {
+            return bitsArr;
         }
 
         @Override
         boolean isSimple() {
-            return true;
+            return isSimple;
         }
 
         @Override
         Data next() {
             if (this == EMPTY) {
                 return EMPTY;
-            } else if (bits < MAX) {
-                long b = bits << 1;
-                return new SimpleData(b);
+            } else if (isSimple) {
+                if (bits < MAX) {
+                    long b = bits << 1;
+                    return new UnmodifiableData(b);
+                } else {
+                    return new UnmodifiableData(new long[] {bits}).next();
+                }
             } else {
-                return new BigIntegerData(BigInteger.valueOf(bits)).next();
+                long[] bts;
+                long last = bitsArr[bitsArr.length-1];
+                if (last < MAX) {
+                    bts = new long[bitsArr.length];
+                    System.arraycopy(bitsArr, 0, bts, 0, bitsArr.length);
+                    bts[bts.length-1] = last << 1;
+                } else {
+                    bts = new long[bitsArr.length + 1];
+                    bts[bts.length-1] = 1;
+                }
+                return new UnmodifiableData(bts);
             }
         }
 
         @Override
         boolean includes(Data other) {
-            if (other.isSimple()) {
-                return includes(bits, other.longValue());
+            if (isSimple) {
+                return (other.isSimple()) ? includes(bits, other.longValue()) : false;
             } 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;
+                return includes(bitsArr, other.longValues());
             }
         }
-    }
-
-    /**
-     * 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;
-            }
+            return (isSimple) ? new Long(bits).hashCode() : bitsArr.hashCode();
         }
     }
 
@@ -408,62 +393,48 @@ public class PrivilegeBits {
      */
     private static class ModifiableData extends Data {
 
-        private long l;
-        private BigInteger bi;
+        private long[] bits;
 
         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;
+            bits = new long[] {PrivilegeRegistry.NO_PRIVILEGE};
         }
 
-        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;
-                }
+        private ModifiableData(Data base) {
+            long[] b = base.longValues();
+            switch (b.length) {
+                case 0:
+                    // empty
+                    bits = new long[] {PrivilegeRegistry.NO_PRIVILEGE};
+                    break;
+                case 1:
+                    // single long
+                    bits = new long[] {b[0]};
+                    break;
+                default:
+                    // copy
+                    bits = new long[b.length];                    
+                    System.arraycopy(b, 0, bits, 0, b.length);
             }
         }
 
         @Override
         boolean isEmpty() {
-            return l == PrivilegeRegistry.NO_PRIVILEGE && bi == null;
+            return bits.length == 1 && bits[0] == PrivilegeRegistry.NO_PRIVILEGE;
         }
 
         @Override
         long longValue() {
-            return (bi == null) ? l : BigIntegerData.ZERO;
+            return (bits.length == 1) ? bits[0] : PrivilegeRegistry.NO_PRIVILEGE;
         }
 
         @Override
-        BigInteger getBigInteger() {
-            return (bi == null) ? BigInteger.valueOf(l) : bi;
+        long[] longValues() {
+            return bits;
         }
 
         @Override
         boolean isSimple() {
-            return bi == null;
+            return bits.length == 1;
         }
 
         @Override
@@ -473,83 +444,104 @@ public class PrivilegeBits {
 
         @Override
         boolean includes(Data other) {
-            if (bi == null) {
-                return (other.isSimple()) ? includes(l, other.longValue()) : false;
+            if (bits.length == 1) {
+                return other.isSimple() && includes(bits[0], other.longValue());
             } else {
-                return this.equals(other) ? true : includes(bi, other.getBigInteger());
+                return includes(bits, other.longValues());
             }
         }
-               
-        public void add(Data other) {
+
+        /**
+         * Add the other Data to this instance.
+         *
+         * @param other
+         */
+        private void add(Data other) {
             if (other != this) {
-                if (bi == null && other.isSimple()) {
-                    l |= other.longValue();
+                if (bits.length == 1 && other.isSimple()) {
+                    bits[0] |= other.longValue();
                 } else {
-                    if (!this.equals(other)) {
-                        bi = getBigInteger().or(other.getBigInteger());
-                    } // else: equals -> nothing to do.
+                    or(other.longValues());
                 }
             }
         }
 
+        /**
+         * Subtract the other Data from this instance.
+         * 
+         * @param other
+         */
         private void diff(Data other) {
-            if (bi == null && other.isSimple()) {
-                l = l & ~other.longValue();
+            if (bits.length == 1 && other.isSimple()) {
+                bits[0] = bits[0] & ~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
-                }
+                bits = diff(bits, other.longValues());
             }
         }
 
+        /**
+         * Add the diff between the specified Data a and b.
+         * 
+         * @param a
+         * @param b
+         */
         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);
-                }
+                bits[0] |= a.longValue() & ~b.longValue();
             } else {
-                diff = a.getBigInteger().andNot(b.getBigInteger());
+                long[] diff = diff(a.longValues(), b.longValues());
+                or(diff);
             }
+        }
 
-            if (diff != null) {
-                BigInteger big = getBigInteger();
-                BigInteger res = big.or(diff);
-                if (!big.equals(res)) {
-                    writeBackResult(res);
-                } // else: no change
-            } else {
-                l |= diffL;
+        private void or(long[] b) {
+            if (b.length > bits.length) {
+                // enlarge the array
+                long[] res = new long[b.length];
+                System.arraycopy(bits, 0, res, 0, bits.length);
+                bits = res;
+            }
+            for (int i = 0; i < b.length; i++) {
+                bits[i] |= b[i];
             }
         }
 
-        //---------------------------------------------------------< Object >---       
-        @Override
-        public int hashCode() {
-            // NOTE: mutable object. hashcode not implemented.
-            return 0;
+        private static long[] diff(long[] a, long[] b) {
+            int index = -1;
+            long[] res = new long[((a.length > b.length) ? a.length : b.length)];
+            for (int i = 0; i < res.length; i++) {
+                if (i < a.length && i < b.length) {
+                    res[i] = a[i] & ~b[i];
+                } else {
+                    res[i] = (i < a.length) ? a[i] : 0;
+                }
+                // remember start of trailing 0 array entries
+                if (res[i] != 0) {
+                    index = -1;
+                } else if (index == -1) {
+                    index = i;
+                }
+            }
+            switch (index) {
+                case -1:
+                    // no need to remove trailing 0-long from the array                    
+                    return res;
+                case 0 :
+                    // array consisting of one or multiple 0
+                    return new long[] {PrivilegeRegistry.NO_PRIVILEGE};
+                default:
+                    // remove trailing 0-long entries from the array
+                    long[] r2 = new long[index];
+                    System.arraycopy(res, 0, r2, 0, index);
+                    return r2;
+            }
         }
 
+        //---------------------------------------------------------< Object >---
         @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;
+        public int hashCode() {
+            // NOTE: mutable object. hashCode not implemented.
+            return 0;
         }
     }
 }
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/CustomPrivilegeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/CustomPrivilegeTest.java?rev=1149613&r1=1149612&r2=1149613&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/CustomPrivilegeTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/CustomPrivilegeTest.java Fri Jul 22 14:22:16 2011
@@ -384,9 +384,11 @@ public class CustomPrivilegeTest extends
             assertNotNull(definition);
             assertEquals(name, definition.getName());
 
-            PrivilegeBits bits = privilegeRegistry.getBits(definition).unmodifiable();
+            PrivilegeBits modifiable = privilegeRegistry.getBits(definition);
+            PrivilegeBits bits = modifiable.unmodifiable();
             assertNotNull(bits);
             assertFalse(bits.isEmpty());
+            assertEquals(modifiable, bits);
 
             assertFalse(previous.equals(bits));
             assertEquals(previous.nextBits(), bits);

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/PrivilegeBitsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/PrivilegeBitsTest.java?rev=1149613&r1=1149612&r2=1149613&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/PrivilegeBitsTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/PrivilegeBitsTest.java Fri Jul 22 14:22:16 2011
@@ -140,7 +140,7 @@ public class PrivilegeBitsTest extends J
             assertTrue(mod.includesRead());
 
             pb = pb.nextBits();
-            assertFalse(pb.includesRead());
+            assertFalse(pb.toString(), pb.includesRead());
             assertFalse(PrivilegeBits.getInstance(pb).includesRead());
 
             PrivilegeBits modifiable = PrivilegeBits.getInstance(pb);
@@ -192,6 +192,10 @@ public class PrivilegeBitsTest extends J
             pb = pb.nextBits();
             mod.add(pb);
             assertFalse(mod.isEmpty());
+            
+            PrivilegeBits tmp = PrivilegeBits.getInstance(pb);
+            tmp.diff(pb);
+            assertTrue(tmp.toString(), tmp.isEmpty());
         }
     }
 
@@ -256,7 +260,7 @@ public class PrivilegeBitsTest extends J
                 assertTrue(tmp.includesRead());
                 assertTrue(tmp.includes(READ_PRIVILEGE_BITS));
             } else {
-                assertFalse(tmp.includesRead());
+                assertFalse(tmp.toString(), tmp.includesRead());
                 assertFalse(tmp.includes(READ_PRIVILEGE_BITS));
             }
             tmp.add(READ_PRIVILEGE_BITS);
@@ -384,7 +388,7 @@ public class PrivilegeBitsTest extends J
             PrivilegeBits tmp = PrivilegeBits.getInstance(mod);
             tmp.addDifference(nxt, READ_PRIVILEGE_BITS);
             mod.add(nxt);
-            assertEquals(mod, tmp); // since there is diff(nxt, read) results in nxt
+            assertEquals(mod, tmp); // since there is diff(nxt, read) which results in nxt
 
             if (!pb.equals(READ_PRIVILEGE_BITS)) {
                 tmp = PrivilegeBits.getInstance(nxt);