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 [7/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...

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java?rev=689499&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java Wed Aug 27 08:12:04 2008
@@ -0,0 +1,317 @@
+/*
+ * 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.principalbased;
+
+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 org.apache.jackrabbit.api.jsr283.security.AccessControlManager;
+import org.apache.jackrabbit.core.NodeImpl;
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.security.authorization.AccessControlConstants;
+import org.apache.jackrabbit.core.security.authorization.AccessControlEntryImpl;
+import org.apache.jackrabbit.core.security.authorization.JackrabbitAccessControlList;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
+import org.apache.jackrabbit.value.ValueFactoryImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Item;
+import javax.jcr.NamespaceException;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Implementation of the {@link JackrabbitAccessControlList} interface that
+ * is detached from the effective access control content. Consequently, any
+ * modifications applied to this ACL only take effect, if the policy gets
+ * {@link org.apache.jackrabbit.api.jsr283.security.AccessControlManager#setPolicy(String, org.apache.jackrabbit.api.jsr283.security.AccessControlPolicy) reapplied}
+ * to the <code>AccessControlManager</code> and the changes are saved.
+ */
+class ACLTemplate implements JackrabbitAccessControlList, AccessControlConstants {
+
+    private static Logger log = LoggerFactory.getLogger(ACLTemplate.class);
+
+    private static final ValueFactory V_FACTORY = ValueFactoryImpl.getInstance();
+
+    /**
+     * rep:nodePath property name (optional if the ACL is stored with the
+     * node itself).
+     */
+    static final Name P_NODE_PATH = NF.create(Name.NS_REP_URI, "nodePath");
+    /**
+     * rep:glob property name used to restrict the number of child nodes
+     * or properties that are affected by the privileges applied at
+     * rep:nodePath
+     */
+    static final Name P_GLOB = NF.create(Name.NS_REP_URI, "glob");
+
+    private final Principal principal;
+    private final String path;
+    private final List entries = new ArrayList();
+
+    private final String jcrNodePathName;
+    private final String jcrGlobName;
+
+    ACLTemplate(Principal principal, String path, NamePathResolver resolver) throws RepositoryException {
+        this(principal, path, null, resolver);
+    }
+
+    ACLTemplate(Principal principal, NodeImpl acNode) throws RepositoryException {
+        this(principal, acNode.getPath(), acNode, (SessionImpl) acNode.getSession());
+    }
+
+    private ACLTemplate(Principal principal, String path, NodeImpl acNode, NamePathResolver resolver)
+            throws RepositoryException {
+        this.principal = principal;
+        this.path = path;
+
+        jcrNodePathName = resolver.getJCRName(P_NODE_PATH);
+        jcrGlobName = resolver.getJCRName(P_GLOB);
+
+        if (acNode != null && acNode.hasNode(N_POLICY)) {
+            // build the list of policy entries;
+            NodeImpl aclNode = acNode.getNode(N_POLICY);
+            AccessControlManager acMgr = ((SessionImpl) aclNode.getSession()).getAccessControlManager();
+
+            // loop over all entries in the aclNode for the princ-Principal
+            for (NodeIterator aceNodes = aclNode.getNodes(); aceNodes.hasNext();) {
+                NodeImpl aceNode = (NodeImpl) aceNodes.nextNode();
+                if (aceNode.isNodeType(NT_REP_ACE)) {
+                    // the isAllow flag:
+                    boolean isAllow = aceNode.isNodeType(NT_REP_GRANT_ACE);
+                    // the privileges
+                    Value[] pValues = aceNode.getProperty(P_PRIVILEGES).getValues();
+                    Privilege[] privileges = new Privilege[pValues.length];
+                    for (int i = 0; i < pValues.length; i++) {
+                        privileges[i] = acMgr.privilegeFromName(pValues[i].getString());
+                    }
+                    // the restrictions:
+                    Map restrictions = new HashMap(2);
+                    Property prop = aceNode.getProperty(P_NODE_PATH);
+                    restrictions.put(prop.getName(), prop.getValue());
+
+                    if (aceNode.hasProperty(P_GLOB)) {
+                        prop = aceNode.getProperty(P_GLOB);
+                        restrictions.put(prop.getName(), prop.getValue());
+                    }
+                    // finally add the entry
+                    Entry entry = new Entry(principal, privileges, isAllow, restrictions);
+                    entries.add(entry);
+                } else {
+                    log.warn("ACE must be of nodetype rep:ACE -> ignored child-node " + aceNode.getPath());
+                }
+            }
+        } // else: no-node at all or no acl-node present.
+    }
+
+    //-----------------------------------------------------< JackrabbitAccessControlList >---
+    /**
+     * @see JackrabbitAccessControlList#getPath()
+     */
+    public String getPath() {
+        return path;
+    }
+
+    /**
+     * @see JackrabbitAccessControlList#isEmpty()
+     */
+    public boolean isEmpty() {
+        return entries.isEmpty();
+    }
+
+    /**
+     * @see JackrabbitAccessControlList#size()
+     */
+    public int size() {
+        return entries.size();
+    }
+
+    /**
+     * @see JackrabbitAccessControlList#addEntry(Principal, Privilege[], boolean)
+     */
+    public boolean addEntry(Principal principal, Privilege[] privileges, boolean isAllow)
+            throws AccessControlException, RepositoryException {
+        return addEntry(principal, privileges, isAllow, null);
+    }
+
+    /**
+     * Known restrictions are:
+     * <pre>
+     *   rep:nodePath  (mandatory) value-type: PATH
+     *   rep:glob      (optional)  value-type: STRING
+     * </pre>
+     *
+     * @see JackrabbitAccessControlList#addEntry(Principal, Privilege[], boolean, Map)
+     */
+    public boolean addEntry(Principal principal, Privilege[] privileges,
+                            boolean isAllow, Map restrictions)
+            throws AccessControlException, RepositoryException {
+        if (restrictions == null || restrictions.isEmpty()) {
+            log.debug("Restrictions missing. Using default: rep:nodePath = " + getPath() + "; rep:glob = null.");
+            // default restrictions:
+            restrictions = Collections.singletonMap(jcrNodePathName,
+                    V_FACTORY.createValue(getPath(), PropertyType.PATH));
+        }
+        Entry entry = new Entry(principal, privileges, isAllow, restrictions);
+        if (entries.contains(entry)) {
+            log.debug("Entry is already contained in policy -> no modification.");
+            return false;
+        } else {
+            // TODO: to be improved. clean redundant entries
+            entries.add(0, entry);
+            return true;
+        }
+    }
+
+    //--------------------------------------------------< AccessControlList >---
+    /**
+     * @see AccessControlList#getAccessControlEntries()
+     */
+    public AccessControlEntry[] getAccessControlEntries()
+            throws RepositoryException {
+        return (Entry[]) entries.toArray(new Entry[entries.size()]);
+    }
+
+    /**
+     * @see AccessControlList#addAccessControlEntry(Principal, Privilege[])
+     */
+    public boolean addAccessControlEntry(Principal principal,
+                                         Privilege[] privileges)
+            throws AccessControlException, RepositoryException {
+        return addEntry(principal, privileges, true, Collections.EMPTY_MAP);
+    }
+
+    /**
+     * @see AccessControlList#removeAccessControlEntry(AccessControlEntry)
+     */
+    public void removeAccessControlEntry(AccessControlEntry ace)
+            throws AccessControlException, RepositoryException {
+        if (!(ace instanceof Entry)) {
+            throw new AccessControlException("Invalid AccessControlEntry implementation " + ace.getClass().getName() + ".");
+        }
+        if (!entries.remove(ace)) {
+            throw new AccessControlException("Cannot remove AccessControlEntry " + ace);
+        }
+    }
+
+    //-------------------------------------------------------------< Object >---
+    /**
+     * Returns zero to satisfy the Object equals/hashCode contract.
+     * This class is mutable and not meant to be used as a hash key.
+     *
+     * @return always zero
+     * @see Object#hashCode()
+     */
+    public int hashCode() {
+        return 0;
+    }
+
+    /**
+     * Returns true if the path and the entries are equal; false otherwise.
+     *
+     * @param obj
+     * @return true if the path and the entries are equal; false otherwise.
+     * @see Object#equals(Object)
+     */
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+
+        if (obj instanceof ACLTemplate) {
+            ACLTemplate acl = (ACLTemplate) obj;
+            return principal.equals(acl.principal) &&
+                   path.equals(acl.path) && entries.equals(acl.entries);
+        }
+        return false;
+    }
+
+    //--------------------------------------------------------------------------
+    /**
+     *
+     */
+    class Entry extends AccessControlEntryImpl {
+
+        /**
+         *
+         */
+        private final String nodePath;
+
+        /**
+         * Globbing pattern
+         */
+        private final GlobPattern pattern;
+
+        Entry(Principal principal, Privilege[] privileges, boolean allow, Map restrictions)
+                throws AccessControlException, RepositoryException {
+            super(principal, privileges, allow, restrictions);
+            checkValidEntry();
+
+            // TODO: review again
+            nodePath = ((Value) getRestriction(jcrNodePathName)).getString();
+            Value glob = ((Value) getRestriction(jcrGlobName));
+            if (glob != null) {
+                StringBuffer b = new StringBuffer(nodePath);
+                b.append(glob.getString());
+                pattern = GlobPattern.create(b.toString());
+            } else {
+                pattern = GlobPattern.create(nodePath);
+            }
+        }
+
+        private void checkValidEntry() throws AccessControlException, NamespaceException {
+            if (!principal.equals(getPrincipal())) {
+                throw new AccessControlException("Invalid principal. Expected: " + principal);
+            }
+            if (!isAllow() && getPrincipal() instanceof Group) {
+                throw new AccessControlException("For group principals permissions can only be added but not denied.");
+            }
+
+            String[] rNames = getRestrictionNames();
+            if (!Arrays.asList(rNames).contains(jcrNodePathName)) {
+                throw new AccessControlException("Missing mandatory restriction: " + jcrNodePathName);
+            }
+        }
+
+        boolean matches(String jcrPath) throws RepositoryException {
+            return pattern.matches(jcrPath);
+        }
+
+        boolean matches(Item item) throws RepositoryException {
+            return pattern.matches(item);
+        }
+
+        boolean matchesNodePath(String jcrPath) {
+            return nodePath.equals(jcrPath);
+        }
+    }
+}
\ No newline at end of file

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

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

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/GlobPattern.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/GlobPattern.java?rev=689499&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/GlobPattern.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/GlobPattern.java Wed Aug 27 08:12:04 2008
@@ -0,0 +1,127 @@
+/*
+ * 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.principalbased;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.util.Text;
+
+import javax.jcr.Item;
+import javax.jcr.RepositoryException;
+
+/**
+ * <code>GlobPattern</code>...
+ */
+class GlobPattern {
+
+    //TODO: add proper impl.
+
+    private static Logger log = LoggerFactory.getLogger(GlobPattern.class);
+
+    private static final char ALL = '*';
+    public static final String WILDCARD_ALL = "*";
+
+    private final String pattern;
+
+    private GlobPattern(String pattern)  {
+        this.pattern = pattern;
+    }
+
+    static GlobPattern create(String pattern) {
+        if (pattern == null) {
+            throw new IllegalArgumentException();
+        }
+        return new GlobPattern(pattern);
+    }
+
+    boolean matches(String toMatch) {
+        // shortcut
+        if (WILDCARD_ALL.equals(pattern)) {
+            return true;
+        }
+        if (toMatch == null) {
+            return false;
+        }
+
+        if (containsWildCard()) {
+            return matches(pattern, toMatch);
+        } else {
+            return pattern.equals(toMatch) || Text.isDescendant(pattern, toMatch);
+        }
+    }
+
+    boolean matches(Item itemToMatch) {
+        try {
+            // TODO: missing proper impl
+            return matches(itemToMatch.getPath());
+        } catch (RepositoryException e) {
+            log.error("Unable to determine match.", e.getMessage());
+            return false;
+        }
+    }
+
+    private boolean containsWildCard() {
+        // TODO: add proper impl
+        return pattern.indexOf(ALL) > -1;
+    }
+
+    private static boolean matches(String pattern, String toMatch) {
+        // TODO: add proper impl
+        char[] c1 = pattern.toCharArray();
+        char[] c2 = toMatch.toCharArray();
+
+        for (int i = 0; i < c1.length; i++) {
+            if (c1[i] == ALL) {
+                return true;
+            }
+            if (i >= c2.length || c1[i] != c2[i]) {
+                return false;
+            }
+        }
+
+        return false;
+    }
+
+    //-------------------------------------------------------------< Object >---
+
+    /**
+     * @see Object#hashCode()
+     */
+    public int hashCode() {
+        return pattern.hashCode();
+    }
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString() {
+        return pattern;
+    }
+
+    /**
+     * @see Object#equals(Object)
+     */
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof GlobPattern) {
+            return pattern.equals(((GlobPattern)obj).pattern);
+        }
+        return false;
+    }
+}
\ No newline at end of file

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

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

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AbstractPrincipalProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AbstractPrincipalProvider.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AbstractPrincipalProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AbstractPrincipalProvider.java Wed Aug 27 08:12:04 2008
@@ -67,6 +67,13 @@
     }
 
     /**
+     * Add an entry to the principal cache.
+     */
+    protected synchronized void addToCache(Principal principal) {
+        cache.put(principal.getName(), principal);
+    }
+
+    /**
      * Called if the cache does not contain the principal requested.<br>
      * Implementations should return a {@link Principal} from their source,
      * if it contains one for the given name or <code>null</code>.
@@ -80,13 +87,6 @@
     //--------------------------------------------------< PrincipalProvider >---
     /**
      * {@inheritDoc}
-     */
-    public boolean hasPrincipal(String principalName) {
-        return getPrincipal(principalName) != null;
-    }
-
-    /**
-     * {@inheritDoc}
      *
      * {@link #providePrincipal(String)} is called, if no principal with the
      * given name is present in the cache.
@@ -97,7 +97,7 @@
         if (principal == null) {
             principal = providePrincipal(principalName);
             if (principal != null) {
-                cache.put(principalName, principal);
+                addToCache(principal);
             }
         }
         return principal;

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AdminPrincipal.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AdminPrincipal.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AdminPrincipal.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/AdminPrincipal.java Wed Aug 27 08:12:04 2008
@@ -21,7 +21,7 @@
  * the access rights and is being authenticated (in contrast to the
  * {@link org.apache.jackrabbit.core.security.SystemPrincipal SystemPrincipal}).
  */
-public final class AdminPrincipal implements JackrabbitPrincipal {
+public class AdminPrincipal implements JackrabbitPrincipal {
 
     private final String adminId;
 

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/DefaultPrincipalProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/DefaultPrincipalProvider.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/DefaultPrincipalProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/DefaultPrincipalProvider.java Wed Aug 27 08:12:04 2008
@@ -37,7 +37,6 @@
 import javax.jcr.observation.EventIterator;
 import javax.jcr.observation.EventListener;
 import java.security.Principal;
-import java.util.Collections;
 import java.util.Iterator;
 import java.util.Set;
 
@@ -71,6 +70,7 @@
     private final EveryonePrincipal everyonePrincipal;
 
     private final String pGroupName;
+    private final String pPrincipalName;
 
     /**
      * Creates a new DefaultPrincipalProvider reading the principals from the
@@ -92,9 +92,11 @@
             NameResolver resolver = (SessionImpl) securitySession;
             ntNames[0] = resolver.getJCRName(UserManagerImpl.NT_REP_USER);
             pGroupName = resolver.getJCRName(UserManagerImpl.P_GROUPS);
+            pPrincipalName = resolver.getJCRName(UserManagerImpl.P_PRINCIPAL_NAME);
         } else {
             ntNames[0] = "rep:User";
             pGroupName = "rep:groups";
+            pPrincipalName = "rep:principalName";
         }
         securitySession.getWorkspace().getObservationManager().addEventListener(this,
                 Event.NODE_REMOVED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED,
@@ -163,7 +165,7 @@
      * @param searchType
      */
     public PrincipalIterator getPrincipals(int searchType) {
-        return findPrincipals("", searchType);
+        return findPrincipals(null, searchType);
     }
 
     /**
@@ -175,9 +177,8 @@
         synchronized (membershipCache) {
             mship = (Set) membershipCache.get(userPrincipal.getName());
             if (mship == null) {
-                mship = new ListOrderedSet();
                 // recursively collect group membership
-                collectGroupMembership(userPrincipal, mship);
+                mship = collectGroupMembership(userPrincipal);
 
                 // make sure everyone-group is not missing
                 if (!mship.contains(everyonePrincipal) && everyonePrincipal.isMember(userPrincipal)) {
@@ -267,25 +268,25 @@
      * @return all Group principals the specified <code>princ</code> is member of
      * including inherited membership.
      */
-    private Set collectGroupMembership(Principal princ, Set membership) {
-        String princName = princ.getName();
-        if (!hasPrincipal(princName)) {
-            return Collections.EMPTY_SET;
-        }
-        try {
-            Authorizable auth = userManager.getAuthorizable(princ);
-            if (auth != null) {
-                Iterator itr = auth.memberOf();
-                while (itr.hasNext()) {
-                    Group group = (Group) itr.next();
-                    membership.add(group.getPrincipal());
+    private Set collectGroupMembership(Principal princ) {
+        Set membership = new ListOrderedSet();
+            try {
+                Authorizable auth = userManager.getAuthorizable(princ);
+                if (auth != null) {
+                    addToCache(princ);
+                    Iterator itr = auth.memberOf();
+                    while (itr.hasNext()) {
+                        Group group = (Group) itr.next();
+                        Principal gp = group.getPrincipal();
+                        addToCache(gp);
+                        membership.add(gp);
+                    }
+                } else {
+                    log.debug("Cannot find authorizable for principal " + princ.getName());
                 }
-            } else {
-                log.debug("Cannot find authorizable for principal " + princ.getName());
+            } catch (RepositoryException e) {
+                log.warn("Failed to determine membership for " + princ.getName(), e.getMessage());
             }
-        } catch (RepositoryException e) {
-            log.warn("Failed to determine membership for " + princName, e.getMessage());
-        }
         return membership;
     }
 
@@ -297,7 +298,7 @@
     private PrincipalIterator findUserPrincipals(String simpleFilter) {
         synchronized (userManager) {
             try {
-                Iterator itr = userManager.findUsers(simpleFilter);
+                Iterator itr = userManager.findAuthorizables(pPrincipalName, simpleFilter, UserManager.SEARCH_TYPE_USER);
                 return new PrincipalIteratorImpl(itr, false);
             } catch (RepositoryException e) {
                 log.error("Error while searching user principals.", e);
@@ -314,7 +315,7 @@
     private PrincipalIterator findGroupPrincipals(final String simpleFilter) {
         synchronized (userManager) {
             try {
-                Iterator itr = userManager.findGroups(simpleFilter);
+                Iterator itr = userManager.findAuthorizables(pPrincipalName, simpleFilter, UserManager.SEARCH_TYPE_GROUP);
 
                 // everyone will not be found by the usermanager -> extra test
                 boolean addEveryone = everyonePrincipal.getName().matches(".*"+simpleFilter+".*");
@@ -348,7 +349,9 @@
         protected Principal seekNext() {
             while (authorizableItr.hasNext()) {
                 try {
-                    return ((Authorizable) authorizableItr.next()).getPrincipal();
+                    Principal p = ((Authorizable) authorizableItr.next()).getPrincipal();
+                    addToCache(p);
+                    return p;
                 } catch (RepositoryException e) {
                     // should never get here
                     log.warn("Error while retrieving principal from group -> skip.");

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalManagerImpl.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalManagerImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalManagerImpl.java Wed Aug 27 08:12:04 2008
@@ -234,7 +234,6 @@
         }
 
         public boolean isMember(Principal member) {
-            // TODO: check if access-restrictions should be checked
             return delegatee.isMember(member);
         }
 

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalProvider.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/PrincipalProvider.java Wed Aug 27 08:12:04 2008
@@ -35,15 +35,6 @@
 public interface PrincipalProvider {
 
     /**
-     * Checks if the principal with the given name is known to this provider.
-     *
-     * @param principalName the name of the principal to check
-     * @return return <code>true</code> if the principal with this name is known
-     *         to this provider; <code>false</code> otherwise.
-     */
-    boolean hasPrincipal(String principalName);
-
-    /**
      * Returns the principal with the given name if is known to this provider
      *
      * @param principalName the name of the principal to retrieve

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java Wed Aug 27 08:12:04 2008
@@ -16,8 +16,6 @@
  */
 package org.apache.jackrabbit.core.security.simple;
 
-import org.apache.jackrabbit.api.jsr283.security.AccessControlEntry;
-import org.apache.jackrabbit.api.jsr283.security.AccessControlException;
 import org.apache.jackrabbit.api.jsr283.security.AccessControlPolicy;
 import org.apache.jackrabbit.api.jsr283.security.Privilege;
 import org.apache.jackrabbit.core.HierarchyManager;
@@ -28,8 +26,8 @@
 import org.apache.jackrabbit.core.security.AnonymousPrincipal;
 import org.apache.jackrabbit.core.security.SystemPrincipal;
 import org.apache.jackrabbit.core.security.authorization.AccessControlProvider;
+import org.apache.jackrabbit.core.security.authorization.NamedAccessControlPolicyImpl;
 import org.apache.jackrabbit.core.security.authorization.Permission;
-import org.apache.jackrabbit.core.security.authorization.PolicyTemplate;
 import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
 import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
 import org.apache.jackrabbit.spi.Name;
@@ -39,9 +37,7 @@
 import javax.jcr.AccessDeniedException;
 import javax.jcr.PathNotFoundException;
 import javax.jcr.RepositoryException;
-import javax.jcr.UnsupportedRepositoryOperationException;
 import javax.security.auth.Subject;
-import java.security.Principal;
 
 /**
  * <code>SimpleAccessManager</code> ...
@@ -49,6 +45,11 @@
 public class SimpleAccessManager extends AbstractAccessControlManager implements AccessManager {
 
     /**
+     * The policy returned upon {@link #getEffectivePolicies(String)}
+     */
+    private static final AccessControlPolicy POLICY = new NamedAccessControlPolicyImpl("Simple AccessControlPolicy");
+
+    /**
      * Subject whose access rights this AccessManager should reflect
      */
     private Subject subject;
@@ -60,6 +61,7 @@
 
     private NamePathResolver resolver;
     private WorkspaceAccessManager wspAccessMgr;
+    private PrivilegeRegistry privilegeRegistry;
 
     private boolean initialized;
 
@@ -75,7 +77,7 @@
         system = false;
     }
 
-    //--------------------------------------------------------< AccessManager >
+    //------------------------------------------------------< AccessManager >---
     /**
      * {@inheritDoc}
      */
@@ -95,6 +97,7 @@
         subject = context.getSubject();
         hierMgr = context.getHierarchyManager();
         resolver = context.getNamePathResolver();
+        privilegeRegistry = new PrivilegeRegistry(resolver);
         wspAccessMgr = wspAccessManager;
         anonymous = !subject.getPrincipals(AnonymousPrincipal.class).isEmpty();
         system = !subject.getPrincipals(SystemPrincipal.class).isEmpty();
@@ -197,7 +200,7 @@
             // null or empty privilege array -> return true
             return true;
         } else {
-            int bits = PrivilegeRegistry.getBits(privileges);
+            int bits = privilegeRegistry.getBits(privileges);
             if (system) {
                 // system has always all permissions
                 return true;
@@ -221,63 +224,28 @@
         checkValidNodePath(absPath);
 
         if (anonymous) {
-            return new Privilege[] {PrivilegeRegistry.READ_PRIVILEGE};
+            return privilegeRegistry.getPrivileges(PrivilegeRegistry.READ);
         } else if (system) {
-            return new Privilege[] {PrivilegeRegistry.ALL_PRIVILEGE};
+            return privilegeRegistry.getPrivileges(PrivilegeRegistry.ALL);
         } else {
             // @todo check permission based on principals
-            return new Privilege[] {PrivilegeRegistry.ALL_PRIVILEGE};
+            return privilegeRegistry.getPrivileges(PrivilegeRegistry.ALL);
         }
     }
 
     /**
      * {@inheritDoc}
      */
-    public AccessControlPolicy getEffectivePolicy(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
-        checkInitialized();
-        checkPrivileges(absPath, PrivilegeRegistry.READ_AC);
-
-        return new AccessControlPolicy() {
-            public String getName() throws RepositoryException {
-                return "Simple AccessControlPolicy";
-            }
-            public String getDescription() throws RepositoryException {
-                return null;
-            }
-        };
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public AccessControlEntry[] getEffectiveAccessControlEntries(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
+    public AccessControlPolicy[] getEffectivePolicies(String absPath) throws PathNotFoundException, AccessDeniedException, RepositoryException {
         checkInitialized();
         checkPrivileges(absPath, PrivilegeRegistry.READ_AC);
 
-        return new AccessControlEntry[0];
-    }
-
-    //-------------------------------------< JackrabbitAccessControlManager >---
-    /**
-     * {@inheritDoc}
-     */
-    public PolicyTemplate editPolicy(String absPath) throws AccessDeniedException, AccessControlException, UnsupportedRepositoryOperationException, RepositoryException {
-        checkInitialized();
-        checkPrivileges(absPath, PrivilegeRegistry.MODIFY_AC);
-
-        throw new UnsupportedRepositoryOperationException("Editing is not supported");
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public PolicyTemplate editPolicy(Principal principal) throws AccessDeniedException, AccessControlException, UnsupportedRepositoryOperationException, RepositoryException {
-        throw new UnsupportedRepositoryOperationException("Editing is not supported");
+        return new AccessControlPolicy[] {POLICY};
     }
 
     //---------------------------------------< AbstractAccessControlManager >---
     /**
-     * {@inheritDoc}
+     * @see AbstractAccessControlManager#checkInitialized()
      */
     protected void checkInitialized() throws IllegalStateException {
         if (!initialized) {
@@ -285,6 +253,9 @@
         }
     }
 
+    /**
+     * @see AbstractAccessControlManager#checkPrivileges(String, int)
+     */
     protected void checkPrivileges(String absPath, int privileges) throws AccessDeniedException, PathNotFoundException, RepositoryException {
         checkValidNodePath(absPath);
         if (anonymous && privileges != PrivilegeRegistry.READ) {
@@ -292,6 +263,18 @@
         }
     }
 
+    /**
+     * @see AbstractAccessControlManager#getPrivilegeRegistry()
+     */
+    protected PrivilegeRegistry getPrivilegeRegistry()
+            throws RepositoryException {
+        checkInitialized();
+        return privilegeRegistry;
+    }
+
+    /**
+     * @see AbstractAccessControlManager#checkValidNodePath(String)
+     */
     protected void checkValidNodePath(String absPath) throws PathNotFoundException, RepositoryException {
         Path path = resolver.getQPath(absPath);
         if (!path.isAbsolute()) {

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleLoginModule.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleLoginModule.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleLoginModule.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleLoginModule.java Wed Aug 27 08:12:04 2008
@@ -18,6 +18,7 @@
 
 import org.apache.jackrabbit.core.security.authentication.AbstractLoginModule;
 import org.apache.jackrabbit.core.security.authentication.Authentication;
+import org.apache.jackrabbit.core.security.principal.PrincipalProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -64,4 +65,27 @@
             }
         };
     }
+
+    /**
+     * Uses the configured {@link PrincipalProvider} to retrieve the principal.
+     * It takes the {@link PrincipalProvider#getPrincipal(String)} for the User-ID
+     * resolved by  {@link #getUserID(Credentials)}, assuming that
+     * User-ID and the corresponding principal name are always identical.
+     *
+     * @param credentials
+     * @return principal or <code>null</code> if the principal provider does
+     * not contain a user-principal with the given userID/principal name.
+     *
+     * @see AbstractLoginModule#getPrincipal(Credentials) 
+     */
+    protected Principal getPrincipal(Credentials credentials) {
+        String userId = getUserID(credentials);
+        Principal principal = principalProvider.getPrincipal(userId);
+        if (principal == null || principal instanceof Group) {
+            // no matching user principal
+            return null;
+        } else {
+            return principal;
+        }
+    }
 }
\ No newline at end of file

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleSecurityManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleSecurityManager.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleSecurityManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleSecurityManager.java Wed Aug 27 08:12:04 2008
@@ -26,9 +26,10 @@
 import org.apache.jackrabbit.core.config.SecurityConfig;
 import org.apache.jackrabbit.core.security.AMContext;
 import org.apache.jackrabbit.core.security.AccessManager;
-import org.apache.jackrabbit.core.security.AnonymousPrincipal;
 import org.apache.jackrabbit.core.security.JackrabbitSecurityManager;
 import org.apache.jackrabbit.core.security.UserPrincipal;
+import org.apache.jackrabbit.core.security.AnonymousPrincipal;
+import org.apache.jackrabbit.core.security.SecurityConstants;
 import org.apache.jackrabbit.core.security.authentication.AuthContext;
 import org.apache.jackrabbit.core.security.authentication.AuthContextProvider;
 import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
@@ -92,6 +93,9 @@
     private String anonymID;
 
     //------------------------------------------< JackrabbitSecurityManager >---
+    /**
+     * @see JackrabbitSecurityManager#init(Repository, Session)
+     */
     public void init(Repository repository, Session systemSession) throws RepositoryException {
         if (initialized) {
             throw new IllegalStateException("already initialized");
@@ -124,9 +128,19 @@
                 adminID = moduleConfig[i].getProperty(LoginModuleConfig.PARAM_ADMIN_ID);
             }
             if (moduleConfig[i].containsKey(LoginModuleConfig.PARAM_ANONYMOUS_ID)) {
-                anonymID = moduleConfig[i].getProperty(LoginModuleConfig.PARAM_ANONYMOUS_ID, null);
+                anonymID = moduleConfig[i].getProperty(LoginModuleConfig.PARAM_ANONYMOUS_ID);
             }
         }
+        // fallback:
+        if (adminID == null) {
+            log.debug("No adminID defined in LoginModule/JAAS config -> using default.");
+            adminID = SecurityConstants.ADMIN_ID;
+        }
+        if (anonymID == null) {
+            log.debug("No anonymousID defined in LoginModule/JAAS config -> using default.");
+            anonymID = SecurityConstants.ANONYMOUS_ID;
+        }
+
         // most simple principal provider registry, that does not read anything
         // from configuration
         PrincipalProvider principalProvider = new SimplePrincipalProvider();
@@ -220,8 +234,10 @@
         if (creds.hasNext()) {
             SimpleCredentials sc = (SimpleCredentials) creds.next();
             uid = sc.getUserID();
+        } else if (anonymID != null && !subject.getPrincipals(AnonymousPrincipal.class).isEmpty()) {
+            uid = anonymID;
         } else {
-            // no SimpleCredentials: assume that UserID and principal name
+            // assume that UserID and principal name
             // are the same (not totally correct) and thus return the name
             // of the first non-group principal.
             for (Iterator it = subject.getPrincipals().iterator(); it.hasNext();) {
@@ -247,7 +263,7 @@
     public AuthContext getAuthContext(Credentials creds, Subject subject)
             throws RepositoryException {
         checkInitialized();
-        return authCtxProvider.getAuthContext(creds, subject, systemSession, principalProviderRegistry);
+        return authCtxProvider.getAuthContext(creds, subject, systemSession, principalProviderRegistry, adminID, anonymID);
     }
 
     //--------------------------------------------------------------------------
@@ -271,13 +287,9 @@
             if (anonymID != null) {
                 principals.put(anonymID, new AnonymousPrincipal());
             }
+
             EveryonePrincipal everyone = EveryonePrincipal.getInstance();
             principals.put(everyone.getName(), everyone);
-
-        }
-
-        public boolean hasPrincipal(String principalName) {
-            return true;
         }
 
         public Principal getPrincipal(String principalName) {

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/GroupImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/GroupImpl.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/GroupImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/GroupImpl.java Wed Aug 27 08:12:04 2008
@@ -172,14 +172,14 @@
         while (itr.hasNext()) {
             NodeImpl n = (NodeImpl) itr.nextProperty().getParent();
             if (n.isNodeType(NT_REP_GROUP)) {
-                Group group = create(n, userManager);
+                Group group = userManager.createGroup(n);
                 // only retrieve indirect group-members if the group is not
                 // yet present (detected eventual circular membership).
                 if (members.add(group) && includeIndirect) {
                     members.addAll(((GroupImpl) group).getMembers(true));
                 }
             } else if (n.isNodeType(NT_REP_USER)) {
-                User user = UserImpl.create(n, userManager);
+                User user = userManager.createUser(n);
                 members.add(user);
             }
         }
@@ -240,9 +240,9 @@
                 try {
                     NodeImpl mem = (NodeImpl) getSession().getNodeByUUID(uuid);
                     if (mem.isNodeType(NT_REP_GROUP)) {
-                        auth = create(mem, userManager);
+                        auth = userManager.createGroup(mem);
                     } else {
-                        auth = UserImpl.create(mem, userManager);
+                        auth = userManager.createUser(mem);
                     }
                 } catch (RepositoryException e) {
                     log.warn("Internal error while building next member.", e.getMessage());

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/ImpersonationImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/ImpersonationImpl.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/ImpersonationImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/ImpersonationImpl.java Wed Aug 27 08:12:04 2008
@@ -99,7 +99,6 @@
         // make sure the given principals belong to an existing authorizable
         Authorizable auth = user.userManager.getAuthorizable(principal);
         if (auth == null || auth.isGroup()) {
-            // TODO: check again if this assumption is correct...
             log.debug("Cannot grant impersonation to a principal that is a Group " +
                       "or an unknown Authorizable.");
             return false;

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/IndexNodeResolver.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/IndexNodeResolver.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/IndexNodeResolver.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/IndexNodeResolver.java Wed Aug 27 08:12:04 2008
@@ -123,22 +123,26 @@
         stmt.append(getSearchRoot(ntName));
         stmt.append("//element(*,");
         stmt.append(getNamePathResolver().getJCRName(ntName));
-        stmt.append(")[");
 
-        int i = 0;
-        Iterator itr = props.iterator();
-        while (itr.hasNext()) {
-            stmt.append((exact) ? "@" : "jcr:like(@");
-            String pName = getNamePathResolver().getJCRName((Name) itr.next());
-            stmt.append(ISO9075.encode(pName));
-            stmt.append((exact) ? "='" : ",'%");
-            stmt.append(value);
-            stmt.append((exact) ? "'" : "%')");
-            if (++i < props.size()) {
-                stmt.append(" or ");
+        if (value == null) {
+            stmt.append(")");
+        } else {
+            stmt.append(")[");
+            int i = 0;
+            Iterator itr = props.iterator();
+            while (itr.hasNext()) {
+                stmt.append((exact) ? "@" : "jcr:like(@");
+                String pName = getNamePathResolver().getJCRName((Name) itr.next());
+                stmt.append(ISO9075.encode(pName));
+                stmt.append((exact) ? "='" : ",'%");
+                stmt.append(value);
+                stmt.append((exact) ? "'" : "%')");
+                if (++i < props.size()) {
+                    stmt.append(" or ");
+                }
             }
+            stmt.append("]");
         }
-        stmt.append("]");
         return queryManager.createQuery(stmt.toString(), Query.XPATH);
     }
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/TraversingNodeResolver.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/TraversingNodeResolver.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/TraversingNodeResolver.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/TraversingNodeResolver.java Wed Aug 27 08:12:04 2008
@@ -213,30 +213,34 @@
 
         boolean match = false;
         if (node.isNodeType(nodeTypeName)) {
-            try {
-                if (propertyNames.isEmpty()) {
-                    match = (exact) ? node.getName().equals(value) :
-                            node.getName().matches(".*"+value+".*");
-                } else {
-                    Iterator pItr = propertyNames.iterator();
-                    while (!match && pItr.hasNext()) {
-                        Name propertyName = (Name) pItr.next();
-                        if (node.hasProperty(propertyName)) {
-                            Property prop = node.getProperty(propertyName);
-                            if (prop.getDefinition().isMultiple()) {
-                                Value[] values = prop.getValues();
-                                for (int i = 0; i < values.length && !match; i++) {
-                                    match = matches(value, values[i].getString(), exact);
+            if (value == null) {
+                match = true;
+            } else {
+                try {
+                    if (propertyNames.isEmpty()) {
+                        match = (exact) ? node.getName().equals(value) :
+                                node.getName().matches(".*"+value+".*");
+                    } else {
+                        Iterator pItr = propertyNames.iterator();
+                        while (!match && pItr.hasNext()) {
+                            Name propertyName = (Name) pItr.next();
+                            if (node.hasProperty(propertyName)) {
+                                Property prop = node.getProperty(propertyName);
+                                if (prop.getDefinition().isMultiple()) {
+                                    Value[] values = prop.getValues();
+                                    for (int i = 0; i < values.length && !match; i++) {
+                                        match = matches(value, values[i].getString(), exact);
+                                    }
+                                } else {
+                                    match = matches(value, prop.getString(), exact);
                                 }
-                            } else {
-                                match = matches(value, prop.getString(), exact);
                             }
                         }
                     }
+                } catch (PatternSyntaxException pe) {
+                    log.debug("couldn't search for {}, pattern invalid: {}",
+                            value, pe.getMessage());
                 }
-            } catch (PatternSyntaxException pe) {
-                log.debug("couldn't search for {}, pattern invalid: {}",
-                          value, pe.getMessage());
             }
         }
         return match;

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java Wed Aug 27 08:12:04 2008
@@ -16,15 +16,19 @@
  */
 package org.apache.jackrabbit.core.security.user;
 
+import org.apache.jackrabbit.api.jsr283.security.AccessControlPolicy;
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.core.ItemImpl;
 import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.observation.SynchronousEventListener;
 import org.apache.jackrabbit.core.security.authorization.AbstractAccessControlProvider;
 import org.apache.jackrabbit.core.security.authorization.AbstractCompiledPermissions;
+import org.apache.jackrabbit.core.security.authorization.AccessControlEditor;
 import org.apache.jackrabbit.core.security.authorization.AccessControlProvider;
 import org.apache.jackrabbit.core.security.authorization.CompiledPermissions;
+import org.apache.jackrabbit.core.security.authorization.NamedAccessControlPolicyImpl;
 import org.apache.jackrabbit.core.security.authorization.Permission;
 import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
 import org.apache.jackrabbit.core.security.principal.ItemBasedPrincipal;
@@ -36,8 +40,6 @@
 
 import javax.jcr.ItemNotFoundException;
 import javax.jcr.Node;
-import javax.jcr.PathNotFoundException;
-import javax.jcr.Property;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.Value;
@@ -45,9 +47,7 @@
 import javax.jcr.observation.EventIterator;
 import java.security.Principal;
 import java.security.acl.Group;
-import java.util.Arrays;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -83,14 +83,14 @@
  * as member to any Group is limited to those that are editable according to
  * the restrictions described above for the 'User administrator'.</li>
  * </ul>
- *
- * TODO: allow for editing of additional ac that extends the default permission evaluted by this provided.
  */
 public class UserAccessControlProvider extends AbstractAccessControlProvider
         implements UserConstants {
 
     private static Logger log = LoggerFactory.getLogger(UserAccessControlProvider.class);
 
+    private final AccessControlPolicy policy;
+
     private Path groupsPath;
     private Path usersPath;
 
@@ -101,18 +101,27 @@
      *
      */
     public UserAccessControlProvider() {
-        super("Access control policy for the 'security' workspace.",
-              "Policy that defines the general access control rules for the security workspace.");
+        policy = new NamedAccessControlPolicyImpl("userPolicy");
     }
 
-    //--------------------------------------< AbstractAccessControlProvider >---
+    //-------------------------------------------------< AccessControlUtils >---
     /**
      * Always returns false, since this ac provider does not use content stored
      * in items to evaluate AC information.
      * 
-     * @see AbstractAccessControlProvider#isAcItem(Path)
+     * @see org.apache.jackrabbit.core.security.authorization.AccessControlUtils#isAcItem(Path)
+     */
+    public boolean isAcItem(Path absPath) throws RepositoryException {
+        return false;
+    }
+
+    /**
+     * Always returns false, since this ac provider does not use content stored
+     * in items to evaluate AC information.
+     *
+     * @see org.apache.jackrabbit.core.security.authorization.AccessControlUtils#isAcItem(ItemImpl)
      */
-    protected boolean isAcItem(Path absPath) throws RepositoryException {
+    public boolean isAcItem(ItemImpl item) throws RepositoryException {
         return false;
     }
 
@@ -120,16 +129,15 @@
     /**
      * @see AccessControlProvider#init(Session, Map)
      */
-    public void init(Session systemSession, Map options) throws RepositoryException {
-        super.init(systemSession, options);
+    public void init(Session systemSession, Map configuration) throws RepositoryException {
+        super.init(systemSession, configuration);
 
          if (systemSession instanceof SessionImpl) {
              SessionImpl sImpl = (SessionImpl) systemSession;
-             userAdminGroup = (options.containsKey(USER_ADMIN_GROUP_NAME)) ? options.get(USER_ADMIN_GROUP_NAME).toString() : USER_ADMIN_GROUP_NAME;
-             groupAdminGroup = (options.containsKey(GROUP_ADMIN_GROUP_NAME)) ? options.get(GROUP_ADMIN_GROUP_NAME).toString() : GROUP_ADMIN_GROUP_NAME;
+             userAdminGroup = (configuration.containsKey(USER_ADMIN_GROUP_NAME)) ? configuration.get(USER_ADMIN_GROUP_NAME).toString() : USER_ADMIN_GROUP_NAME;
+             groupAdminGroup = (configuration.containsKey(GROUP_ADMIN_GROUP_NAME)) ? configuration.get(GROUP_ADMIN_GROUP_NAME).toString() : GROUP_ADMIN_GROUP_NAME;
 
              // make sure the groups exist (and ev. create them).
-             // TODO: review again.
              UserManager uMgr = sImpl.getUserManager();
              if (!initGroup(uMgr, userAdminGroup)) {
                  log.warn("Unable to initialize User admininistrator group -> no user admins.");
@@ -142,12 +150,34 @@
 
              usersPath = sImpl.getQPath(USERS_PATH);
              groupsPath = sImpl.getQPath(GROUPS_PATH);
-
          } else {
              throw new RepositoryException("SessionImpl (system session) expected.");
          }
      }
 
+    /**
+     * @see AccessControlProvider#getEffectivePolicies(Path)
+     */
+    public AccessControlPolicy[] getEffectivePolicies(Path absPath) throws ItemNotFoundException, RepositoryException {
+        checkInitialized();
+        return new AccessControlPolicy[] {policy};
+    }
+
+    /**
+     * Always returns <code>null</code>.
+     *
+     * @see AccessControlProvider#getEditor(Session)
+     */
+    public AccessControlEditor getEditor(Session session) {
+        checkInitialized();
+        // not editable at all: policy is always the default and cannot be
+        // changed using the JCR API.
+        return null;
+    }
+
+    /**
+     * @see AccessControlProvider#compilePermissions(Set)
+     */
     public CompiledPermissions compilePermissions(Set principals) throws RepositoryException {
         checkInitialized();
         if (isAdminOrSystem(principals)) {
@@ -165,6 +195,9 @@
         }
     }
 
+    /**
+     * @see AccessControlProvider#canAccessRoot(Set)
+     */
     public boolean canAccessRoot(Set principals) throws RepositoryException {
         checkInitialized();
         return true;
@@ -203,20 +236,6 @@
         return userNode;
     }
 
-    private boolean isMember(Node userNode, Path memberPath) throws RepositoryException, PathNotFoundException {
-        // precondition: memberPath points to a rep:members property
-        String propPath = session.getJCRPath(memberPath);
-        if (session.propertyExists(propPath)) {
-            // check if any of the ref-values equals to the value created from
-            // the user-Node (which must be present if the user is member of the group)
-            Property membersProp = session.getProperty(propPath);
-            List values = Arrays.asList(membersProp.getValues());
-            return values.contains(session.getValueFactory().createValue(userNode));
-        } else {
-            return false;
-        }
-    }
-
     private Node getExistingNode(Path path) throws RepositoryException {
         String absPath = resolver.getJCRPath(path.getNormalizedPath());
         if (session.nodeExists(absPath)) {
@@ -233,22 +252,6 @@
         }
     }
 
-    /**
-     * Determine if for the given <code>path</code>, the set of privileges
-     * must be calculated.
-     *
-     * @param path
-     * @return true if <code>path</code> denotes an existing <code>Node</code>,
-     * false otherwise.
-     * @throws RepositoryException
-     */
-    private boolean doCalculatePrivileges(Path path) throws RepositoryException {
-        String absPath = resolver.getJCRPath(path.getNormalizedPath());
-        // privileges can only be determined for existing nodes.
-        // not for properties and neither for non-existing nodes.
-        return session.nodeExists(absPath);
-    }
-
     private static boolean containsGroup(Set principals, String groupName) {
         for (Iterator it = principals.iterator(); it.hasNext() && groupName != null;) {
             Principal p = (Principal) it.next();
@@ -306,18 +309,21 @@
          * @see AbstractCompiledPermissions#buildResult(Path)
          */
         protected Result buildResult(Path path) throws RepositoryException {
-            // default permission and default privileges
-            int perms = Permission.READ;
+            // no explicit denied permissions:
+            int denies = Permission.NONE;
+            // default allow permission and default privileges
+            int allows = Permission.READ;
             int privs;
-            boolean calcPrivs = doCalculatePrivileges(path);
+            // Determine if for path, the set of privileges must be calculated:
+            // Generally, privileges can only be determined for existing nodes.
+            boolean calcPrivs = session.nodeExists(resolver.getJCRPath(path.getNormalizedPath()));
             if (calcPrivs) {
                 privs = PrivilegeRegistry.READ;
             } else {
-                privs = 0;
+                privs = PrivilegeRegistry.NO_PRIVILEGE;
             }
 
             Path abs2Path = path.subPath(0, 4);
-            //
             if (usersPath.equals(abs2Path)) {
                 /*
                  below the user-tree
@@ -370,7 +376,7 @@
                                 // -> user can modify items below the user-node except rep:group.
                                 // principals contains 'user-admin' + 'group-admin'
                                 // -> user can modify rep:group property as well.
-                                perms = Permission.ALL;
+                                allows = Permission.ALL;
                                 if (calcPrivs) {
                                     // grant WRITE privilege
                                     // note: ac-read/modification is not included
@@ -379,7 +385,7 @@
                             } else if (userNode.isSame(node) && (!isGroupProp || isGroupAdmin)) {
                                 // user can only read && write his own props
                                 // except for the rep:group property.
-                                perms |= (Permission.SET_PROPERTY | Permission.REMOVE_PROPERTY);
+                                allows |= (Permission.SET_PROPERTY | Permission.REMOVE_PROPERTY);
                                 if (calcPrivs) {
                                     privs |= PrivilegeRegistry.MODIFY_PROPERTIES;
                                 }
@@ -397,7 +403,7 @@
                             if rep:groups is the target item.
                             */
                             if (requiredGroups) {
-                                perms = Permission.ALL;
+                                allows = Permission.ALL;
                                 if (calcPrivs) {
                                     // grant WRITE privilege
                                     // note: ac-read/modification is not included
@@ -412,14 +418,13 @@
                 - test if the user is group-administrator.
                 */
                 if (isGroupAdmin) {
-                    perms = Permission.ALL;
+                    allows = Permission.ALL;
                     if (calcPrivs) {
                         privs |= PrivilegeRegistry.WRITE;
                     }
                 }
             } // else outside of user/group tree -> read only.
-
-            return new Result(perms, privs);
+            return new Result(allows, denies, privs, PrivilegeRegistry.NO_PRIVILEGE);
         }
 
         //--------------------------------------------< CompiledPermissions >---
@@ -478,7 +483,6 @@
                                 break;
                             case Event.PROPERTY_ADDED:
                             case Event.PROPERTY_CHANGED:
-                                // TODO: improve
                                 Value[] vs = session.getProperty(evPath).getValues();
                                 String princName = session.getJCRName(P_PRINCIPAL_NAME);
                                 for (int i = 0; i < vs.length; i++) {

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImpl.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserImpl.java Wed Aug 27 08:12:04 2008
@@ -22,6 +22,7 @@
 import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.security.authentication.CryptedSimpleCredentials;
 import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
+import org.apache.jackrabbit.core.security.principal.ItemBasedPrincipal;
 import org.apache.jackrabbit.util.Text;
 
 import javax.jcr.Credentials;
@@ -124,7 +125,7 @@
     public Principal getPrincipal() throws RepositoryException {
         if (principal == null) {
             if (isAdmin()) {
-                principal = new AdminPrincipal(getPrincipalName());
+                principal = new NodeBasedAdminPrincipal(getPrincipalName());
             } else {
                 principal = new NodeBasedPrincipal(getPrincipalName());
             }
@@ -152,4 +153,19 @@
         Value v = getSession().getValueFactory().createValue(buildPasswordValue(password));
         userManager.setProtectedProperty(getNode(), P_PASSWORD, v);
     }
+
+    //--------------------------------------------------------------------------
+    /**
+     *
+     */
+    private class NodeBasedAdminPrincipal extends AdminPrincipal implements ItemBasedPrincipal {
+
+        public NodeBasedAdminPrincipal(String adminId) {
+            super(adminId);
+        }
+
+        public String getPath() throws RepositoryException {
+            return getNode().getPath();
+        }
+    }
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java Wed Aug 27 08:12:04 2008
@@ -30,6 +30,7 @@
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.util.Text;
+import org.apache.commons.collections.map.LRUMap;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -48,6 +49,7 @@
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.util.Set;
+import java.util.Map;
 
 /**
  * UserManagerImpl
@@ -60,7 +62,13 @@
     private final String adminId;
     private final NodeResolver authResolver;
 
-    private String currentUserPath;
+    /**
+     * Simple unmanaged map from authorizableID to nodePath (node representing
+     * the authorizable) used limit the number of calls to the
+     * <code>NodeResolver</code> in order to find authorizable nodes by the
+     * authorizable id.
+     */
+    private final Map idPathMap = new LRUMap(1000);
 
     public UserManagerImpl(SessionImpl session, String adminId) throws RepositoryException {
         this.session = session;
@@ -85,14 +93,13 @@
             throw new IllegalArgumentException("Invalid authorizable name '" + id + "'");
         }
         Authorizable authorz = null;
-        NodeImpl n = (NodeImpl) authResolver.findNode(P_USERID, id, NT_REP_USER);
+        NodeImpl n = getUserNode(id);
         if (n != null) {
-            authorz = UserImpl.create(n, this);
+            authorz = createUser(n);
         } else {
-            Name nodeName = session.getQName(id);
-            n = (NodeImpl) authResolver.findNode(nodeName, NT_REP_GROUP);
+            n = getGroupNode(id);
             if (n != null) {
-                authorz = GroupImpl.create(n, this);
+                authorz = createGroup(n);
             }
         }
         return authorz;
@@ -121,9 +128,9 @@
         // build the corresponding authorizable object
         if (n != null) {
             if (n.isNodeType(NT_REP_USER)) {
-               return UserImpl.create(n, this);
+               return createUser(n);
             } else if (n.isNodeType(NT_REP_GROUP)) {
-               return GroupImpl.create(n, this);
+               return createGroup(n);
             } else {
                 log.warn("Unexpected user nodetype " + n.getPrimaryNodeType().getName());
             }
@@ -132,12 +139,33 @@
     }
 
     /**
-     * @see UserManager#findAuthorizable(String,String)
+     * @see UserManager#findAuthorizables(String,String)
      */
-    public Iterator findAuthorizable(String propertyName, String value) throws RepositoryException {
+    public Iterator findAuthorizables(String propertyName, String value) throws RepositoryException {
+        return findAuthorizables(propertyName, value, SEARCH_TYPE_AUTHORIZABLE);
+    }
+
+    /**
+     * @see UserManager#findAuthorizables(String,String, int)
+     */
+    public Iterator findAuthorizables(String propertyName, String value, int searchType)
+            throws RepositoryException {
         Name name = session.getQName(propertyName);
-        NodeIterator auths  = authResolver.findNodes(name, value, NT_REP_AUTHORIZABLE, true);
-        return new AuthorizableIterator(auths);
+        Name ntName;
+        switch (searchType) {
+            case SEARCH_TYPE_AUTHORIZABLE:
+                ntName = NT_REP_AUTHORIZABLE;
+                break;
+            case SEARCH_TYPE_GROUP:
+                ntName = NT_REP_GROUP;
+                break;
+            case SEARCH_TYPE_USER:
+                ntName = NT_REP_USER;
+                break;
+            default: throw new IllegalArgumentException("Invalid search type " + searchType);
+        }
+        NodeIterator nodes = authResolver.findNodes(name, value, ntName, true);
+        return new AuthorizableIterator(nodes);
     }
 
     /**
@@ -195,7 +223,7 @@
             parent.save();
 
             log.info("User created: " + userID + "; " + userNode.getPath());
-            return UserImpl.create(userNode, this);
+            return createUser(userNode);
         } catch (RepositoryException e) {
             // something went wrong -> revert changes and rethrow
             if (parent != null) {
@@ -248,7 +276,7 @@
 
             log.info("Group created: " + groupID + "; " + groupNode.getPath());
 
-            return GroupImpl.create(groupNode, this);
+            return createGroup(groupNode);
         } catch (RepositoryException e) {
             if (parent != null) {
                 parent.refresh(false);
@@ -260,38 +288,6 @@
 
     //--------------------------------------------------------------------------
     /**
-     * Simple search for <code>User</code>s<br>
-     * The argument is a substring which must match the UserId or main
-     * Principal's name.
-     *
-     * @param simpleFilter substring to match against. The empty String matches
-     * all users.
-     * @return Iterator containing Authorizable-objects
-     * @throws RepositoryException
-     */
-    public Iterator findUsers(String simpleFilter) throws RepositoryException {
-        Set s = new HashSet(2);
-        s.add(P_USERID);
-        s.add(P_PRINCIPAL_NAME);
-        NodeIterator nodes = authResolver.findNodes(s, simpleFilter, NT_REP_USER, false, Long.MAX_VALUE);
-        return new AuthorizableIterator(nodes);
-    }
-
-    /**
-     * Simple search for a <code>Group</code>s<br>
-     * The argument is a substring which must match the Group's Principal name.
-     *
-     * @param simpleFilter substring to match against. The empty String matches
-     * all groups.
-     * @return Iterator containing Authorizable-objects
-     * @throws RepositoryException
-     */
-    public Iterator findGroups(String simpleFilter) throws RepositoryException {
-        NodeIterator nodes = authResolver.findNodes(P_PRINCIPAL_NAME, simpleFilter, NT_REP_GROUP, false);
-        return new AuthorizableIterator(nodes);
-    }
-
-    /**
      *
      * @param principal
      * @return
@@ -348,45 +344,112 @@
      * @return true if the given userID belongs to the administrator user.
      */
     boolean isAdminId(String userID) {
-        return adminId.equals(userID);
+        return (adminId == null) ? false : adminId.equals(userID);
     }
 
-    UserImpl getCurrentUser() {
-        try {
-            String uid = session.getUserID();
-            if (uid != null) {
-                AuthorizableImpl auth = (AuthorizableImpl) getAuthorizable(session.getUserID());
-                if (auth != null && !auth.isGroup()) {
-                    return (UserImpl) auth;
+    /**
+     * Build the User object from the given user node.
+     *
+     * @param userNode
+     * @return
+     * @throws RepositoryException
+     */
+    User createUser(NodeImpl userNode) throws RepositoryException {
+        User user = UserImpl.create(userNode, this);
+        idPathMap.put(user.getID(), userNode.getPath());
+        return user;
+    }
+
+    /**
+     * Build the Group object from the given group node.
+     *
+     * @param groupNode
+     * @return
+     * @throws RepositoryException
+     */
+    Group createGroup(NodeImpl groupNode) throws RepositoryException {
+        Group group = GroupImpl.create(groupNode, this);
+        idPathMap.put(group.getID(), groupNode.getPath());
+        return group;
+    }
+
+    /**
+     * @param userID
+     * @return the node associated with the given userID or <code>null</code>.
+     */
+    private NodeImpl getUserNode(String userID) throws RepositoryException {
+        NodeImpl n = null;
+        if (idPathMap.containsKey(userID)) {
+            String path = idPathMap.get(userID).toString();
+            if (session.itemExists(path)) {
+                Item itm = session.getItem(path);
+                // make sure the item really represents the node associated with
+                // the given userID. if not the search below is execute.
+                if (itm.isNode()) {
+                    NodeImpl tmp = (NodeImpl) itm;
+                    if (tmp.isNodeType(NT_REP_USER) && userID.equals(((NodeImpl) itm).getProperty(P_USERID).getString())) {
+                        n = (NodeImpl) itm;
+                    }
                 }
             }
-        } catch (RepositoryException e) {
-            // should never get here
-            log.error("Internal error: unable to build current user path.", e.getMessage());
         }
-        return null;
+
+        if (n == null) {
+            // clear eventual previous entry
+            idPathMap.remove(userID);
+            // search for it the node belonging to that userID
+            n = (NodeImpl) authResolver.findNode(P_USERID, userID, NT_REP_USER);
+        }
+        return n;
     }
 
+    private NodeImpl getGroupNode(String groupID) throws RepositoryException {
+        NodeImpl n = null;
+        if (idPathMap.containsKey(groupID)) {
+            String path = idPathMap.get(groupID).toString();
+            if (session.itemExists(path)) {
+                Item itm = session.getItem(path);
+                // make sure the item really represents the node associated with
+                // the given userID. if not the search below is execute.
+                if (itm.isNode()) {
+                    NodeImpl tmp = (NodeImpl) itm;
+                    if (tmp.isNodeType(NT_REP_GROUP) && groupID.equals(tmp.getName())) {
+                        n = (NodeImpl) itm;
+                    }
+                }
+            }
+        }
+        if (n == null) {
+            // clear eventual previous entry
+            idPathMap.remove(groupID);
+            // search for it the node belonging to that groupID
+            Name nodeName = session.getQName(groupID);
+            n = (NodeImpl) authResolver.findNode(nodeName, NT_REP_GROUP);
+        }
+        return n;
+    }
+
+    /**
+     * @return the path refering to the node associated with the user this
+     * <code>UserManager</code> has been built for.
+     */
     private String getCurrentUserPath() {
-        if (currentUserPath == null) {
-            StringBuffer b = new StringBuffer();
+        // fallback: default user-path
+        String currentUserPath = USERS_PATH;;
+        String userId = session.getUserID();
+
+        if (idPathMap.containsKey(userId)) {
+            currentUserPath = idPathMap.get(userId).toString();
+        } else {
             try {
-                String uid = session.getUserID();
-                if (uid != null) {
-                    UserImpl user = getCurrentUser();
-                    if (user != null) {
-                        b.append(user.getNode().getPath());
-                    }
+                Node n = getUserNode(userId);
+                if (n != null) {
+                    currentUserPath = n.getPath();
                 }
             } catch (RepositoryException e) {
                 // should never get here
                 log.error("Internal error: unable to build current user path.", e.getMessage());
             }
-            if (b.length() == 0) {
-                // fallback: default user-path
-                b.append(USERS_PATH);
-            }
-            currentUserPath = b.toString();
         }
         return currentUserPath;
     }
@@ -488,9 +551,9 @@
                     if (!served.contains(node.getUUID())) {
                         Authorizable authr;
                         if (node.isNodeType(NT_REP_USER)) {
-                            authr = UserImpl.create(node, UserManagerImpl.this);
+                            authr = createUser(node);
                         } else if (node.isNodeType(NT_REP_GROUP)) {
-                            authr = GroupImpl.create(node, UserManagerImpl.this);
+                            authr = createGroup(node);
                         } else {
                             log.warn("Ignoring unexpected nodetype: " + node.getPrimaryNodeType().getName());
                             continue;
@@ -508,5 +571,4 @@
             return null;
         }
     }
-
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/repository.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/repository.xml?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/repository.xml (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/repository.xml Wed Aug 27 08:12:04 2008
@@ -57,15 +57,14 @@
         </AccessManager>
 
         <LoginModule class="org.apache.jackrabbit.core.security.simple.SimpleLoginModule">
-           <!-- anonymous user id -->
+           <!-- 
+              anonymous user name ('anonymous' is the default value)
+            -->
            <param name="anonymousId" value="anonymous"/>
-           <!-- administrator user id (default value if param is missing is 'admin') -->
-           <param name="adminId" value="admin"/>
            <!--
-              default user name to be used instead of the anonymous user
-              when no login credentials are provided (unset by default)
-           -->
-           <!-- <param name="defaultUserId" value="superuser"/> -->
+              administrator user id (default value if param is missing is 'admin')
+            -->
+           <param name="adminId" value="admin"/>
         </LoginModule>
     </Security>
 

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/retention/AbstractRetentionTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/retention/AbstractRetentionTest.java?rev=689499&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/retention/AbstractRetentionTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/retention/AbstractRetentionTest.java Wed Aug 27 08:12:04 2008
@@ -0,0 +1,56 @@
+/*
+ * $Id$
+ *
+ * Copyright 1997-2005 Day Management AG
+ * Barfuesserplatz 6, 4001 Basel, Switzerland
+ * All Rights Reserved.
+ *
+ * This software is the confidential and proprietary information of
+ * Day Management AG, ("Confidential Information"). You shall not
+ * disclose such Confidential Information and shall use it only in
+ * accordance with the terms of the license agreement you entered into
+ * with Day.
+ */
+package org.apache.jackrabbit.api.jsr283.retention;
+
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.NotExecutableException;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.UnsupportedRepositoryOperationException;
+
+/**
+ * <code>AbstractAccessControlTest</code>...
+ */
+public abstract class AbstractRetentionTest extends AbstractJCRTest {
+
+    protected RetentionManager retentionMgr;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        retentionMgr = getRetentionManager(superuser);
+    }
+
+    protected static RetentionManager getRetentionManager(Session s) throws RepositoryException, NotExecutableException {
+        // TODO: fix (Replace by Session) test as soon as jackrabbit implements 283
+        if (!(s instanceof SessionImpl)) {
+            throw new NotExecutableException();
+        }
+        // TODO: uncomment again.
+        // checkSupportedOption(Repository.OPTION_RETENTION_SUPPORTED);
+        try {
+            return ((SessionImpl) s).getRetentionManager();
+        } catch (UnsupportedRepositoryOperationException e) {
+            throw new NotExecutableException();
+        }
+    }
+
+    protected static void checkSupportedOption(Session s, String option) throws NotExecutableException {
+        if (Boolean.FALSE.toString().equals(s.getRepository().getDescriptor(option))) {
+            throw new NotExecutableException();
+        }
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/retention/AbstractRetentionTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/retention/AbstractRetentionTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/security/AbstractAccessControlTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/security/AbstractAccessControlTest.java?rev=689499&r1=689498&r2=689499&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/security/AbstractAccessControlTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/security/AbstractAccessControlTest.java Wed Aug 27 08:12:04 2008
@@ -33,7 +33,6 @@
 
     protected void setUp() throws Exception {
         super.setUp();
-
         acMgr = getAccessControlManager(superuser);
     }
 
@@ -43,7 +42,7 @@
             throw new NotExecutableException();
         }
         // TODO: uncomment again.
-        // checkSupportedOption(Repository.OPTION_SIMPLE_ACCESS_CONTROL_SUPPORTED);
+        // checkSupportedOption(Repository.OPTION_ACCESS_CONTROL_SUPPORTED);
         try {
             return ((SessionImpl) s).getAccessControlManager();
         } catch (UnsupportedRepositoryOperationException e) {
@@ -57,14 +56,28 @@
         }
     }
 
+    protected Privilege[] privilegesFromName(String privilegeName) throws RepositoryException, NotExecutableException {
+        AccessControlManager acMgr = getAccessControlManager(superuser);
+        return new Privilege[] {acMgr.privilegeFromName(privilegeName)};
+    }
+
+    protected Privilege[] privilegesFromNames(String[] privilegeNames) throws RepositoryException, NotExecutableException {
+        AccessControlManager acMgr = getAccessControlManager(superuser);
+        Privilege[] privs = new Privilege[privilegeNames.length];
+        for (int i = 0; i < privilegeNames.length; i++) {
+            privs[i] = acMgr.privilegeFromName(privilegeNames[i]);
+        }
+        return privs;
+    }
+
     protected void checkCanReadAc(String path) throws RepositoryException, NotExecutableException {
-        if (!acMgr.hasPrivileges(path, new Privilege[] {getPrivilege(Privilege.READ_ACCESS_CONTROL)})) {
+        if (!acMgr.hasPrivileges(path, privilegesFromName(Privilege.JCR_READ_ACCESS_CONTROL))) {
             throw new NotExecutableException();
         }
     }
 
     protected void checkCanModifyAc(String path) throws RepositoryException, NotExecutableException {
-        if (!acMgr.hasPrivileges(path, new Privilege[] {getPrivilege(Privilege.MODIFY_ACCESS_CONTROL)})) {
+        if (!acMgr.hasPrivileges(path, privilegesFromName(Privilege.JCR_MODIFY_ACCESS_CONTROL))) {
             throw new NotExecutableException();
         }
     }
@@ -90,18 +103,4 @@
         }
         return path;
     }
-
-    private Privilege getPrivilege(String name) throws NotExecutableException {
-        try {
-            Privilege[] supported = acMgr.getSupportedPrivileges(testRootNode.getPath());
-            for (int i = 0; i < supported.length; i++) {
-                if (supported[i].getName().equals(name)) {
-                    return supported[i];
-                }
-            }
-            throw new NotExecutableException("Unable to retrieve privilege with name "+ name);
-        } catch (RepositoryException e) {
-            throw new NotExecutableException("Unable to retrieve privilege with name "+ name);
-        }
-    }
 }
\ No newline at end of file