jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ang...@apache.org
Subject svn commit: r985147 - in /jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security: principal/ user/
Date Fri, 13 Aug 2010 09:54:29 GMT
Author: angela
Date: Fri Aug 13 09:54:29 2010
New Revision: 985147

URL: http://svn.apache.org/viewvc?rev=985147&view=rev
Log:
JCR-2706 - Evaluate if membershipcache (JCR-2703) obsoletes the cache in DefaultPrincipalProvider

Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/principal/DefaultPrincipalProvider.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/AuthorizableImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/GroupImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/MembershipCache.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserPerWorkspaceUserManager.java

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=985147&r1=985146&r2=985147&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
Fri Aug 13 09:54:29 2010
@@ -17,7 +17,6 @@
 package org.apache.jackrabbit.core.security.principal;
 
 import org.apache.commons.collections.iterators.IteratorChain;
-import org.apache.commons.collections.map.LRUMap;
 import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
 import org.apache.jackrabbit.api.security.principal.PrincipalManager;
 import org.apache.jackrabbit.api.security.user.Authorizable;
@@ -41,7 +40,6 @@ import javax.security.auth.Subject;
 import java.security.Principal;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
-import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 
@@ -73,19 +71,11 @@ public class DefaultPrincipalProvider ex
     private static Logger log = LoggerFactory.getLogger(DefaultPrincipalProvider.class);
 
     /**
-     * a cache for group memberships: maps principal-name to a set of principals
-     * representing the members.
-     */
-    private final Map<String, Set<Principal>> membershipCache;
-
-    /**
      * Principal-Base of this Provider
      */
     private final UserManagerImpl userManager;
 
     private final EveryonePrincipal everyonePrincipal;
-
-    private final String pMembers;
     private final String pPrincipalName;
 
     /**
@@ -101,20 +91,14 @@ public class DefaultPrincipalProvider ex
 
         this.userManager = systemUserManager;
         everyonePrincipal = EveryonePrincipal.getInstance();
-        membershipCache = new LRUMap();
 
-        // listen to modifications of group-membership
-        String[] ntNames = new String[2];
+        String[] ntNames = new String[1];
         if (systemSession instanceof SessionImpl) {
             NameResolver resolver = (NameResolver) systemSession;
-            ntNames[0] = resolver.getJCRName(UserManagerImpl.NT_REP_GROUP);
-            ntNames[1] = resolver.getJCRName(UserManagerImpl.NT_REP_AUTHORIZABLE_FOLDER);
-            pMembers = resolver.getJCRName(UserManagerImpl.P_MEMBERS);
+            ntNames[0] = resolver.getJCRName(UserManagerImpl.NT_REP_AUTHORIZABLE_FOLDER);
             pPrincipalName = resolver.getJCRName(UserManagerImpl.P_PRINCIPAL_NAME);
         } else {
-            ntNames[0] = "rep:Group";
-            ntNames[1] = "rep:AuthorizableFolder";
-            pMembers = "rep:members";
+            ntNames[0] = "rep:AuthorizableFolder";
             pPrincipalName = "rep:principalName";
         }
 
@@ -125,12 +109,7 @@ public class DefaultPrincipalProvider ex
             targetPath = Text.getRelativeParent(targetPath, 1);
         }
         systemSession.getWorkspace().getObservationManager().addEventListener(this,
-                Event.NODE_ADDED | Event.NODE_REMOVED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED
| Event.PROPERTY_REMOVED,
-                targetPath,
-                true,
-                null,
-                ntNames,
-                false);
+                Event.NODE_ADDED | Event.NODE_REMOVED, targetPath, true, null, ntNames, false);
     }
 
     //------------------------------------------< AbstractPrincipalProvider >---
@@ -221,19 +200,10 @@ public class DefaultPrincipalProvider ex
      */
     public PrincipalIterator getGroupMembership(Principal userPrincipal) {
         checkInitialized();
-        Set<Principal> mship;
-        synchronized (membershipCache) {
-            mship = membershipCache.get(userPrincipal.getName());
-            if (mship == null) {
-                // recursively collect group membership
-                mship = collectGroupMembership(userPrincipal);
-
-                // make sure everyone-group is not missing
-                if (!mship.contains(everyonePrincipal) && everyonePrincipal.isMember(userPrincipal))
{
-                    mship.add(everyonePrincipal);
-                }
-                membershipCache.put(userPrincipal.getName(), mship);
-            }
+        Set<Principal> mship = collectGroupMembership(userPrincipal);
+        // make sure everyone-group is not missing
+        if (!mship.contains(everyonePrincipal) && everyonePrincipal.isMember(userPrincipal))
{
+            mship.add(everyonePrincipal);
         }
         return new PrincipalIteratorAdapter(mship);
 
@@ -245,7 +215,6 @@ public class DefaultPrincipalProvider ex
     @Override
     public synchronized void close() {
         super.close();
-        membershipCache.clear();
     }
 
     /**
@@ -279,26 +248,6 @@ public class DefaultPrincipalProvider ex
     public void onEvent(EventIterator eventIterator) {
         // superclass: flush all cached
         clearCache();
-
-        // membership cache:
-        while (eventIterator.hasNext()) {
-            Event ev = eventIterator.nextEvent();
-            int type = ev.getType();
-            if (type == Event.PROPERTY_ADDED || type == Event.PROPERTY_CHANGED
-                    || type == Event.PROPERTY_REMOVED) {
-                try {
-                    if (pMembers.equals(Text.getName(ev.getPath()))) {
-                        synchronized (membershipCache) {
-                            membershipCache.clear();
-                        }
-                        break;
-                    }
-                } catch (RepositoryException e) {
-                    // should never get here
-                    log.warn(e.getMessage());
-                }
-            }
-        }
     }
 
     //--------------------------------------------------------------------------

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/AuthorizableImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/AuthorizableImpl.java?rev=985147&r1=985146&r2=985147&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/AuthorizableImpl.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/AuthorizableImpl.java
Fri Aug 13 09:54:29 2010
@@ -234,8 +234,7 @@ abstract class AuthorizableImpl implemen
     public synchronized void remove() throws RepositoryException {
         // don't allow for removal of the administrator even if the executing
         // session has all permissions.
-        boolean isGroup = isGroup();
-        if (!isGroup && ((User) this).isAdmin()) {
+        if (!isGroup() && ((User) this).isAdmin()) {
             throw new RepositoryException("The administrator cannot be removed.");
         }
         Session s = getSession();
@@ -243,11 +242,6 @@ abstract class AuthorizableImpl implemen
         if (userManager.isAutoSave()) {
             s.save();
         }
-
-        // upon successful removal of a Group -> clear the membership cache
-        if (isGroup) {
-            userManager.getMembershipCache().clear();
-        }
     }
 
     //-------------------------------------------------------------< Object >---

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=985147&r1=985146&r2=985147&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
Fri Aug 13 09:54:29 2010
@@ -400,7 +400,6 @@ class GroupImpl extends AuthorizableImpl
             values[values.length - 1] = toAdd;
 
             userManager.setProtectedProperty(node, P_MEMBERS, values, PropertyType.WEAKREFERENCE);
-            userManager.getMembershipCache().clear();
             return true;
         }
 
@@ -423,7 +422,6 @@ class GroupImpl extends AuthorizableImpl
                         Value[] values = valList.toArray(new Value[valList.size()]);
                         userManager.setProtectedProperty(node, P_MEMBERS, values);
                     }
-                    userManager.getMembershipCache().clear();
                     return true;
                 } catch (RepositoryException e) {
                     // modification failed -> revert all pending changes.
@@ -476,7 +474,6 @@ class GroupImpl extends AuthorizableImpl
                 if (userManager.isAutoSave()) {
                     node.save();
                 }
-                userManager.getMembershipCache().clear();
                 return true;
             }
             catch (RepositoryException e) {
@@ -509,7 +506,6 @@ class GroupImpl extends AuthorizableImpl
                 if (userManager.isAutoSave()) {
                     node.save();
                 }
-                userManager.getMembershipCache().clear();
                 return true;
             }
             catch (RepositoryException e) {

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/MembershipCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/MembershipCache.java?rev=985147&r1=985146&r2=985147&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/MembershipCache.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/MembershipCache.java
Fri Aug 13 09:54:29 2010
@@ -20,7 +20,12 @@ import org.apache.commons.collections.ma
 import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.PropertyImpl;
 import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.SessionListener;
+import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
+import org.apache.jackrabbit.core.observation.SynchronousEventListener;
+import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.util.Text;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -33,8 +38,9 @@ import javax.jcr.PropertyIterator;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.Value;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
 import javax.jcr.util.TraversingItemVisitor;
-
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
@@ -44,7 +50,7 @@ import java.util.Set;
 /**
  * <code>MembershipCache</code>...
  */
-public class MembershipCache implements UserConstants {
+public class MembershipCache implements UserConstants, SynchronousEventListener, SessionListener
{
 
     /**
      * logger instance
@@ -54,24 +60,123 @@ public class MembershipCache implements 
     private final SessionImpl systemSession;
     private final String groupsPath;
     private final boolean useMembersNode;
+    private final String pMembers;
     private final Map<String, Collection<String>> cache;
 
     @SuppressWarnings("unchecked")
-    MembershipCache(SessionImpl systemSession, String groupsPath, boolean useMembersNode)
{
+    MembershipCache(SessionImpl systemSession, String groupsPath, boolean useMembersNode)
throws RepositoryException {
         this.systemSession = systemSession;
         this.groupsPath = (groupsPath == null) ? UserConstants.GROUPS_PATH : groupsPath;
         this.useMembersNode = useMembersNode;
+
+        pMembers = systemSession.getJCRName(UserManagerImpl.P_MEMBERS);
         cache = new LRUMap();
+                
+        String[] ntNames = new String[] {
+                systemSession.getJCRName(UserConstants.NT_REP_GROUP),
+                systemSession.getJCRName(UserConstants.NT_REP_MEMBERS)
+        };
+        // register event listener to be informed about membership changes.
+        systemSession.getWorkspace().getObservationManager().addEventListener(this,
+                Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED,
+                groupsPath,
+                true,
+                null,
+                ntNames,
+                false);
+        // make sure the membership cache is informed if the system session is
+        // logged out in order to stop listening to events.
+        systemSession.addListener(this);
+    }
+
+
+    //------------------------------------------------------< EventListener >---
+    /**
+     * @see javax.jcr.observation.EventListener#onEvent(javax.jcr.observation.EventIterator)
+     */
+    public void onEvent(EventIterator eventIterator) {
+        // evaluate if the membership cache needs to be cleared;
+        boolean clear = false;
+        while (eventIterator.hasNext() && !clear) {
+            Event ev = eventIterator.nextEvent();
+            try {
+                if (pMembers.equals(Text.getName(ev.getPath()))) {
+                    // simple case: a rep:members property that is affected
+                    clear = true;
+                } else if (useMembersNode) {
+                    // test if it affects a property defined by rep:Members node type.
+                    int type = ev.getType();
+                    if (type == Event.PROPERTY_ADDED || type == Event.PROPERTY_CHANGED) {
+                        Property p = systemSession.getProperty(ev.getPath());
+                        Name declNtName = ((NodeTypeImpl) p.getDefinition().getDeclaringNodeType()).getQName();
+                        clear = NT_REP_MEMBERS.equals(declNtName);
+                    } else {
+                        // PROPERTY_REMOVED
+                        // test if the primary node type of the parent node is rep:Members
+                        // this could potentially by some other property as well as the
+                        // rep:Members node are not protected and could changed by
+                        // adding a mixin type.
+                        // ignoring this and simply clear the cache
+                        String parentId = ev.getIdentifier();
+                        Node n = systemSession.getNodeByIdentifier(parentId);
+                        Name ntName = ((NodeTypeImpl) n.getPrimaryNodeType()).getQName();
+                        clear = (UserConstants.NT_REP_MEMBERS.equals(ntName));
+                    }
+                }
+            } catch (RepositoryException e) {
+                log.warn(e.getMessage());
+                // exception while processing the event -> clear the cache to
+                // be sure it isn't outdated.
+                clear = true;
+            }
+        }
+
+        if (clear) {
+            synchronized (cache) {
+                cache.clear();
+            }
+        }
+    }
+
+    //----------------------------------------------------< SessionListener >---
+    /**
+     * @see SessionListener#loggingOut(org.apache.jackrabbit.core.SessionImpl)
+     */
+    public void loggingOut(SessionImpl session) {
+        try {
+            systemSession.getWorkspace().getObservationManager().removeEventListener(this);
+        } catch (RepositoryException e) {
+            log.error("Unexpected error: Failed to stop event listening of MembershipCache.",
e);
+        }
+
     }
 
-    synchronized void clear() {
-        cache.clear();
+    /**
+     * @see SessionListener#loggedOut(org.apache.jackrabbit.core.SessionImpl)
+     */
+    public void loggedOut(SessionImpl session) {
+        // nothing to do
     }
 
+    //--------------------------------------------------------------------------
+    /**
+     * @param authorizableNodeIdentifier The identifier of the node representing
+     * the authorizable to retrieve the declared membership for.
+     * @return A collection of node identifiers of those group nodes the
+     * authorizable in question is declared member of.
+     * @throws RepositoryException If an error occurs.
+     */
     synchronized Collection<String> getDeclaredMemberOf(String authorizableNodeIdentifier)
throws RepositoryException {
         return declaredMemberOf(authorizableNodeIdentifier);
     }
 
+    /**
+     * @param authorizableNodeIdentifier The identifier of the node representing
+     * the authorizable to retrieve the membership for.
+     * @return A collection of node identifiers of those group nodes the
+     * authorizable in question is a direct or indirect member of.
+     * @throws RepositoryException If an error occurs.
+     */
     synchronized Collection<String> getMemberOf(String authorizableNodeIdentifier)
throws RepositoryException {
         Set<String> groupNodeIds = new HashSet<String>();
         memberOf(authorizableNodeIdentifier, groupNodeIds);
@@ -82,10 +187,12 @@ public class MembershipCache implements 
      * Collects the declared memberships for the specified identifier of an
      * authorizable using the specified session.
      * 
-     * @param authorizableNodeIdentifier
-     * @param session
-     * @return
-     * @throws RepositoryException
+     * @param authorizableNodeIdentifier The identifier of the node representing
+     * the authorizable to retrieve the membership for.
+     * @param session The session to be used to read the membership information.
+     * @return @return A collection of node identifiers of those group nodes the
+     * authorizable in question is a direct member of.
+     * @throws RepositoryException If an error occurs.
      */
     Collection<String> collectDeclaredMembership(String authorizableNodeIdentifier,
Session session) throws RepositoryException {
         Collection<String> groupNodeIds = collectDeclaredMembershipFromReferences(authorizableNodeIdentifier,
session);
@@ -99,10 +206,12 @@ public class MembershipCache implements 
      * Collects the complete memberships for the specified identifier of an
      * authorizable using the specified session.
      *
-     * @param authorizableNodeIdentifier
-     * @param session
-     * @return
-     * @throws RepositoryException
+     * @param authorizableNodeIdentifier The identifier of the node representing
+     * the authorizable to retrieve the membership for.
+     * @param session The session to be used to read the membership information.
+     * @return A collection of node identifiers of those group nodes the
+     * authorizable in question is a direct or indirect member of.
+     * @throws RepositoryException If an error occurs.
      */
     Collection<String> collectMembership(String authorizableNodeIdentifier, Session
session) throws RepositoryException {
         Set<String> groupNodeIds = new HashSet<String>();

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=985147&r1=985146&r2=985147&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
Fri Aug 13 09:54:29 2010
@@ -262,7 +262,7 @@ public class UserManagerImpl extends Pro
      * @param session The editing/reading session.
      * @param adminId The user ID of the administrator.
      */
-    public UserManagerImpl(SessionImpl session, String adminId) {
+    public UserManagerImpl(SessionImpl session, String adminId) throws RepositoryException
{
         this(session, adminId, null, null);
     }
 
@@ -273,7 +273,7 @@ public class UserManagerImpl extends Pro
      * @param adminId The user ID of the administrator.
      * @param config The configuration parameters.
      */
-    public UserManagerImpl(SessionImpl session, String adminId, Properties config) {
+    public UserManagerImpl(SessionImpl session, String adminId, Properties config) throws
RepositoryException {
         this(session, adminId, config, null);
     }
 
@@ -297,9 +297,10 @@ public class UserManagerImpl extends Pro
      * @param adminId The user ID of the administrator.
      * @param config The configuration parameters.
      * @param mCache Shared membership cache.
+     * @throws javax.jcr.RepositoryException
      */
     public UserManagerImpl(SessionImpl session, String adminId, Properties config,
-                           MembershipCache mCache) {
+                           MembershipCache mCache) throws RepositoryException {
         this.session = session;
         this.adminId = adminId;
 

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserPerWorkspaceUserManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserPerWorkspaceUserManager.java?rev=985147&r1=985146&r2=985147&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserPerWorkspaceUserManager.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserPerWorkspaceUserManager.java
Fri Aug 13 09:54:29 2010
@@ -44,7 +44,7 @@ public class UserPerWorkspaceUserManager
      * @param adminId
      * @throws RepositoryException
      */
-    public UserPerWorkspaceUserManager(SessionImpl session, String adminId) {
+    public UserPerWorkspaceUserManager(SessionImpl session, String adminId) throws RepositoryException
{
         super(session, adminId);
     }
 
@@ -57,7 +57,7 @@ public class UserPerWorkspaceUserManager
      * @param config
      * @throws javax.jcr.RepositoryException
      */
-    public UserPerWorkspaceUserManager(SessionImpl session, String adminId, Properties config)
{
+    public UserPerWorkspaceUserManager(SessionImpl session, String adminId, Properties config)
throws RepositoryException {
         super(session, adminId, config);
     }
         
@@ -71,7 +71,7 @@ public class UserPerWorkspaceUserManager
      * @throws javax.jcr.RepositoryException
      */
     public UserPerWorkspaceUserManager(SessionImpl session, String adminId,
-                                       Properties config, MembershipCache mCache) {
+                                       Properties config, MembershipCache mCache) throws
RepositoryException {
         super(session, adminId, config, mCache);
     }
 



Mime
View raw message