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/28 10:50:51 UTC
svn commit: r738422 [1/3] - in /jackrabbit/trunk/jackrabbit-core/src:
main/java/org/apache/jackrabbit/core/
main/java/org/apache/jackrabbit/core/lock/
main/java/org/apache/jackrabbit/core/retention/
main/java/org/apache/jackrabbit/core/security/authori...
Author: angela
Date: Wed Jan 28 09:50:50 2009
New Revision: 738422
URL: http://svn.apache.org/viewvc?rev=738422&view=rev
Log:
JCR-1589: JSR 283 Retention & Hold Management (work in progress)
JCR-1957: Move common validation checks to a single place
Added:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/retention/HoldImpl.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/retention/RetentionPolicyImpl.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/retention/RetentionRegistry.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/retention/RetentionRegistryImpl.java (with props)
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/retention/HoldEffectTest.java (with props)
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/retention/HoldTest.java (with props)
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/retention/RetentionPolicyEffectTest.java (with props)
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/retention/RetentionPolicyTest.java (with props)
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/retention/TestAll.java (with props)
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/RetentionRegistryImplTest.java (with props)
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/retention/
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/retention/HoldTest.java (with props)
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/retention/RetentionPolicyTest.java (with props)
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/retention/TestAll.java (with props)
Removed:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SecurityItemModifier.java
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/ItemImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemValidator.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/PropertyImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/retention/RetentionManagerImpl.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/principalbased/ACLEditor.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java
jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.cnd
jackrabbit/trunk/jackrabbit-core/src/main/resources/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/SessionRemoveItemTest.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/retention/AbstractRetentionTest.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/security/RSessionAccessControlTest.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestAll.java
jackrabbit/trunk/jackrabbit-core/src/test/resources/repositoryStubImpl.properties
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=738422&r1=738421&r2=738422&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 Jan 28 09:50:50 2009
@@ -81,45 +81,11 @@
protected static final int CLONE_REMOVE_EXISTING = 2;
/**
- * option for <code>{@link #checkAddNode}</code> and
- * <code>{@link #checkRemoveNode}</code> methods:<p/>
- * check access rights
- */
- public static final int CHECK_ACCESS = 1;
- /**
- * option for <code>{@link #checkAddNode}</code> and
- * <code>{@link #checkRemoveNode}</code> methods:<p/>
- * check lock status
- */
- public static final int CHECK_LOCK = 2;
- /**
- * option for <code>{@link #checkAddNode}</code> and
- * <code>{@link #checkRemoveNode}</code> methods:<p/>
- * check checked-out status
- */
- public static final int CHECK_VERSIONING = 4;
- /**
- * option for <code>{@link #checkAddNode}</code> and
- * <code>{@link #checkRemoveNode}</code> methods:<p/>
- * check constraints defined in node type
- */
- public static final int CHECK_CONSTRAINTS = 16;
- /**
- * option for <code>{@link #checkRemoveNode}</code> method:<p/>
- * check that target node is not being referenced
- */
- public static final int CHECK_REFERENCES = 8;
-
- /**
* wrapped item state manager
*/
protected final UpdatableItemStateManager stateMgr;
/**
- * lock manager used for checking locking status
- */
- protected final LockManager lockMgr;
- /**
- * current session used for checking access rights and locking status
+ * current session used for checking access rights
*/
protected final SessionImpl session;
@@ -131,15 +97,15 @@
* @param lockMgr lock manager
* @param session current session
* @param hierMgr hierarchy manager
+ * @throws RepositoryException
*/
public BatchedItemOperations(UpdatableItemStateManager stateMgr,
NodeTypeRegistry ntReg,
LockManager lockMgr,
SessionImpl session,
- HierarchyManager hierMgr) {
- super(ntReg, hierMgr, session);
+ HierarchyManager hierMgr) throws RepositoryException {
+ super(ntReg, hierMgr, session, lockMgr, session.getAccessManager(), session.getRetentionRegistry());
this.stateMgr = stateMgr;
- this.lockMgr = lockMgr;
this.session = session;
}
@@ -301,7 +267,7 @@
// 2. check access rights, lock status, node type constraints, etc.
checkAddNode(destParentState, destName,
srcState.getNodeTypeName(), CHECK_ACCESS | CHECK_LOCK
- | CHECK_VERSIONING | CHECK_CONSTRAINTS);
+ | CHECK_VERSIONING | CHECK_CONSTRAINTS | CHECK_HOLD | CHECK_RETENTION);
// 3. verify that source has mixin mix:shareable
if (!isShareable(srcState)) {
@@ -435,7 +401,7 @@
checkAddNode(destParentState, destName.getName(),
srcState.getNodeTypeName(), CHECK_ACCESS | CHECK_LOCK
- | CHECK_VERSIONING | CHECK_CONSTRAINTS);
+ | CHECK_VERSIONING | CHECK_CONSTRAINTS | CHECK_HOLD | CHECK_RETENTION);
// check read access right on source node using source access manager
try {
if (!srcAccessMgr.isGranted(srcPath, Permission.READ)) {
@@ -580,10 +546,11 @@
// 2. check if target state can be removed from old/added to new parent
checkRemoveNode(target, srcParent.getNodeId(),
- CHECK_ACCESS | CHECK_LOCK | CHECK_VERSIONING | CHECK_CONSTRAINTS);
+ CHECK_ACCESS | CHECK_LOCK | CHECK_VERSIONING | CHECK_CONSTRAINTS |
+ CHECK_HOLD | CHECK_RETENTION);
checkAddNode(destParent, destName.getName(),
target.getNodeTypeName(), CHECK_ACCESS | CHECK_LOCK
- | CHECK_VERSIONING | CHECK_CONSTRAINTS);
+ | CHECK_VERSIONING | CHECK_CONSTRAINTS | CHECK_HOLD | CHECK_RETENTION);
// 3. do move operation (modify and store affected states)
boolean renameOnly = srcParent.getNodeId().equals(destParent.getNodeId());
@@ -670,7 +637,7 @@
// 2. check if target state can be removed from parent
checkRemoveNode(target, parentId,
CHECK_ACCESS | CHECK_LOCK | CHECK_VERSIONING
- | CHECK_CONSTRAINTS | CHECK_REFERENCES);
+ | CHECK_CONSTRAINTS | CHECK_REFERENCES | CHECK_HOLD | CHECK_RETENTION);
// 3. do remove operation
removeNodeState(target);
@@ -697,7 +664,8 @@
* parent node is checked-out</li>
* <li><code>{@link #CHECK_CONSTRAINTS}</code>:
* make sure no node type constraints would be violated</li>
- * <li><code>{@link #CHECK_REFERENCES}</code></li>
+ * <li><code>{@link #CHECK_HOLD}</code>: check for effective holds preventing the add operation</li>
+ * <li><code>{@link #CHECK_RETENTION}</code>: check for effective retention policy preventing the add operation</code></li>
* </ul>
* @throws ConstraintViolationException
* @throws AccessDeniedException
@@ -732,7 +700,6 @@
// 3. access rights
if ((options & CHECK_ACCESS) == CHECK_ACCESS) {
- AccessManager accessMgr = session.getAccessManager();
// make sure current session is granted read access on parent node
if (!accessMgr.isGranted(parentPath, Permission.READ)) {
throw new ItemNotFoundException(safeGetJCRPath(parentState.getNodeId()));
@@ -796,6 +763,17 @@
}
}
}
+
+ if ((options & CHECK_HOLD) == CHECK_HOLD) {
+ if (retentionReg.hasEffectiveHold(parentPath, false)) {
+ throw new RepositoryException("Unable to add node. Parent is affected by a hold.");
+ }
+ }
+ if ((options & CHECK_RETENTION) == CHECK_RETENTION) {
+ if (retentionReg.hasEffectiveRetention(parentPath, false)) {
+ throw new RepositoryException("Unable to add node. Parent is affected by a retention.");
+ }
+ }
}
/**
@@ -816,6 +794,8 @@
* make sure no node type constraints would be violated</li>
* <li><code>{@link #CHECK_REFERENCES}</code>:
* make sure no references exist on target node</li>
+ * <li><code>{@link #CHECK_HOLD}</code>: check for effective holds preventing the add operation</li>
+ * <li><code>{@link #CHECK_RETENTION}</code: check for effective retention policy preventing the add operation</code></li>
* </ul>
* @throws ConstraintViolationException
* @throws AccessDeniedException
@@ -852,6 +832,8 @@
* make sure no node type constraints would be violated</li>
* <li><code>{@link #CHECK_REFERENCES}</code>:
* make sure no references exist on target node</li>
+ * <li><code>{@link #CHECK_HOLD}</code>: check for effective holds preventing the add operation</li>
+ * <li><code>{@link #CHECK_RETENTION}</code>: check for effective retention policy preventing the add operation</code></li>
* </ul>
* @throws ConstraintViolationException
* @throws AccessDeniedException
@@ -892,7 +874,6 @@
// 3. access rights
if ((options & CHECK_ACCESS) == CHECK_ACCESS) {
- AccessManager accessMgr = session.getAccessManager();
try {
// make sure current session is granted read access on parent node
if (!accessMgr.isGranted(targetPath, Permission.READ)) {
@@ -952,6 +933,17 @@
}
}
}
+
+ if ((options & CHECK_HOLD) == CHECK_HOLD) {
+ if (retentionReg.hasEffectiveHold(targetPath, true)) {
+ throw new RepositoryException("Unable to perform removal. Node is affected by a hold.");
+ }
+ }
+ if ((options & CHECK_RETENTION) == CHECK_RETENTION) {
+ if (retentionReg.hasEffectiveRetention(targetPath, true)) {
+ throw new RepositoryException("Unable to perform removal. Node is affected by a retention.");
+ }
+ }
}
/**
@@ -963,6 +955,7 @@
* <li>the node must not be locked by another session</li>
* <li>the node must not be checked-in</li>
* <li>the node must not be protected</li>
+ * <li>the node must not be affected by a hold or a retention policy</li>
* </ul>
*
* @param nodePath path of node to check
@@ -988,7 +981,6 @@
NodeState node = getNodeState(nodePath);
// access rights
- AccessManager accessMgr = session.getAccessManager();
// make sure current session is granted read access on node
if (!accessMgr.isGranted(nodePath, Permission.READ)) {
throw new PathNotFoundException(safeGetJCRPath(node.getNodeId()));
@@ -1007,6 +999,13 @@
// versioning status
verifyCheckedOut(nodePath);
+
+ if (retentionReg.hasEffectiveHold(nodePath, false)) {
+ throw new RepositoryException("Unable to write. Node is affected by a hold.");
+ }
+ if (retentionReg.hasEffectiveRetention(nodePath, false)) {
+ throw new RepositoryException("Unable to write. Node is affected by a retention.");
+ }
}
/**
@@ -1027,7 +1026,6 @@
public void verifyCanRead(Path nodePath)
throws PathNotFoundException, RepositoryException {
// access rights
- AccessManager accessMgr = session.getAccessManager();
// make sure current session is granted read access on node
if (!accessMgr.isGranted(nodePath, Permission.READ)) {
throw new PathNotFoundException(safeGetJCRPath(nodePath));
@@ -1599,13 +1597,17 @@
try {
NodeState nodeState = (NodeState) stateMgr.getItemState(nodeId);
// check if child node can be removed
- // (access rights, locking & versioning status);
+ // (access rights, locking & versioning status as well
+ // as retention and hold);
// referential integrity (references) is checked
// on commit
checkRemoveNode(nodeState, targetState.getNodeId(),
CHECK_ACCESS
| CHECK_LOCK
- | CHECK_VERSIONING);
+ | CHECK_VERSIONING
+ | CHECK_HOLD
+ | CHECK_RETENTION
+ );
// remove child node
recursiveRemoveNodeState(nodeState);
} catch (ItemStateException ise) {
@@ -1728,12 +1730,14 @@
// check if existing can be removed
// (access rights, locking & versioning status,
- // node type constraints)
+ // node type constraints and retention/hold)
checkRemoveNode(existingState,
CHECK_ACCESS
| CHECK_LOCK
| CHECK_VERSIONING
- | CHECK_CONSTRAINTS);
+ | CHECK_CONSTRAINTS
+ | CHECK_HOLD
+ | CHECK_RETENTION);
// do remove existing
removeNodeState(existingState);
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java?rev=738422&r1=738421&r2=738422&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java Wed Jan 28 09:50:50 2009
@@ -53,7 +53,6 @@
import javax.jcr.ItemVisitor;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
-import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.ReferentialIntegrityException;
import javax.jcr.RepositoryException;
@@ -814,32 +813,16 @@
}
NodeImpl parentNode = (NodeImpl) getParent();
-
if (!noChecks) {
- // check if protected
- ItemDefinition definition;
- if (isNode()) {
- definition = ((Node) this).getDefinition();
- } else {
- definition = ((Property) this).getDefinition();
- }
- if (definition.isProtected()) {
- throw new ConstraintViolationException(
- "Cannot remove a protected item: " + this);
- }
-
- // verify that parent node is checked-out and not protected
- if (!parentNode.internalIsCheckedOut()) {
- throw new VersionException(
- "Cannot remove a child of a checked-in node: " + this);
- }
- if (parentNode.getDefinition().isProtected()) {
- throw new ConstraintViolationException(
- "Cannot remove a child of a protected node: " + this);
- }
-
- // check lock status
- parentNode.checkLock();
+ // check if protected and not under retention/hold
+ int options = ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD |
+ ItemValidator.CHECK_RETENTION;
+ session.getValidator().checkRemove(this, options, Permission.NONE);
+
+ // parent node: make sure it is checked-out and not protected nor locked.
+ options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_VERSIONING |
+ ItemValidator.CHECK_CONSTRAINTS;
+ session.getValidator().checkModify(parentNode, options, Permission.NONE);
}
// delegate the removal of the child item to the parent node
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemValidator.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemValidator.java?rev=738422&r1=738421&r2=738422&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemValidator.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemValidator.java Wed Jan 28 09:50:50 2009
@@ -24,6 +24,10 @@
import org.apache.jackrabbit.core.state.NodeState;
import org.apache.jackrabbit.core.state.PropertyState;
import org.apache.jackrabbit.core.value.InternalValue;
+import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.core.security.AccessManager;
+import org.apache.jackrabbit.core.lock.LockManager;
+import org.apache.jackrabbit.core.retention.RetentionRegistry;
import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.spi.commons.conversion.PathResolver;
import org.apache.jackrabbit.spi.Name;
@@ -34,7 +38,13 @@
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.ItemNotFoundException;
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.lock.LockException;
+import javax.jcr.version.VersionException;
import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.ItemDefinition;
/**
* Utility class for validating an item against constraints
@@ -43,6 +53,50 @@
public class ItemValidator {
/**
+ * check access permissions
+ */
+ public static final int CHECK_ACCESS = 1;
+
+ /**
+ * option to check lock status
+ */
+ public static final int CHECK_LOCK = 2;
+ /**
+ * option to check checked-out status
+ */
+ public static final int CHECK_VERSIONING = 4;
+
+ /**
+ * check for referential integrity upon removal
+ */
+ public static final int CHECK_REFERENCES = 8;
+
+ /**
+ * option to check if the item is protected by it's nt definition
+ */
+ public static final int CHECK_CONSTRAINTS = 16;
+
+ /**
+ * option to check for pending changes on the session
+ */
+ public static final int CHECK_PENDING_CHANGES = 32;
+
+ /**
+ * option to check for pending changes on the specified node
+ */
+ public static final int CHECK_PENDING_CHANGES_ON_NODE = 64;
+
+ /**
+ * option to check for effective holds
+ */
+ public static final int CHECK_HOLD = 128;
+
+ /**
+ * option to check for effective retention policies
+ */
+ public static final int CHECK_RETENTION = 256;
+
+ /**
* Logger instance for this class
*/
private static Logger log = LoggerFactory.getLogger(ItemValidator.class);
@@ -66,18 +120,49 @@
protected final PathResolver resolver;
/**
+ *
+ */
+ protected final LockManager lockMgr;
+
+ protected final AccessManager accessMgr;
+
+ protected final RetentionRegistry retentionReg;
+
+ /**
* Creates a new <code>ItemValidator</code> instance.
*
* @param ntReg node type registry
* @param hierMgr hierarchy manager
- * @param resolver path resolver
+ * @param session session
*/
public ItemValidator(NodeTypeRegistry ntReg,
HierarchyManager hierMgr,
- PathResolver resolver) {
+ SessionImpl session) throws RepositoryException {
+ this(ntReg, hierMgr, session, session.getLockManager(), session.getAccessManager(), session.getRetentionRegistry());
+ }
+
+ /**
+ * Creates a new <code>ItemValidator</code> instance.
+ *
+ * @param ntReg node type registry
+ * @param hierMgr hierarchy manager
+ * @param resolver resolver
+ * @param lockMgr lockMgr
+ * @param accessMgr accessMgr
+ * @param retentionReg
+ */
+ public ItemValidator(NodeTypeRegistry ntReg,
+ HierarchyManager hierMgr,
+ PathResolver resolver,
+ LockManager lockMgr,
+ AccessManager accessMgr,
+ RetentionRegistry retentionReg) {
this.ntReg = ntReg;
this.hierMgr = hierMgr;
this.resolver = resolver;
+ this.lockMgr = lockMgr;
+ this.accessMgr = accessMgr;
+ this.retentionReg = retentionReg;
}
/**
@@ -178,6 +263,161 @@
EffectiveNodeType.checkSetPropertyValueConstraints(def, values);
}
+ public void checkModify(ItemImpl item, int options, int permissions) throws RepositoryException {
+ checkCondition(item, options, permissions, false);
+ }
+
+ public void checkRemove(ItemImpl item, int options, int permissions) throws RepositoryException {
+ checkCondition(item, options, permissions, true);
+ }
+
+ private void checkCondition(ItemImpl item, int options, int permissions, boolean isRemoval) throws RepositoryException {
+ if ((options & CHECK_PENDING_CHANGES) == CHECK_PENDING_CHANGES) {
+ if (item.getSession().hasPendingChanges()) {
+ String msg = "Unable to perform operation. Session has pending changes.";
+ log.debug(msg);
+ throw new InvalidItemStateException(msg);
+ }
+ }
+ if ((options & CHECK_PENDING_CHANGES_ON_NODE) == CHECK_PENDING_CHANGES_ON_NODE) {
+ if (item.isNode() && ((NodeImpl) item).hasPendingChanges()) {
+ String msg = "Unable to perform operation. Session has pending changes.";
+ log.debug(msg);
+ throw new InvalidItemStateException(msg);
+ }
+ }
+ if ((options & CHECK_CONSTRAINTS) == CHECK_CONSTRAINTS) {
+ if (isProtected(item)) {
+ String msg = "Unable to perform operation. Node is protected.";
+ log.debug(msg);
+ throw new ConstraintViolationException(msg);
+ }
+ }
+ if ((options & CHECK_VERSIONING) == CHECK_VERSIONING) {
+ NodeImpl node = (item.isNode()) ? (NodeImpl) item : (NodeImpl) item.getParent();
+ if (!node.internalIsCheckedOut()) {
+ String msg = "Unable to perform operation. Node is checked-in.";
+ log.debug(msg);
+ throw new VersionException(msg);
+ }
+ }
+ if ((options & CHECK_LOCK) == CHECK_LOCK) {
+ checkLock(item);
+ }
+
+ if (permissions > Permission.NONE) {
+ Path path = item.getPrimaryPath();
+ accessMgr.checkPermission(path, permissions);
+ }
+ if ((options & CHECK_HOLD) == CHECK_HOLD) {
+ if (hasHold(item, isRemoval)) {
+ throw new RepositoryException("Unable to perform operation. Node is affected by a hold.");
+ }
+ }
+ if ((options & CHECK_RETENTION) == CHECK_RETENTION) {
+ if (hasRetention(item, isRemoval)) {
+ throw new RepositoryException("Unable to perform operation. Node is affected by a retention.");
+ }
+ }
+ }
+
+ public boolean canModify(ItemImpl item, int options, int permissions) throws RepositoryException {
+ return hasCondition(item, options, permissions, false);
+ }
+
+ private boolean hasCondition(ItemImpl item, int options, int permissions, boolean isRemoval) throws RepositoryException {
+ if ((options & CHECK_PENDING_CHANGES) == CHECK_PENDING_CHANGES) {
+ if (item.getSession().hasPendingChanges()) {
+ return false;
+ }
+ }
+ if ((options & CHECK_PENDING_CHANGES_ON_NODE) == CHECK_PENDING_CHANGES_ON_NODE) {
+ if (item.isNode() && ((NodeImpl) item).hasPendingChanges()) {
+ return false;
+ }
+ }
+ if ((options & CHECK_CONSTRAINTS) == CHECK_CONSTRAINTS) {
+ if (isProtected(item)) {
+ return false;
+ }
+ }
+ if ((options & CHECK_VERSIONING) == CHECK_VERSIONING) {
+ NodeImpl node = (item.isNode()) ? (NodeImpl) item : (NodeImpl) item.getParent();
+ if (!node.internalIsCheckedOut()) {
+ return false;
+ }
+ }
+ if ((options & CHECK_LOCK) == CHECK_LOCK) {
+ try {
+ checkLock(item);
+ } catch (LockException e) {
+ return false;
+ }
+ }
+ if (permissions > Permission.NONE) {
+ Path path = item.getPrimaryPath();
+ if (!accessMgr.isGranted(item.getPrimaryPath(), permissions)) {
+ return false;
+ }
+ }
+ if ((options & CHECK_HOLD) == CHECK_HOLD) {
+ if (hasHold(item, isRemoval)) {
+ return false;
+ }
+ }
+ if ((options & CHECK_RETENTION) == CHECK_RETENTION) {
+ if (hasRetention(item, isRemoval)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void checkLock(ItemImpl item) throws LockException, RepositoryException {
+ if (item.isNew()) {
+ // a new item needs no check
+ return;
+ }
+ NodeImpl node = (item.isNode()) ? (NodeImpl) item : (NodeImpl) item.getParent();
+ lockMgr.checkLock(node);
+ }
+
+ private boolean isProtected(ItemImpl item) throws RepositoryException {
+ ItemDefinition def;
+ if (item.isNode()) {
+ def = ((Node) item).getDefinition();
+ } else {
+ def = ((Property) item).getDefinition();
+ }
+ return def.isProtected();
+ }
+
+ private boolean hasHold(ItemImpl item, boolean isRemoval) throws RepositoryException {
+ if (item.isNew()) {
+ return false;
+ }
+ Path path = item.getPrimaryPath();
+ if (!item.isNode()) {
+ path = path.getAncestor(1);
+ }
+ boolean checkParent = (item.isNode() && isRemoval);
+ return retentionReg.hasEffectiveHold(path, checkParent);
+ }
+
+ private boolean hasRetention(ItemImpl item, boolean isRemoval) throws RepositoryException {
+ if (item.isNew()) {
+ return false;
+ }
+ Path path = item.getPrimaryPath();
+ if (!item.isNode()) {
+ path = path.getAncestor(1);
+ }
+ boolean checkParent = (item.isNode() && isRemoval);
+ return retentionReg.hasEffectiveRetention(path, checkParent);
+ }
+
+
+
//-------------------------------------------------< misc. helper methods >
/**
* Helper method that builds the effective (i.e. merged and resolved)
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=738422&r1=738421&r2=738422&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 Jan 28 09:50:50 2009
@@ -45,7 +45,6 @@
import org.apache.jackrabbit.core.version.VersionImpl;
import org.apache.jackrabbit.core.version.VersionSelector;
import org.apache.jackrabbit.core.security.authorization.Permission;
-import org.apache.jackrabbit.core.security.AccessManager;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
@@ -722,15 +721,9 @@
throw new PathNotFoundException(relPath);
}
- // make sure that parent node is checked-out
- if (!parentNode.internalIsCheckedOut()) {
- String msg = this + ": cannot add a child to a checked-in node";
- log.debug(msg);
- throw new VersionException(msg);
- }
-
- // check lock status
- parentNode.checkLock();
+ // make sure that parent node is checked-out and not locked
+ int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_VERSIONING;
+ session.getValidator().checkModify(parentNode, options, Permission.NONE);
// delegate the creation of the child node to the parent node
return parentNode.internalAddChildNode(nodeName, nodeType, id);
@@ -794,13 +787,10 @@
}
}
- // check protected flag of parent (i.e. this) node
- final NodeDefinition definition = data.getNodeDefinition();
- if (definition.isProtected()) {
- String msg = this + ": cannot add a child to a protected node";
- log.debug(msg);
- throw new ConstraintViolationException(msg);
- }
+ // check protected flag of parent (i.e. this) node and retention/hold
+ int options = ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD |
+ ItemValidator.CHECK_RETENTION;
+ session.getValidator().checkModify(this, options, Permission.NONE);
// now do create the child node
return createChildNode(nodeName, def, nodeType, id);
@@ -1007,33 +997,16 @@
// check state of this instance
sanityCheck();
- // make sure this node is checked-out
- if (!internalIsCheckedOut()) {
- String msg = this + ": cannot add a mixin node type to a checked-in node";
- log.debug(msg);
- throw new VersionException(msg);
- }
-
- // check protected flag
- final NodeDefinition definition = data.getNodeDefinition();
- if (definition.isProtected()) {
- String msg = this + ": cannot add a mixin node type to a protected node";
- log.debug(msg);
- throw new ConstraintViolationException(msg);
- }
-
- // check lock status
- checkLock();
- // check permissions
- Path p = getPrimaryPath();
- AccessManager acMgr = session.getAccessManager();
- acMgr.checkPermission(p, Permission.NODE_TYPE_MNGMT);
+ int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_VERSIONING |
+ ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD;
+ int permissions = Permission.NODE_TYPE_MNGMT;
// special handling of mix:versionable. since adding the mixin alters
// the version storage jcr:versionManagement privilege is required
// in addition.
if (NameConstants.MIX_VERSIONABLE.equals(mixinName)) {
- acMgr.checkPermission(p, Permission.VERSION_MNGMT);
+ permissions |= Permission.VERSION_MNGMT;
}
+ session.getValidator().checkModify(this, options, permissions);
NodeTypeManagerImpl ntMgr = session.getNodeTypeManager();
NodeTypeImpl mixin = ntMgr.getNodeType(mixinName);
@@ -1129,27 +1102,10 @@
// check state of this instance
sanityCheck();
- // make sure this node is checked-out
- if (!internalIsCheckedOut()) {
- String msg =
- this + ": cannot remove a mixin node type from a checked-in node";
- log.debug(msg);
- throw new VersionException(msg);
- }
-
- // check protected flag
- NodeDefinition definition = data.getNodeDefinition();
- if (definition.isProtected()) {
- String msg =
- this + ": cannot remove a mixin node type from a protected node";
- log.debug(msg);
- throw new ConstraintViolationException(msg);
- }
-
- // check lock status
- checkLock();
- // check permission
- session.getAccessManager().checkPermission(getPrimaryPath(), Permission.NODE_TYPE_MNGMT);
+ int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_VERSIONING |
+ ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD;
+ int permissions = Permission.NODE_TYPE_MNGMT;
+ session.getValidator().checkModify(this, options, permissions);
// check if mixin is assigned
final NodeState state = data.getNodeState();
@@ -1325,15 +1281,9 @@
*/
protected void checkSetProperty()
throws VersionException, LockException, RepositoryException {
- // make sure this node is checked-out
- if (!internalIsCheckedOut()) {
- String msg = this + ": cannot set property of a checked-in node";
- log.debug(msg);
- throw new VersionException(msg);
- }
-
- // check lock status
- checkLock();
+ // make sure this node is checked-out and is not locked
+ int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_VERSIONING;
+ session.getValidator().checkModify(this, options, Permission.NONE);
}
/**
@@ -1590,15 +1540,9 @@
// check state of this instance
sanityCheck();
- // make sure this node is checked-out
- if (!internalIsCheckedOut()) {
- String msg = this + ": cannot add node to a checked-in node";
- log.debug(msg);
- throw new VersionException(msg);
- }
-
- // check lock status
- checkLock();
+ // make sure this node is checked-out and not locked by another session.
+ int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_VERSIONING;
+ session.getValidator().checkModify(this, options, Permission.NONE);
NodeTypeImpl nt = null;
if (nodeTypeName != null) {
@@ -1827,25 +1771,10 @@
this + " has no child node with name " + name);
}
- // make sure this node is checked-out
- if (!internalIsCheckedOut()) {
- String msg =
- this + ": cannot change child node ordering of a checked-in node";
- log.debug(msg);
- throw new VersionException(msg);
- }
-
- // check protected flag
- final NodeDefinition definition = data.getNodeDefinition();
- if (definition.isProtected()) {
- String msg =
- this + ": cannot change child node ordering of a protected node";
- log.debug(msg);
- throw new ConstraintViolationException(msg);
- }
-
- // check lock status
- checkLock();
+ // make sure this node is checked-out and neither protected nor locked
+ int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_VERSIONING |
+ ItemValidator.CHECK_CONSTRAINTS;
+ session.getValidator().checkModify(this, options, Permission.NONE);
ArrayList list = new ArrayList(data.getNodeState().getChildNodeEntries());
int srcInd = -1, destInd = -1;
@@ -2011,16 +1940,12 @@
}
// (1) make sure that parent node is checked-out
- if (!internalIsCheckedOut()) {
- String msg = this + ": cannot add a child to a checked-in node";
- log.debug(msg);
- throw new VersionException(msg);
- }
-
// (2) check lock status
- checkLock();
+ // (3) check protected flag of parent (i.e. this) node
+ int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_VERSIONING | ItemValidator.CHECK_CONSTRAINTS;
+ session.getValidator().checkModify(this, options, Permission.NONE);
- // (3) check for name collisions
+ // (4) check for name collisions
NodeDefinitionImpl def;
try {
def = getApplicableChildNodeDefinition(name, null);
@@ -2044,14 +1969,6 @@
}
}
- // (4) check protected flag of parent (i.e. this) node
- final NodeDefinition definition = data.getNodeDefinition();
- if (definition.isProtected()) {
- String msg = this + ": cannot add a child to a protected node";
- log.debug(msg);
- throw new ConstraintViolationException(msg);
- }
-
// (5) do clone operation
NodeId parentId = getNodeId();
src.addShareParent(parentId);
@@ -2851,49 +2768,23 @@
// check state of this instance
sanityCheck();
- // check checked-out status
- if (!internalIsCheckedOut()) {
- return false;
- }
-
- // check protected flag
- if (data.getNodeDefinition().isProtected()) {
- return false;
- }
-
- // check lock status
- try {
- checkLock();
- } catch (LockException le) {
- return false;
- }
-
- Name ntName;
- try {
- ntName = session.getQName(mixinName);
- } catch (NameException e) {
- throw new RepositoryException(
- "invalid mixin type name: " + mixinName, e);
- }
-
- // check permissions
- Path p = getPrimaryPath();
- AccessManager acMgr = session.getAccessManager();
- if (!acMgr.isGranted(p, Permission.NODE_TYPE_MNGMT)) {
+ Name ntName = session.getQName(mixinName);
+ NodeTypeManagerImpl ntMgr = session.getNodeTypeManager();
+ NodeTypeImpl mixin = ntMgr.getNodeType(ntName);
+ if (!mixin.isMixin()) {
return false;
}
+
+ int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_VERSIONING |
+ ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD;
+ int permissions = Permission.NODE_TYPE_MNGMT;
// special handling of mix:versionable. since adding the mixin alters
// the version storage jcr:versionManagement privilege is required
// in addition.
if (NameConstants.MIX_VERSIONABLE.equals(ntName)) {
- if (!acMgr.isGranted(p, Permission.VERSION_MNGMT)) {
- return false;
- }
+ permissions |= Permission.VERSION_MNGMT;
}
-
- NodeTypeManagerImpl ntMgr = session.getNodeTypeManager();
- NodeTypeImpl mixin = ntMgr.getNodeType(ntName);
- if (!mixin.isMixin()) {
+ if (!session.getValidator().canModify(this, options, permissions)) {
return false;
}
@@ -3339,17 +3230,9 @@
return getBaseVersion();
}
- // check for pending changes
- if (hasPendingChanges()) {
- String msg = "Unable to checkin node. Node has pending changes: " + this;
- log.debug(msg);
- throw new InvalidItemStateException(msg);
- }
-
- // check lock status
- checkLock();
- // check permission
- session.getAccessManager().checkPermission(getPrimaryPath(), Permission.VERSION_MNGMT);
+ // check lock status, holds and permissions
+ int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_HOLD | ItemValidator.CHECK_PENDING_CHANGES_ON_NODE;
+ session.getValidator().checkModify(this, options, Permission.VERSION_MNGMT);
Version v = session.getVersionManager().checkin(this);
boolean success = false;
@@ -3392,10 +3275,8 @@
return;
}
- // check lock status
- checkLock();
- // check permission
- session.getAccessManager().checkPermission(getPrimaryPath(), Permission.VERSION_MNGMT);
+ int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_HOLD;
+ session.getValidator().checkModify(this, options, Permission.VERSION_MNGMT);
boolean hasPendingChanges = hasPendingChanges();
Property[] props = new Property[2];
@@ -3487,8 +3368,8 @@
// checks
sanityCheck();
- checkSessionHasPending();
- checkLock();
+ int options = ItemValidator.CHECK_PENDING_CHANGES | ItemValidator.CHECK_LOCK | ItemValidator.CHECK_HOLD;
+ session.getValidator().checkModify(this, options, Permission.NONE);
Version v = getVersionHistory().getVersion(versionName);
DateVersionSelector gvs = new DateVersionSelector(v.getCreated());
@@ -3506,9 +3387,9 @@
// do checks
sanityCheck();
- checkSessionHasPending();
checkVersionable();
- checkLock();
+ int options = ItemValidator.CHECK_PENDING_CHANGES | ItemValidator.CHECK_LOCK| ItemValidator.CHECK_HOLD;
+ session.getValidator().checkModify(this, options, Permission.NONE);
// check if 'own' version
if (!version.getContainingHistory().isSame(getVersionHistory())) {
@@ -3529,8 +3410,8 @@
// do checks
sanityCheck();
- checkSessionHasPending();
- checkLock();
+ int options = ItemValidator.CHECK_PENDING_CHANGES | ItemValidator.CHECK_LOCK | ItemValidator.CHECK_HOLD;
+ session.getValidator().checkModify(this, options, Permission.NONE);
// if node exists, do a 'normal' restore
if (hasNode(relPath)) {
@@ -3578,8 +3459,8 @@
// do checks
sanityCheck();
- checkSessionHasPending();
- checkLock();
+ int options = ItemValidator.CHECK_PENDING_CHANGES | ItemValidator.CHECK_LOCK| ItemValidator.CHECK_HOLD;
+ session.getValidator().checkModify(this, options, Permission.NONE);
Version v = getVersionHistory().getVersionByLabel(versionLabel);
if (v == null) {
@@ -3642,24 +3523,6 @@
}
/**
- * Checks if this nodes session has pending changes.
- *
- * @throws InvalidItemStateException if this nodes session has pending changes
- * @throws RepositoryException
- */
- private void checkSessionHasPending()
- throws InvalidItemStateException, RepositoryException {
- // check for pending changes
- if (session.hasPendingChanges()) {
- String msg = "Unable to perform operation. Session has pending changes.";
- log.debug(msg);
- throw new InvalidItemStateException(msg);
- }
-
-
- }
-
- /**
* Returns the corresponding node in the workspace of the given session.
* <p/>
* Given a node N1 in workspace W1, its corresponding node N2 in workspace
@@ -3834,28 +3697,12 @@
// check state of this instance
sanityCheck();
- // check for pending changes
- if (hasPendingChanges()) {
- String msg =
- "Unable to finish merge. Node has pending changes: " + this;
- log.debug(msg);
- throw new InvalidItemStateException(msg);
- }
-
// check versionable
checkVersionable();
- // check lock
- checkLock();
- // check permission
- session.getAccessManager().checkPermission(getPrimaryPath(), Permission.VERSION_MNGMT);
-
- // check if checked out
- if (!internalIsCheckedOut()) {
- String msg = "Unable to finish merge. Node is checked-in: " + this;
- log.error(msg);
- throw new VersionException(msg);
- }
+ // check lock, permissions and checkout-status
+ int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_VERSIONING | ItemValidator.CHECK_PENDING_CHANGES_ON_NODE | ItemValidator.CHECK_HOLD;
+ session.getValidator().checkModify(this, options, Permission.VERSION_MNGMT);
// check if version is in mergeFailed list
Set failed = internalGetMergeFailed();
@@ -4089,9 +3936,7 @@
// do checks
sanityCheck();
- checkSessionHasPending();
- // check permission
- session.getAccessManager().checkPermission(getPrimaryPath(), Permission.VERSION_MNGMT);
+ session.getValidator().checkModify(this, ItemValidator.CHECK_PENDING_CHANGES, Permission.VERSION_MNGMT);
// if same workspace, ignore
if (srcWorkspaceName.equals(session.getWorkspace().getName())) {
@@ -4151,8 +3996,9 @@
return;
}
- // check lock status
- checkLock();
+ // check lock and hold status
+ int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_HOLD;
+ session.getValidator().checkModify(this, options, Permission.NONE);
// update the properties
PropertyIterator iter = getProperties();
@@ -4616,6 +4462,7 @@
*
* @throws LockException if this node is locked by somebody else
* @throws RepositoryException if some other error occurs
+ * @deprecated
*/
protected void checkLock() throws LockException, RepositoryException {
if (isNew()) {
@@ -4687,19 +4534,11 @@
// check state of this instance
sanityCheck();
- // make sure this node is checked-out
- if (!internalIsCheckedOut()) {
- String msg = this + ": cannot set primary type of a checked-in node";
- log.debug(msg);
- throw new VersionException(msg);
- }
-
- // check protected flag
- if (data.getDefinition().isProtected()) {
- String msg = this + ": cannot set primary type of a protected node";
- log.debug(msg);
- throw new ConstraintViolationException(msg);
- }
+ // make sure this node is checked-out, neither protected nor locked and
+ // the editing session has sufficient permission to change the primary type.
+ int options = ItemValidator.CHECK_VERSIONING | ItemValidator.CHECK_LOCK |
+ ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD;
+ session.getValidator().checkModify(this, options, Permission.NODE_TYPE_MNGMT);
final NodeState state = data.getNodeState();
if (state.getParentId() == null) {
@@ -4708,20 +4547,9 @@
throw new RepositoryException(msg);
}
- // check lock status
- checkLock();
- // check permission
- session.getAccessManager().checkPermission(getPrimaryPath(), Permission.NODE_TYPE_MNGMT);
-
- Name ntName;
- try {
- ntName = session.getQName(nodeTypeName);
- } catch (NameException e) {
- throw new RepositoryException(
- "invalid node type name: " + nodeTypeName, e);
- }
-
+ Name ntName = session.getQName(nodeTypeName);
if (ntName.equals(state.getNodeTypeName())) {
+ log.debug("Node already has " + nodeTypeName + " as primary node type.");
return;
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java?rev=738422&r1=738421&r2=738422&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java Wed Jan 28 09:50:50 2009
@@ -23,6 +23,7 @@
import org.apache.jackrabbit.core.value.InternalValue;
import org.apache.jackrabbit.core.nodetype.PropDefId;
import org.apache.jackrabbit.core.nodetype.PropertyDefinitionImpl;
+import org.apache.jackrabbit.core.security.authorization.Permission;
import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.value.ValueHelper;
@@ -236,36 +237,22 @@
RepositoryException {
NodeImpl parent = (NodeImpl) getParent();
PropertyDefinition definition = data.getPropertyDefinition();
-
- // verify that parent node is checked-out
- if (!parent.internalIsCheckedOut()) {
- throw new VersionException(
- "Cannot set a property of a checked-in node: " + this);
- }
-
- // check protected flag
- if (definition.isProtected()) {
- throw new ConstraintViolationException(
- "Cannot set the value of a protected property: " + this);
- }
-
// check multi-value flag
- if (multipleValues) {
- if (!definition.isMultiple()) {
- throw new ValueFormatException(
- "Single-valued property can not be set to"
- + " an array of values: " + this);
- }
- } else {
- if (definition.isMultiple()) {
- throw new ValueFormatException(
- "Multivalued property can not be set to a single"
- + " value (an array of lenght one is OK): " + this);
- }
+ if (multipleValues != definition.isMultiple()) {
+ String msg = (multipleValues) ?
+ "Single-valued property can not be set to an array of values:" :
+ "Multivalued property can not be set to a single value (an array of lenght one is OK): ";
+ throw new ValueFormatException(msg + this);
}
- // check lock status
- parent.checkLock();
+ // check protected flag and for retention/hold
+ int options = ItemValidator.CHECK_CONSTRAINTS;
+ session.getValidator().checkModify(this, options, Permission.NONE);
+
+ // make sure the parent is checked-out and neither locked nor under retention
+ options = ItemValidator.CHECK_VERSIONING | ItemValidator.CHECK_LOCK |
+ ItemValidator.CHECK_HOLD | ItemValidator.CHECK_RETENTION;
+ session.getValidator().checkModify(parent, options, Permission.NONE);
}
/**
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java?rev=738422&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java Wed Jan 28 09:50:50 2009
@@ -0,0 +1,166 @@
+/*
+ * 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;
+
+import org.apache.jackrabbit.core.nodetype.NodeDefinitionImpl;
+import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
+import org.apache.jackrabbit.core.security.AccessManager;
+import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.core.security.authorization.acl.ACLEditor;
+import org.apache.jackrabbit.core.security.user.UserManagerImpl;
+import org.apache.jackrabbit.core.state.ChildNodeEntry;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.value.InternalValue;
+import org.apache.jackrabbit.core.retention.RetentionManagerImpl;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.Path;
+
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ItemExistsException;
+import javax.jcr.AccessDeniedException;
+
+/**
+ * <code>SecurityItemModifier</code>: An abstract helper class to allow classes
+ * of the security API residing outside of the core package to modify and remove
+ * protected items for security. The protected item definitions are required in
+ * order not to have security relevant content being changed through common
+ * item operations but forcing the usage of the security API. The latter asserts
+ * that implementation specific constraints are not violated.
+ */
+public abstract class ProtectedItemModifier {
+
+ private static final int DEFAULT_PERM_CHECK = -1;
+ private final int permission;
+
+ protected ProtectedItemModifier() {
+ this(DEFAULT_PERM_CHECK);
+ }
+
+ protected ProtectedItemModifier(int permission) {
+ Class cl = getClass();
+ if (!(cl.equals(UserManagerImpl.class) ||
+ cl.equals(RetentionManagerImpl.class) ||
+ cl.equals(ACLEditor.class) ||
+ cl.equals(org.apache.jackrabbit.core.security.authorization.principalbased.ACLEditor.class))) {
+ throw new IllegalArgumentException("Only UserManagerImpl, RetentionManagerImpl and ACLEditor may extend from the ProtectedItemModifier");
+ }
+ this.permission = permission;
+ }
+
+ protected NodeImpl addNode(NodeImpl parentImpl, Name name, Name ntName) throws RepositoryException {
+ checkPermission(parentImpl, name, getPermission(true, false));
+ // validation: make sure Node is not locked or checked-in.
+ parentImpl.checkSetProperty();
+
+ NodeTypeImpl nodeType = parentImpl.session.getNodeTypeManager().getNodeType(ntName);
+ NodeDefinitionImpl def = parentImpl.getApplicableChildNodeDefinition(name, ntName);
+
+ // check for name collisions
+ // TODO: improve. copied from NodeImpl
+ NodeState thisState = (NodeState) parentImpl.getItemState();
+ ChildNodeEntry cne = thisState.getChildNodeEntry(name, 1);
+ if (cne != null) {
+ // there's already a child node entry with that name;
+ // check same-name sibling setting of new node
+ if (!def.allowsSameNameSiblings()) {
+ throw new ItemExistsException();
+ }
+ // check same-name sibling setting of existing node
+ NodeId newId = cne.getId();
+ NodeImpl n = (NodeImpl) parentImpl.session.getItemManager().getItem(newId);
+ if (!n.getDefinition().allowsSameNameSiblings()) {
+ throw new ItemExistsException();
+ }
+ }
+
+ return parentImpl.createChildNode(name, def, nodeType, null);
+ }
+
+ protected Property setProperty(NodeImpl parentImpl, Name name, Value value) throws RepositoryException {
+ return setProperty(parentImpl, name, value, false);
+ }
+
+ protected Property setProperty(NodeImpl parentImpl, Name name, Value value, boolean ignorePermissions) throws RepositoryException {
+ if (!ignorePermissions) {
+ checkPermission(parentImpl, name, getPermission(false, false));
+ }
+ // validation: make sure Node is not locked or checked-in.
+ parentImpl.checkSetProperty();
+ InternalValue intVs = InternalValue.create(value, parentImpl.session);
+ return parentImpl.internalSetProperty(name, intVs);
+ }
+
+ protected Property setProperty(NodeImpl parentImpl, Name name, Value[] values) throws RepositoryException {
+ checkPermission(parentImpl, name, getPermission(false, false));
+ // validation: make sure Node is not locked or checked-in.
+ parentImpl.checkSetProperty();
+ InternalValue[] intVs = new InternalValue[values.length];
+ for (int i = 0; i < values.length; i++) {
+ intVs[i] = InternalValue.create(values[i], parentImpl.session);
+ }
+ return parentImpl.internalSetProperty(name, intVs);
+ }
+
+ protected void removeItem(ItemImpl itemImpl) throws RepositoryException {
+ NodeImpl n;
+ if (itemImpl.isNode()) {
+ n = (NodeImpl) itemImpl;
+ } else {
+ n = (NodeImpl) itemImpl.getParent();
+ }
+ checkPermission(itemImpl, getPermission(itemImpl.isNode(), true));
+ // validation: make sure Node is not locked or checked-in.
+ n.checkSetProperty();
+ itemImpl.internalRemove(true);
+ }
+
+ private void checkPermission(ItemImpl item, int perm) throws RepositoryException {
+ if (perm > Permission.NONE) {
+ SessionImpl sImpl = (SessionImpl) item.getSession();
+ AccessManager acMgr = sImpl.getAccessManager();
+
+ Path path = item.getPrimaryPath();
+ acMgr.checkPermission(path, perm);
+ }
+ }
+
+ private void checkPermission(NodeImpl node, Name childName, int perm) throws RepositoryException {
+ if (perm > Permission.NONE) {
+ SessionImpl sImpl = (SessionImpl) node.getSession();
+ AccessManager acMgr = sImpl.getAccessManager();
+
+ boolean isGranted = acMgr.isGranted(node.getPrimaryPath(), childName, perm);
+ if (!isGranted) {
+ throw new AccessDeniedException("Permission denied.");
+ }
+ }
+ }
+
+ private int getPermission(boolean isNode, boolean isRemove) {
+ if (permission < Permission.NONE) {
+ if (isNode) {
+ return (isRemove) ? Permission.REMOVE_NODE : Permission.ADD_NODE;
+ } else {
+ return (isRemove) ? Permission.REMOVE_PROPERTY : Permission.SET_PROPERTY;
+ }
+ } else {
+ return permission;
+ }
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?rev=738422&r1=738421&r2=738422&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java Wed Jan 28 09:50:50 2009
@@ -67,6 +67,8 @@
import org.apache.jackrabbit.core.version.VersionManager;
import org.apache.jackrabbit.core.version.VersionManagerImpl;
import org.apache.jackrabbit.core.xml.ClonedInputSource;
+import org.apache.jackrabbit.core.retention.RetentionRegistry;
+import org.apache.jackrabbit.core.retention.RetentionRegistryImpl;
import org.apache.jackrabbit.spi.commons.name.NameConstants;
import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
import org.apache.jackrabbit.spi.commons.namespace.RegistryNamespaceResolver;
@@ -940,6 +942,21 @@
}
/**
+ * Returns the {@link org.apache.jackrabbit.core.retention.RetentionRegistry} for the workspace with name
+ * <code>workspaceName</code>
+ *
+ * @param workspaceName workspace name
+ * @return <code>RetentionEvaluator</code> for the workspace
+ * @throws NoSuchWorkspaceException if such a workspace does not exist
+ * @throws RepositoryException if some other error occurs
+ */
+ RetentionRegistry getRetentionRegistry(String workspaceName) throws NoSuchWorkspaceException, RepositoryException {
+ // check sanity of this instance
+ sanityCheck();
+ return getWorkspaceInfo(workspaceName).getRetentionRegistry();
+ }
+
+ /**
* Returns the {@link SystemSession} for the workspace with name
* <code>workspaceName</code>
*
@@ -1573,6 +1590,12 @@
private LockManagerImpl lockMgr;
/**
+ * internal manager for evaluation of effective retention policies
+ * and holds
+ */
+ private RetentionRegistryImpl retentionReg;
+
+ /**
* flag indicating whether this instance has been initialized.
*/
private boolean initialized;
@@ -1798,6 +1821,24 @@
}
/**
+ * Return manager used for evaluating effect retention and holds.
+ *
+ * @return
+ * @throws RepositoryException
+ */
+ protected RetentionRegistry getRetentionRegistry() throws RepositoryException {
+ if (!isInitialized()) {
+ throw new IllegalStateException("workspace '" + getName() + "' not initialized");
+ }
+ synchronized (this) {
+ if (retentionReg == null) {
+ retentionReg = new RetentionRegistryImpl(getSystemSession(), fs);
+ }
+ return retentionReg;
+ }
+ }
+
+ /**
* Returns the system session for this workspace.
*
* @return the system session for this workspace
@@ -2043,12 +2084,17 @@
lockMgr = null;
}
+ // close retention registry
+ if (retentionReg != null) {
+ retentionReg.close();
+ retentionReg = null;
+ }
+
// close workspace file system
try {
fs.close();
} catch (FileSystemException fse) {
- log.error("error while closing file system of workspace "
- + config.getName(), fse);
+ log.error("error while closing file system of workspace " + config.getName(), fse);
}
fs = null;
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java?rev=738422&r1=738421&r2=738422&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java Wed Jan 28 09:50:50 2009
@@ -49,6 +49,7 @@
import org.apache.jackrabbit.core.xml.ImportHandler;
import org.apache.jackrabbit.core.xml.SessionImporter;
import org.apache.jackrabbit.core.retention.RetentionManagerImpl;
+import org.apache.jackrabbit.core.retention.RetentionRegistry;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.spi.commons.conversion.DefaultNamePathResolver;
@@ -228,6 +229,12 @@
private RetentionManager retentionManager;
/**
+ * Internal helper class for common validation checks (lock status, checkout
+ * status, protection etc. etc.)
+ */
+ private ItemValidator validator;
+
+ /**
* Protected constructor.
*
* @param rep
@@ -372,6 +379,17 @@
}
/**
+ * @return ItemValidator instance for this session.
+ * @throws RepositoryException If an error occurs.
+ */
+ public synchronized ItemValidator getValidator() throws RepositoryException {
+ if (validator == null) {
+ validator = new ItemValidator(rep.getNodeTypeRegistry(), getHierarchyManager(), this);
+ }
+ return validator;
+ }
+
+ /**
* Returns the <code>Subject</code> associated with this session.
*
* @return the <code>Subject</code> associated with this session
@@ -462,6 +480,18 @@
return versionMgr;
}
+
+ /**
+ * Returns the internal retention manager used for evaluation of effective
+ * retention policies and holds.
+ *
+ * @return internal retention manager
+ * @throws RepositoryException
+ */
+ protected RetentionRegistry getRetentionRegistry() throws RepositoryException {
+ return wsp.getRetentionRegistry();
+ }
+
/**
* Retrieves the referenceable node with the given <code>UUID</code>.
*
@@ -867,28 +897,6 @@
}
/**
- * Determines if there are pending unsaved changes either on the passed
- * item or on any item in it's subtree.
- *
- * @param item Item start of the subtree to be tested for pending changes.
- * @return <code>true</code> if there are pending unsaved changes,
- * <code>false</code> otherwise.
- * @throws RepositoryException if an error occurred
- */
- public boolean hasPendingChanges(Item item) throws RepositoryException {
- if (!(item instanceof ItemImpl) || ((ItemImpl) item).session != this) {
- throw new IllegalArgumentException();
- }
- sanityCheck();
- ItemImpl itemImpl = (ItemImpl) item;
- if (itemImpl.isTransient()) {
- return true;
- } else {
- return item.isNode() && ((NodeImpl) item).hasPendingChanges();
- }
- }
-
- /**
* {@inheritDoc}
*/
public void move(String srcAbsPath, String destAbsPath)
@@ -961,20 +969,7 @@
throw new RepositoryException(msg);
}
- // verify that both source and destination parent nodes are checked-out
- if (!srcParentNode.internalIsCheckedOut()) {
- String msg = srcAbsPath + ": cannot move a child of a checked-in node";
- log.debug(msg);
- throw new VersionException(msg);
- }
- if (!destParentNode.internalIsCheckedOut()) {
- String msg = destAbsPath + ": cannot move a target to a checked-in node";
- log.debug(msg);
- throw new VersionException(msg);
- }
-
// check for name collisions
-
NodeImpl existing = null;
try {
existing = getItemManager().getNode(destPath);
@@ -991,8 +986,15 @@
// no name collision, fall through
}
- // check constraints
+ // verify for both source and destination parent nodes that
+ // - they are checked-out
+ // - are not protected neither by node type constraints nor by retention/hold
+ int options = ItemValidator.CHECK_VERSIONING | ItemValidator.CHECK_LOCK |
+ ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD | ItemValidator.CHECK_RETENTION;
+ getValidator().checkRemove(srcParentNode, options, Permission.NONE);
+ getValidator().checkModify(destParentNode, options, Permission.NONE);
+ // check constraints
// get applicable definition of target node at new location
NodeTypeImpl nt = (NodeTypeImpl) targetNode.getPrimaryNodeType();
NodeDefinitionImpl newTargetDef;
@@ -1012,22 +1014,6 @@
"Same name siblings not allowed: " + existing);
}
- // check protected flag of old & new parent
- if (destParentNode.getDefinition().isProtected()) {
- String msg = destAbsPath + ": cannot add a child node to a protected node";
- log.debug(msg);
- throw new ConstraintViolationException(msg);
- }
- if (srcParentNode.getDefinition().isProtected()) {
- String msg = srcAbsPath + ": cannot remove a child node from a protected node";
- log.debug(msg);
- throw new ConstraintViolationException(msg);
- }
-
- // check lock status
- srcParentNode.checkLock();
- destParentNode.checkLock();
-
NodeId targetId = targetNode.getNodeId();
int index = srcName.getIndex();
if (index == 0) {
@@ -1098,22 +1084,11 @@
throw new PathNotFoundException(parentAbsPath);
}
- // verify that parent node is checked-out
- if (!parent.internalIsCheckedOut()) {
- String msg = parentAbsPath + ": cannot add a child to a checked-in node";
- log.debug(msg);
- throw new VersionException(msg);
- }
-
- // check protected flag of parent node
- if (parent.getDefinition().isProtected()) {
- String msg = parentAbsPath + ": cannot add a child to a protected node";
- log.debug(msg);
- throw new ConstraintViolationException(msg);
- }
-
- // check lock status
- parent.checkLock();
+ // verify that parent node is checked-out, not locked and not protected
+ // by either node type constraints nor by some retention or hold.
+ int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_VERSIONING |
+ ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD | ItemValidator.CHECK_RETENTION;
+ getValidator().checkModify(parent, options, Permission.NONE);
SessionImporter importer = new SessionImporter(parent, this, uuidBehavior);
return new ImportHandler(importer, this);
@@ -1522,9 +1497,14 @@
* @see org.apache.jackrabbit.api.jsr283.Session#getRetentionManager()
* @since JCR 2.0
*/
- public synchronized RetentionManager getRetentionManager()
+ public RetentionManager getRetentionManager()
throws UnsupportedRepositoryOperationException, RepositoryException {
+ // check sanity of this session
+ sanityCheck();
if (retentionManager == null) {
+ // make sure the internal retention manager exists.
+ getRetentionRegistry();
+ // create the api level retention manager.
retentionManager = new RetentionManagerImpl(this);
}
return retentionManager;
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java?rev=738422&r1=738421&r2=738422&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java Wed Jan 28 09:50:50 2009
@@ -37,6 +37,7 @@
import org.apache.jackrabbit.core.xml.WorkspaceImporter;
import org.apache.jackrabbit.core.cluster.ClusterNode;
import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
+import org.apache.jackrabbit.core.retention.RetentionRegistry;
import org.apache.jackrabbit.commons.AbstractWorkspace;
import org.apache.jackrabbit.spi.commons.conversion.NameException;
import org.apache.jackrabbit.spi.Path;
@@ -119,9 +120,19 @@
*/
protected LockManager lockMgr;
+ /**
+ * The API LockManager for this workspace, used to create and release
+ * locks and determine the lock status.
+ */
private org.apache.jackrabbit.api.jsr283.lock.LockManager jcr283LockManager;
/**
+ * The internal manager used to evaluate effective retention policies and
+ * holds.
+ */
+ private RetentionRegistry retentionRegistry;
+
+ /**
* Protected constructor.
*
* @param wspConfig The workspace configuration
@@ -520,6 +531,22 @@
return lockMgr;
}
+ /**
+ * Return the internal effective retention/hold manager for this workspace.
+ * If not already done, creates a new instance.
+ *
+ * @return effective retention/hold manager for this workspace
+ * @throws RepositoryException if an error occurs
+ */
+ synchronized RetentionRegistry getRetentionRegistry() throws RepositoryException {
+ // check state of this instance
+ sanityCheck();
+ if (retentionRegistry == null) {
+ retentionRegistry = rep.getRetentionRegistry(wspConfig.getName());
+ }
+ return retentionRegistry;
+ }
+
//------------------------------------------------------------< Workspace >
/**
* {@inheritDoc}
@@ -864,7 +891,7 @@
log.debug(msg);
throw new InvalidItemStateException(msg);
}
-
+ // TODO: add checks for lock/hold...
boolean success = false;
try {
// now restore all versions that have a node in the ws
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java?rev=738422&r1=738421&r2=738422&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java Wed Jan 28 09:50:50 2009
@@ -19,6 +19,7 @@
import org.apache.jackrabbit.api.jsr283.lock.Lock;
import org.apache.jackrabbit.core.NodeImpl;
import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.ItemValidator;
import org.apache.jackrabbit.core.security.authorization.Permission;
import org.apache.jackrabbit.spi.commons.name.NameConstants;
import org.slf4j.Logger;
@@ -150,14 +151,10 @@
public Lock lock(String absPath, boolean isDeep, boolean isSessionScoped,
long timeoutHint, String ownerInfo) throws RepositoryException {
NodeImpl node = (NodeImpl) session.getNode(absPath);
-
- if (session.hasPendingChanges(node)) {
- String msg = "Unable to lock node. Node has pending changes: " + this;
- log.debug(msg);
- throw new InvalidItemStateException(msg);
- }
+
+ int options = ItemValidator.CHECK_HOLD | ItemValidator.CHECK_PENDING_CHANGES_ON_NODE;
+ session.getValidator().checkModify(node, options, Permission.LOCK_MNGMT);
checkLockable(node);
- session.getAccessManager().checkPermission(session.getQPath(node.getPath()), Permission.LOCK_MNGMT);
synchronized (systemLockMgr) {
return (Lock) systemLockMgr.lock(node, isDeep, isSessionScoped, timeoutHint, ownerInfo);
@@ -173,13 +170,9 @@
RepositoryException {
NodeImpl node = (NodeImpl) session.getNode(absPath);
- if (session.hasPendingChanges(node)) {
- String msg = "Unable to unlock node. Node has pending changes: " + this;
- log.debug(msg);
- throw new InvalidItemStateException(msg);
- }
+ int options = ItemValidator.CHECK_HOLD | ItemValidator.CHECK_PENDING_CHANGES_ON_NODE;
+ session.getValidator().checkModify(node, options, Permission.LOCK_MNGMT);
checkLockable(node);
- session.getAccessManager().checkPermission(session.getQPath(node.getPath()), Permission.LOCK_MNGMT);
synchronized (systemLockMgr) {
// basic checks if unlock can be called on the node.
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/retention/HoldImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/retention/HoldImpl.java?rev=738422&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/retention/HoldImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/retention/HoldImpl.java Wed Jan 28 09:50:50 2009
@@ -0,0 +1,126 @@
+/*
+ * 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.retention;
+
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.NameFactory;
+import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
+import org.apache.jackrabbit.spi.commons.conversion.NameResolver;
+import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.PropertyImpl;
+import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.api.jsr283.retention.Hold;
+
+import javax.jcr.Value;
+import javax.jcr.RepositoryException;
+import javax.jcr.ValueFactory;
+
+/**
+ * <code>HoldImpl</code>...
+ */
+class HoldImpl implements Hold {
+
+ private static final NameFactory NAME_FACTORY = NameFactoryImpl.getInstance();
+
+ private static final String DEEP = "D_";
+ private static final String SHALLOW = "S_";
+
+ private final Name name;
+ private final boolean isDeep;
+ private final NodeId nodeId;
+
+ private final NameResolver resolver;
+
+ private int hashCode = 0;
+
+ HoldImpl(Name name, boolean isDeep, NodeId nodeId, NameResolver resolver) {
+ this.name = name;
+ this.isDeep = isDeep;
+ this.nodeId = nodeId;
+ this.resolver = resolver;
+ }
+
+ NodeId getNodeId() {
+ return nodeId;
+ }
+
+ Value toValue(ValueFactory valueFactory) throws RepositoryException {
+ String str = ((isDeep) ? DEEP : SHALLOW) + name.toString();
+ return valueFactory.createValue(str);
+ }
+
+ static Hold createFromValue(Value val, NodeId nodeId, NameResolver resolver) throws RepositoryException {
+ String str = val.getString();
+ Name name = NAME_FACTORY.create(str.substring(2));
+ boolean isDeep = str.startsWith(DEEP);
+ return new HoldImpl(name, isDeep, nodeId, resolver);
+ }
+
+ static Hold[] createFromProperty(PropertyImpl property, NodeId nodeId) throws RepositoryException {
+ Value[] vs = property.getValues();
+ Hold[] holds = new Hold[vs.length];
+ for (int i = 0; i < vs.length; i++) {
+ holds[i] = createFromValue(vs[i], nodeId, (SessionImpl) property.getSession());
+ }
+ return holds;
+ }
+
+ //-----------------------------------------------------------< Hold >---
+ /**
+ * @see org.apache.jackrabbit.api.jsr283.retention.Hold#isDeep()
+ */
+ public boolean isDeep() throws RepositoryException {
+ return isDeep;
+ }
+
+ /**
+ * @see org.apache.jackrabbit.api.jsr283.retention.Hold#getName()
+ */
+ public String getName() throws RepositoryException {
+ return resolver.getJCRName(name);
+ }
+
+ //---------------------------------------------------------< Object >---
+ /**
+ * @see Object#hashCode()
+ */
+ public int hashCode() {
+ if (hashCode == 0) {
+ int h = 17;
+ h = 37 * h + name.hashCode();
+ h = 37 * h + nodeId.hashCode();
+ h = 37 * h + Boolean.valueOf(isDeep).hashCode();
+ hashCode = h;
+ }
+ return hashCode;
+ }
+
+ /**
+ * @see Object#equals(Object)
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (obj instanceof HoldImpl) {
+ HoldImpl other = (HoldImpl) obj;
+ return isDeep == other.isDeep && name.equals(other.name) && nodeId.equals(other.nodeId);
+ }
+ return false;
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/retention/HoldImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/retention/HoldImpl.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url