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 2009/01/08 12:52:45 UTC
svn commit: r732693 [3/6] - in /jackrabbit/trunk:
jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jsr283/security/
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ jackra...
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=732693&r1=732692&r2=732693&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 Thu Jan 8 03:52:38 2009
@@ -305,7 +305,7 @@
return true;
} catch (RepositoryException e) {
// revert all pending changes and rethrow.
- log.error("Error while editing group membership:", e.getMessage());
+ log.warn("Error while editing group membership:", e.getMessage());
getSession().refresh(false);
throw e;
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.java Thu Jan 8 03:52:38 2009
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.core.security.user;
import org.apache.jackrabbit.api.jsr283.security.AccessControlPolicy;
+import org.apache.jackrabbit.api.jsr283.security.Privilege;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.jackrabbit.core.ItemImpl;
@@ -189,7 +190,7 @@
// no 'user' within set of principals -> READ-only
return getReadOnlyPermissions();
} else {
- return new CompiledPermissionsImpl(principals, userNode);
+ return new CompiledPermissionsImpl(principals, userNode.getPath());
}
}
}
@@ -251,6 +252,11 @@
}
}
+ private int getPrivilegeBits(String privName) throws RepositoryException {
+ Privilege[] privs = new Privilege[] {session.getAccessControlManager().privilegeFromName(privName)};
+ return PrivilegeRegistry.getBits(privs);
+ }
+
private static boolean containsGroup(Set principals, String groupName) {
for (Iterator it = principals.iterator(); it.hasNext() && groupName != null;) {
Principal p = (Principal) it.next();
@@ -289,13 +295,13 @@
private class CompiledPermissionsImpl extends AbstractCompiledPermissions
implements SynchronousEventListener {
- private final NodeImpl userNode;
+ private final String userNodePath;
private boolean isUserAdmin;
private boolean isGroupAdmin;
- protected CompiledPermissionsImpl(Set principals, NodeImpl userNode) throws RepositoryException {
- this.userNode = userNode;
+ protected CompiledPermissionsImpl(Set principals, String userNodePath) throws RepositoryException {
+ this.userNodePath = userNodePath;
isUserAdmin = containsGroup(principals, userAdminGroup);
isGroupAdmin = containsGroup(principals, groupAdminGroup);
@@ -308,6 +314,22 @@
* @see AbstractCompiledPermissions#buildResult(Path)
*/
protected Result buildResult(Path path) throws RepositoryException {
+ NodeImpl userNode = null;
+ try {
+ if (session.nodeExists(userNodePath)) {
+ userNode = (NodeImpl) session.getNode(userNodePath);
+ }
+ } catch (RepositoryException e) {
+ // ignore
+ }
+
+ if (userNode == null) {
+ // no Node corresponding to user for which the permissions are
+ // calculated -> no permissions/priviles.
+ log.debug("No node at " + userNodePath);
+ return new Result(Permission.NONE, Permission.NONE, PrivilegeRegistry.NO_PRIVILEGE, PrivilegeRegistry.NO_PRIVILEGE);
+ }
+
// no explicit denied permissions:
int denies = Permission.NONE;
// default allow permission and default privileges
@@ -317,7 +339,7 @@
// Generally, privileges can only be determined for existing nodes.
boolean calcPrivs = session.nodeExists(resolver.getJCRPath(path.getNormalizedPath()));
if (calcPrivs) {
- privs = PrivilegeRegistry.READ;
+ privs = getPrivilegeBits(Privilege.JCR_READ);
} else {
privs = PrivilegeRegistry.NO_PRIVILEGE;
}
@@ -370,23 +392,32 @@
3) special treatment for rep:group property which can
only be modified by group-administrators
*/
+ Path aPath = session.getQPath(authN.getPath());
if (requiredGroups) {
// principals contain 'user-admin'
// -> user can modify items below the user-node except rep:group.
// principals contains 'user-admin' + 'group-admin'
// -> user can modify rep:group property as well.
- allows = Permission.ALL;
+ if (path.equals(aPath)) {
+ allows |= (Permission.ADD_NODE | Permission.REMOVE_PROPERTY | Permission.SET_PROPERTY);
+ } else {
+ allows |= Permission.ALL;
+ }
if (calcPrivs) {
// grant WRITE privilege
// note: ac-read/modification is not included
- privs |= PrivilegeRegistry.WRITE;
+ // remove_node is not included
+ privs |= getPrivilegeBits(PrivilegeRegistry.REP_WRITE);
+ if (!path.equals(aPath)) {
+ privs |= getPrivilegeBits(Privilege.JCR_REMOVE_NODE);
+ }
}
} else if (userNode.isSame(node) && (!isGroupProp || isGroupAdmin)) {
// user can only read && write his own props
// except for the rep:group property.
allows |= (Permission.SET_PROPERTY | Permission.REMOVE_PROPERTY);
if (calcPrivs) {
- privs |= PrivilegeRegistry.MODIFY_PROPERTIES;
+ privs |= getPrivilegeBits(Privilege.JCR_MODIFY_PROPERTIES);
}
} // else some other node below but not U-admin -> read-only.
break;
@@ -406,7 +437,7 @@
if (calcPrivs) {
// grant WRITE privilege
// note: ac-read/modification is not included
- privs |= PrivilegeRegistry.WRITE;
+ privs |= getPrivilegeBits(PrivilegeRegistry.REP_WRITE);
}
}
}
@@ -419,7 +450,7 @@
if (isGroupAdmin) {
allows = Permission.ALL;
if (calcPrivs) {
- privs |= PrivilegeRegistry.WRITE;
+ privs |= getPrivilegeBits(PrivilegeRegistry.REP_WRITE);
}
}
} // else outside of user/group tree -> read only.
@@ -473,7 +504,7 @@
String repGroups = session.getJCRName(UserConstants.P_GROUPS);
// TODO: add better evaluation.
if (repGroups.equals(Text.getName(evPath)) &&
- userNode.getPath().equals(Text.getRelativeParent(evPath, 1))) {
+ userNodePath.equals(Text.getRelativeParent(evPath, 1))) {
// recalculate the is...Admin flags
switch (ev.getType()) {
case Event.PROPERTY_REMOVED:
@@ -482,15 +513,17 @@
break;
case Event.PROPERTY_ADDED:
case Event.PROPERTY_CHANGED:
- Value[] vs = session.getProperty(evPath).getValues();
- String princName = session.getJCRName(P_PRINCIPAL_NAME);
- for (int i = 0; i < vs.length; i++) {
- Node groupNode = session.getNodeByUUID(vs[i].getString());
- String pName = groupNode.getProperty(princName).getString();
- if (userAdminGroup.equals(pName)) {
- isUserAdmin = true;
- } else if (groupAdminGroup.equals(pName)) {
- isGroupAdmin = true;
+ if (session.propertyExists(evPath)) {
+ Value[] vs = session.getProperty(evPath).getValues();
+ String princName = session.getJCRName(P_PRINCIPAL_NAME);
+ for (int i = 0; i < vs.length; i++) {
+ Node groupNode = session.getNodeByUUID(vs[i].getString());
+ String pName = groupNode.getProperty(princName).getString();
+ if (userAdminGroup.equals(pName)) {
+ isUserAdmin = true;
+ } else if (groupAdminGroup.equals(pName)) {
+ isGroupAdmin = true;
+ }
}
}
break;
@@ -508,4 +541,4 @@
}
}
}
-}
\ No newline at end of file
+}
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=732693&r1=732692&r2=732693&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 Thu Jan 8 03:52:38 2009
@@ -71,6 +71,7 @@
private final Map idPathMap = new LRUMap(1000);
public UserManagerImpl(SessionImpl session, String adminId) throws RepositoryException {
+ super(false);
this.session = session;
this.adminId = adminId;
@@ -222,7 +223,7 @@
setSecurityProperty(userNode, P_PRINCIPAL_NAME, getValue(principal.getName()));
parent.save();
- log.info("User created: " + userID + "; " + userNode.getPath());
+ log.debug("User created: " + userID + "; " + userNode.getPath());
return createUser(userNode);
} catch (RepositoryException e) {
// something went wrong -> revert changes and rethrow
@@ -274,7 +275,7 @@
setSecurityProperty(groupNode, P_PRINCIPAL_NAME, getValue(principal.getName()));
parent.save();
- log.info("Group created: " + groupID + "; " + groupNode.getPath());
+ log.debug("Group created: " + groupID + "; " + groupNode.getPath());
return createGroup(groupNode);
} catch (RepositoryException e) {
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/XAItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/XAItemStateManager.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/XAItemStateManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/XAItemStateManager.java Thu Jan 8 03:52:38 2009
@@ -31,8 +31,6 @@
import javax.jcr.ReferentialIntegrityException;
import javax.jcr.PropertyType;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.IdentityHashMap;
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java Thu Jan 8 03:52:38 2009
@@ -16,21 +16,23 @@
*/
package org.apache.jackrabbit.core.version;
-import org.apache.jackrabbit.core.ItemManager;
import org.apache.jackrabbit.core.AbstractNodeData;
+import org.apache.jackrabbit.core.ItemManager;
import org.apache.jackrabbit.core.NodeId;
-import org.apache.jackrabbit.core.SessionImpl;
import org.apache.jackrabbit.core.NodeImpl;
-import org.apache.jackrabbit.spi.commons.conversion.NameException;
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.security.authorization.Permission;
import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.commons.conversion.NameException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.jcr.InvalidItemStateException;
import javax.jcr.Item;
+import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.UnsupportedRepositoryOperationException;
-import javax.jcr.NodeIterator;
-import javax.jcr.InvalidItemStateException;
+import javax.jcr.ItemNotFoundException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.version.Version;
import javax.jcr.version.VersionException;
@@ -51,10 +53,7 @@
* Create a new instance of this class.
* @param itemMgr item manager
* @param session session
- * @param id node id
- * @param state node state
- * @param definition node definition
- * @param listeners life cycle listeners
+ * @param data
*/
public VersionHistoryImpl(ItemManager itemMgr, SessionImpl session, AbstractNodeData data) {
super(itemMgr, session, data);
@@ -132,6 +131,8 @@
public void addVersionLabel(String versionName, String label, boolean move)
throws VersionException, RepositoryException {
try {
+ // check permissions
+ checkVersionManagementPermission();
session.getVersionManager().setVersionLabel(
this, session.getQName(versionName),
session.getQName(label), move);
@@ -145,8 +146,9 @@
*/
public void removeVersionLabel(String label) throws RepositoryException {
try {
- Version existing = session.getVersionManager().setVersionLabel(
- this, null, session.getQName(label), true);
+ // check permissions
+ checkVersionManagementPermission();
+ Version existing = session.getVersionManager().setVersionLabel(this, null, session.getQName(label), true);
if (existing == null) {
throw new VersionException("No version with label '" + label + "' exists in this version history.");
}
@@ -215,8 +217,9 @@
throws UnsupportedRepositoryOperationException, VersionException,
RepositoryException {
try {
- session.getVersionManager().removeVersion(
- this, session.getQName(versionName));
+ // check permissions
+ checkVersionManagementPermission();
+ session.getVersionManager().removeVersion(this, session.getQName(versionName));
} catch (NameException e) {
throw new RepositoryException(e);
}
@@ -247,6 +250,19 @@
}
/**
+ *
+ * @return
+ * @throws RepositoryException
+ */
+ private void checkVersionManagementPermission() throws RepositoryException {
+ try {
+ session.getAccessManager().checkPermission(getPrimaryPath(), Permission.VERSION_MNGMT);
+ } catch (ItemNotFoundException e) {
+ // ignore.
+ }
+ }
+
+ /**
* Checks if the given version belongs to this history
*
* @param version
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java Thu Jan 8 03:52:38 2009
@@ -19,6 +19,7 @@
import org.apache.jackrabbit.core.NodeId;
import org.apache.jackrabbit.core.NodeImpl;
import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.security.authorization.Permission;
import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.commons.name.NameConstants;
@@ -27,6 +28,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.jcr.AccessDeniedException;
import javax.jcr.ImportUUIDBehavior;
import javax.jcr.ItemExistsException;
import javax.jcr.ItemNotFoundException;
@@ -65,7 +67,7 @@
* @param importTargetNode
* @param session
* @param uuidBehavior any of the constants declared by
- * {@link ImportUUIDBehavior}
+ * {@link javax.jcr.ImportUUIDBehavior}
*/
public SessionImporter(NodeImpl importTargetNode,
SessionImpl session,
@@ -184,6 +186,13 @@
log.debug("Skipping node: " + nodeName);
return;
}
+
+ // make sure the editing session is allowed create nodes with a
+ // specified node type (and ev. mixins)
+ if (!session.getAccessManager().isGranted(session.getQPath(parent.getPath()), nodeName, Permission.NODE_TYPE_MNGMT)) {
+ throw new AccessDeniedException("Insufficient permission.");
+ }
+
if (parent.hasNode(nodeName)) {
// a node with that name already exists...
NodeImpl existing = parent.getNode(nodeName);
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/AbstractLockTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/AbstractLockTest.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/AbstractLockTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/AbstractLockTest.java Thu Jan 8 03:52:38 2009
@@ -108,9 +108,6 @@
assertTrue("Seconds remaining must be a positive long or 0.", lock.getSecondsRemaining() >= 0);
}
-
-
-
public void testRemoveMixLockableFromLockedNode() throws RepositoryException {
try {
lockedNode.removeMixin(mixLockable);
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/DeepLockTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/DeepLockTest.java?rev=732693&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/DeepLockTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/DeepLockTest.java Thu Jan 8 03:52:38 2009
@@ -0,0 +1,188 @@
+/*
+ * 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.api.jsr283.lock;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.apache.jackrabbit.test.NotExecutableException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.lock.LockException;
+
+/** <code>DeepLockTest</code>... */
+public class DeepLockTest extends AbstractJCRTest {
+
+ private static Logger log = LoggerFactory.getLogger(DeepLockTest.class);
+
+ protected Node lockedNode;
+ protected Node childNode;
+ protected Lock lock;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ lockedNode = testRootNode.addNode(nodeName1, testNodeType);
+ lockedNode.addMixin(mixLockable);
+ childNode = lockedNode.addNode(nodeName2, testNodeType);
+ testRootNode.save();
+
+ // TODO: remove cast
+ // TODO: replace by LockManager#lock call
+ lock = (Lock) lockedNode.lock(true, true);
+ }
+
+ protected void tearDown() throws Exception {
+ // make sure all locks are removed
+ try {
+ lockedNode.unlock();
+ } catch (RepositoryException e) {
+ // ignore
+ }
+ super.tearDown();
+ }
+
+ // TODO: replace locking calls by LockManager#...
+
+ public void testNewBelowDeepLock() throws RepositoryException {
+ Node newNode = lockedNode.addNode(nodeName3);
+ assertTrue(newNode.isLocked());
+ }
+
+ public void testLockHoldingNode() throws RepositoryException {
+ assertTrue("Lock.getNode() must be lockholding node.", lock.getNode().isSame(lockedNode));
+ }
+
+ public void testLockIsDeep() throws RepositoryException {
+ assertTrue("Lock.isDeep() if lock has been created deeply.", lock.isDeep());
+ }
+
+ public void testNodeIsLocked() throws RepositoryException {
+ assertTrue("Creating a deep lock must create a lock on the lock-holding node", lockedNode.isLocked());
+ assertTrue("Creating a deep lock must create a lock on the lock-holding node", lockedNode.holdsLock());
+ }
+
+ public void testIsLockedChild() throws RepositoryException {
+ assertTrue("Child node below deep lock must be locked", childNode.isLocked());
+ }
+
+ public void testIsLockedNewChild() throws RepositoryException {
+ Node newChild = lockedNode.addNode(nodeName3, testNodeType);
+ assertTrue("Child node below deep lock must be locked even if it is NEW",
+ newChild.isLocked());
+ }
+
+ public void testNotHoldsLockChild() throws RepositoryException {
+ assertFalse("Child node below deep lock must not be lock holder",
+ childNode.holdsLock());
+ }
+
+ public void testGetLockOnChild() throws RepositoryException {
+ // get lock must succeed even if child is not lockable.
+ javax.jcr.lock.Lock lock = childNode.getLock();
+ assertNotNull(lock);
+ assertTrue("Lock.getNode() must return the lock holding node",
+ lockedNode.isSame(lock.getNode()));
+ }
+
+ public void testGetLockOnNewChild() throws RepositoryException {
+ // get lock must succeed even if child is not lockable.
+ Node newChild = lockedNode.addNode(nodeName3, testNodeType);
+ javax.jcr.lock.Lock lock = newChild.getLock();
+ assertNotNull(lock);
+ assertTrue("Lock.getNode() must return the lock holding node",
+ lockedNode.isSame(lock.getNode()));
+ }
+
+ public void testGetNodeOnLockObtainedFromChild() throws RepositoryException {
+ javax.jcr.lock.Lock lock = childNode.getLock();
+ assertTrue("Lock.getNode() must return the lock holding node even if lock is obtained from child node.", lock.getNode().isSame(lockedNode));
+ }
+
+ public void testGetNodeOnLockObtainedFromNewChild() throws RepositoryException {
+ Node newChild = lockedNode.addNode(nodeName3, testNodeType);
+ javax.jcr.lock.Lock lock = newChild.getLock();
+ assertTrue("Lock.getNode() must return the lock holding node even if lock is obtained from child node.", lock.getNode().isSame(lockedNode));
+ }
+
+ public void testParentChildDeepLock() throws RepositoryException {
+ childNode.addMixin(mixLockable);
+ testRootNode.save();
+
+ // try to lock child node
+ try {
+ childNode.lock(false, false);
+ fail("child node is already locked by deep lock on parent.");
+ } catch (LockException e) {
+ // ok
+ }
+ }
+
+ public void testDeepLockAboveLockedChild() throws RepositoryException, NotExecutableException {
+ try {
+ Node parent = lockedNode.getParent();
+ if (!parent.isNodeType(mixLockable)) {
+ try {
+ parent.addMixin(mixLockable);
+ parent.save();
+ } catch (RepositoryException e) {
+ throw new NotExecutableException();
+ }
+ }
+
+ parent.lock(true, true);
+ fail("Creating a deep lock on a parent of a locked node must fail.");
+ } catch (LockException e) {
+ // expected
+ }
+ }
+
+ public void testShallowLockAboveLockedChild() throws RepositoryException, NotExecutableException {
+ Node parent = lockedNode.getParent();
+ try {
+ if (!parent.isNodeType(mixLockable)) {
+ try {
+ parent.addMixin(mixLockable);
+ parent.save();
+ } catch (RepositoryException e) {
+ throw new NotExecutableException();
+ }
+ }
+
+ // creating a shallow lock on the parent must succeed.
+ parent.lock(false, true);
+ } finally {
+ parent.unlock();
+ }
+ }
+
+ public void testRemoveLockedChild() throws RepositoryException {
+ Session otherSession = helper.getReadWriteSession();
+ try {
+ Node child = (Node) otherSession.getItem(childNode.getPath());
+ child.remove();
+ otherSession.save();
+ fail("A node below a deeply locked node cannot be removed by another Session.");
+ } catch (LockException e) {
+ // success
+ } finally {
+ otherSession.logout();
+ }
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/DeepLockTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/DeepLockTest.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/LockManagerTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/LockManagerTest.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/LockManagerTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/LockManagerTest.java Thu Jan 8 03:52:38 2009
@@ -19,7 +19,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.jackrabbit.test.AbstractJCRTest;
-import org.apache.jackrabbit.test.NotExecutableException;
/** <code>LockManagerTest</code>... */
public class LockManagerTest extends AbstractJCRTest {
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/OpenScopedLockTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/OpenScopedLockTest.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/OpenScopedLockTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/OpenScopedLockTest.java Thu Jan 8 03:52:38 2009
@@ -18,8 +18,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.jackrabbit.test.AbstractJCRTest;
-import org.apache.jackrabbit.test.NotExecutableException;
/** <code>OpenScopedLockTest</code>... */
public class OpenScopedLockTest extends AbstractLockTest {
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/SessionScopedLockTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/SessionScopedLockTest.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/SessionScopedLockTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/SessionScopedLockTest.java Thu Jan 8 03:52:38 2009
@@ -18,15 +18,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.jackrabbit.test.AbstractJCRTest;
-import org.apache.jackrabbit.test.NotExecutableException;
-
-import javax.jcr.lock.LockException;
-import javax.jcr.AccessDeniedException;
-import javax.jcr.UnsupportedRepositoryOperationException;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.Node;
/** <code>SessionScopedLockTest</code>... */
public class SessionScopedLockTest extends AbstractLockTest {
@@ -47,5 +38,4 @@
public void testGetLockToken() {
assertNull("A session scoped lock may never expose the token.", lock.getLockToken());
}
-
}
\ No newline at end of file
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/TestAll.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/TestAll.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/TestAll.java Thu Jan 8 03:52:38 2009
@@ -35,6 +35,7 @@
suite.addTestSuite(LockManagerTest.class);
suite.addTestSuite(OpenScopedLockTest.class);
suite.addTestSuite(SessionScopedLockTest.class);
+ suite.addTestSuite(DeepLockTest.class);
*/
return suite;
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/security/AccessControlListTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/security/AccessControlListTest.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/security/AccessControlListTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/security/AccessControlListTest.java Thu Jan 8 03:52:38 2009
@@ -16,24 +16,24 @@
*/
package org.apache.jackrabbit.api.jsr283.security;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.jackrabbit.test.NotExecutableException;
import org.apache.jackrabbit.core.SessionImpl;
import org.apache.jackrabbit.core.security.TestPrincipal;
+import org.apache.jackrabbit.test.NotExecutableException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import javax.jcr.AccessDeniedException;
import javax.jcr.Node;
-import javax.jcr.Session;
import javax.jcr.RepositoryException;
-import javax.jcr.AccessDeniedException;
-import java.util.Iterator;
-import java.util.Arrays;
-import java.util.List;
+import javax.jcr.Session;
+import java.security.Principal;
+import java.security.acl.Group;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
import java.util.Set;
-import java.security.Principal;
-import java.security.acl.Group;
/**
* <code>AccessControlEntryTest</code>...
@@ -88,7 +88,6 @@
protected void tearDown() throws Exception {
try {
- // TODO: review if correct.
// restore original entries (remove others).
AccessControlList list = getList(acMgr, path);
AccessControlEntry[] entries = list.getAccessControlEntries();
@@ -98,10 +97,15 @@
list.removeAccessControlEntry(ace);
}
}
- list.addAccessControlEntry(testPrincipal, (Privilege[]) privilegesToRestore.toArray(new Privilege[privilegesToRestore.size()]));
- superuser.save();
+ if (!privilegesToRestore.isEmpty()) {
+ list.addAccessControlEntry(testPrincipal, (Privilege[]) privilegesToRestore.toArray(new Privilege[privilegesToRestore.size()]));
+ }
+ if (list.getAccessControlEntries().length > 0 && acMgr.getPolicies(path).length > 0) {
+ acMgr.setPolicy(path, list);
+ superuser.save();
+ }
} catch (Exception e) {
- AccessControlListTest.log.error("Unexpected error while removing test entries.", e);
+ log.warn("Unexpected error while removing test entries.", e);
}
super.tearDown();
}
@@ -215,6 +219,30 @@
}
}
+ public void testAddAbstractPrivilege() throws NotExecutableException, RepositoryException {
+ checkCanModifyAc(path);
+
+ Privilege abstractPriv = null;
+ Privilege[] allPrivs = acMgr.privilegeFromName(Privilege.JCR_ALL).getAggregatePrivileges();
+ for (int i = 0; i < allPrivs.length; i++) {
+ if (allPrivs[i].isAbstract()) {
+ abstractPriv = allPrivs[i];
+ break;
+ }
+ }
+ if (abstractPriv == null) {
+ throw new NotExecutableException("No abstract privilege found.");
+ }
+
+ AccessControlList acl = getList(acMgr, path);
+ try {
+ acl.addAccessControlEntry(testPrincipal, new Privilege[] {abstractPriv});
+ fail("Adding an ACE with an abstract privilege must fail.");
+ } catch (AccessControlException e) {
+ // success
+ }
+ }
+
public void testAddPrivilegesPresentInEntries() throws NotExecutableException, RepositoryException {
checkCanModifyAc(path);
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java Thu Jan 8 03:52:38 2009
@@ -24,6 +24,8 @@
import javax.jcr.Session;
import javax.jcr.RepositoryException;
import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.InvalidItemStateException;
import javax.jcr.version.VersionException;
import javax.jcr.version.Version;
import javax.jcr.lock.Lock;
@@ -88,7 +90,7 @@
}
/**
- * @see junit.framework#runTest
+ * @see junit.framework.TestCase#runTest
*
* Make sure that tested repository supports transactions
*/
@@ -746,38 +748,39 @@
*/
public void testLockCommit() throws Exception {
Session other = helper.getSuperuserSession();
+ try {
+ // add node that is both lockable and referenceable, save
+ Node n = testRootNode.addNode(nodeName1);
+ n.addMixin(mixLockable);
+ n.addMixin(mixReferenceable);
+ testRootNode.save();
- // add node that is both lockable and referenceable, save
- Node n = testRootNode.addNode(nodeName1);
- n.addMixin(mixLockable);
- n.addMixin(mixReferenceable);
- testRootNode.save();
-
- // reference node in second session
- Node nOther = other.getNodeByUUID(n.getUUID());
-
- // verify node is not locked in either session
- assertFalse("Node not locked in session 1", n.isLocked());
- assertFalse("Node not locked in session 2", nOther.isLocked());
-
- // get user transaction object, start and lock node
- UserTransaction utx = new UserTransactionImpl(superuser);
- utx.begin();
- n.lock(false, true);
-
- // verify node is locked in first session only
- assertTrue("Node locked in session 1", n.isLocked());
- assertFalse("Node not locked in session 2", nOther.isLocked());
+ // reference node in second session
+ Node nOther = other.getNodeByUUID(n.getUUID());
- // commit in first session
- utx.commit();
+ // verify node is not locked in either session
+ assertFalse("Node not locked in session 1", n.isLocked());
+ assertFalse("Node not locked in session 2", nOther.isLocked());
+
+ // get user transaction object, start and lock node
+ UserTransaction utx = new UserTransactionImpl(superuser);
+ utx.begin();
+ n.lock(false, true);
+
+ // verify node is locked in first session only
+ assertTrue("Node locked in session 1", n.isLocked());
+ assertFalse("Node not locked in session 2", nOther.isLocked());
- // verify node is locked in both sessions
- assertTrue("Node locked in session 1", n.isLocked());
- assertTrue("Node locked in session 2", nOther.isLocked());
+ // commit in first session
+ utx.commit();
- // logout
- other.logout();
+ // verify node is locked in both sessions
+ assertTrue("Node locked in session 1", n.isLocked());
+ assertTrue("Node locked in session 2", nOther.isLocked());
+ } finally {
+ // logout
+ other.logout();
+ }
}
/**
@@ -787,38 +790,41 @@
*/
public void testLockRollback() throws Exception {
Session other = helper.getSuperuserSession();
+ try {
+ // add node that is both lockable and referenceable, save
+ Node n = testRootNode.addNode(nodeName1);
+ n.addMixin(mixLockable);
+ n.addMixin(mixReferenceable);
+ testRootNode.save();
- // add node that is both lockable and referenceable, save
- Node n = testRootNode.addNode(nodeName1);
- n.addMixin(mixLockable);
- n.addMixin(mixReferenceable);
- testRootNode.save();
-
- // reference node in second session
- Node nOther = other.getNodeByUUID(n.getUUID());
-
- // verify node is not locked in either session
- assertFalse("Node not locked in session 1", n.isLocked());
- assertFalse("Node not locked in session 2", nOther.isLocked());
-
- // get user transaction object, start and lock node
- UserTransaction utx = new UserTransactionImpl(superuser);
- utx.begin();
- n.lock(false, true);
-
- // verify node is locked in first session only
- assertTrue("Node locked in session 1", n.isLocked());
- assertFalse("Node not locked in session 2", nOther.isLocked());
-
- // rollback in first session
- utx.rollback();
-
- // verify node is not locked in either session
- assertFalse("Node not locked in session 1", n.isLocked());
- assertFalse("Node not locked in session 2", nOther.isLocked());
+ // reference node in second session
+ Node nOther = other.getNodeByUUID(n.getUUID());
- // logout
- other.logout();
+ // verify node is not locked in either session
+ assertFalse("Node not locked in session 1", n.isLocked());
+ assertFalse("Node not locked in session 2", nOther.isLocked());
+
+ // get user transaction object, start and lock node
+ UserTransaction utx = new UserTransactionImpl(superuser);
+ utx.begin();
+ n.lock(false, true);
+
+ // verify node is locked in first session only
+ assertTrue("Node locked in session 1", n.isLocked());
+ assertFalse("Node not locked in session 2", nOther.isLocked());
+ assertFalse("Node not locked in session 2", nOther.hasProperty(jcrLockOwner));
+
+ // rollback in first session
+ utx.rollback();
+
+ // verify node is not locked in either session
+ assertFalse("Node not locked in session 1", n.isLocked());
+ assertFalse("Node not locked in session 2", nOther.isLocked());
+ assertFalse("Node not locked in session 2", nOther.hasProperty(jcrlockIsDeep));
+ } finally {
+ // logout
+ other.logout();
+ }
}
/**
@@ -828,46 +834,50 @@
*/
public void testLockTwice() throws Exception {
Session other = helper.getSuperuserSession();
+ try {
+ // add node that is both lockable and referenceable, save
+ Node n = testRootNode.addNode(nodeName1);
+ n.addMixin(mixLockable);
+ n.addMixin(mixReferenceable);
+ testRootNode.save();
- // add node that is both lockable and referenceable, save
- Node n = testRootNode.addNode(nodeName1);
- n.addMixin(mixLockable);
- n.addMixin(mixReferenceable);
- testRootNode.save();
-
- // reference node in second session
- Node nOther = other.getNodeByUUID(n.getUUID());
-
- // verify node is not locked in either session
- assertFalse("Node not locked in session 1", n.isLocked());
- assertFalse("Node not locked in session 2", nOther.isLocked());
-
- // get user transaction object, start and lock node
- UserTransaction utx = new UserTransactionImpl(superuser);
- utx.begin();
- n.lock(false, true);
+ // reference node in second session
+ Node nOther = other.getNodeByUUID(n.getUUID());
- // lock node in non-transactional session, too
- nOther.lock(false, true);
+ // verify node is not locked in either session
+ assertFalse("Node not locked in session 1", n.isLocked());
+ assertFalse("Node not locked in session 2", nOther.isLocked());
+
+ // get user transaction object, start and lock node
+ UserTransaction utx = new UserTransactionImpl(superuser);
+ utx.begin();
+ n.lock(false, true);
+
+ // lock node in non-transactional session, too
+ nOther.lock(false, true);
+
+ // verify node is locked in both sessions
+ assertTrue("Node locked in session 1", n.isLocked());
+ assertTrue("Node locked in session 2", nOther.isLocked());
+ assertTrue("Node locked in session 2", nOther.hasProperty(jcrLockOwner));
+
+ // assertion: commit must fail since node has already been locked
+ try {
+ utx.commit();
+ fail("Commit succeeds with double locking");
+ } catch (RollbackException e) {
+ /* expected */
+ }
- // verify node is locked in both sessions
- assertTrue("Node locked in session 1", n.isLocked());
- assertTrue("Node locked in session 2", nOther.isLocked());
+ // verify node is locked in both sessions
+ assertTrue("Node locked in session 1", n.isLocked());
+ assertTrue("Node locked in session 2", nOther.isLocked());
+ assertTrue("Node locked in session 2", nOther.hasProperty(jcrlockIsDeep));
- // assertion: commit must fail since node has already been locked
- try {
- utx.commit();
- fail("Commit succeeds with double locking");
- } catch (RollbackException e) {
- /* expected */
+ } finally {
+ // logout
+ other.logout();
}
-
- // verify node is locked in both sessions
- assertTrue("Node locked in session 1", n.isLocked());
- assertTrue("Node locked in session 2", nOther.isLocked());
-
- // logout
- other.logout();
}
/**
@@ -986,6 +996,126 @@
assertTrue("Lock live", lock.isLive());
}
+ /**
+ * Test correct behaviour of lock related properties within transaction.
+ *
+ * @throws Exception
+ */
+ public void testLockProperties() throws Exception {
+ Node n = testRootNode.addNode(nodeName1);
+ n.addMixin(mixLockable);
+ n.addMixin(mixReferenceable);
+ testRootNode.save();
+
+ // get user transaction object, start and lock node
+ UserTransaction utx = new UserTransactionImpl(superuser);
+ utx.begin();
+ Lock lock = n.lock(false, true);
+
+ // verify that the lock properties have been created and are neither
+ // NEW nor MODIFIED.
+ assertTrue(n.hasProperty(jcrLockOwner));
+ Property lockOwner = n.getProperty(jcrLockOwner);
+ assertFalse(lockOwner.isNew());
+ assertFalse(lockOwner.isModified());
+
+ assertTrue(n.hasProperty(jcrlockIsDeep));
+ Property lockIsDeep = n.getProperty(jcrlockIsDeep);
+ assertFalse(lockIsDeep.isNew());
+ assertFalse(lockIsDeep.isModified());
+
+ // rollback
+ utx.rollback();
+
+ // verify that the lock properties have been removed again.
+ assertFalse(n.hasProperty(jcrLockOwner));
+ try {
+ lockOwner.getPath();
+ fail("jcr:lockIsDeep property must have been invalidated.");
+ } catch (InvalidItemStateException e) {
+ // success
+ }
+ assertFalse(n.hasProperty(jcrlockIsDeep));
+ try {
+ lockIsDeep.getPath();
+ fail("jcr:lockIsDeep property must have been invalidated.");
+ } catch (InvalidItemStateException e) {
+ // success
+ }
+ }
+
+ /**
+ * Test correct behaviour of lock related properties within transaction.
+ *
+ * @throws Exception
+ */
+ public void testLockProperties2() throws Exception {
+ // add node that is both lockable and referenceable, save
+ Node n = testRootNode.addNode(nodeName1);
+ n.addMixin(mixLockable);
+ n.addMixin(mixReferenceable);
+ testRootNode.save();
+
+ Lock lock = n.lock(false, true);
+
+ // get user transaction object, start
+ UserTransaction utx = new UserTransactionImpl(superuser);
+ utx.begin();
+
+ // verify that the lock properties are present
+ assertTrue(n.hasProperty(jcrLockOwner));
+ assertTrue(n.hasProperty(jcrlockIsDeep));
+
+ // unlock
+ n.unlock();
+
+ // verify that the lock properties have been removed.
+ assertFalse(n.hasProperty(jcrLockOwner));
+ assertFalse(n.hasProperty(jcrlockIsDeep));
+
+ // rollback
+ utx.rollback();
+
+ // verify lock is live again -> properties must be present
+ assertTrue(n.hasProperty(jcrLockOwner));
+ assertTrue(n.hasProperty(jcrlockIsDeep));
+ }
+
+ /**
+ * Test visibility of lock properties by another session.
+ */
+ public void testLockProperties3() throws Exception {
+ // add node that is both lockable and referenceable, save
+ Node n = testRootNode.addNode(nodeName1);
+ n.addMixin(mixLockable);
+ n.addMixin(mixReferenceable);
+ testRootNode.save();
+
+ Lock lock = n.lock(false, true);
+
+ // get user transaction object, start
+ UserTransaction utx = new UserTransactionImpl(superuser);
+ utx.begin();
+
+ // unlock
+ n.unlock();
+
+ Node n2 = (Node) otherSuperuser.getItem(n.getPath());
+ assertTrue(n2.isLocked());
+ assertTrue(n2.hasProperty(jcrLockOwner));
+ assertTrue(n2.hasProperty(jcrlockIsDeep));
+ Lock lock2 = n2.getLock();
+
+ // rollback
+ utx.commit();
+
+ n2.refresh(false);
+ assertFalse(lock2.isLive());
+ assertFalse(n2.isLocked());
+ assertFalse(n2.hasProperty(jcrLockOwner));
+ assertFalse(n2.hasProperty(jcrlockIsDeep));
+ }
+
//-----------------------------------------------------------< versioning >
/**
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cluster/SimpleEventListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cluster/SimpleEventListener.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cluster/SimpleEventListener.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cluster/SimpleEventListener.java Thu Jan 8 03:52:38 2009
@@ -50,10 +50,10 @@
/**
* {@inheritDoc}
*/
- public void externalLock(NodeId nodeId, boolean isDeep, String userId)
+ public void externalLock(NodeId nodeId, boolean isDeep, String lockOwner)
throws RepositoryException {
- clusterEvents.add(new LockEvent(nodeId, isDeep, userId));
+ clusterEvents.add(new LockEvent(nodeId, isDeep, lockOwner));
}
/**
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/daily/DailyIntegrationTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/daily/DailyIntegrationTest.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/daily/DailyIntegrationTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/daily/DailyIntegrationTest.java Thu Jan 8 03:52:38 2009
@@ -29,6 +29,8 @@
import org.apache.jackrabbit.core.ConcurrentVersioningWithTransactionsTest;
import org.apache.jackrabbit.core.LockTest;
import org.apache.jackrabbit.core.ReadVersionsWhileModified;
+import org.apache.jackrabbit.core.lock.ConcurrentLockingTest;
+import org.apache.jackrabbit.core.lock.ConcurrentLockingWithTransactionsTest;
/**
* Contains tests that are run on a daily basis.
@@ -52,6 +54,8 @@
suite.addTestSuite(ConcurrentCheckinMixedTransactionTest.class);
suite.addTestSuite(LockTest.class);
suite.addTestSuite(ReadVersionsWhileModified.class);
+ suite.addTestSuite(ConcurrentLockingTest.class);
+ suite.addTestSuite(ConcurrentLockingWithTransactionsTest.class);
return suite;
}
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingTest.java?rev=732693&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingTest.java Thu Jan 8 03:52:38 2009
@@ -0,0 +1,90 @@
+/*
+ * 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.lock;
+
+import org.apache.jackrabbit.core.AbstractConcurrencyTest;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Node;
+import javax.jcr.lock.Lock;
+
+/**
+ * <code>ConcurrentLockingTest</code> contains test cases that run lock
+ * operations with concurrent threads.
+ */
+public class ConcurrentLockingTest extends AbstractConcurrencyTest {
+
+ /**
+ * The number of threads.
+ */
+ private static final int CONCURRENCY = 10;
+
+ /**
+ * The total number of operations to execute. E.g. number of lock
+ * performed by the threads.
+ */
+ private static final int NUM_OPERATIONS = 200;
+
+ public void testConcurrentLockUnlock() throws RepositoryException {
+ runTask(new Task() {
+ public void execute(Session session, Node test) throws RepositoryException {
+ Node n = test.addNode("test");
+ n.addMixin(mixLockable);
+ session.save();
+
+ for (int i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
+ n.lock(false, true);
+ n.unlock();
+ }
+ }
+ }, CONCURRENCY);
+ }
+
+ public void testConcurrentCreateAndLockUnlock() throws RepositoryException {
+ runTask(new Task() {
+ public void execute(Session session, Node test) throws RepositoryException {
+ // add versionable nodes
+ for (int i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
+ Node n = test.addNode("test" + i);
+ n.addMixin(mixLockable);
+ session.save();
+ Lock l = n.lock(false, true);
+ l.refresh();
+ n.unlock();
+ }
+ }
+ }, CONCURRENCY);
+ }
+
+ public void testConcurrentLock() throws RepositoryException {
+ runTask(new Task() {
+ public void execute(Session session, Node test) throws RepositoryException {
+ Node n = test.addNode("test");
+ n.addMixin(mixLockable);
+ session.save();
+
+ for (int i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
+ if (n.isLocked()) {
+ n.unlock();
+ }
+ n.lock(false, true);
+ }
+ }
+ }, CONCURRENCY);
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingTest.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingWithTransactionsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingWithTransactionsTest.java?rev=732693&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingWithTransactionsTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingWithTransactionsTest.java Thu Jan 8 03:52:38 2009
@@ -0,0 +1,120 @@
+/*
+ * 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.lock;
+
+import org.apache.jackrabbit.core.state.StaleItemStateException;
+import org.apache.jackrabbit.core.AbstractConcurrencyTest;
+import org.apache.jackrabbit.core.UserTransactionImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.lock.Lock;
+import javax.transaction.UserTransaction;
+
+/** <code>ConcurrentLockingWithTransactionsTest</code>... */
+public class ConcurrentLockingWithTransactionsTest extends AbstractConcurrencyTest {
+
+ private static Logger log = LoggerFactory.getLogger(ConcurrentLockingWithTransactionsTest.class);
+
+ /**
+ * The number of threads.
+ */
+ private static final int CONCURRENCY = 100;
+
+ /**
+ * The total number of operations to execute. E.g. number of locking operations
+ * performed by the threads.
+ */
+ private static final int NUM_OPERATIONS = 100;
+
+ public void testConcurrentRefreshInTransaction()
+ throws RepositoryException {
+ runTask(new Task() {
+ public void execute(Session session, Node test)
+ throws RepositoryException {
+ int i = 0;
+ try {
+ Node n = test.addNode("test");
+ n.addMixin(mixLockable);
+ session.save();
+ for (i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
+ Lock lock = n.lock(false, true);
+
+ final UserTransaction utx = new UserTransactionImpl(test.getSession());
+ utx.begin();
+ lock.refresh();
+ utx.commit();
+
+ n.unlock();
+ }
+ } catch (Exception e) {
+ final String threadName = Thread.currentThread().getName();
+ final Throwable deepCause = getLevel2Cause(e);
+ if (deepCause != null && deepCause instanceof StaleItemStateException) {
+ // ignore
+ } else {
+ throw new RepositoryException(threadName + ", i=" + i + ":" + e.getClass().getName(), e);
+ }
+ }
+ }
+ }, CONCURRENCY);
+ }
+
+ public void testConcurrentCreateAndLockUnLockInTransaction()
+ throws RepositoryException {
+ runTask(new Task() {
+ public void execute(Session session, Node test)
+ throws RepositoryException {
+ // add versionable nodes
+ for (int i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
+ try {
+ final UserTransaction utx = new UserTransactionImpl(test.getSession());
+ utx.begin();
+ Node n = test.addNode("test" + i);
+ n.addMixin(mixLockable);
+ session.save();
+ Lock l = n.lock(false, true);
+ n.unlock();
+ utx.commit();
+ } catch (Exception e) {
+ final String threadName = Thread.currentThread().getName();
+ final Throwable deepCause = getLevel2Cause(e);
+ if (deepCause != null && deepCause instanceof StaleItemStateException) {
+ // ignore
+ } else {
+ throw new RepositoryException(threadName + ", i=" + i + ":" + e.getClass().getName(), e);
+ }
+ }
+ }
+ }
+ }, CONCURRENCY);
+ }
+
+ private static Throwable getLevel2Cause(Throwable t) {
+ Throwable result = null;
+ try {
+ result = t.getCause().getCause();
+ } catch (NullPointerException npe) {
+ // ignore, we have no deep cause
+ }
+ return result;
+
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingWithTransactionsTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingWithTransactionsTest.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ExtendedLockingTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ExtendedLockingTest.java?rev=732693&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ExtendedLockingTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ExtendedLockingTest.java Thu Jan 8 03:52:38 2009
@@ -0,0 +1,53 @@
+/*
+ * 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.lock;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.lock.Lock;
+import java.util.List;
+import java.util.Arrays;
+
+/**
+ * <code>ExtendedLockingTest</code>...
+ */
+public class ExtendedLockingTest extends AbstractJCRTest {
+
+ public void testRemoveMixLockableFromLockedNode() throws RepositoryException {
+
+ Node n = testRootNode.addNode(nodeName1);
+ n.addMixin(mixLockable);
+ testRootNode.save();
+
+ Lock l = n.lock(true, true);
+
+ try {
+ n.removeMixin(mixLockable);
+ n.save();
+ fail("Removing mix:lockable from a locked node must fail.");
+ } catch (ConstraintViolationException e) {
+ // success
+ } finally {
+ if (n.isLocked()) {
+ n.unlock();
+ }
+ }
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ExtendedLockingTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ExtendedLockingTest.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/TestAll.java?rev=732693&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/TestAll.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/TestAll.java Thu Jan 8 03:52:38 2009
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.lock;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Test suite that includes all testcases for package org.apache.jackrabbit.core.lock.
+ */
+public class TestAll extends TestCase {
+
+ /**
+ * Returns a <code>Test</code> suite that executes all tests inside this
+ * package.
+ *
+ * @return a <code>Test</code> suite that executes all tests inside this
+ * package.
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite("org.apache.jackrabbit.core.lock tests");
+
+ suite.addTestSuite(ExtendedLockingTest.class);
+
+ return suite;
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/TestAll.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/TestAll.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplateTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplateTest.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplateTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplateTest.java Thu Jan 8 03:52:38 2009
@@ -110,8 +110,8 @@
public boolean isAllow() {
return false;
}
- public int getPrivilegeBits() {
- return PrivilegeRegistry.READ;
+ public int getPrivilegeBits() throws RepositoryException, NotExecutableException {
+ return PrivilegeRegistry.getBits(privilegesFromName(Privilege.JCR_READ));
}
public String[] getRestrictionNames() {
return new String[0];
@@ -182,11 +182,13 @@
public void testEffect() throws RepositoryException, NotExecutableException {
JackrabbitAccessControlList pt = createEmptyTemplate(getTestPath());
- pt.addAccessControlEntry(testPrincipal, privilegesFromName(Privilege.JCR_READ));
+ Privilege[] read = privilegesFromName(Privilege.JCR_READ);
+ Privilege[] modProp = privilegesFromName(Privilege.JCR_MODIFY_PROPERTIES);
+
+ pt.addAccessControlEntry(testPrincipal, read);
// add deny entry for mod_props
- assertTrue(pt.addEntry(testPrincipal, privilegesFromName(Privilege.JCR_MODIFY_PROPERTIES),
- false, null));
+ assertTrue(pt.addEntry(testPrincipal, modProp, false, null));
// test net-effect
int allows = PrivilegeRegistry.NO_PRIVILEGE;
@@ -195,7 +197,7 @@
for (int i = 0; i < entries.length; i++) {
AccessControlEntry ace = entries[i];
if (testPrincipal.equals(ace.getPrincipal()) && ace instanceof JackrabbitAccessControlEntry) {
- int entryBits = ((JackrabbitAccessControlEntry) ace).getPrivilegeBits();
+ int entryBits = PrivilegeRegistry.getBits(ace.getPrivileges());
if (((JackrabbitAccessControlEntry) ace).isAllow()) {
allows |= Permission.diff(entryBits, denies);
} else {
@@ -203,8 +205,8 @@
}
}
}
- assertEquals(PrivilegeRegistry.READ, allows);
- assertEquals(PrivilegeRegistry.MODIFY_PROPERTIES, denies);
+ assertEquals(PrivilegeRegistry.getBits(read), allows);
+ assertEquals(PrivilegeRegistry.getBits(modProp), denies);
}
public void testEffect2() throws RepositoryException, NotExecutableException {
@@ -221,7 +223,7 @@
for (int i = 0; i < entries.length; i++) {
AccessControlEntry ace = entries[i];
if (testPrincipal.equals(ace.getPrincipal()) && ace instanceof JackrabbitAccessControlEntry) {
- int entryBits = ((JackrabbitAccessControlEntry) ace).getPrivilegeBits();
+ int entryBits = PrivilegeRegistry.getBits(ace.getPrivileges());
if (((JackrabbitAccessControlEntry) ace).isAllow()) {
allows |= Permission.diff(entryBits, denies);
} else {
@@ -231,7 +233,7 @@
}
assertEquals(PrivilegeRegistry.NO_PRIVILEGE, allows);
- assertEquals(PrivilegeRegistry.READ, denies);
+ assertEquals(PrivilegeRegistry.getBits(privilegesFromName(Privilege.JCR_READ)), denies);
}
public void testRemoveEntry() throws RepositoryException,
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEntryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEntryTest.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEntryTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEntryTest.java Thu Jan 8 03:52:38 2009
@@ -72,12 +72,14 @@
public void testGetPrivilegeBits() throws RepositoryException, NotExecutableException {
JackrabbitAccessControlEntry tmpl = createEntry(new String[] {Privilege.JCR_READ}, true);
- int privs = tmpl.getPrivilegeBits();
- assertTrue(privs == PrivilegeRegistry.READ);
-
- tmpl = createEntry(new String[] {Privilege.JCR_WRITE}, true);
- privs = tmpl.getPrivilegeBits();
- assertTrue(privs == PrivilegeRegistry.WRITE);
+ int privs = PrivilegeRegistry.getBits(tmpl.getPrivileges());
+ assertEquals(1, tmpl.getPrivileges().length);
+ assertEquals(getAccessControlManager(superuser).privilegeFromName(Privilege.JCR_READ),
+ tmpl.getPrivileges()[0]);
+
+ tmpl = createEntry(new String[] {PrivilegeRegistry.REP_WRITE}, true);
+ assertEquals(getAccessControlManager(superuser).privilegeFromName(PrivilegeRegistry.REP_WRITE),
+ tmpl.getPrivileges()[0]);
}
public void testGetPrivileges() throws RepositoryException, NotExecutableException {
@@ -87,14 +89,14 @@
assertNotNull(privs);
assertEquals(1, privs.length);
assertEquals(privs[0], acMgr.privilegeFromName(Privilege.JCR_READ));
- assertTrue(PrivilegeRegistry.getBits(privs) == entry.getPrivilegeBits());
+ assertTrue(PrivilegeRegistry.getBits(privs) == PrivilegeRegistry.getBits(entry.getPrivileges()));
- entry = createEntry(new String[] {Privilege.JCR_WRITE}, true);
+ entry = createEntry(new String[] {PrivilegeRegistry.REP_WRITE}, true);
privs = entry.getPrivileges();
assertNotNull(privs);
assertEquals(1, privs.length);
- assertEquals(privs[0], acMgr.privilegeFromName(Privilege.JCR_WRITE));
- assertTrue(PrivilegeRegistry.getBits(privs) == entry.getPrivilegeBits());
+ assertEquals(privs[0], acMgr.privilegeFromName(PrivilegeRegistry.REP_WRITE));
+ assertTrue(PrivilegeRegistry.getBits(privs) == PrivilegeRegistry.getBits(entry.getPrivileges()));
entry = createEntry(new String[] {Privilege.JCR_ADD_CHILD_NODES,
Privilege.JCR_REMOVE_CHILD_NODES}, true);
@@ -107,7 +109,7 @@
Privilege.JCR_REMOVE_CHILD_NODES
});
assertEquals(Arrays.asList(param), Arrays.asList(privs));
- assertEquals(PrivilegeRegistry.getBits(privs), entry.getPrivilegeBits());
+ assertEquals(PrivilegeRegistry.getBits(privs), PrivilegeRegistry.getBits(entry.getPrivileges()));
}
public void testEquals() throws RepositoryException, NotExecutableException {
@@ -157,7 +159,7 @@
}
// ACE template with different privileges and 'allows
try {
- otherAces.add(createEntry(new String[] {Privilege.JCR_WRITE}, false));
+ otherAces.add(createEntry(new String[] {PrivilegeRegistry.REP_WRITE}, false));
} catch (RepositoryException e) {
}
@@ -169,8 +171,8 @@
public boolean isAllow() {
return true;
}
- public int getPrivilegeBits() {
- return PrivilegeRegistry.ALL;
+ public int getPrivilegeBits() throws AccessControlException {
+ return PrivilegeRegistry.getBits(privs);
}
public String[] getRestrictionNames() {
return new String[0];