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 2008/08/27 17:12:07 UTC

svn commit: r689499 [4/11] - in /jackrabbit/trunk: jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jsr283/ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jsr283/retention/ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jsr283/sec...

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEditor.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEditor.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEditor.java Wed Aug 27 08:12:04 2008
@@ -16,14 +16,12 @@
  */
 package org.apache.jackrabbit.core.security.authorization;
 
-import org.apache.jackrabbit.api.jsr283.security.AccessControlEntry;
 import org.apache.jackrabbit.api.jsr283.security.AccessControlException;
-import org.apache.jackrabbit.api.jsr283.security.Privilege;
+import org.apache.jackrabbit.api.jsr283.security.AccessControlPolicy;
 
 import javax.jcr.AccessDeniedException;
 import javax.jcr.PathNotFoundException;
 import javax.jcr.RepositoryException;
-import javax.jcr.UnsupportedRepositoryOperationException;
 import java.security.Principal;
 
 /**
@@ -33,21 +31,21 @@
 public interface AccessControlEditor {
 
     /**
-     * Retrieves the policy template for the Node identified by the given
-     * <code>NodeId</code>. In contrast to {@link #editPolicyTemplate} this method
-     * returns <code>null</code> if no policy has been applied before by calling
-     * {@link #setPolicyTemplate}). Still the returned PolicyTemplate is detached from
-     * the AccessControlProvider and is only an external representation.
-     * Modification will therefore not take effect, until it is written back to
+     * Retrieves the policies for the Node identified by the given
+     * <code>nodePath</code>. In contrast to {@link #editAccessControlPolicies} this method
+     * returns an empty array if no policy has been applied before by calling
+     * {@link #setPolicy}). Still the returned policies are detached from
+     * the <code>AccessControlProvider</code> and are only an external representation.
+     * Modification will therefore not take effect, until they are written back to
      * the editor and persisted.
      * <p/>
-     * Compared to the policy returned by {@link AccessControlProvider#getPolicy(org.apache.jackrabbit.spi.Path)},
-     * the scope of the PolicyTemplate it limited to the Node itself and does
+     * Compared to the policy returned by {@link AccessControlProvider#getEffectivePolicies(org.apache.jackrabbit.spi.Path)},
+     * the scope of the policies it limited to the Node itself and does
      * not take inherited elements into account.
      *
      * @param nodePath Absolute path to an existing node object.
-     * @return the PolicyTemplate or <code>null</code> no policy has been
-     * applied to the node before.
+     * @return the policies applied so far or an empty array if no
+     * policy has been applied to the node before.
      * @throws AccessControlException If the Node identified by the given
      * <code>nodePath</code> does not allow access control modifications (e.g.
      * the node itself stores the access control information for its parent).
@@ -55,135 +53,67 @@
      * <code>nodePath</code>.
      * @throws RepositoryException if an error occurs
      */
-    PolicyTemplate getPolicyTemplate(String nodePath) throws AccessControlException, PathNotFoundException, RepositoryException;
+    AccessControlPolicy[] getPolicies(String nodePath) throws AccessControlException, PathNotFoundException, RepositoryException;
 
     /**
-     * Retrieves the policy template for the Node identified by the given
-     * <code>NodeId</code>. If the node does not yet have an policy set an
-     * new (empty) template is created (see also {@link #getPolicyTemplate(String)}.<br>
-     * The PolicyTemplate returned is detached from the underlying
+     * Retrieves the editable policies for the Node identified by the given
+     * <code>nodePath</code>. If the node does not yet have any policy set an
+     * new (empty) 'template' is created (see also {@link #getPolicies(String)}.<br>
+     * The AccessControlPolicy objects returned are detached from the underlying
      * <code>AccessControlProvider</code> and is only an external
-     * representation. Modification will therefore not take effect, until it is
-     * written back to the editor and persisted.
+     * representation. Modification will therefore not take effect, until a
+     * modified policy is written back to the editor and persisted.
      * <p/>
-     * Compared to the policy returned by {@link AccessControlProvider#getPolicy(org.apache.jackrabbit.spi.Path)},
-     * the scope of the PolicyTemplate it limited to the Node itself and does
-     * never not take inherited elements into account.
+     * Compared to the policies returned by {@link AccessControlProvider#getEffectivePolicies(org.apache.jackrabbit.spi.Path)},
+     * the scope of the policies returned by this methods it limited to the Node
+     * itself and does never not take inherited elements into account.
      *
      * @param nodePath Absolute path to an existing node object.
-     * @return policy template
+     * @return an array of editable access control policies.
      * @throws AccessControlException If the Node identified by the given
      * <code>nodePath</code> does not allow access control modifications.
      * @throws PathNotFoundException if no node exists for the given
      * <code>nodePath</code>.
      * @throws RepositoryException if an error occurs
      */
-    PolicyTemplate editPolicyTemplate(String nodePath) throws AccessControlException, PathNotFoundException, RepositoryException;
+    AccessControlPolicy[] editAccessControlPolicies(String nodePath) throws AccessControlException, PathNotFoundException, RepositoryException;
 
     /**
-     * Returns a policy template for the given <code>principal</code>.
+     * Returns an array of editable policies for the given <code>principal</code>.
      *
-     * @return policy template for the specified <code>principal.</code>.
+     * @return an array of editable policies for the given <code>principal</code>.
      * @throws AccessControlException if the specified principal does not exist,
-     * if this implementation does provide policy tempates for principals or
+     * if this implementation cannot provide policies for individual principals or
      * if same other access control related exception occurs.
      * @throws RepositoryException if another error occurs.
      */
-    PolicyTemplate editPolicyTemplate(Principal principal) throws AccessDeniedException, AccessControlException, RepositoryException;
+    AccessControlPolicy[] editAccessControlPolicies(Principal principal) throws AccessDeniedException, AccessControlException, RepositoryException;
 
     /**
      * Stores the policy template to the respective node.
      *
      * @param nodePath Absolute path to an existing node object.
-     * @param template the <code>PolicyTemplate</code> to store.
-     * @throws AccessControlException If the PolicyTemplate is <code>null</code> or
+     * @param policy the <code>AccessControlPolicy</code> to store.
+     * @throws AccessControlException If the policy is <code>null</code> or
      * if it is not applicable to the Node identified by the given
      * <code>nodePath</code>.
      * @throws PathNotFoundException if no node exists for the given
      * <code>nodePath</code>.
      * @throws RepositoryException if an other error occurs.
      */
-    void setPolicyTemplate(String nodePath, PolicyTemplate template) throws AccessControlException, PathNotFoundException, RepositoryException;
+    void setPolicy(String nodePath, AccessControlPolicy policy) throws AccessControlException, PathNotFoundException, RepositoryException;
 
     /**
-     * Removes the template from the respective node.
+     * Removes the specified policy from the node at <code>nodePath</code>.
      *
      * @param nodePath Absolute path to an existing node object.
-     * @return the PolicyTemplate that has been remove or <code>null</code>
-     * if there was no policy to remove.
+     * @param policy The policy to be removed at <code>nodePath</code>.
      * @throws AccessControlException If the Node identified by the given
-     * <code>nodePath</code> does not allow policy modifications.
+     * <code>nodePath</code> does not allow policy modifications or does not have
+     * the specified policy attached.
      * @throws PathNotFoundException if no node exists for the given
      * <code>nodePath</code>.
      * @throws RepositoryException if an other error occurs
      */
-    PolicyTemplate removePolicyTemplate(String nodePath) throws AccessControlException, PathNotFoundException, RepositoryException;
-
-    /**
-     * Returns the access control entries present with the node
-     * identified by  <code>id</code>, that have
-     * been added using {@link #addAccessControlEntry(String,Principal,Privilege[])}.
-     * The implementation may return other entries, if they can be removed
-     * using {@link #removeAccessControlEntry(String,AccessControlEntry)}.
-     *
-     * @param nodePath Absolute path to an existing node object.
-     * @return the (granting) access control entries present with the node
-     * identified by  <code>id</code>.
-     * @throws AccessControlException
-     * @throws PathNotFoundException if no node exists for the given
-     * <code>nodePath</code>.
-     * @throws UnsupportedRepositoryOperationException if only simple access
-     * control is supported.
-     * @throws RepositoryException
-     */
-    AccessControlEntry[] getAccessControlEntries(String nodePath) throws AccessControlException, PathNotFoundException, UnsupportedRepositoryOperationException, RepositoryException;
-
-    /**
-     * Adds an access control entry to the node identified by
-     * <code>id</code>. An implementation that always keeps entries with an
-     * existing <code>AccessControlPolicy</code> may choose to treat this
-     * method as short-cut for {@link #editPolicyTemplate(String)} and
-     * subsequent template modification.
-     * Note, that in addition an implementation may only allow granting
-     * ACEs as specified by JSR 283.
-     *
-     * @param nodePath Absolute path to an existing node object.
-     * @param principal
-     * @param privileges
-     * @return The entry that results from adding the specified
-     * privileges for the specified principal.
-     * @throws AccessControlException If the Node identified by the given nodePath.
-     * does not allow access control modifications, if the principal does not
-     * exist or if any of the specified privileges is unknown.
-     * @throws PathNotFoundException if no node exists for the given
-     * <code>nodePath</code>.
-     * @throws UnsupportedRepositoryOperationException if only simple access
-     * control is supported.
-     * @throws RepositoryException if an other error occurs
-     */
-    AccessControlEntry addAccessControlEntry(String nodePath, Principal principal, Privilege[] privileges) throws AccessControlException, PathNotFoundException, UnsupportedRepositoryOperationException, RepositoryException;
-
-    /**
-     * Removes the access control entry represented by the given
-     * <code>template</code> from the node identified by
-     * <code>id</code>. An implementation that always keeps entries with an
-     * existing <code>AccessControlPolicy</code> may choose to treat this
-     * method as short-cut for {@link #getPolicyTemplate(String)} and
-     * subsequent template modification.
-     * Note that only <code>PolicyEntry</code>s accessible through
-     * {@link #getAccessControlEntries(String)} can be removed by this call.
-     *
-     * @param nodePath Absolute path to an existing node object.
-     * @param entry The access control entry to be removed.
-     * @return true if entry was contained could be successfully removed.
-     * @throws AccessControlException If an access control specific exception
-     * occurs (e.g. invalid entry implementation, entry cannot be removed
-     * by this call, etc.).
-     * @throws PathNotFoundException if no node exists for the given
-     * <code>nodePath</code>.
-     * @throws UnsupportedRepositoryOperationException if only simple access
-     * control is supported.
-     * @throws RepositoryException if another error occurs.
-     */
-    boolean removeAccessControlEntry(String nodePath, AccessControlEntry entry) throws AccessControlException, PathNotFoundException, UnsupportedRepositoryOperationException, RepositoryException;
+    void removePolicy(String nodePath, AccessControlPolicy policy) throws AccessControlException, PathNotFoundException, RepositoryException;
 }

Added: 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=689499&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryImpl.java Wed Aug 27 08:12:04 2008
@@ -0,0 +1,217 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.security.authorization;
+
+import org.apache.jackrabbit.api.jsr283.security.AccessControlException;
+import org.apache.jackrabbit.api.jsr283.security.Privilege;
+import org.apache.jackrabbit.value.StringValue;
+import org.apache.jackrabbit.value.ValueHelper;
+import org.apache.jackrabbit.value.ValueFactoryImpl;
+
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import java.security.Principal;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.HashMap;
+
+/**
+ * Simple, immutable implementation of the
+ * {@link org.apache.jackrabbit.api.jsr283.security.AccessControlEntry}
+ * and the {@link JackrabbitAccessControlEntry} interfaces.
+ */
+public abstract class AccessControlEntryImpl implements JackrabbitAccessControlEntry {
+
+    private static final ValueFactory VALUE_FACTORY = ValueFactoryImpl.getInstance();
+
+    /**
+     * Privileges contained in this entry
+     */
+    private final Privilege[] privileges;
+
+    /**
+     * PrivilegeBits calculated from the privileges
+     */
+    private final int privilegeBits;
+
+    /**
+     * the Principal of this entry
+     */
+    private final Principal principal;
+
+    /**
+     * Jackrabbit specific extension: if the actions contained are allowed or
+     * denied.
+     */
+    private final boolean allow;
+
+    /**
+     * Jackrabbit specific extension: the list of additional restrictions to be
+     * included in the evaluation.
+     */
+    private final Map restrictions;
+
+    /**
+     * Hash code being calculated on demand.
+     */
+    private int hashCode = -1;
+
+    /**
+     * Construct an access control entry for the given principal and privileges.
+     *
+     * @param principal
+     * @param privileges
+     */
+    protected AccessControlEntryImpl(Principal principal, Privilege[] privileges)
+            throws AccessControlException {
+        this(principal, privileges, true, null);
+    }
+
+    /**
+     * Construct an access control entry for the given principal and privileges.
+     *
+     * @param principal
+     * @param privileges
+     * @param isAllow
+     * @param restrictions
+     */
+    protected AccessControlEntryImpl(Principal principal, Privilege[] privileges,
+                                     boolean isAllow, Map restrictions)
+            throws AccessControlException {
+        if (principal == null) {
+            throw new IllegalArgumentException();
+        }
+        this.principal = principal;
+        this.privileges = privileges;
+        this.privilegeBits = PrivilegeRegistry.getBits(privileges);;
+        this.allow = isAllow;
+        if (restrictions == null) {
+            this.restrictions = Collections.EMPTY_MAP;
+        } else {
+            this.restrictions = new HashMap(restrictions.size());
+            // validate the passed restrictions and fill the map
+            for (Iterator it = restrictions.keySet().iterator(); it.hasNext();) {
+                Object key = it.next();
+                Object v = restrictions.get(key);
+                Value value;
+                if (v instanceof Value) {
+                    // create copy of the value
+                    value = ValueHelper.copy((Value) v, VALUE_FACTORY);
+                } else {
+                    // fallback
+                    value = new StringValue(v.toString());
+                }
+                this.restrictions.put(key.toString(), value);
+            }
+        }
+    }
+
+    /**
+     * Build the hash code.
+     *
+     * @return the hash code.
+     */
+    protected int buildHashCode() {
+        int h = 17;
+        h = 37 * h + principal.getName().hashCode();
+        h = 37 * h + privilegeBits;
+        h = 37 * h + Boolean.valueOf(allow).hashCode();
+        h = 37 * h + restrictions.hashCode();
+        return h;
+    }
+
+    //-------------------------------------------------< AccessControlEntry >---
+    /**
+     * @see org.apache.jackrabbit.api.jsr283.security.AccessControlEntry#getPrincipal()
+     */
+    public Principal getPrincipal() {
+        return principal;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.api.jsr283.security.AccessControlEntry#getPrivileges()
+     */
+    public Privilege[] getPrivileges() {
+        return privileges;
+    }
+
+
+    //---------------------------------------< JackrabbitAccessControlEntry >---
+    /**
+     * @see JackrabbitAccessControlEntry#isAllow()
+     */
+    public boolean isAllow() {
+        return allow;
+    }
+
+    /**
+     * @see JackrabbitAccessControlEntry#getPrivilegeBits()
+     */
+    public int getPrivilegeBits() {
+        return privilegeBits;
+    }
+
+    /**
+     * @see JackrabbitAccessControlEntry#getRestrictionNames()
+     */
+    public String[] getRestrictionNames() {
+        return (String[]) restrictions.keySet().toArray(new String[restrictions.size()]);
+    }
+
+    /**
+     * @see JackrabbitAccessControlEntry#getRestriction(String)
+     */
+    public Value getRestriction(String restrictionName) {
+        if (restrictions.containsKey(restrictionName)) {
+            return (Value) ValueHelper.copy((Value) restrictions.get(restrictionName), VALUE_FACTORY);
+        } else {
+            return null;
+        }
+    }
+
+    //-------------------------------------------------------------< Object >---
+    /**
+     * @see Object#hashCode()
+     */
+    public int hashCode() {
+        if (hashCode == -1) {
+            hashCode = buildHashCode();
+        }
+        return hashCode;
+    }
+
+    /**
+     * Returns true if the principal and all privileges are equal / the same.
+     *
+     * @param obj
+     * @return
+     * @see Object#equals(Object)
+     */
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof AccessControlEntryImpl) {
+            AccessControlEntryImpl tmpl = (AccessControlEntryImpl) obj;
+            return principal.getName().equals(tmpl.principal.getName()) &&
+                   privilegeBits == tmpl.privilegeBits && allow == tmpl.allow &&
+                   restrictions.equals(tmpl.restrictions);
+        }
+        return false;
+    }
+}
\ No newline at end of file

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

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryImpl.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryIterator.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryIterator.java?rev=689499&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryIterator.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryIterator.java Wed Aug 27 08:12:04 2008
@@ -0,0 +1,88 @@
+/*
+ * 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 org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.api.jsr283.security.AccessControlList;
+import org.apache.jackrabbit.api.jsr283.security.AccessControlEntry;
+
+import javax.jcr.RepositoryException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.NoSuchElementException;
+import java.util.Arrays;
+
+/**
+ * <code>AccessControlEntryIterator</code>...
+ */
+public class AccessControlEntryIterator implements Iterator {
+
+    private static Logger log = LoggerFactory.getLogger(AccessControlEntryIterator.class);
+
+    private final List acls = new ArrayList();
+    private Iterator currentEntries;
+    private Object next;
+
+    public AccessControlEntryIterator(List aces) {
+        this(new AccessControlList[] {new UnmodifiableAccessControlList(aces)});
+    }
+
+    public AccessControlEntryIterator(AccessControlList[] acls) {
+        for (int i = 0; i < acls.length; i++) {
+            this.acls.add(acls[i]);
+        }
+        next = seekNext();
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException();
+    }
+
+    public boolean hasNext() {
+        return next != null;
+    }
+
+    public Object next() {
+        if (next == null) {
+            throw new NoSuchElementException();
+        }
+        Object ret = next;
+        next = seekNext();
+        return ret;
+    }
+
+    private Object seekNext() {
+        while (currentEntries == null || !currentEntries.hasNext()) {
+            if (acls.isEmpty()) {
+                // reached last acl -> break out of while loop
+                currentEntries = null;
+                break;
+            } else {
+                AccessControlEntry[] entries = new AccessControlEntry[0];
+                try {
+                    entries = ((AccessControlList) acls.remove(0)).getAccessControlEntries();
+                } catch (RepositoryException e) {
+                    log.error("Unable to retrieve ACEs: " + e.getMessage() + " -> try next.");
+                }
+                currentEntries = Arrays.asList(entries).iterator();
+            }
+        }
+        return (currentEntries == null) ? null : currentEntries.next();
+    }
+}
\ No newline at end of file

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

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryIterator.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlProvider.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlProvider.java Wed Aug 27 08:12:04 2008
@@ -16,7 +16,6 @@
  */
 package org.apache.jackrabbit.core.security.authorization;
 
-import org.apache.jackrabbit.api.jsr283.security.AccessControlEntry;
 import org.apache.jackrabbit.api.jsr283.security.AccessControlPolicy;
 import org.apache.jackrabbit.spi.Path;
 
@@ -58,12 +57,12 @@
 
     /**
      * Allows the {@link AccessControlProviderFactory} to pass a session
-     * and configuration options to the <code>AccessControlProvider</code>.
+     * and configuration parameters to the <code>AccessControlProvider</code>.
      *
      * @param systemSession
-     * @param options
+     * @param configuration
      */
-    void init(Session systemSession, Map options) throws RepositoryException;
+    void init(Session systemSession, Map configuration) throws RepositoryException;
 
     /**
      * Closes this provider when it is no longer used by the respective
@@ -72,31 +71,16 @@
     void close();
 
     /**
-     * Returns the effective policy for the node at the given absPath.
+     * Returns the effective policies for the node at the given absPath.
      *
      * @param absPath an absolute path.
-     * @return The effective policy that applies at <code>absPath</code>.
+     * @return The effective policies that apply at <code>absPath</code>.
      * @throws ItemNotFoundException If no Node with the specified
      * <code>absPath</code> exists.
      * @throws RepositoryException If another error occurs.
-     * @see org.apache.jackrabbit.api.jsr283.security.AccessControlManager#getEffectivePolicy(String)
+     * @see org.apache.jackrabbit.api.jsr283.security.AccessControlManager#getEffectivePolicies(String)
      */
-    AccessControlPolicy getPolicy(Path absPath) throws ItemNotFoundException, RepositoryException;
-
-    /**
-     * Returns the effective 'grant' access control entries for the node at absPath.
-     * An implementation may retrieve the entries from the effective
-     * policy or by other implementation specific means.
-     *
-     * @param absPath an absolute path.
-     * @return The effective access control entries or an empty array if
-     * no entries apply at <code>absPath</code>.
-     * @throws ItemNotFoundException If no Node with the specified
-     * <code>absPath</code> exists.
-     * @throws RepositoryException If an error occurs.
-     * @see org.apache.jackrabbit.api.jsr283.security.AccessControlManager#getEffectiveAccessControlEntries(String)
-     */
-    AccessControlEntry[] getAccessControlEntries(Path absPath) throws RepositoryException;
+    AccessControlPolicy[] getEffectivePolicies(Path absPath) throws ItemNotFoundException, RepositoryException;
 
     /**
      * Returns an <code>AccessControlEditor</code> for the given Session object
@@ -105,8 +89,9 @@
      *
      * @param session
      * @return the ACL editor or <code>null</code>
+     * @throws RepositoryException If an error occurs.
      */
-    AccessControlEditor getEditor(Session session);
+    AccessControlEditor getEditor(Session session) throws RepositoryException;
 
     /**
      * Compiles the effective policy for the specified set of

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlUtils.java?rev=689499&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlUtils.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlUtils.java Wed Aug 27 08:12:04 2008
@@ -0,0 +1,72 @@
+/*
+ * 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 org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.core.ItemImpl;
+
+import javax.jcr.RepositoryException;
+import java.util.Set;
+
+/**
+ * <code>AccessControlUtils</code>...
+ */
+public interface AccessControlUtils {
+
+    /**
+     * Test if the specified path points to an item that defines AC
+     * information.
+     *
+     * @param absPath
+     * @return true if the item at the specified <code>absPath</code> contains
+     * access control information.
+     */
+    boolean isAcItem(Path absPath) throws RepositoryException;
+
+    /**
+     * Test if the specified path points to an item that defines AC
+     * information and consequently should be considered protected.
+     *
+     * @param item
+     * @return true if the item at the specified <code>item</code> defines
+     * access control related information is should therefore be considered
+     * protected.
+     */
+    boolean isAcItem(ItemImpl item) throws RepositoryException;
+
+    /**
+     * Test if the specified set of principals contains an admin or system
+     * principal.
+     *
+     * @param principals
+     * @return true if the specified set of principals contains an
+     * <code>AdminPrincipal</code> or a <code>SystemPrincipal</code>.
+     */
+    boolean isAdminOrSystem(Set principals);
+
+    /**
+     * Test if if the specified set of principals will have read-only permissions
+     * only. False otherwise (or if it cannot be determined from the principal
+     * set only).
+     *
+     * @param principals
+     * @return true if the specified set of principals will only be granted
+     * read permission on all items.
+     */
+    boolean isReadOnly(Set principals);
+
+}
\ No newline at end of file

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

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlUtils.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/JackrabbitAccessControlEntry.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/JackrabbitAccessControlEntry.java?rev=689499&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/JackrabbitAccessControlEntry.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/JackrabbitAccessControlEntry.java Wed Aug 27 08:12:04 2008
@@ -0,0 +1,58 @@
+/*
+ * 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 org.apache.jackrabbit.api.jsr283.security.AccessControlEntry;
+
+import javax.jcr.Value;
+
+/**
+ * <code>JackrabbitAccessControlEntry</code> is a Jackrabbit specific extension
+ * of the <code>AccessControlEntry</code> interface. It represents an single
+ * entry of a {@link JackrabbitAccessControlList}.
+ */
+public interface JackrabbitAccessControlEntry extends AccessControlEntry {
+
+    /**
+     * @return true if this entry adds <code>Privilege</code>s for the principal;
+     * false otherwise.
+     */
+    boolean isAllow();
+
+    /**
+     * @return the int representation of the privileges defined for this entry.
+     * @see #getPrivileges()
+     */
+    int getPrivilegeBits();
+
+    /**
+     * Return the names of the restrictions present with this access control entry.
+     *
+     * @return the names of the restrictions
+     */
+    String[] getRestrictionNames();
+
+    /**
+     * Return the value of the restriction with the specified name or
+     * <code>null</code> if no such restriction exists.
+     *
+     * @param restrictionName
+     * @return value of the restriction with the specified name or
+     * <code>null</code> if no such restriction exists
+     */
+    Value getRestriction(String restrictionName);
+}

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

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/JackrabbitAccessControlEntry.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/JackrabbitAccessControlList.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/JackrabbitAccessControlList.java?rev=689499&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/JackrabbitAccessControlList.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/JackrabbitAccessControlList.java Wed Aug 27 08:12:04 2008
@@ -0,0 +1,101 @@
+/*
+ * 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 org.apache.jackrabbit.api.jsr283.security.AccessControlPolicy;
+import org.apache.jackrabbit.api.jsr283.security.AccessControlList;
+import org.apache.jackrabbit.api.jsr283.security.AccessControlException;
+import org.apache.jackrabbit.api.jsr283.security.Privilege;
+
+import javax.jcr.RepositoryException;
+import java.security.Principal;
+import java.util.Map;
+
+/**
+ * <code>JackrabbitAccessControlList</code> is an extension of the <code>AccessControlList</code>.
+ * Similar to the latter any modifications made will not take effect, until it is
+ * {@link org.apache.jackrabbit.api.jsr283.security.AccessControlManager#setPolicy(String, AccessControlPolicy)
+ * written back} and {@link javax.jcr.Session#save() saved}.
+ */
+public interface JackrabbitAccessControlList extends AccessControlList {
+
+    /**
+     * Returns the path of the node this policy has been created for.
+     *  
+     * @return the path of the node this policy has been created for.
+     */
+    String getPath();
+
+    /**
+     * Returns <code>true</code> if this policy does not yet define any
+     * entries.
+     *
+     * @return If no entries are present.
+     */
+    boolean isEmpty();
+
+    /**
+     * Returns the number of entries or 0 if the policy {@link #isEmpty() is empty}.
+     *
+     * @return The number of entries present or 0 if the policy {@link #isEmpty() is empty}.
+     */
+    int size();
+
+    /**
+     * Same as {@link #addEntry(Principal, Privilege[], boolean, Map)} using
+     * some implementation specific restrictions.
+     *
+     * @param principal
+     * @param privileges
+     * @param isAllow
+     * @return true if this policy has changed by incorporating the given entry;
+     * false otherwise.
+     * @throws AccessControlException If any of the given parameter is invalid
+     * or cannot be handled by the implementation.
+     * @throws RepositoryException If another error occurs.
+     * @see AccessControlList#addAccessControlEntry(Principal, Privilege[])
+     */
+    boolean addEntry(Principal principal, Privilege[] privileges, boolean isAllow) throws AccessControlException, RepositoryException;
+
+    /**
+     * Adds an access control entry to this policy consisting of the specified
+     * <code>principal</code>, the specified <code>privileges</code>, the
+     * <code>isAllow</code> flag and an optional map containing additional
+     * restrictions.
+     * <p/>
+     * This method returns <code>true</code> if this policy was modified,
+     * <code>false</code> otherwise.
+     * <p/>
+     * An <code>AccessControlException</code> is thrown if any of the specified
+     * parameters is invalid or if some other access control related exception occurs.
+     * 
+     * @param principal
+     * @param privileges
+     * @param isAllow
+     * @param restrictions A map of additional restrictions used to narrow the
+     * effect of the entry to be created. The map must map JCR names to a single
+     * {@link javax.jcr.Value} object.
+     * @return true if this policy has changed by incorporating the given entry;
+     * false otherwise.
+     * @throws AccessControlException If any of the given parameter is invalid
+     * or cannot be handled by the implementation.
+     * @throws RepositoryException If another error occurs.
+     * @see AccessControlList#addAccessControlEntry(Principal, Privilege[])
+     */
+    boolean addEntry(Principal principal, Privilege[] privileges,
+                     boolean isAllow, Map restrictions) throws AccessControlException, RepositoryException;
+}

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

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/JackrabbitAccessControlList.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/NamedAccessControlPolicyImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/NamedAccessControlPolicyImpl.java?rev=689499&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/NamedAccessControlPolicyImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/NamedAccessControlPolicyImpl.java Wed Aug 27 08:12:04 2008
@@ -0,0 +1,42 @@
+/*
+ * 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 org.apache.jackrabbit.api.jsr283.security.NamedAccessControlPolicy;
+
+import javax.jcr.RepositoryException;
+
+/** <code>NamedAccessControlPolicyImpl</code>... */
+public final class NamedAccessControlPolicyImpl implements NamedAccessControlPolicy {
+
+    private final String jcrName;
+
+    public NamedAccessControlPolicyImpl(String jcrName) {
+        if (jcrName == null) {
+            throw new IllegalArgumentException("The name of a named access control policy might not be null.");
+        }
+        this.jcrName = jcrName;
+    }
+
+    //-------------------------------------------< NamedAccessControlPolicy >---
+    /**
+     * @see NamedAccessControlPolicy#getName()
+     */
+    public String getName() throws RepositoryException {
+        return jcrName;
+    }
+}
\ No newline at end of file

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

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/NamedAccessControlPolicyImpl.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/Permission.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/Permission.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/Permission.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/Permission.java Wed Aug 27 08:12:04 2008
@@ -23,14 +23,14 @@
 
     public static final int NONE = 0;
 
-    public static final int READ = 1;
+    public static final int READ = 1;   
+
+    public static final int SET_PROPERTY = 2;
 
     public static final int ADD_NODE = 4;
 
     public static final int REMOVE_NODE = 8;
 
-    public static final int SET_PROPERTY = 2;
-
     public static final int REMOVE_PROPERTY = 16;
 
     public static final int ALL = (READ | SET_PROPERTY | ADD_NODE | REMOVE_NODE | REMOVE_PROPERTY);
@@ -45,11 +45,13 @@
      * 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_node, remove).
+     * on a Node (add_child_nodes, remove_child_nodes).
+     * @param isAllow
      * @param protectsPolicy
      * @return the permissions granted evaluating the given privileges.
      */
-    public static int calculatePermissions(int privs, int parentPrivs, boolean protectsPolicy) {
+    public static int calculatePermissions(int privs, int parentPrivs,
+                                           boolean isAllow, boolean protectsPolicy) {
         int perm = Permission.NONE;
         if (protectsPolicy) {
             if ((parentPrivs & PrivilegeRegistry.READ_AC) == PrivilegeRegistry.READ_AC) {
@@ -69,12 +71,29 @@
                 perm |= Permission.SET_PROPERTY;
                 perm |= Permission.REMOVE_PROPERTY;
             }
-            // the following permissions are granted through privilege on the parent.
+            // add_node permission is granted through privilege on the parent.
             if ((parentPrivs & PrivilegeRegistry.ADD_CHILD_NODES) == PrivilegeRegistry.ADD_CHILD_NODES) {
                 perm |= Permission.ADD_NODE;
             }
-            if ((parentPrivs & PrivilegeRegistry.REMOVE_CHILD_NODES) == PrivilegeRegistry.REMOVE_CHILD_NODES) {
-                perm |= Permission.REMOVE_NODE;
+            /*
+             remove_node is
+             allowed: only if remove_child_nodes privilege is present on
+                      the parent AND remove_node is present on the node itself
+             denied : if either remove_child_nodes is denied on the parent
+                      OR remove_node is denied on the node itself.
+            */
+            if (isAllow) {
+                if ((parentPrivs & PrivilegeRegistry.REMOVE_CHILD_NODES) ==
+                        PrivilegeRegistry.REMOVE_CHILD_NODES &&
+                        (privs & PrivilegeRegistry.REMOVE_NODE) == PrivilegeRegistry.REMOVE_NODE) {
+                    perm |= Permission.REMOVE_NODE;
+                }
+            } else {
+                if ((parentPrivs & PrivilegeRegistry.REMOVE_CHILD_NODES) ==
+                        PrivilegeRegistry.REMOVE_CHILD_NODES ||
+                        (privs & PrivilegeRegistry.REMOVE_NODE) == PrivilegeRegistry.REMOVE_NODE) {
+                    perm |= Permission.REMOVE_NODE;
+                }
             }
         }
         return perm;

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=689499&r1=689498&r2=689499&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 Wed Aug 27 08:12:04 2008
@@ -18,9 +18,14 @@
 
 import org.apache.jackrabbit.api.jsr283.security.AccessControlException;
 import org.apache.jackrabbit.api.jsr283.security.Privilege;
+import org.apache.jackrabbit.spi.commons.conversion.NameResolver;
+import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.NameFactory;
 
+import javax.jcr.RepositoryException;
+import javax.jcr.NamespaceException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -30,90 +35,99 @@
 import java.util.Set;
 
 /**
- * The <code>PrivilegeSet</code> represents a set of {@link Privilege}s.
+ * The <code>PrivilegeRegistry</code> defines the set of <code>Privilege</code>s
+ * known to the repository.
  */
 public final class PrivilegeRegistry {
 
-    private static final Map REGISTERED_PRIVILEGES = new HashMap(10);
+    private static final Set REGISTERED_PRIVILEGES = new HashSet(10);
     private static final Map BITS_TO_PRIVILEGES = new HashMap();
+    private static final NameFactory NAME_FACTORY = NameFactoryImpl.getInstance();
+
+    private static final Privilege[] EMPTY_ARRAY = new Privilege[0];
 
     public static final int NO_PRIVILEGE = 0;
     public static final int READ = 1;
     public static final int MODIFY_PROPERTIES = 2;
     public static final int ADD_CHILD_NODES = 4;
     public static final int REMOVE_CHILD_NODES = 8;
-    public static final int READ_AC = 16;
-    public static final int MODIFY_AC =32;
+    public static final int REMOVE_NODE = 16;
+    public static final int READ_AC = 32;
+    public static final int MODIFY_AC = 64;
     public static final int WRITE = 14;
-    public static final int ALL = 63;
+    public static final int ALL = 127;
 
-    public static final Privilege READ_PRIVILEGE = registerPrivilege(Privilege.READ, READ);
-    public static final Privilege MODIFY_PROPERTIES_PRIVILEGE = registerPrivilege(Privilege.MODIFY_PROPERTIES, MODIFY_PROPERTIES);
-    public static final Privilege ADD_CHILD_NODES_PRIVILEGE = registerPrivilege(Privilege.ADD_CHILD_NODES, ADD_CHILD_NODES);
-    public static final Privilege REMOVE_CHILD_NODES_PRIVILEGE = registerPrivilege(Privilege.REMOVE_CHILD_NODES, REMOVE_CHILD_NODES);
-    public static final Privilege READ_AC_PRIVILEGE = registerPrivilege(Privilege.READ_ACCESS_CONTROL, READ_AC);
-    public static final Privilege MODIFY_AC_PRIVILEGE = registerPrivilege(Privilege.MODIFY_ACCESS_CONTROL, MODIFY_AC);
-    public static final Privilege WRITE_PRIVILEGE = registerPrivilege(Privilege.WRITE, new PrivilegeImpl[] {
-            (PrivilegeImpl) MODIFY_PROPERTIES_PRIVILEGE,
-            (PrivilegeImpl) ADD_CHILD_NODES_PRIVILEGE,
-            (PrivilegeImpl) REMOVE_CHILD_NODES_PRIVILEGE });
-    public static final Privilege ALL_PRIVILEGE = registerPrivilege(new AllPrivilege());
+    private static final InternalPrivilege READ_PRIVILEGE = registerPrivilege(new InternalPrivilege(Privilege.JCR_READ, READ));
+    private static final InternalPrivilege MODIFY_PROPERTIES_PRIVILEGE = registerPrivilege(new InternalPrivilege(Privilege.JCR_MODIFY_PROPERTIES, MODIFY_PROPERTIES));
+    private static final InternalPrivilege ADD_CHILD_NODES_PRIVILEGE = registerPrivilege(new InternalPrivilege(Privilege.JCR_ADD_CHILD_NODES, ADD_CHILD_NODES));
+    private static final InternalPrivilege REMOVE_CHILD_NODES_PRIVILEGE = registerPrivilege(new InternalPrivilege(Privilege.JCR_REMOVE_CHILD_NODES, REMOVE_CHILD_NODES));
+    private static final InternalPrivilege REMOVE_NODE_PRIVILEGE = registerPrivilege(new InternalPrivilege(Privilege.JCR_REMOVE_NODE, REMOVE_NODE));
+    private static final InternalPrivilege READ_AC_PRIVILEGE = registerPrivilege(new InternalPrivilege(Privilege.JCR_READ_ACCESS_CONTROL, READ_AC));
+    private static final InternalPrivilege MODIFY_AC_PRIVILEGE = registerPrivilege(new InternalPrivilege(Privilege.JCR_MODIFY_ACCESS_CONTROL, MODIFY_AC));
+    private static final InternalPrivilege WRITE_PRIVILEGE = registerPrivilege(new InternalPrivilege(Privilege.JCR_WRITE, new InternalPrivilege[] {
+            MODIFY_PROPERTIES_PRIVILEGE,
+            ADD_CHILD_NODES_PRIVILEGE,
+            REMOVE_CHILD_NODES_PRIVILEGE }));
+    private static final InternalPrivilege ALL_PRIVILEGE = registerPrivilege(new InternalPrivilege(Privilege.JCR_ALL, new InternalPrivilege[] {
+            READ_PRIVILEGE,
+            WRITE_PRIVILEGE,
+            REMOVE_NODE_PRIVILEGE,
+            READ_AC_PRIVILEGE,
+            MODIFY_AC_PRIVILEGE}));
 
-    public static Privilege[] getRegisteredPrivileges() {
-        return (Privilege[]) REGISTERED_PRIVILEGES.values().toArray(new Privilege[REGISTERED_PRIVILEGES.size()]);
-    }
+    /**
+     * The name resolver used to determine the correct privilege
+     * {@link Privilege#getName() name} depending on the sessions namespace
+     * mappings.
+     */
+    private final NameResolver resolver;
 
-    public static Privilege[] getPrivileges(String[] privilegeNames) throws AccessControlException {
-        if (privilegeNames == null || privilegeNames.length == 0) {
-            throw new AccessControlException();
-        }
-        PrivilegeImpl[] privileges = new PrivilegeImpl[privilegeNames.length];
-        for (int i = 0; i < privilegeNames.length; i++) {
-            String name = privilegeNames[i];
-            if (REGISTERED_PRIVILEGES.containsKey(name)) {
-                privileges[i] = (PrivilegeImpl) REGISTERED_PRIVILEGES.get(name);
-            } else {
-                throw new AccessControlException("Unknown privilege " + name);
-            }
-        }
-        return privileges;
-    }
+    /**
+     * Per instance map containing the instance specific representation of
+     * the registered privileges.
+     */
+    private final Map localCache;
 
     /**
+     * Create a new <code>PrivilegeRegistry</code> instance.
      *
-     * @param privilegeNames
-     * @return
-     * @throws AccessControlException if the specified <code>privilegeNames</code>
-     * are <code>null</code>, an empty array or if any of the names is not known
-     * to this registry.
+     * @param resolver NameResolver used to calculate the JCR name of the
+     * privileges.
      */
-    public static int getBits(String[] privilegeNames) throws AccessControlException {
-        if (privilegeNames == null || privilegeNames.length == 0) {
-            throw new AccessControlException();
-        }
-        PrivilegeImpl[] privileges = new PrivilegeImpl[privilegeNames.length];
-        for (int i = 0; i < privilegeNames.length; i++) {
-            String name = privilegeNames[i];
-            if (REGISTERED_PRIVILEGES.containsKey(name)) {
-                privileges[i] = (PrivilegeImpl) REGISTERED_PRIVILEGES.get(name);
-            } else {
-                throw new AccessControlException("Unknown privilege " + name);
-            }
+    public PrivilegeRegistry(NameResolver resolver) {
+        this.resolver = resolver;
+        localCache = new HashMap(REGISTERED_PRIVILEGES.size());
+        for (Iterator it = REGISTERED_PRIVILEGES.iterator(); it.hasNext();) {
+            InternalPrivilege ip = (InternalPrivilege) it.next();
+            Privilege priv = new PrivilegeImpl(ip, resolver);
+            localCache.put(ip.name, priv);
         }
-        return PrivilegeImpl.getBits(privileges, false);
     }
 
     /**
-     * @param privileges
-     * @return
-     * @throws AccessControlException If the specified array is null
-     * or if it contains an unregistered privilege.
+     * Returns all registered privileges.
+     *
+     * @return all registered privileges.
      */
-    public static int getBits(Privilege[] privileges) throws AccessControlException {
-        if (privileges == null || privileges.length == 0) {
-            throw new AccessControlException();
+    public Privilege[] getRegisteredPrivileges() {
+        return (Privilege[]) localCache.values().toArray(new Privilege[localCache.size()]);
+    }
+
+    /**
+     * Returns the privilege with the specified <code>privilegeName</code>.
+     *
+     * @param privilegeName
+     * @return the privilege with the specified <code>privilegeName</code>.
+     * @throws AccessControlException If no privilege with the given name exists.
+     * @throws RepositoryException If another error occurs.
+     */
+    public Privilege getPrivilege(String privilegeName) throws AccessControlException, RepositoryException {
+        Name name = resolver.getQName(privilegeName);
+        if (localCache.containsKey(name)) {
+            return (Privilege) localCache.get(name);
+        } else {
+            throw new AccessControlException("Unknown privilege " + privilegeName);
         }
-        return PrivilegeImpl.getBits(privileges, false);
     }
 
     /**
@@ -129,63 +143,52 @@
      * or an empty array if <code>bits</code> is lower than {@link #READ} or
      * cannot be resolved to registered <code>Privilege</code>s.
      */
-    public static Privilege[] getPrivileges(int bits) {
-        Privilege[] privs = new Privilege[0];
+    public Privilege[] getPrivileges(int bits) {
+        Privilege[] privs;
         if (bits > NO_PRIVILEGE) {
-            PrivilegeImpl privilege = getPrivilege(bits);
-            if (REGISTERED_PRIVILEGES.containsKey(privilege.getName())) {
-                privs = new Privilege[] {privilege};
-            } else {
-                privs = privilege.getDeclaredAggregatePrivileges();
+            InternalPrivilege[] internalPrivs = getInteralPrivileges(bits);
+            privs = new Privilege[internalPrivs.length];
+            for (int i = 0; i < internalPrivs.length; i++) {
+                privs[i] = (Privilege) localCache.get(internalPrivs[i].name);
             }
+        } else {
+            privs = new Privilege[0];
         }
         return privs;
     }
 
     /**
-     * Returns those bits from <code>bits</code> that are not present in
-     * the <code>otherBits</code>, i.e. subtracts the other privileges from
-     * this one.<br>
-     * If the specified <code>otherBits</code> do not intersect with
-     * <code>bits</code>,  <code>bits</code> are returned.<br>
-     * If <code>bits</code> is included <code>otherBits</code>,
-     * {@link #NO_PRIVILEGE} is returned.
-     *
-     * @param bits
-     * @param otherBits
-     * @return the differences of the 2 privileges or <code>{@link #NO_PRIVILEGE}</code>.
-     */
-    public static int diff(int bits, int otherBits) {
-        return bits & ~otherBits;
-    }
-
-    /**
-     *
-     * @param name
-     * @param description
      * @param privileges
-     * @return new aggregate from the specified privileges.
+     * @return
+     * @throws AccessControlException If the specified array is null
+     * or if it contains an unregistered privilege.
      */
-    private static PrivilegeImpl getPrivilege(String name, String description, PrivilegeImpl[] privileges) {
-        return new AggregatePrivilege(name, description, privileges);
+    public static int getBits(Privilege[] privileges) throws AccessControlException {
+        if (privileges == null || privileges.length == 0) {
+            throw new AccessControlException();
+        }
+        int bits = NO_PRIVILEGE;
+        for (int i = 0; i < privileges.length; i++) {
+            Privilege priv = privileges[i];
+            if (priv instanceof PrivilegeImpl) {
+                bits |= ((PrivilegeImpl) priv).internalPrivilege.getBits();
+            } else {
+                throw new AccessControlException("Unknown privilege '" + priv.getName() + "'.");
+            }
+        }
+        return bits;
     }
 
     /**
      *
      * @param bits
-     * @return PrivilegeImpl that corresponds to the given bits.
+     * @return InternalPrivilege that corresponds to the given bits.
      */
-    private static PrivilegeImpl getPrivilege(int bits) {
-        PrivilegeImpl priv = null;
+    private static InternalPrivilege[] getInteralPrivileges(int bits) {
         Object key = new Integer(bits);
         if (BITS_TO_PRIVILEGES.containsKey(key)) {
-            return (PrivilegeImpl) BITS_TO_PRIVILEGES.get(key);
+            return (InternalPrivilege[]) BITS_TO_PRIVILEGES.get(key);
         } else {
-            // shortcut
-            if ((bits & ALL) == ALL) {
-                return (PrivilegeImpl) ALL_PRIVILEGE;
-            }
-
             List privileges = new ArrayList();
             if ((bits & READ) == READ) {
                 privileges.add(READ_PRIVILEGE);
@@ -203,6 +206,9 @@
                     privileges.add(REMOVE_CHILD_NODES_PRIVILEGE);
                 }
             }
+            if ((bits & REMOVE_NODE) == REMOVE_NODE) {
+                privileges.add(REMOVE_NODE_PRIVILEGE);
+            }
             if ((bits & READ_AC) == READ_AC) {
                 privileges.add(READ_AC_PRIVILEGE);
             }
@@ -210,226 +216,172 @@
                 privileges.add(MODIFY_AC_PRIVILEGE);
             }
 
+            InternalPrivilege[] privs;
             if (!privileges.isEmpty()) {
-                if (privileges.size() == 1) {
-                    priv = (PrivilegeImpl) privileges.get(0);
-                } else {
-                    String name = "AggregatePrivilege" + bits;
-                    priv = getPrivilege(name, null, (PrivilegeImpl[]) privileges.toArray(new PrivilegeImpl[privileges.size()]));
-                }
-                BITS_TO_PRIVILEGES.put(key, priv);
+                privs = (InternalPrivilege[]) privileges.toArray(new InternalPrivilege[privileges.size()]);
+                BITS_TO_PRIVILEGES.put(key, privs);
+            } else {
+                privs = new InternalPrivilege[0];
             }
-            return priv;
+            return privs;
         }
     }
 
-    private static Privilege registerPrivilege(String name, int bits) {
-        PrivilegeImpl priv = new SimplePrivilege(name, null, bits);
-        return registerPrivilege(priv);
-    }
-
-    private static Privilege registerPrivilege(String name, PrivilegeImpl[] privileges) {
-        PrivilegeImpl priv = getPrivilege(name, null, privileges);
-        return registerPrivilege(priv);
-    }
-
-    private static Privilege registerPrivilege(PrivilegeImpl privilege) {
-        REGISTERED_PRIVILEGES.put(privilege.getName(), privilege);
-        BITS_TO_PRIVILEGES.put(new Integer(privilege.getBits()), privilege);
+    private static InternalPrivilege registerPrivilege(InternalPrivilege privilege) {
+        REGISTERED_PRIVILEGES.add(privilege);
+        BITS_TO_PRIVILEGES.put(new Integer(privilege.getBits()), new InternalPrivilege[] {privilege});
         return privilege;
     }
 
     //--------------------------------------------------------------------------
     /**
-     * Avoid instanciation of the <code>PrivilegeRegistry</code>.
-     */
-    private PrivilegeRegistry() {}
-
-    //--------------------------------------------------------------------------
-    /**
-     *
+     * Internal representation of the registered privileges (without JCR
+     * name).
      */
-    private static abstract class PrivilegeImpl implements Privilege {
+    private static class InternalPrivilege {
 
-        static final Privilege[] EMPTY_ARRAY = new Privilege[0];
+        private final Name name;
+        private final boolean isAbstract = false;
+        private final boolean isAggregate;
+        private final InternalPrivilege[] declaredAggregates;
+        private final Set aggregates;
 
-        private final String name;
-        private final String description;
+        private final int bits;
 
-        private PrivilegeImpl(String name, String description) {
+        /**
+         * Create a simple (non-aggregate) internal privilege.
+         */
+        private InternalPrivilege(String name, int bits) {
             if (name == null) {
                 throw new IllegalArgumentException("A privilege must have a name.");
             }
-            this.name = name;
-            this.description = description;
-        }
-
-        abstract int getBits();
-
-        //------------------------------------------------------< Privilege >---
-        public String getName() {
-            return name;
-        }
-
-        public String getDescription() {
-            return description;
-        }
+            this.name = NAME_FACTORY.create(name);
+            this.bits = bits;
 
-        public boolean isAbstract() {
-            return false;
+            declaredAggregates = null;
+            aggregates = null;
+            isAggregate = false;
         }
 
         /**
-         * @param  privileges to get the bit representation for
-         * @param ignoreUnkown
-         * @return bit representing the Action
-         * @throws AccessControlException If <code>ignoreUnkown</code> is false
-         * and any of the specified privileges not a registered privilege.
+         * Create an aggregate internal privilege
          */
-        private static int getBits(Privilege[] privileges, boolean ignoreUnkown) throws AccessControlException {
-            int bits = NO_PRIVILEGE;
-            for (int i = 0; i < privileges.length; i++) {
-                Privilege priv = privileges[i];
-                if (priv instanceof PrivilegeImpl) {
-                    bits |= ((PrivilegeImpl) priv).getBits();
-                } else if (priv.isAggregate()) {
-                    // try to resolve the aggregates
-                    bits |= getBits(priv.getDeclaredAggregatePrivileges(), ignoreUnkown);
+        private InternalPrivilege(String name, InternalPrivilege[] declaredAggregates) {
+            if (name == null) {
+                throw new IllegalArgumentException("A privilege must have a name.");
+            }
+            this.name = NAME_FACTORY.create(name);
+            this.declaredAggregates = declaredAggregates;
+
+            Set aggrgt = new HashSet();
+            int bts = 0;
+            for (int i = 0; i < declaredAggregates.length; i++) {
+                InternalPrivilege priv = declaredAggregates[i];
+                bts |= priv.getBits();
+                if (priv.isAggregate) {
+                    aggrgt.addAll(priv.aggregates);
                 } else {
-                    PrivilegeImpl p = (PrivilegeImpl) REGISTERED_PRIVILEGES.get(priv.getName());
-                    if (p != null) {
-                        bits |= p.getBits();
-                    } else if (!ignoreUnkown) {
-                        throw new AccessControlException("Unknown privilege '" + priv.getName() + "'.");
-                    }
+                    aggrgt.add(priv);
                 }
             }
+            aggregates = Collections.unmodifiableSet(aggrgt);
+            bits = bts;
+            isAggregate = true;
+        }
+
+        int getBits() {
             return bits;
         }
 
         //---------------------------------------------------------< Object >---
         public int hashCode() {
-            return getBits();
+            return bits;
         }
 
         public boolean equals(Object obj) {
             if (obj == this) {
                 return true;
             }
-            if (obj instanceof PrivilegeImpl) {
-                return getBits() == ((PrivilegeImpl) obj).getBits();
+            if (obj instanceof InternalPrivilege) {
+                return bits == ((InternalPrivilege) obj).bits;
             }
             return false;
         }
     }
 
     /**
-     * Simple (non-aggregate) privilege.
+     * Simple wrapper used to provide an public representation of the
+     * registered internal privileges properly exposing the JCR name.
      */
-    private static class SimplePrivilege extends PrivilegeImpl {
-
-        private final int bits;
-
-        private SimplePrivilege(String name, String description, int bits) {
-            super(name, description);
-            this.bits = bits;
-        }
-
-        int getBits() {
-            return bits;
-        }
-
-        //------------------------------------------------------< Privilege >---
-
-        public boolean isAggregate() {
-            return false;
-        }
+    private class PrivilegeImpl implements Privilege {
 
-        public Privilege[] getDeclaredAggregatePrivileges() {
-            return EMPTY_ARRAY;
-        }
+        private final InternalPrivilege internalPrivilege;
+        private final NameResolver resolver;
 
-        public Privilege[] getAggregatePrivileges() {
-            return EMPTY_ARRAY;
+        private PrivilegeImpl(InternalPrivilege internalPrivilege,
+                              NameResolver resolver) {
+            this.internalPrivilege = internalPrivilege;
+            this.resolver = resolver;
         }
-    }
-
-    /**
-     * Aggregate privilege
-     */
-    private static class AggregatePrivilege extends PrivilegeImpl {
 
-        private final Privilege[] declaredAggregates;
-        private final Set aggregates;
-        private final int bits;
-
-        private AggregatePrivilege(String name, String description, PrivilegeImpl[] declaredAggregates) {
-            super(name, description);
-            this.declaredAggregates = declaredAggregates;
-            Set aggrgt = new HashSet();
-            int bts = 0;
-            for (int i = 0; i < declaredAggregates.length; i++) {
-                PrivilegeImpl priv = declaredAggregates[i];
-                bts |= priv.getBits();
-                if (priv.isAggregate()) {
-                    aggrgt.addAll(Arrays.asList(priv.getAggregatePrivileges()));
-                } else {
-                    aggrgt.add(priv);
-                }
+        public String getName() {
+            try {
+                return resolver.getJCRName(internalPrivilege.name);
+            } catch (NamespaceException e) {
+                // should not occur -> return internal name representation.
+                return internalPrivilege.name.toString();
             }
-            aggregates = Collections.unmodifiableSet(aggrgt);
-            bits = bts;
         }
 
-        int getBits() {
-            return bits;
+        public boolean isAbstract() {
+            return internalPrivilege.isAbstract;
         }
 
-        //------------------------------------------------------< Privilege >---
         public boolean isAggregate() {
-            return true;
+            return internalPrivilege.isAggregate;
         }
 
         public Privilege[] getDeclaredAggregatePrivileges() {
-            return declaredAggregates;
+            if (internalPrivilege.isAggregate) {
+                int len = internalPrivilege.declaredAggregates.length;
+                Privilege[] privs = new Privilege[len];
+                for (int i = 0; i < len; i++) {
+                    InternalPrivilege ip = internalPrivilege.declaredAggregates[i];
+                    privs[i] = (Privilege) localCache.get(ip.name);
+                }
+                return privs;
+            } else {
+                return EMPTY_ARRAY;
+            }
         }
 
         public Privilege[] getAggregatePrivileges() {
-            return (Privilege[]) aggregates.toArray(new Privilege[aggregates.size()]);
-        }
-    }
-
-    /**
-     * The ALL privilege
-     */
-    private static class AllPrivilege extends PrivilegeImpl {
-
-        private AllPrivilege() {
-            super(Privilege.ALL, null);
-        }
-
-        int getBits() {
-            return PrivilegeRegistry.ALL;
-        }
-
-        //------------------------------------------------------< Privilege >---
-        public boolean isAggregate() {
-            return true;
+            if (internalPrivilege.isAggregate) {
+                Privilege[] privs = new Privilege[internalPrivilege.aggregates.size()];
+                int i = 0;
+                for (Iterator it = internalPrivilege.aggregates.iterator(); it.hasNext();) {
+                    InternalPrivilege ip = (InternalPrivilege) it.next();
+                    privs[i++] = (Privilege) localCache.get(ip.name);
+                }
+                return privs;
+            } else {
+                return EMPTY_ARRAY;
+            }
         }
 
-        public Privilege[] getDeclaredAggregatePrivileges() {
-            return getAggregatePrivileges();
+        public int hashCode() {
+            return internalPrivilege.hashCode();
         }
 
-        public Privilege[] getAggregatePrivileges() {
-            Set all = new HashSet(REGISTERED_PRIVILEGES.values());
-            for (Iterator it = all.iterator(); it.hasNext();) {
-                Privilege priv = (Privilege) it.next();
-                if (priv.isAggregate()) {
-                    it.remove();
-                }
+        public boolean equals(Object obj) {
+            if (obj == this) {
+                return true;
             }
-            return (Privilege[]) all.toArray(new Privilege[all.size()]);
+            if (obj instanceof PrivilegeImpl) {
+                PrivilegeImpl other = (PrivilegeImpl) obj;
+                return internalPrivilege.equals(other.internalPrivilege);
+            }
+            return false;
         }
     }
 }

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/UnmodifiableAccessControlList.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/UnmodifiableAccessControlList.java?rev=689499&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/UnmodifiableAccessControlList.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/UnmodifiableAccessControlList.java Wed Aug 27 08:12:04 2008
@@ -0,0 +1,82 @@
+/*
+ * 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 org.apache.jackrabbit.api.jsr283.security.AccessControlEntry;
+import org.apache.jackrabbit.api.jsr283.security.AccessControlException;
+import org.apache.jackrabbit.api.jsr283.security.AccessControlList;
+import org.apache.jackrabbit.api.jsr283.security.Privilege;
+
+import javax.jcr.RepositoryException;
+import java.security.Principal;
+import java.util.List;
+
+/**
+ * An implementation of the <code>AccessControlList</code> interface that only
+ * allows for reading. The write methods
+ * ({@link #addAccessControlEntry(Principal principal, Privilege[] privileges) addAccessControlEntry}
+ * and {@link #removeAccessControlEntry(AccessControlEntry) removeAccessControlEntry})
+ * throw an <code>AccessControlException</code>.
+ */
+public class UnmodifiableAccessControlList implements AccessControlList {
+
+    private final AccessControlEntry[] accessControlEntries;
+
+    /**
+     * Construct a new <code>UnmodifiableAccessControlList</code>
+     *
+     * @param acl
+     */
+    public UnmodifiableAccessControlList(AccessControlList acl) throws RepositoryException {
+        accessControlEntries = acl.getAccessControlEntries();
+    }
+
+    /**
+     * Construct a new <code>UnmodifiableAccessControlList</code>
+     *
+     * @param accessControlEntries
+     */
+    public UnmodifiableAccessControlList(List accessControlEntries) {
+        this.accessControlEntries = (AccessControlEntry[]) accessControlEntries.toArray(new AccessControlEntry[accessControlEntries.size()]);
+    }
+
+    //--------------------------------------------------< AccessControlList >---
+    /**
+     * @see AccessControlList#getAccessControlEntries()
+     */
+    public AccessControlEntry[] getAccessControlEntries()
+            throws RepositoryException {
+        return accessControlEntries;
+    }
+
+    /**
+     * @see AccessControlList#addAccessControlEntry(Principal, Privilege[])
+     */
+    public boolean addAccessControlEntry(Principal principal,
+                                         Privilege[] privileges)
+            throws AccessControlException, RepositoryException {
+        throw new AccessControlException("Unmodifiable ACL. Use AccessControlManager#getApplicablePolicies in order to obtain an modifiable ACL.");
+    }
+
+    /**
+     * @see AccessControlList#removeAccessControlEntry(AccessControlEntry)
+     */
+    public void removeAccessControlEntry(AccessControlEntry ace)
+            throws AccessControlException, RepositoryException {
+        throw new AccessControlException("Unmodifiable ACL. Use AccessControlManager#getApplicablePolicies in order to obtain an modifiable ACL.");
+    }
+}
\ No newline at end of file

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

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/UnmodifiableAccessControlList.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/WorkspaceAccessManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/WorkspaceAccessManager.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/WorkspaceAccessManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/WorkspaceAccessManager.java Wed Aug 27 08:12:04 2008
@@ -44,8 +44,8 @@
     void close() throws RepositoryException;
 
     /**
-     * Returns true if access to the workspace with the given name is granted to
-     * the to any of the specified principals.
+     * Returns <code>true</code> if access to the workspace with the given name
+     * is granted to the to any of the specified principals.
      *
      * @param principals
      * @param workspaceName