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);
}
|