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 2010/06/02 11:00:46 UTC
svn commit: r950440 [1/3] - in /jackrabbit/trunk/jackrabbit-core/src:
main/java/org/apache/jackrabbit/core/
main/java/org/apache/jackrabbit/core/observation/
main/java/org/apache/jackrabbit/core/query/lucene/
main/java/org/apache/jackrabbit/core/securi...
Author: angela
Date: Wed Jun 2 09:00:44 2010
New Revision: 950440
URL: http://svn.apache.org/viewvc?rev=950440&view=rev
Log:
JCR-2573 - Performance of AC Evaluation [work in progress]
Added:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlListener.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlModifications.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlObserver.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/CachingEntryCollector.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/EntryCollector.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/EntryFilter.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/EntryFilterImpl.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/EntriesCache.java (with props)
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/EntryCollectorTest.java (with props)
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/UserPerWorkspaceSecurityManager.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventConsumer.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AccessManager.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SimpleJBossAccessManager.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplate.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractCompiledPermissions.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/CompiledPermissions.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/UnmodifiableAccessControlList.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLEditor.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLProvider.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/combined/CombinedProvider.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLProvider.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/GlobPattern.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleLoginModule.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/AccessManagerTest.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/EntryTest.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/TestAll.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/combined/WriteTest.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java?rev=950440&r1=950439&r2=950440&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java Wed Jun 2 09:00:44 2010
@@ -1757,11 +1757,11 @@ public class BatchedItemOperations exten
}
// copy properties
for (Name propName : srcState.getPropertyNames()) {
- Path propPath = PathFactoryImpl.getInstance().create(srcPath, propName, true);
- if (!srcAccessMgr.canRead(propPath)) {
+ Path propPath = PathFactoryImpl.getInstance().create(srcPath, propName, true);
+ PropertyId propId = new PropertyId(srcState.getNodeId(), propName);
+ if (!srcAccessMgr.canRead(propPath, propId)) {
continue;
}
- PropertyId propId = new PropertyId(srcState.getNodeId(), propName);
PropertyState srcChildState =
(PropertyState) srcStateMgr.getItemState(propId);
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java?rev=950440&r1=950439&r2=950440&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java Wed Jun 2 09:00:44 2010
@@ -39,7 +39,7 @@ import org.apache.jackrabbit.core.id.Pro
import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
import org.apache.jackrabbit.core.nodetype.EffectiveNodeType;
import org.apache.jackrabbit.core.nodetype.NodeTypeConflictException;
-import org.apache.jackrabbit.core.security.AccessManager;
+import org.apache.jackrabbit.core.security.authorization.Permission;
import org.apache.jackrabbit.core.state.ChildNodeEntry;
import org.apache.jackrabbit.core.state.ItemState;
import org.apache.jackrabbit.core.state.ItemStateException;
@@ -51,6 +51,7 @@ import org.apache.jackrabbit.core.state.
import org.apache.jackrabbit.core.util.Dumpable;
import org.apache.jackrabbit.core.version.VersionHistoryImpl;
import org.apache.jackrabbit.core.version.VersionImpl;
+import org.apache.jackrabbit.core.security.AccessManager;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.spi.QPropertyDefinition;
@@ -437,26 +438,48 @@ public class ItemManager implements Dump
if (state == null) {
throw new InvalidItemStateException(data.getId() + ": the item does not exist anymore");
}
- if (state.getStatus() == ItemState.STATUS_NEW &&
- !data.getDefinition().isProtected()) {
- // NEW items can always be read as long they have been added
- // through the API and NOT by the system (i.e. protected props).
- return true;
+ if (state.getStatus() == ItemState.STATUS_NEW) {
+ if (!data.getDefinition().isProtected()) {
+ /*
+ NEW items can always be read as long they have been added through
+ the API and NOT by the system (i.e. protected items).
+ */
+ return true;
+ } else {
+ /*
+ NEW protected (system) item:
+ need use the path to evaluate the effective permissions.
+ */
+ return (path == null) ?
+ session.getAccessManager().isGranted(data.getId(), AccessManager.READ) :
+ session.getAccessManager().isGranted(path, Permission.READ);
+ }
} else {
- return (path == null) ?
- canRead(data.getId()) :
- session.getAccessManager().canRead(path);
+ /* item is not NEW -> save to call acMgr.canRead(Path,ItemId) */
+ return session.getAccessManager().canRead(path, data.getId());
}
}
/**
- * @param id
- * @return true if the item with the given <code>id</code> can be read;
+ * @param parent The item data of the parent node.
+ * @param childId
+ * @return true if the item with the given <code>childId</code> can be read;
* <code>false</code> otherwise.
* @throws RepositoryException
*/
- private boolean canRead(ItemId id) throws RepositoryException {
- return session.getAccessManager().isGranted(id, AccessManager.READ);
+ private boolean canRead(ItemData parent, ItemId childId) throws RepositoryException {
+ if (parent.getStatus() == ItemState.STATUS_EXISTING) {
+ /*
+ child item is for sure not NEW (because then the parent was modified).
+ safe to use AccessManager#canRead(Path, ItemId).
+ */
+ return session.getAccessManager().canRead(null, childId);
+ } else {
+ /*
+ child could be NEW -> don't use AccessManager#canRead(Path, ItemId)
+ */
+ return session.getAccessManager().isGranted(childId, AccessManager.READ);
+ }
}
//--------------------------------------------------< item access methods >
@@ -697,7 +720,7 @@ public class ItemManager implements Dump
NodeState state = (NodeState) data.getState();
for (ChildNodeEntry entry : state.getChildNodeEntries()) {
// make sure any of the properties can be read.
- if (canRead(entry.getId())) {
+ if (canRead(data, entry.getId())) {
return true;
}
}
@@ -758,7 +781,7 @@ public class ItemManager implements Dump
while (iter.hasNext()) {
Name propName = iter.next();
// make sure any of the properties can be read.
- if (canRead(new PropertyId(parentId, propName))) {
+ if (canRead(data, new PropertyId(parentId, propName))) {
return true;
}
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java?rev=950440&r1=950439&r2=950440&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java Wed Jun 2 09:00:44 2010
@@ -3026,7 +3026,7 @@ public class NodeImpl extends ItemImpl i
*
* @return parent id
*/
- NodeId getParentId() {
+ public NodeId getParentId() {
return data.getParentId();
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java?rev=950440&r1=950439&r2=950440&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java Wed Jun 2 09:00:44 2010
@@ -48,10 +48,10 @@ class SystemSession extends SessionImpl
/**
* Package private factory method
*
- * @param rep
- * @param wspConfig
- * @return
- * @throws RepositoryException
+ * @param repositoryContext The repository context
+ * @param wspConfig The workspace configuration
+ * @return A new instance of <code>SystemSession</code>
+ * @throws RepositoryException If an error occurs
*/
static SystemSession create(
RepositoryContext repositoryContext, WorkspaceConfig wspConfig)
@@ -69,7 +69,9 @@ class SystemSession extends SessionImpl
* private constructor
*
* @param repositoryContext repository context
- * @param wspConfig
+ * @param subject The subject
+ * @param wspConfig The workspace configuration
+ * @throws javax.jcr.RepositoryException If an error occurs.
*/
private SystemSession(
RepositoryContext repositoryContext, Subject subject,
@@ -193,10 +195,9 @@ class SystemSession extends SessionImpl
/**
* Always returns true.
*
- * @see AccessManager#canRead(Path)
- * @param itemPath
+ * @see AccessManager#canRead(org.apache.jackrabbit.spi.Path,org.apache.jackrabbit.core.id.ItemId)
*/
- public boolean canRead(Path itemPath) throws RepositoryException {
+ public boolean canRead(Path itemPath, ItemId itemId) throws RepositoryException {
return true;
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/UserPerWorkspaceSecurityManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/UserPerWorkspaceSecurityManager.java?rev=950440&r1=950439&r2=950440&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/UserPerWorkspaceSecurityManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/UserPerWorkspaceSecurityManager.java Wed Jun 2 09:00:44 2010
@@ -63,6 +63,7 @@ import java.util.Set;
public class UserPerWorkspaceSecurityManager extends DefaultSecurityManager {
private final Map<String, PrincipalProviderRegistry> ppRegistries = new HashMap<String, PrincipalProviderRegistry>();
+ private final Object monitor = new Object();
/**
* List of workspace names for which {@link #createSystemUsers} has already
@@ -72,25 +73,27 @@ public class UserPerWorkspaceSecurityMan
private PrincipalProviderRegistry getPrincipalProviderRegistry(SessionImpl s) throws RepositoryException {
String wspName = s.getWorkspace().getName();
- PrincipalProviderRegistry p = ppRegistries.get(wspName);
- if (p == null) {
- SystemSession systemSession;
- if (s instanceof SystemSession) {
- systemSession = (SystemSession) s;
- } else {
- RepositoryImpl repo = (RepositoryImpl) getRepository();
- systemSession = repo.getSystemSession(wspName);
- // TODO: review again... this workaround is used in several places.
- repo.onSessionCreated(systemSession);
- }
+ synchronized (monitor) {
+ PrincipalProviderRegistry p = ppRegistries.get(wspName);
+ if (p == null) {
+ SystemSession systemSession;
+ if (s instanceof SystemSession) {
+ systemSession = (SystemSession) s;
+ } else {
+ RepositoryImpl repo = (RepositoryImpl) getRepository();
+ systemSession = repo.getSystemSession(wspName);
+ // TODO: review again... this workaround is used in several places.
+ repo.onSessionCreated(systemSession);
+ }
- PrincipalProvider defaultPP = new DefaultPrincipalProvider(systemSession, (UserManagerImpl) getUserManager(systemSession));
- defaultPP.init(new Properties());
-
- p = new WorkspaceBasedPrincipalProviderRegistry(defaultPP);
- ppRegistries.put(wspName, p);
+ PrincipalProvider defaultPP = new DefaultPrincipalProvider(systemSession, (UserManagerImpl) getUserManager(systemSession));
+ defaultPP.init(new Properties());
+
+ p = new WorkspaceBasedPrincipalProviderRegistry(defaultPP);
+ ppRegistries.put(wspName, p);
+ }
+ return p;
}
- return p;
}
//------------------------------------------< JackrabbitSecurityManager >---
@@ -110,7 +113,7 @@ public class UserPerWorkspaceSecurityMan
@Override
public void dispose(String workspaceName) {
super.dispose(workspaceName);
- synchronized (ppRegistries) {
+ synchronized (monitor) {
PrincipalProviderRegistry reg = ppRegistries.remove(workspaceName);
if (reg != null) {
reg.getDefault().close();
@@ -124,7 +127,7 @@ public class UserPerWorkspaceSecurityMan
@Override
public void close() {
super.close();
- synchronized (ppRegistries) {
+ synchronized (monitor) {
for (PrincipalProviderRegistry registry : ppRegistries.values()) {
registry.getDefault().close();
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventConsumer.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventConsumer.java?rev=950440&r1=950439&r2=950440&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventConsumer.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventConsumer.java Wed Jun 2 09:00:44 2010
@@ -301,6 +301,6 @@ class EventConsumer {
*/
private boolean canRead(EventState eventState) throws RepositoryException {
Path targetPath = pathFactory.create(eventState.getParentPath(), eventState.getChildRelPath().getName(), eventState.getChildRelPath().getNormalizedIndex(), true);
- return session.getAccessManager().canRead(targetPath);
+ return session.getAccessManager().canRead(targetPath, null);
}
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java?rev=950440&r1=950439&r2=950440&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java Wed Jun 2 09:00:44 2010
@@ -371,8 +371,7 @@ public abstract class QueryResultImpl im
throws RepositoryException {
for (ScoreNode node : nodes) {
try {
- // TODO: rather use AccessManager.canRead(Path)
- if (node != null && !accessMgr.isGranted(node.getNodeId(), AccessManager.READ)) {
+ if (node != null && !accessMgr.canRead(null, node.getNodeId())) {
return false;
}
} catch (ItemNotFoundException e) {
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AccessManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AccessManager.java?rev=950440&r1=950439&r2=950440&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AccessManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AccessManager.java Wed Jun 2 09:00:44 2010
@@ -171,13 +171,24 @@ public interface AccessManager {
boolean isGranted(Path parentPath, Name childName, int permissions) throws RepositoryException;
/**
- * Determines whether the item at the specified absolute path can be read.
+ * Determines whether the item with the specified <code>itemPath</code>
+ * or <code>itemId</code> can be read. Either of the two parameters
+ * may be <code>null</code>.<br>
+ * Note, that this method should only be called for persisted items as NEW
+ * items may not be visible to the permission evaluation.
+ * For new items {@link #isGranted(Path, int)} should be used instead.<p/>
+ * If this method is called with both Path and ItemId it is left to the
+ * evaluation, which parameter is used.
*
- * @param itemPath Path to the item to be tested.s
+ * @param itemPath The path to the item or <code>null</code> if itemId
+ * should be used to determine the READ permission.
+ * @param itemId Id of the item to be tested or <code>null</code> if the
+ * itemPath should be used to determine the permission.
* @return <code>true</code> if the item can be read; otherwise <code>false</code>.
- * @throws RepositoryException if an error occurs.
+ * @throws RepositoryException if the item is NEW and only an itemId is
+ * specified or if another error occurs.
*/
- boolean canRead(Path itemPath) throws RepositoryException;
+ boolean canRead(Path itemPath, ItemId itemId) throws RepositoryException;
/**
* Determines whether the subject of the current context is granted access
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java?rev=950440&r1=950439&r2=950440&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java Wed Jun 2 09:00:44 2010
@@ -215,6 +215,7 @@ public class DefaultAccessManager extend
if ((actions & REMOVE) == REMOVE) {
perm |= (id.denotesNode()) ? Permission.REMOVE_NODE : Permission.REMOVE_PROPERTY;
}
+
Path path = hierMgr.getPath(id);
return isGranted(path, perm);
}
@@ -240,13 +241,14 @@ public class DefaultAccessManager extend
}
/**
- * @see AccessManager#canRead(Path)
+ * @see AccessManager#canRead(org.apache.jackrabbit.spi.Path,org.apache.jackrabbit.core.id.ItemId)
*/
- public boolean canRead(Path itemPath) throws RepositoryException {
+ public boolean canRead(Path itemPath, ItemId itemId) throws RepositoryException {
+ checkInitialized();
if (compiledPermissions.canReadAll()) {
return true;
} else {
- return isGranted(itemPath, Permission.READ);
+ return compiledPermissions.canRead(itemPath, itemId);
}
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SimpleJBossAccessManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SimpleJBossAccessManager.java?rev=950440&r1=950439&r2=950440&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SimpleJBossAccessManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SimpleJBossAccessManager.java Wed Jun 2 09:00:44 2010
@@ -121,7 +121,7 @@ public class SimpleJBossAccessManager im
return internalIsGranted(permissions);
}
- public boolean canRead(Path itemPath) throws RepositoryException {
+ public boolean canRead(Path itemPath, ItemId itemId) throws RepositoryException {
return true;
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplate.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplate.java?rev=950440&r1=950439&r2=950440&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplate.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplate.java Wed Jun 2 09:00:44 2010
@@ -76,12 +76,9 @@ public abstract class AbstractACLTemplat
* Return the list of entries, if they are held in a orderable list.
*
* @return the list of entries.
- * @throws UnsupportedRepositoryOperationException If the implementation
- * does not held the entries in a list.
- * @throws RepositoryException
* @see #orderBefore(AccessControlEntry, AccessControlEntry)
*/
- protected abstract List<? extends AccessControlEntry> getEntries() throws UnsupportedRepositoryOperationException, RepositoryException;
+ protected abstract List<? extends AccessControlEntry> getEntries();
//--------------------------------------< JackrabbitAccessControlPolicy >---
/**
@@ -101,6 +98,20 @@ public abstract class AbstractACLTemplat
}
/**
+ * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#size()
+ */
+ public int size() {
+ return getEntries().size();
+ }
+
+ /**
+ * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#isEmpty()
+ */
+ public boolean isEmpty() {
+ return getEntries().isEmpty();
+ }
+
+ /**
*
* @param srcEntry The access control entry to be moved within the list.
* @param destEntry The entry before which the <code>srcEntry</code> will be moved.
@@ -131,6 +142,14 @@ public abstract class AbstractACLTemplat
//--------------------------------------------------< AccessControlList >---
/**
+ * @see javax.jcr.security.AccessControlList#getAccessControlEntries()
+ */
+ public AccessControlEntry[] getAccessControlEntries() throws RepositoryException {
+ List<? extends AccessControlEntry> l = getEntries();
+ return l.toArray(new AccessControlEntry[l.size()]);
+ }
+
+ /**
* @see javax.jcr.security.AccessControlList#addAccessControlEntry(java.security.Principal , javax.jcr.security.Privilege[])
*/
public boolean addAccessControlEntry(Principal principal, Privilege[] privileges)
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java?rev=950440&r1=950439&r2=950440&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java Wed Jun 2 09:00:44 2010
@@ -25,9 +25,14 @@ import javax.jcr.Session;
import javax.jcr.observation.ObservationManager;
import javax.jcr.security.Privilege;
+import org.apache.jackrabbit.core.ItemImpl;
+import org.apache.jackrabbit.core.NodeImpl;
import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.id.ItemId;
+import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
import org.apache.jackrabbit.core.security.SystemPrincipal;
import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
+import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
@@ -35,7 +40,7 @@ import org.apache.jackrabbit.spi.commons
* <code>AbstractAccessControlProvider</code>...
*/
public abstract class AbstractAccessControlProvider implements AccessControlProvider,
- AccessControlUtils {
+ AccessControlUtils, AccessControlConstants {
/**
* Constant for the name of the configuration option "omit-default-permission".
@@ -98,6 +103,9 @@ public abstract class AbstractAccessCont
public boolean canReadAll() {
return true;
}
+ public boolean canRead(Path itemPath, ItemId itemId) throws RepositoryException {
+ return true;
+ }
};
}
@@ -131,11 +139,48 @@ public abstract class AbstractAccessCont
public boolean canReadAll() {
return false;
}
+ public boolean canRead(Path itemPath, ItemId itemId) throws RepositoryException {
+ if (itemPath != null) {
+ return !isAcItem(itemPath);
+ } else {
+ return !isAcItem(session.getItemManager().getItem(itemId));
+ }
+ }
};
}
//-------------------------------------------------< AccessControlUtils >---
/**
+ * @see org.apache.jackrabbit.core.security.authorization.AccessControlUtils#isAcItem(Path)
+ */
+ public boolean isAcItem(Path absPath) throws RepositoryException {
+ Path.Element[] elems = absPath.getElements();
+ // start looking for a rep:policy name starting from the last element.
+ // NOTE: with the current content structure max. 3 levels must be looked
+ // at as the rep:policy node may only have ACE nodes with a properties.
+ if (elems.length > 1) {
+ for (int index = elems.length-1, j = 1; index >= 0 && j <= 3; index--, j++) {
+ if (N_POLICY.equals(elems[index].getName())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Test if the given node is itself a rep:ACL or a rep:ACE node.
+ * @see org.apache.jackrabbit.core.security.authorization.AccessControlUtils#isAcItem(org.apache.jackrabbit.core.ItemImpl)
+ */
+ public boolean isAcItem(ItemImpl item) throws RepositoryException {
+ NodeImpl n = ((item.isNode()) ? (NodeImpl) item : (NodeImpl) item.getParent());
+ Name ntName = ((NodeTypeImpl) n.getPrimaryNodeType()).getQName();
+ return ntName.equals(NT_REP_ACL) ||
+ ntName.equals(NT_REP_GRANT_ACE) ||
+ ntName.equals(NT_REP_DENY_ACE);
+ }
+
+ /**
* @see AccessControlUtils#isAdminOrSystem(Set)
*/
public boolean isAdminOrSystem(Set<Principal> principals) {
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractCompiledPermissions.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractCompiledPermissions.java?rev=950440&r1=950439&r2=950440&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractCompiledPermissions.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractCompiledPermissions.java Wed Jun 2 09:00:44 2010
@@ -16,12 +16,11 @@
*/
package org.apache.jackrabbit.core.security.authorization;
-import java.util.Map;
-
import org.apache.commons.collections.map.LRUMap;
import org.apache.jackrabbit.spi.Path;
import javax.jcr.RepositoryException;
+import java.util.Map;
/**
* <code>AbstractCompiledPermissions</code>...
@@ -30,6 +29,7 @@ public abstract class AbstractCompiledPe
// cache mapping a Path to a 'Result' containing permissions and privileges.
private final Map<Path, Result> cache;
+ private final Object monitor = new Object();
@SuppressWarnings("unchecked")
protected AbstractCompiledPermissions() {
@@ -44,7 +44,7 @@ public abstract class AbstractCompiledPe
*/
public Result getResult(Path absPath) throws RepositoryException {
Result result;
- synchronized (cache) {
+ synchronized (monitor) {
result = cache.get(absPath);
if (result == null) {
result = buildResult(absPath);
@@ -66,7 +66,7 @@ public abstract class AbstractCompiledPe
* Removes all entries from the cache.
*/
protected void clearCache() {
- synchronized (cache) {
+ synchronized (monitor) {
cache.clear();
}
}
@@ -113,20 +113,13 @@ public abstract class AbstractCompiledPe
private final int allowPrivileges;
private final int denyPrivileges;
- private final int hashCode;
+ private int hashCode = -1;
public Result(int allows, int denies, int allowPrivileges, int denyPrivileges) {
this.allows = allows;
this.denies = denies;
this.allowPrivileges = allowPrivileges;
this.denyPrivileges = denyPrivileges;
-
- int h = 17;
- h = 37 * h + allows;
- h = 37 * h + denies;
- h = 37 * h + allowPrivileges;
- h = 37 * h + denyPrivileges;
- hashCode = h;
}
public boolean grants(int permissions) {
@@ -148,13 +141,23 @@ public abstract class AbstractCompiledPe
/**
* @see Object#hashCode()
*/
+ @Override
public int hashCode() {
+ if (hashCode == -1) {
+ int h = 17;
+ h = 37 * h + allows;
+ h = 37 * h + denies;
+ h = 37 * h + allowPrivileges;
+ h = 37 * h + denyPrivileges;
+ hashCode = h;
+ }
return hashCode;
}
/**
* @see Object#equals(Object)
*/
+ @Override
public boolean equals(Object object) {
if (object == this) {
return true;
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlListener.java?rev=950440&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlListener.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlListener.java Wed Jun 2 09:00:44 2010
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+/**
+ *
+ */
+public interface AccessControlListener {
+
+ /**
+ * Informs this listener about changes made to access control content.
+ *
+ * @param modifications Information about access control modifications.
+ */
+ void acModified(AccessControlModifications modifications);
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlListener.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlListener.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlModifications.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlModifications.java?rev=950440&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlModifications.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlModifications.java Wed Jun 2 09:00:44 2010
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.security.authorization;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * <code>AccessControlModifications</code> is an unmodifiable collection of
+ * modifications made to access control content allowing the
+ * {@link AccessControlListener modification listeners} to keep caches up to date.
+ */
+public class AccessControlModifications<K> {
+
+ /**
+ * logger instance
+ */
+ private static final Logger log = LoggerFactory.getLogger(AccessControlModifications.class);
+
+ private final Map<K, Integer> modificationMap;
+
+ /**
+ * @param modificationMap Map specifying the access control modifications.
+ * The keys allows to identify the <code>Node</code> that was modified by
+ * the policy modifications. The values specifies the modification type,
+ * which may be any of
+ * <ul>
+ * <li>{@link AccessControlObserver#POLICY_ADDED}</li>
+ * <li>{@link AccessControlObserver#POLICY_MODIFIED}</li>
+ * <li>{@link AccessControlObserver#POLICY_REMOVED}</li>
+ * </ul>
+ */
+ public AccessControlModifications(Map<K, Integer> modificationMap) {
+ this.modificationMap = Collections.unmodifiableMap(modificationMap);
+ }
+
+ /**
+ * @return Set of <code>Node</code> identifiers or paths.
+ */
+ public Set<K> getNodeIdentifiers() {
+ return modificationMap.keySet();
+ }
+
+ /**
+ * @param identifier
+ * @return The modification type for the specified "identifier". Note that
+ * the object type of the identifier is independent specific.
+ */
+ public Integer getType(K identifier) {
+ return modificationMap.get(identifier);
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlModifications.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlModifications.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlObserver.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlObserver.java?rev=950440&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlObserver.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlObserver.java Wed Jun 2 09:00:44 2010
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.security.authorization;
+
+import org.apache.jackrabbit.core.observation.SynchronousEventListener;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * <code>AccessControlObserver</code>...
+ */
+public abstract class AccessControlObserver implements SynchronousEventListener {
+
+ public static final int POLICY_ADDED = 1;
+ public static final int POLICY_REMOVED = 2;
+ public static final int POLICY_MODIFIED = 4;
+
+ private final Set<AccessControlListener> listeners = new HashSet<AccessControlListener>();
+ private final Object listenerMonitor = new Object();
+
+ protected void close() {
+ synchronized (listenerMonitor) {
+ listeners.clear();
+ }
+ }
+
+ /**
+ * Add a listener that needs to be informed about changes made to access
+ * control.
+ *
+ * @param listener <code>EntryListener</code> to be added.
+ */
+ public void addListener(AccessControlListener listener) {
+ synchronized (listenerMonitor) {
+ listeners.add(listener);
+ }
+ }
+
+ /**
+ * Remove a listener added before.
+ *
+ * @param listener <code>EntryListener</code> to be removed.
+ */
+ public void removeListener(AccessControlListener listener) {
+ synchronized (listenerMonitor) {
+ listeners.remove(listener);
+ }
+ }
+
+ /**
+ * Notifies the listeners about AC modifications.
+ *
+ * @param modifications
+ */
+ protected void notifyListeners(AccessControlModifications modifications) {
+ AccessControlListener[] lstnrs;
+ synchronized (listenerMonitor) {
+ lstnrs = listeners.toArray(new AccessControlListener[listeners.size()]);
+ }
+ for (AccessControlListener lstnr : lstnrs) {
+ lstnr.acModified(modifications);
+ }
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlObserver.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlObserver.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/CompiledPermissions.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/CompiledPermissions.java?rev=950440&r1=950439&r2=950440&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/CompiledPermissions.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/CompiledPermissions.java Wed Jun 2 09:00:44 2010
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.core.security.authorization;
import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.core.id.ItemId;
import javax.jcr.RepositoryException;
@@ -74,6 +75,27 @@ public interface CompiledPermissions {
boolean canReadAll() throws RepositoryException;
/**
+ * Returns <code>true</code> if READ permission is granted for the
+ * <i>existing</i> item with the given <code>Path</code> and/or
+ * <code>ItemId</code>.
+ * This method acts as shortcut for {@link #grants(Path, int)} where
+ * permissions is {@link Permission#READ} and allows to shorten the
+ * evaluation time given the fact that a check for READ permissions is
+ * considered to be the most frequent test.<br>
+ * If both Path and ItemId are not <code>null</code> it is left to the
+ * implementation which parameter to use.n
+ *
+ * @param itemPath The path to the item or <code>null</code> if the ID
+ * should be used to determine the READ permission.
+ * @param itemId The itemId or <code>null</code> if the path should be
+ * used to determine the READ permission.
+ * @return <code>true</code> if the READ permission is granted.
+ * @throws RepositoryException If no item exists with the specified path or
+ * itemId or if some other error occurs.
+ */
+ boolean canRead(Path itemPath, ItemId itemId) throws RepositoryException;
+
+ /**
* Static implementation of a <code>CompiledPermissions</code> that doesn't
* grant any permissions at all.
*/
@@ -91,5 +113,8 @@ public interface CompiledPermissions {
public boolean canReadAll() {
return false;
}
+ public boolean canRead(Path itemPath, ItemId itemId) throws RepositoryException {
+ return false;
+ }
};
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/UnmodifiableAccessControlList.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/UnmodifiableAccessControlList.java?rev=950440&r1=950439&r2=950440&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/UnmodifiableAccessControlList.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/UnmodifiableAccessControlList.java Wed Jun 2 09:00:44 2010
@@ -26,6 +26,7 @@ import javax.jcr.Value;
import javax.jcr.PropertyType;
import java.security.Principal;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Collections;
@@ -48,6 +49,8 @@ public class UnmodifiableAccessControlLi
private final String path;
+ private int hashCode = 0;
+
/**
* Construct a new <code>UnmodifiableAccessControlList</code>
*
@@ -78,10 +81,21 @@ public class UnmodifiableAccessControlLi
*
* @param accessControlEntries A list of {@link AccessControlEntry access control entries}.
*/
- public UnmodifiableAccessControlList(List<AccessControlEntry> accessControlEntries) {
+ public UnmodifiableAccessControlList(List<? extends AccessControlEntry> accessControlEntries) {
+ this(accessControlEntries, null, Collections.<String, Integer>emptyMap());
+ }
+
+ /**
+ * Construct a new <code>UnmodifiableAccessControlList</code>
+ *
+ * @param accessControlEntries
+ * @param path
+ * @param restrictions
+ */
+ public UnmodifiableAccessControlList(List<? extends AccessControlEntry> accessControlEntries, String path, Map<String, Integer>restrictions) {
this.accessControlEntries = accessControlEntries.toArray(new AccessControlEntry[accessControlEntries.size()]);
- path = null;
- restrictions = Collections.emptyMap();
+ this.path = path;
+ this.restrictions = restrictions;
}
//--------------------------------------------------< AccessControlList >---
@@ -110,10 +124,17 @@ public class UnmodifiableAccessControlLi
throw new AccessControlException("Unmodifiable ACL. Use AccessControlManager#getApplicablePolicies in order to obtain an modifiable ACL.");
}
+ //----------------------------------------< JackrabbitAccessControlList >---
+ /**
+ * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#getRestrictionNames()
+ */
public String[] getRestrictionNames() {
return restrictions.keySet().toArray(new String[restrictions.size()]);
}
+ /**
+ * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#getRestrictionType(String)
+ */
public int getRestrictionType(String restrictionName) {
if (restrictions.containsKey(restrictionName)) {
return restrictions.get(restrictionName);
@@ -122,27 +143,83 @@ public class UnmodifiableAccessControlLi
}
}
+ /**
+ * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#isEmpty()
+ */
public boolean isEmpty() {
return accessControlEntries.length == 0;
}
+ /**
+ * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#size()
+ */
public int size() {
return accessControlEntries.length;
}
+ /**
+ * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#addEntry(Principal, Privilege[], boolean)
+ */
public boolean addEntry(Principal principal, Privilege[] privileges, boolean isAllow) throws AccessControlException {
throw new AccessControlException("Unmodifiable ACL. Use AccessControlManager#getPolicy or #getApplicablePolicies in order to obtain an modifiable ACL.");
}
+ /**
+ * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#addEntry(Principal, Privilege[], boolean, Map)
+ */
public boolean addEntry(Principal principal, Privilege[] privileges, boolean isAllow, Map<String, Value> restrictions) throws AccessControlException {
throw new AccessControlException("Unmodifiable ACL. Use AccessControlManager#getPolicy or #getApplicablePolicies in order to obtain an modifiable ACL.");
}
+ /**
+ * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#orderBefore(AccessControlEntry, AccessControlEntry)
+ */
public void orderBefore(AccessControlEntry srcEntry, AccessControlEntry destEntry) throws AccessControlException {
throw new AccessControlException("Unmodifiable ACL. Use AccessControlManager#getPolicy or #getApplicablePolicy in order to obtain a modifiable ACL.");
}
+ /**
+ * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#getPath()
+ */
public String getPath() {
return path;
}
+
+ //-------------------------------------------------------------< Object >---
+ /**
+ * @see Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ if (hashCode == 0) {
+ int result = 17;
+ result = 37 * result + (path != null ? path.hashCode() : 0);
+ for (AccessControlEntry entry : accessControlEntries) {
+ result = 37 * result + entry.hashCode();
+ }
+ for (String restrictionName : restrictions.keySet()) {
+ result = 37 * (restrictionName + "." + restrictions.get(restrictionName)).hashCode();
+ }
+ hashCode = result;
+ }
+ return hashCode;
+ }
+
+ /**
+ * @see Object#equals(Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (obj instanceof UnmodifiableAccessControlList) {
+ UnmodifiableAccessControlList acl = (UnmodifiableAccessControlList) obj;
+ return ((path == null) ? acl.path == null : path.equals(acl.path)) &&
+ Arrays.equals(accessControlEntries, acl.accessControlEntries) &&
+ restrictions.equals(acl.restrictions);
+ }
+ return false;
+ }
}
\ No newline at end of file
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLEditor.java?rev=950440&r1=950439&r2=950440&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLEditor.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLEditor.java Wed Jun 2 09:00:44 2010
@@ -44,7 +44,6 @@ import javax.jcr.ValueFormatException;
import javax.jcr.NodeIterator;
import javax.jcr.security.AccessControlEntry;
import javax.jcr.security.AccessControlException;
-import javax.jcr.security.AccessControlList;
import javax.jcr.security.AccessControlPolicy;
import javax.jcr.security.Privilege;
import java.security.Principal;
@@ -87,7 +86,7 @@ public class ACLEditor extends Protected
* @return the control list
* @throws RepositoryException if an error occurs
*/
- AccessControlList getACL(NodeImpl aclNode) throws RepositoryException {
+ ACLTemplate getACL(NodeImpl aclNode) throws RepositoryException {
return new ACLTemplate(aclNode, privilegeRegistry);
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLProvider.java?rev=950440&r1=950439&r2=950440&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLProvider.java Wed Jun 2 09:00:44 2010
@@ -16,49 +16,48 @@
*/
package org.apache.jackrabbit.core.security.authorization.acl;
-import java.security.Principal;
-import java.security.acl.Group;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Iterator;
-
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.observation.Event;
-import javax.jcr.observation.EventIterator;
-import javax.jcr.security.AccessControlEntry;
-import javax.jcr.security.AccessControlList;
-import javax.jcr.security.AccessControlManager;
-import javax.jcr.security.AccessControlPolicy;
-import javax.jcr.security.Privilege;
-
+import org.apache.commons.collections.map.LRUMap;
import org.apache.jackrabbit.api.security.principal.PrincipalManager;
import org.apache.jackrabbit.core.ItemImpl;
+import org.apache.jackrabbit.core.ItemManager;
import org.apache.jackrabbit.core.NodeImpl;
-import org.apache.jackrabbit.core.PropertyImpl;
import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.id.ItemId;
import org.apache.jackrabbit.core.id.NodeId;
-import org.apache.jackrabbit.core.observation.SynchronousEventListener;
+import org.apache.jackrabbit.core.id.PropertyId;
+import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
import org.apache.jackrabbit.core.security.SecurityConstants;
+import org.apache.jackrabbit.core.security.authorization.AccessControlListener;
import org.apache.jackrabbit.core.security.authorization.AbstractAccessControlProvider;
import org.apache.jackrabbit.core.security.authorization.AbstractCompiledPermissions;
import org.apache.jackrabbit.core.security.authorization.AccessControlConstants;
import org.apache.jackrabbit.core.security.authorization.AccessControlEditor;
+import org.apache.jackrabbit.core.security.authorization.AccessControlModifications;
import org.apache.jackrabbit.core.security.authorization.CompiledPermissions;
import org.apache.jackrabbit.core.security.authorization.Permission;
import org.apache.jackrabbit.core.security.authorization.PrivilegeRegistry;
import org.apache.jackrabbit.core.security.authorization.UnmodifiableAccessControlList;
+import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.Path;
-import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
-import org.apache.jackrabbit.util.Text;
-import org.apache.commons.collections.iterators.IteratorChain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.security.AccessControlEntry;
+import javax.jcr.security.AccessControlList;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
+import javax.jcr.security.Privilege;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
/**
* The ACLProvider generates access control policies out of the items stored
* in the workspace applying the following rules:
@@ -97,28 +96,12 @@ public class ACLProvider extends Abstrac
*/
private NodeId rootNodeId;
- //-------------------------------------------------< AccessControlUtils >---
/**
- * @see org.apache.jackrabbit.core.security.authorization.AccessControlUtils#isAcItem(Path)
+ * Cache to ease the retrieval of ACEs defined for a given node. This cache
+ * is used by the ACLPermissions created individually for each Session
+ * instance.
*/
- public boolean isAcItem(Path absPath) throws RepositoryException {
- Path.Element[] elems = absPath.getElements();
- for (Path.Element elem : elems) {
- if (N_POLICY.equals(elem.getName())) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Test if the given node is itself a rep:ACL or a rep:ACE node.
- * @see org.apache.jackrabbit.core.security.authorization.AccessControlUtils#isAcItem(ItemImpl)
- */
- public boolean isAcItem(ItemImpl item) throws RepositoryException {
- NodeImpl n = ((item.isNode()) ? (NodeImpl) item : (NodeImpl) item.getParent());
- return n.isNodeType(NT_REP_ACL) || n.isNodeType(NT_REP_ACE);
- }
+ private EntryCollector entryCollector;
//----------------------------------------------< AccessControlProvider >---
/**
@@ -133,11 +116,20 @@ public class ACLProvider extends Abstrac
NodeImpl root = (NodeImpl) session.getRootNode();
rootNodeId = root.getNodeId();
systemEditor = new ACLEditor(systemSession, this);
+
// TODO: replace by configurable default policy (see JCR-2331)
boolean initializedWithDefaults = !configuration.containsKey(PARAM_OMIT_DEFAULT_PERMISSIONS);
if (initializedWithDefaults && !isAccessControlled(root)) {
initRootACL(session, systemEditor);
}
+
+ entryCollector = createEntryCollector((SessionImpl) systemSession);
+ }
+
+ @Override
+ public void close() {
+ super.close();
+ entryCollector.close();
}
/**
@@ -148,7 +140,7 @@ public class ACLProvider extends Abstrac
checkInitialized();
NodeImpl targetNode = (NodeImpl) session.getNode(session.getJCRPath(absPath));
- NodeImpl node = getNode(targetNode);
+ NodeImpl node = getNode(targetNode, isAcItem(targetNode));
List<AccessControlList> acls = new ArrayList<AccessControlList>();
// collect all ACLs effective at node
@@ -194,22 +186,37 @@ public class ACLProvider extends Abstrac
return true;
} else {
CompiledPermissions cp = new AclPermissions(principals, false);
- return cp.grants(PathFactoryImpl.getInstance().getRootPath(), Permission.READ);
+ return cp.canRead(null, rootNodeId);
}
}
//----------------------------------------------------------< protected >---
/**
+ * Create the <code>EntryCollector</code> instance that is used by this
+ * provider to gather the effective ACEs for a given list of principals at a
+ * given node during AC evaluation.
+ *
+ * @param systemSession The system session to create the entry collector for.
+ * @return A new instance of <code>CachingEntryCollector</code>.
+ * @throws RepositoryException If an error occurs.
+ * @see #retrieveResultEntries(NodeImpl, EntryFilter)
+ */
+ protected EntryCollector createEntryCollector(SessionImpl systemSession) throws RepositoryException {
+ return new CachingEntryCollector(systemSession, systemEditor, rootNodeId);
+ }
+
+ /**
* Retrieve an iterator of <code>AccessControlEntry</code> to be evaluated
* upon {@link AbstractCompiledPermissions#buildResult}.
*
* @param node Target node.
- * @param principalNames List of principal names.
+ * @param filter The entry filter used to collect the access control entries.
* @return an iterator of <code>AccessControlEntry</code>.
* @throws RepositoryException If an error occurs.
*/
- protected Iterator<AccessControlEntry> retrieveResultEntries(NodeImpl node, List<String> principalNames) throws RepositoryException {
- return new Entries(node, principalNames).iterator();
+ protected Iterator<AccessControlEntry> retrieveResultEntries(NodeImpl node, EntryFilter filter) throws RepositoryException {
+ Iterator<AccessControlEntry> itr = entryCollector.collectEntries(node, filter).iterator();
+ return itr;
}
//------------------------------------------------------------< private >---
@@ -219,13 +226,17 @@ public class ACLProvider extends Abstrac
* searched and returned.
*
* @param targetNode The node for which AC information needs to be retrieved.
- * @return the node
+ * @param isAcItem true if the specified target node defines access control
+ * content; false otherwise.
+ * @return the given <code>targetNode</code> or the nearest non-ac-parent
+ * in case the <code>targetNode</code> itself defines access control content.
* @throws RepositoryException if an error occurs
*/
- private NodeImpl getNode(NodeImpl targetNode) throws RepositoryException {
+ private NodeImpl getNode(NodeImpl targetNode, boolean isAcItem) throws RepositoryException {
NodeImpl node;
- if (isAcItem(targetNode)) {
- if (targetNode.isNodeType(NT_REP_ACL)) {
+ if (isAcItem) {
+ Name ntName = ((NodeTypeImpl) targetNode.getPrimaryNodeType()).getQName();
+ if (ntName.equals(NT_REP_ACL)) {
node = (NodeImpl) targetNode.getParent();
} else {
node = (NodeImpl) targetNode.getParent().getParent();
@@ -248,10 +259,8 @@ public class ACLProvider extends Abstrac
// if the given node is access-controlled, construct a new ACL and add
// it to the list
if (isAccessControlled(node)) {
- // build acl for the access controlled node
- NodeImpl aclNode = node.getNode(N_POLICY);
- AccessControlList acl = systemEditor.getACL(aclNode);
- acls.add(new UnmodifiableAccessControlList(acl));
+ // retrieve the entries for the access controlled node
+ acls.add(new UnmodifiableAccessControlList(entryCollector.getEntries(node), node.getPath(), Collections.<String, Integer>emptyMap()));
}
// then, recursively look for access controlled parents up the hierarchy.
if (!rootNodeId.equals(node.getId())) {
@@ -316,22 +325,24 @@ public class ACLProvider extends Abstrac
* and if it has a child node named
* {@link AccessControlConstants#N_POLICY "rep:ACL"}.
*
- * @param node hte node
- * @return <code>true</code> if the node is access controlled;
- * <code>false</code> otherwise.
+ * @param node the node to be tested
+ * @return <code>true</code> if the node is access controlled and has a
+ * rep:policy child; <code>false</code> otherwise.
* @throws RepositoryException if an error occurs
*/
static boolean isAccessControlled(NodeImpl node) throws RepositoryException {
- return node.isNodeType(NT_REP_ACCESS_CONTROLLABLE) && node.hasNode(N_POLICY);
+ return node.hasNode(N_POLICY) && node.isNodeType(NT_REP_ACCESS_CONTROLLABLE);
}
//------------------------------------------------< CompiledPermissions >---
/**
*
*/
- private class AclPermissions extends AbstractCompiledPermissions implements SynchronousEventListener {
+ private class AclPermissions extends AbstractCompiledPermissions implements AccessControlListener {
private final List<String> principalNames;
+ private final Map<NodeId, Boolean> readCache = new LRUMap(1000);
+ private final Object monitor = new Object();
private AclPermissions(Set<Principal> principals) throws RepositoryException {
this(principals, true);
@@ -346,58 +357,17 @@ public class ACLProvider extends Abstrac
if (listenToEvents) {
/*
Make sure this AclPermission recalculates the permissions if
- any ACL concerning it is modified. interesting events are:
- - new ACE-entry for any of the principals (NODE_ADDED)
- - changing ACE-entry for any of the principals (PROPERTY_CHANGED)
- > new permissions granted/denied
- >
- - removed ACE-entry for any of the principals (NODE_REMOVED)
- */
- int events = Event.PROPERTY_CHANGED | Event.NODE_ADDED | Event.NODE_REMOVED;
- String[] ntNames = new String[] {
- resolver.getJCRName(NT_REP_ACE),
- resolver.getJCRName(NT_REP_ACL)
- };
- observationMgr.addEventListener(this, events, session.getRootNode().getPath(), true, null, ntNames, true);
+ any ACL concerning it is modified.
+ */
+ entryCollector.addListener(this);
}
}
- //------------------------------------< AbstractCompiledPermissions >---
- /**
- * @see AbstractCompiledPermissions#buildResult(Path)
- */
- @Override
- protected Result buildResult(Path absPath) throws RepositoryException {
- boolean existingNode = false;
- NodeImpl node = null;
- String jcrPath = resolver.getJCRPath(absPath);
-
- if (session.nodeExists(jcrPath)) {
- node = (NodeImpl) session.getNode(jcrPath);
- existingNode = true;
- } else {
- // path points to existing prop or non-existing item (node or prop).
- // -> find the nearest persisted node
- String parentPath = Text.getRelativeParent(jcrPath, 1);
- while (parentPath.length() > 0) {
- if (session.nodeExists(parentPath)) {
- node = (NodeImpl) session.getNode(parentPath);
- break;
- }
- parentPath = Text.getRelativeParent(parentPath, 1);
- }
- }
-
- if (node == null) {
- // should never get here
- throw new ItemNotFoundException("Item out of hierarchy.");
- }
-
- boolean isAcItem = isAcItem(absPath);
-
+ private Result buildResult(NodeImpl node, boolean existingNode, boolean isAcItem, EntryFilter filter) throws RepositoryException {
// retrieve all ACEs at path or at the direct ancestor of path that
// apply for the principal names.
- Iterator<AccessControlEntry> entries = retrieveResultEntries(getNode(node), principalNames);
+ Iterator<AccessControlEntry> entries = retrieveResultEntries(getNode(node, isAcItem), filter);
+
/*
Calculate privileges and permissions:
Since the ACEs only define privileges on a node and do not allow
@@ -421,7 +391,7 @@ public class ACLProvider extends Abstrac
defined locally must be treated different than inherited entries.
*/
int entryBits = ace.getPrivilegeBits();
- boolean isLocal = existingNode && ace.isLocal(jcrPath);
+ boolean isLocal = existingNode && ace.isLocal(node.getNodeId());
if (!isLocal) {
if (ace.isAllow()) {
parentAllows |= Permission.diff(entryBits, parentDenies);
@@ -442,163 +412,115 @@ public class ACLProvider extends Abstrac
return new Result(allows, denies, allowPrivileges, denyPrivileges);
}
- //--------------------------------------------< CompiledPermissions >---
+ //------------------------------------< AbstractCompiledPermissions >---
/**
- * @see CompiledPermissions#close()
+ * @see AbstractCompiledPermissions#buildResult(Path)
*/
@Override
- public void close() {
+ protected Result buildResult(Path absPath) throws RepositoryException {
+ boolean existingNode = false;
+ NodeImpl node;
+
+ ItemManager itemMgr = session.getItemManager();
try {
- observationMgr.removeEventListener(this);
+ ItemImpl item = itemMgr.getItem(absPath);
+ if (item.isNode()) {
+ node = (NodeImpl) item;
+ existingNode = true;
+ } else {
+ node = (NodeImpl) item.getParent();
+ }
} catch (RepositoryException e) {
- log.debug("Unable to unregister listener: ", e.getMessage());
+ // path points to a non-persisted item.
+ // -> find the nearest persisted node starting from the root.
+ Path.Element[] elems = absPath.getElements();
+ NodeImpl parent = (NodeImpl) session.getRootNode();
+ for (int i = 1; i < elems.length - 1; i++) {
+ Name name = elems[i].getName();
+ int index = elems[i].getIndex();
+ if (!parent.hasNode(name, index)) {
+ // last persisted node reached
+ break;
+ }
+ parent = parent.getNode(name, index);
+
+ }
+ node = parent;
}
- super.close();
+
+ if (node == null) {
+ // should never get here
+ throw new ItemNotFoundException("Item out of hierarchy.");
+ }
+
+ boolean isAcItem = isAcItem(absPath);
+ return buildResult(node, existingNode, isAcItem, new EntryFilterImpl(principalNames));
}
- //--------------------------------------------------< EventListener >---
/**
- * @see javax.jcr.observation.EventListener#onEvent(EventIterator)
+ * @see AbstractCompiledPermissions#clearCache()
*/
- public synchronized void onEvent(EventIterator events) {
- // only invalidate cache if any of the events affects the
- // nodes defining permissions for principals compiled here.
- boolean clearCache = false;
- while (events.hasNext() && !clearCache) {
- try {
- Event ev = events.nextEvent();
- String path = ev.getPath();
- switch (ev.getType()) {
- case Event.NODE_ADDED:
- // test if the new node is an ACE node that affects
- // the permission of any of the principals listed in
- // principalNames.
- NodeImpl n = (NodeImpl) session.getNode(path);
- if (n.isNodeType(NT_REP_ACE) &&
- principalNames.contains(n.getProperty(P_PRINCIPAL_NAME).getString())) {
- clearCache = true;
- }
- break;
- case Event.PROPERTY_REMOVED:
- case Event.NODE_REMOVED:
- // can't find out if the removed ACL/ACE node was
- // relevant for the principals
- clearCache = true;
- break;
- case Event.PROPERTY_ADDED:
- case Event.PROPERTY_CHANGED:
- // test if the added/changed prop belongs to an ACe
- // node and affects the permission of any of the
- // principals listed in principalNames.
- PropertyImpl p = (PropertyImpl) session.getProperty(path);
- NodeImpl parent = (NodeImpl) p.getParent();
- if (parent.isNodeType(NT_REP_ACE)) {
- String principalName = null;
- if (P_PRIVILEGES.equals(p.getQName())) {
- // test if principal-name sibling-prop matches
- principalName = parent.getProperty(P_PRINCIPAL_NAME).getString();
- } else if (P_PRINCIPAL_NAME.equals(p.getQName())) {
- // a new ace or an ace change its principal-name.
- principalName = p.getString();
- }
- if (principalName != null &&
- principalNames.contains(principalName)) {
- clearCache = true;
- }
- }
- break;
- case Event.NODE_MOVED:
- // protected ac nodes cannot be moved around
- // -> nothing to do TODO check again
- break;
- default:
- // illegal event-type: should never occur. ignore
- }
- } catch (RepositoryException e) {
- // should not get here
- log.warn("Internal error: ", e.getMessage());
- }
- }
- if (clearCache) {
- clearCache();
+ @Override
+ protected void clearCache() {
+ synchronized (monitor) {
+ readCache.clear();
}
+ super.clearCache();
}
- }
-
- //--------------------------------------------------------------------------
- /**
- * Inner class used to collect ACEs for a given set of principals throughout
- * the node hierarchy.
- */
- private class Entries {
- private final Collection<String> principalNames;
- private final List<AccessControlEntry> userAces = new ArrayList();
- private final List<AccessControlEntry> groupAces = new ArrayList();
-
- private Entries(NodeImpl node, Collection<String> principalNames) throws RepositoryException {
- this.principalNames = principalNames;
- collectEntries(node);
- }
-
- private void collectEntries(NodeImpl node) throws RepositoryException {
- // if the given node is access-controlled, construct a new ACL and add
- // it to the list
- if (isAccessControlled(node)) {
- // build acl for the access controlled node
- NodeImpl aclNode = node.getNode(N_POLICY);
- //collectEntries(aclNode, principalNamesToEntries);
- collectEntriesFromAcl(aclNode);
- }
- // recursively look for access controlled parents up the hierarchy.
- if (!rootNodeId.equals(node.getId())) {
- NodeImpl parentNode = (NodeImpl) node.getParent();
- collectEntries(parentNode);
- }
+ //--------------------------------------------< CompiledPermissions >---
+ /**
+ * @see CompiledPermissions#close()
+ */
+ @Override
+ public void close() {
+ entryCollector.removeListener(this);
+ super.close();
}
/**
- * Separately collect the entries defined for the user and group
- * principals.
- *
- * @param aclNode acl node
- * @throws RepositoryException if an error occurs
+ * @see CompiledPermissions#canRead(Path, ItemId)
*/
- private void collectEntriesFromAcl(NodeImpl aclNode) throws RepositoryException {
- // first collect aces present on the given aclNode.
- List<AccessControlEntry> gaces = new ArrayList<AccessControlEntry>();
- List<AccessControlEntry> uaces = new ArrayList<AccessControlEntry>();
-
- ACLTemplate tmpl = (ACLTemplate) systemEditor.getACL(aclNode);
- for (AccessControlEntry ace : tmpl.getAccessControlEntries()) {
- Principal principal = ace.getPrincipal();
- // only process aceNode if 'principalName' is contained in the given set
- if (principalNames.contains(principal.getName())) {
- // add it to the proper list (e.g. separated by principals)
- /**
- * NOTE: access control entries must be collected in reverse
- * order in order to assert proper evaluation.
- */
- if (principal instanceof Group) {
- gaces.add(0, ace);
- } else {
- uaces.add(0, ace);
- }
- }
+ public boolean canRead(Path path, ItemId itemId) throws RepositoryException {
+ ItemId id = (itemId == null) ? session.getHierarchyManager().resolvePath(path) : itemId;
+ /* currently READ access cannot be denied to individual properties.
+ if the parent node is readable the properties are as well.
+ this simplifies the canRead test as well as the caching.
+ */
+ boolean existingNode = false;
+ NodeId nodeId;
+ if (id.denotesNode()) {
+ nodeId = (NodeId) id;
+ // since method may only be called for existing nodes the
+ // flag be set to true if the id identifies a node.
+ existingNode = true;
+ } else {
+ nodeId = ((PropertyId) id).getParentId();
}
- // add the lists of aces to the overall lists that contain the entries
- // throughout the hierarchy.
- if (!gaces.isEmpty()) {
- groupAces.addAll(gaces);
- }
- if (!uaces.isEmpty()) {
- userAces.addAll(uaces);
+ boolean canRead;
+ synchronized (monitor) {
+ if (readCache.containsKey(nodeId)) {
+ canRead = readCache.get(nodeId);
+ } else {
+ ItemManager itemMgr = session.getItemManager();
+ NodeImpl node = (NodeImpl) itemMgr.getItem(nodeId);
+ Result result = buildResult(node, existingNode, isAcItem(node), new EntryFilterImpl(principalNames));
+
+ canRead = result.grants(Permission.READ);
+ readCache.put(nodeId, canRead);
+ }
}
+ return canRead;
}
- private Iterator<AccessControlEntry> iterator() {
- return new IteratorChain(userAces.iterator(), groupAces.iterator());
+ //----------------------------------------< ACLModificationListener >---
+ /**
+ * @see org.apache.jackrabbit.core.security.authorization.AccessControlListener#acModified(AccessControlModifications)
+ */
+ public void acModified(AccessControlModifications modifications) {
+ // ignore the details of the modifications and clear all caches.
+ clearCache();
}
}
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java?rev=950440&r1=950439&r2=950440&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplate.java Wed Jun 2 09:00:44 2010
@@ -36,6 +36,8 @@ import org.apache.jackrabbit.api.securit
import org.apache.jackrabbit.api.security.principal.PrincipalManager;
import org.apache.jackrabbit.core.NodeImpl;
import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.id.NodeId;
+import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
import org.apache.jackrabbit.core.security.authorization.AbstractACLTemplate;
import org.apache.jackrabbit.core.security.authorization.AccessControlConstants;
import org.apache.jackrabbit.core.security.authorization.AccessControlEntryImpl;
@@ -76,6 +78,14 @@ class ACLTemplate extends AbstractACLTem
private final PrivilegeRegistry privilegeRegistry;
/**
+ * The id of the access controlled node or <code>null</code> if this
+ * ACLTemplate isn't created for an existing access controlled node.
+ * Used for the Entry#isLocal(NodeId) call only in order to avoid calls
+ * to {@link javax.jcr.Node#getPath()}.
+ */
+ private final NodeId id;
+
+ /**
* Construct a new empty {@link ACLTemplate}.
*
* @param path path
@@ -88,6 +98,7 @@ class ACLTemplate extends AbstractACLTem
super(path, valueFactory);
this.principalMgr = principalMgr;
this.privilegeRegistry = privilegeRegistry;
+ this.id = null;
}
/**
@@ -100,13 +111,14 @@ class ACLTemplate extends AbstractACLTem
*/
ACLTemplate(NodeImpl aclNode, PrivilegeRegistry privilegeRegistry) throws RepositoryException {
super((aclNode != null) ? aclNode.getParent().getPath() : null, (aclNode != null) ? aclNode.getSession().getValueFactory() : null);
- if (aclNode == null || !aclNode.isNodeType(AccessControlConstants.NT_REP_ACL)) {
+ if (aclNode == null || !AccessControlConstants.NT_REP_ACL.equals(((NodeTypeImpl)aclNode.getPrimaryNodeType()).getQName())) {
throw new IllegalArgumentException("Node must be of type 'rep:ACL'");
}
SessionImpl sImpl = (SessionImpl) aclNode.getSession();
principalMgr = sImpl.getPrincipalManager();
-
+
this.privilegeRegistry = privilegeRegistry;
+ this.id = aclNode.getParentId();
// load the entries:
AccessControlManager acMgr = sImpl.getAccessControlManager();
@@ -130,7 +142,7 @@ class ACLTemplate extends AbstractACLTem
Entry ace = createEntry(
princ,
privs,
- aceNode.isNodeType(AccessControlConstants.NT_REP_GRANT_ACE));
+ AccessControlConstants.NT_REP_GRANT_ACE.equals(((NodeTypeImpl) aceNode.getPrimaryNodeType()).getQName()));
// add the entry
internalAdd(ace);
} catch (RepositoryException e) {
@@ -141,7 +153,7 @@ class ACLTemplate extends AbstractACLTem
/**
* Create a new entry omitting any validation checks.
- *
+ *
* @param principal
* @param privileges
* @param isAllow
@@ -267,14 +279,6 @@ class ACLTemplate extends AbstractACLTem
//--------------------------------------------------< AccessControlList >---
/**
- * @see javax.jcr.security.AccessControlList#getAccessControlEntries()
- */
- public AccessControlEntry[] getAccessControlEntries() throws RepositoryException {
- List<? extends AccessControlEntry> l = getEntries();
- return l.toArray(new AccessControlEntry[l.size()]);
- }
-
- /**
* @see javax.jcr.security.AccessControlList#removeAccessControlEntry(AccessControlEntry)
*/
public synchronized void removeAccessControlEntry(AccessControlEntry ace)
@@ -310,20 +314,6 @@ class ACLTemplate extends AbstractACLTem
}
/**
- * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#isEmpty()
- */
- public boolean isEmpty() {
- return entries.isEmpty();
- }
-
- /**
- * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#size()
- */
- public int size() {
- return getEntries().size();
- }
-
- /**
* @see org.apache.jackrabbit.api.security.JackrabbitAccessControlList#addEntry(Principal, Privilege[], boolean, Map)
*/
public boolean addEntry(Principal principal, Privilege[] privileges,
@@ -342,6 +332,7 @@ class ACLTemplate extends AbstractACLTem
* @return always zero
* @see Object#hashCode()
*/
+ @Override
public int hashCode() {
return 0;
}
@@ -353,6 +344,7 @@ class ACLTemplate extends AbstractACLTem
* @return true if the path and the entries are equal; false otherwise.
* @see Object#equals(Object)
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
@@ -377,12 +369,12 @@ class ACLTemplate extends AbstractACLTem
}
/**
- * @param nodePath
+ * @param nodeId
* @return <code>true</code> if this entry is defined on the node
- * at <code>nodePath</code>
+ * at <code>nodeId</code>
*/
- boolean isLocal(String nodePath) {
- return path != null && path.equals(nodePath);
+ boolean isLocal(NodeId nodeId) {
+ return id != null && id.equals(nodeId);
}
}
}