jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ang...@apache.org
Subject svn commit: r732693 [1/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...
Date Thu, 08 Jan 2009 11:52:45 GMT
Author: angela
Date: Thu Jan  8 03:52:38 2009
New Revision: 732693

URL: http://svn.apache.org/viewvc?rev=732693&view=rev
Log:
JCR-1588 - JSR 283: Access Control (work in progress)
JCR-1590 - JSR 283: Locking
JCR-1915 - Node.setPrimaryNodeType should only redefine child-definitions that are not covered by the new effective nt
JCR-1875 - Failing Node.unlock() might leave inconsistent transient state
JCR-538 - Failing Node.checkin() or Node.checkout() might leave inconsistent transient state

Added:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/DeepLockTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ConcurrentLockingWithTransactionsTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/ExtendedLockingTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/lock/TestAll.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractLockManagementTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractNodeTypeManagementTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractVersionManagementTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractWriteTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/EvaluationUtil.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/LockTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/NodeTypeTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/VersionTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/WriteTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/combined/WriteTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/EvaluationUtil.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/LockTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/NodeTypeTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/VersionTest.java   (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/WriteTest.java   (with props)
Removed:
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/EvaluationTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/combined/EvaluationTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/EvaluationTest.java
Modified:
    jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jsr283/security/Privilege.java
    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/ItemManager.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/SecurityItemModifier.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/SystemSession.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/cluster/ClusterNode.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/LockEventListener.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/LockRecord.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/AbstractLockInfo.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AbstractAccessControlManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/AccessManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/DefaultAccessManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/SimpleJBossAccessManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AbstractAccessControlProvider.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/AccessControlEntryImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/CompiledPermissions.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/JackrabbitAccessControlEntry.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/Permission.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/PrivilegeRegistry.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLEditor.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/acl/ACLProvider.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLEditor.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLProvider.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/authorization/principalbased/ACLTemplate.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/simple/SimpleAccessManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/AuthorizableImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserAccessControlProvider.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/state/XAItemStateManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/xml/SessionImporter.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/AbstractLockTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/LockManagerTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/OpenScopedLockTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/SessionScopedLockTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/TestAll.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/security/AccessControlListTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cluster/SimpleEventListener.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/daily/DailyIntegrationTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractACLTemplateTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEntryTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/AbstractEvaluationTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/JackrabbitAccessControlListTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/PrivilegeRegistryTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/ACLTemplateTest.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/acl/TestAll.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/combined/TestAll.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/authorization/principalbased/TestAll.java

Modified: jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jsr283/security/Privilege.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jsr283/security/Privilege.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jsr283/security/Privilege.java (original)
+++ jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/jsr283/security/Privilege.java Thu Jan  8 03:52:38 2009
@@ -107,6 +107,31 @@
     public static final String JCR_MODIFY_ACCESS_CONTROL = "{http://www.jcp.org/jcr/1.0}modifyAccessControl";
 
     /**
+     * A constant representing <code>jcr:retentionManagement</code>.
+     */
+    public static final String JCR_RETENTION_MANAGEMENT = "{http://www.jcp.org/jcr/1.0}retentionManagement";
+
+    /**
+     * A constant representing <code>jcr:lifecycleManagement</code>.
+     */
+    public static final String JCR_LIFECYCLE_MANAGEMENT = "{http://www.jcp.org/jcr/1.0}lifecycleManagement";
+
+    /**
+     * A constant representing <code>jcr:versionManagement</code>.
+     */
+    public static final String JCR_VERSION_MANAGEMENT = "{http://www.jcp.org/jcr/1.0}versionManagement";
+
+    /**
+     * A constant representing <code>jcr:lockManagement</code>.
+     */
+    public static final String JCR_LOCK_MANAGEMENT = "{http://www.jcp.org/jcr/1.0}lockManagement";
+
+    /**
+     * A constant representing <code>jcr:nodeTypeManagement</code>.
+     */
+    public static final String JCR_NODE_TYPE_MANAGEMENT = "{http://www.jcp.org/jcr/1.0}nodeTypeManagement";
+
+    /**
      * A constant representing <code>jcr:all</code> (in extended form), an aggregate privilege that contains
      * all predefined privileges:
      * <ul>

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=732693&r1=732692&r2=732693&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 Thu Jan  8 03:52:38 2009
@@ -742,6 +742,12 @@
                 throw new AccessDeniedException(safeGetJCRPath(parentState.getNodeId())
                         + ": not allowed to add child node");
             }
+            // make sure the editing session is allowed create nodes with a
+            // specified node type (and ev. mixins)
+            if (!accessMgr.isGranted(parentPath, nodeName, Permission.NODE_TYPE_MNGMT)) {
+                throw new AccessDeniedException(safeGetJCRPath(parentState.getNodeId())
+                        + ": not allowed to add child node");
+            }
         }
 
         // 4. node type constraints
@@ -1028,86 +1034,6 @@
         }
     }
 
-    /**
-     * Helper method that finds the applicable definition for a child node with
-     * the given name and node type in the parent node's node type and
-     * mixin types.
-     *
-     * @param name
-     * @param nodeTypeName
-     * @param parentState
-     * @return a <code>NodeDef</code>
-     * @throws ConstraintViolationException if no applicable child node definition
-     *                                      could be found
-     * @throws RepositoryException          if another error occurs
-     */
-    public NodeDef findApplicableNodeDefinition(Name name,
-                                                Name nodeTypeName,
-                                                NodeState parentState)
-            throws RepositoryException, ConstraintViolationException {
-        EffectiveNodeType entParent = getEffectiveNodeType(parentState);
-        return entParent.getApplicableChildNodeDef(name, nodeTypeName, ntReg);
-    }
-
-    /**
-     * Helper method that finds the applicable definition for a property with
-     * the given name, type and multiValued characteristic in the parent node's
-     * node type and mixin types. If there more than one applicable definitions
-     * then the following rules are applied:
-     * <ul>
-     * <li>named definitions are preferred to residual definitions</li>
-     * <li>definitions with specific required type are preferred to definitions
-     * with required type UNDEFINED</li>
-     * </ul>
-     *
-     * @param name
-     * @param type
-     * @param multiValued
-     * @param parentState
-     * @return a <code>PropDef</code>
-     * @throws ConstraintViolationException if no applicable property definition
-     *                                      could be found
-     * @throws RepositoryException          if another error occurs
-     */
-    public PropDef findApplicablePropertyDefinition(Name name,
-                                                    int type,
-                                                    boolean multiValued,
-                                                    NodeState parentState)
-            throws RepositoryException, ConstraintViolationException {
-        EffectiveNodeType entParent = getEffectiveNodeType(parentState);
-        return entParent.getApplicablePropertyDef(name, type, multiValued);
-    }
-
-    /**
-     * Helper method that finds the applicable definition for a property with
-     * the given name, type in the parent node's node type and mixin types.
-     * Other than <code>{@link #findApplicablePropertyDefinition(Name, int, boolean, NodeState)}</code>
-     * this method does not take the multiValued flag into account in the
-     * selection algorithm. If there more than one applicable definitions then
-     * the following rules are applied:
-     * <ul>
-     * <li>named definitions are preferred to residual definitions</li>
-     * <li>definitions with specific required type are preferred to definitions
-     * with required type UNDEFINED</li>
-     * <li>single-value definitions are preferred to multiple-value definitions</li>
-     * </ul>
-     *
-     * @param name
-     * @param type
-     * @param parentState
-     * @return a <code>PropDef</code>
-     * @throws ConstraintViolationException if no applicable property definition
-     *                                      could be found
-     * @throws RepositoryException          if another error occurs
-     */
-    public PropDef findApplicablePropertyDefinition(Name name,
-                                                    int type,
-                                                    NodeState parentState)
-            throws RepositoryException, ConstraintViolationException {
-        EffectiveNodeType entParent = getEffectiveNodeType(parentState);
-        return entParent.getApplicablePropertyDef(name, type);
-    }
-
     //--------------------------------------------< low-level item operations >
     /**
      * Creates a new node.
@@ -2015,7 +1941,7 @@
      *
      * @param state node state to check
      * @return true if the specified node is <i>shareable</i>, false otherwise.
-     * @throws ItemStateException if an error occurs
+     * @throws RepositoryException if an error occurs
      */
     private boolean isShareable(NodeState state) throws RepositoryException {
         // shortcut: check some wellknown built-in types first

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=732693&r1=732692&r2=732693&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 Thu Jan  8 03:52:38 2009
@@ -27,13 +27,13 @@
 import org.apache.jackrabbit.core.nodetype.PropertyDefinitionImpl;
 import org.apache.jackrabbit.core.security.AccessManager;
 import org.apache.jackrabbit.core.security.authorization.Permission;
+import org.apache.jackrabbit.core.state.ChildNodeEntry;
 import org.apache.jackrabbit.core.state.ItemState;
 import org.apache.jackrabbit.core.state.ItemStateException;
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.state.PropertyState;
 import org.apache.jackrabbit.core.state.SessionItemStateManager;
 import org.apache.jackrabbit.core.state.StaleItemStateException;
-import org.apache.jackrabbit.core.state.ChildNodeEntry;
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.core.version.VersionHistoryInfo;
 import org.apache.jackrabbit.core.version.VersionManager;
@@ -244,17 +244,17 @@
 
                     case ItemState.STATUS_STALE_MODIFIED:
                         throw new InvalidItemStateException(
-                                "Item cannot be saved because it has been"
+                                "Item cannot be saved because it has been "
                                 + "modified externally: " + this);
 
                     case ItemState.STATUS_STALE_DESTROYED:
                         throw new InvalidItemStateException(
-                                "Item cannot be saved because it has been"
+                                "Item cannot be saved because it has been "
                                 + "deleted externally: " + this);
 
                     case ItemState.STATUS_UNDEFINED:
                         throw new InvalidItemStateException(
-                                "Item cannot be saved; it seems to have been"
+                                "Item cannot be saved; it seems to have been "
                                 + "removed externally: " + this);
 
                     default:
@@ -348,7 +348,7 @@
          * the following validations/checks are performed on transient items:
          *
          * for every transient item:
-         * - if it is 'modified' check the WRITE permission
+         * - if it is 'modified' or 'new' check the corresponding write permission.
          * - if it is 'removed' check the REMOVE permission
          *
          * for every transient node:
@@ -365,42 +365,44 @@
          * Node.addMixin/removeMixin/setPrimaryType (for type changes on nodes)
          * and in Property.setValue (for properties to be modified).
          */
-
         AccessManager accessMgr = session.getAccessManager();
         NodeTypeManagerImpl ntMgr = session.getNodeTypeManager();
         // walk through list of dirty transient items and validate each
         while (dirtyIter.hasNext()) {
             ItemState itemState = (ItemState) dirtyIter.next();
-
-            if (itemState.getStatus() != ItemState.STATUS_NEW) {
-                /* transient item is not 'new', therefore it has to be 'modified'
-                   detect the effective set of modification:
-                   - child additions -> add_node perm on the child
-                   - property additions, modifications or removals -> set_property permission
+            ItemDefinition def;
+            if (itemState.isNode()) {
+                def = ntMgr.getNodeDefinition(((NodeState) itemState).getDefinitionId());
+            } else {
+                def = ntMgr.getPropertyDefinition(((PropertyState) itemState).getDefinitionId());
+            }
+            /* check permissions for non-protected items. protected items are
+               only added through API methods which need to assert that
+               permissions are not violated.
+             */
+            if (!def.isProtected()) {
+                /* detect the effective set of modification:
+                   - new added node -> add_node perm on the child
+                   - new property added -> set_property permission
+                   - property modified -> set_property permission
+                   - modified nodes can be ignored for changes only included
+                     child-item addition or removal or changes of protected
+                     properties such as mixin-types which are covered separately
                    note: removed items are checked later on.
                 */
-                // check WRITE permission
                 Path path = stateMgr.getHierarchyMgr().getPath(itemState.getId());
                 boolean isGranted = true;
                 if (itemState.isNode()) {
-                    // modified node state -> check possible modifications
-                    NodeState nState = (NodeState) itemState;
-                    for (Iterator it = nState.getAddedChildNodeEntries().iterator();
-                         it.hasNext() && isGranted;) {
-                        Name nodeName = ((ChildNodeEntry) it.next()).getName();
-                        isGranted = accessMgr.isGranted(path, nodeName, Permission.ADD_NODE);
-                    }
-                    for (Iterator it = nState.getAddedPropertyNames().iterator();
-                         it.hasNext() && isGranted;) {
-                        Name propName = (Name) it.next();
-                        isGranted = accessMgr.isGranted(path, propName, Permission.SET_PROPERTY);
-                    }
+                    if (itemState.getStatus() == ItemState.STATUS_NEW) {
+                        isGranted = accessMgr.isGranted(path, Permission.ADD_NODE);
+                    } // else: modified node (see comment above)
                 } else {
+                    // modified or new property: set_property permission
                     isGranted = accessMgr.isGranted(path, Permission.SET_PROPERTY);
                 }
 
                 if (!isGranted) {
-                    String msg = itemMgr.safeGetJCRPath(path) + ": not allowed to modify item";
+                    String msg = itemMgr.safeGetJCRPath(path) + ": not allowed to add or modify item";
                     log.debug(msg);
                     throw new AccessDeniedException(msg);
                 }
@@ -410,7 +412,7 @@
                 // the transient item is a node
                 NodeState nodeState = (NodeState) itemState;
                 ItemId id = nodeState.getNodeId();
-                NodeDefinition def = ntMgr.getNodeDefinition(nodeState.getDefinitionId());
+                NodeDefinition nodeDef = (NodeDefinition) def;
                 // primary type
                 NodeTypeImpl pnt = ntMgr.getNodeType(nodeState.getNodeTypeName());
                 // effective node type (primary type incl. mixins)
@@ -423,7 +425,7 @@
                 if (nodeState.getStatus() == ItemState.STATUS_NEW
                         || !nodeState.getNodeTypeName().equals(
                             ((NodeState) nodeState.getOverlayedState()).getNodeTypeName())) {
-                    NodeType[] nta = def.getRequiredPrimaryTypes();
+                    NodeType[] nta = nodeDef.getRequiredPrimaryTypes();
                     for (int i = 0; i < nta.length; i++) {
                         NodeTypeImpl ntReq = (NodeTypeImpl) nta[i];
                         if (!(pnt.getQName().equals(ntReq.getQName())
@@ -476,8 +478,7 @@
                 // the transient item is a property
                 PropertyState propState = (PropertyState) itemState;
                 ItemId propId = propState.getPropertyId();
-                PropertyDefinitionImpl def =
-                        ntMgr.getPropertyDefinition(propState.getDefinitionId());
+                PropertyDefinitionImpl propDef = (PropertyDefinitionImpl) def;
 
                 /**
                  * check value constraints
@@ -486,12 +487,12 @@
                  * cannot be set by the user through the api)
                  */
                 if (!def.isProtected()) {
-                    String[] constraints = def.getValueConstraints();
+                    String[] constraints = propDef.getValueConstraints();
                     if (constraints != null) {
                         InternalValue[] values = propState.getValues();
                         try {
                             EffectiveNodeType.checkSetPropertyValueConstraints(
-                                    def.unwrap(), values);
+                                    propDef.unwrap(), values);
                         } catch (RepositoryException e) {
                             // repack exception for providing more verbose error message
                             String msg = itemMgr.safeGetJCRPath(propId) + ": " + e.getMessage();
@@ -505,7 +506,7 @@
                          * be checked)
                          */
                         if (constraints.length > 0
-                                && def.getRequiredType() == PropertyType.REFERENCE) {
+                                && propDef.getRequiredType() == PropertyType.REFERENCE) {
                             for (int i = 0; i < values.length; i++) {
                                 boolean satisfied = false;
                                 String constraintViolationMsg = null;
@@ -569,14 +570,22 @@
         // walk through list of removed transient items and check REMOVE permission
         while (removedIter.hasNext()) {
             ItemState itemState = (ItemState) removedIter.next();
-            Path path = stateMgr.getAtticAwareHierarchyMgr().getPath(itemState.getId());
-            // check REMOVE permission
-            int permission = (itemState.isNode()) ? Permission.REMOVE_NODE : Permission.REMOVE_PROPERTY;
-            if (!accessMgr.isGranted(path, permission)) {
-                String msg = itemMgr.safeGetJCRPath(path)
-                        + ": not allowed to remove item";
-                log.debug(msg);
-                throw new AccessDeniedException(msg);
+            ItemDefinition def;
+            if (itemState.isNode()) {
+                def = ntMgr.getNodeDefinition(((NodeState) itemState).getDefinitionId());
+            } else {
+                def = ntMgr.getPropertyDefinition(((PropertyState) itemState).getDefinitionId());
+            }
+            if (!def.isProtected()) {
+                Path path = stateMgr.getAtticAwareHierarchyMgr().getPath(itemState.getId());
+                // check REMOVE permission
+                int permission = (itemState.isNode()) ? Permission.REMOVE_NODE : Permission.REMOVE_PROPERTY;
+                if (!accessMgr.isGranted(path, permission)) {
+                    String msg = itemMgr.safeGetJCRPath(path)
+                            + ": not allowed to remove item";
+                    log.debug(msg);
+                    throw new AccessDeniedException(msg);
+                }
             }
         }
     }
@@ -1018,16 +1027,14 @@
                     for (Iterator cneIt =
                             nodeState.getRemovedChildNodeEntries().iterator();
                          cneIt.hasNext();) {
-                        ChildNodeEntry cne =
-                                (ChildNodeEntry) cneIt.next();
+                        ChildNodeEntry cne = (ChildNodeEntry) cneIt.next();
                         dependentIDs.add(cne.getId());
                     }
                     // added child node entries
                     for (Iterator cneIt =
                             nodeState.getAddedChildNodeEntries().iterator();
                          cneIt.hasNext();) {
-                        ChildNodeEntry cne =
-                                (ChildNodeEntry) cneIt.next();
+                        ChildNodeEntry cne = (ChildNodeEntry) cneIt.next();
                         dependentIDs.add(cne.getId());
                     }
 

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java Thu Jan  8 03:52:38 2009
@@ -508,7 +508,7 @@
         if (parentId == null) {
             return (NodeImpl) getItem(id);
         }
-        AbstractNodeData data = (AbstractNodeData) retrieveItem(id, parentId);
+        AbstractNodeData data = retrieveItem(id, parentId);
         if (data == null) {
             data = (AbstractNodeData) getItemData(id);
         }

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=732693&r1=732692&r2=732693&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 Thu Jan  8 03:52:38 2009
@@ -202,6 +202,86 @@
     }
 
     /**
+     * Helper method that finds the applicable definition for a child node with
+     * the given name and node type in the parent node's node type and
+     * mixin types.
+     *
+     * @param name
+     * @param nodeTypeName
+     * @param parentState
+     * @return a <code>NodeDef</code>
+     * @throws ConstraintViolationException if no applicable child node definition
+     *                                      could be found
+     * @throws RepositoryException          if another error occurs
+     */
+    public NodeDef findApplicableNodeDefinition(Name name,
+                                                Name nodeTypeName,
+                                                NodeState parentState)
+            throws RepositoryException, ConstraintViolationException {
+        EffectiveNodeType entParent = getEffectiveNodeType(parentState);
+        return entParent.getApplicableChildNodeDef(name, nodeTypeName, ntReg);
+    }
+
+    /**
+     * Helper method that finds the applicable definition for a property with
+     * the given name, type and multiValued characteristic in the parent node's
+     * node type and mixin types. If there more than one applicable definitions
+     * then the following rules are applied:
+     * <ul>
+     * <li>named definitions are preferred to residual definitions</li>
+     * <li>definitions with specific required type are preferred to definitions
+     * with required type UNDEFINED</li>
+     * </ul>
+     *
+     * @param name
+     * @param type
+     * @param multiValued
+     * @param parentState
+     * @return a <code>PropDef</code>
+     * @throws ConstraintViolationException if no applicable property definition
+     *                                      could be found
+     * @throws RepositoryException          if another error occurs
+     */
+    public PropDef findApplicablePropertyDefinition(Name name,
+                                                    int type,
+                                                    boolean multiValued,
+                                                    NodeState parentState)
+            throws RepositoryException, ConstraintViolationException {
+        EffectiveNodeType entParent = getEffectiveNodeType(parentState);
+        return entParent.getApplicablePropertyDef(name, type, multiValued);
+    }
+
+    /**
+     * Helper method that finds the applicable definition for a property with
+     * the given name, type in the parent node's node type and mixin types.
+     * Other than <code>{@link #findApplicablePropertyDefinition(Name, int, boolean, NodeState)}</code>
+     * this method does not take the multiValued flag into account in the
+     * selection algorithm. If there more than one applicable definitions then
+     * the following rules are applied:
+     * <ul>
+     * <li>named definitions are preferred to residual definitions</li>
+     * <li>definitions with specific required type are preferred to definitions
+     * with required type UNDEFINED</li>
+     * <li>single-value definitions are preferred to multiple-value definitions</li>
+     * </ul>
+     *
+     * @param name
+     * @param type
+     * @param parentState
+     * @return a <code>PropDef</code>
+     * @throws ConstraintViolationException if no applicable property definition
+     *                                      could be found
+     * @throws RepositoryException          if another error occurs
+     */
+    public PropDef findApplicablePropertyDefinition(Name name,
+                                                    int type,
+                                                    NodeState parentState)
+            throws RepositoryException, ConstraintViolationException {
+        EffectiveNodeType entParent = getEffectiveNodeType(parentState);
+        return entParent.getApplicablePropertyDef(name, type);
+    }
+
+    /**
      * Failsafe conversion of internal <code>Path</code> to JCR path for use in
      * error messages etc.
      *

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=732693&r1=732692&r2=732693&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 Thu Jan  8 03:52:38 2009
@@ -18,7 +18,6 @@
 
 import org.apache.jackrabbit.commons.iterator.NodeIteratorAdapter;
 import org.apache.jackrabbit.commons.iterator.PropertyIteratorAdapter;
-import org.apache.jackrabbit.core.lock.LockManager;
 import org.apache.jackrabbit.core.nodetype.EffectiveNodeType;
 import org.apache.jackrabbit.core.nodetype.ItemDef;
 import org.apache.jackrabbit.core.nodetype.NodeDef;
@@ -45,6 +44,8 @@
 import org.apache.jackrabbit.core.version.LabelVersionSelector;
 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;
@@ -55,6 +56,7 @@
 import org.apache.jackrabbit.util.ChildrenCollectorFilter;
 import org.apache.jackrabbit.uuid.UUID;
 import org.apache.jackrabbit.value.ValueHelper;
+import org.apache.jackrabbit.api.jsr283.lock.LockManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -765,6 +767,10 @@
         if (nodeType == null) {
             // use default node type
             nodeType = (NodeTypeImpl) def.getDefaultPrimaryType();
+        } else {
+            // adding a node with explicit specifying the node type name
+            // requires the editing session to have nt_management privilege.
+            session.getAccessManager().checkPermission(nodePath, Permission.NODE_TYPE_MNGMT);
         }
 
         // check for name collisions
@@ -1013,6 +1019,16 @@
 
         // check lock status
         checkLock();
+        // check permissions
+        Path p = getPrimaryPath();
+        AccessManager acMgr = session.getAccessManager();
+        acMgr.checkPermission(p, 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);
+        }
 
         NodeTypeManagerImpl ntMgr = session.getNodeTypeManager();
         NodeTypeImpl mixin = ntMgr.getNodeType(mixinName);
@@ -1127,6 +1143,8 @@
 
         // check lock status
         checkLock();
+        // check permission
+        session.getAccessManager().checkPermission(getPrimaryPath(), Permission.NODE_TYPE_MNGMT);
 
         // check if mixin is assigned
         final NodeState state = data.getNodeState();
@@ -1195,37 +1213,47 @@
             return;
         }
 
-        // walk through properties and child nodes and remove those that have been
-        // defined by the specified mixin type
-
-        // use temp set to avoid ConcurrentModificationException
-        HashSet set = new HashSet(thisState.getPropertyNames());
-        for (Iterator iter = set.iterator(); iter.hasNext();) {
-            Name propName = (Name) iter.next();
-            PropertyImpl prop = (PropertyImpl) itemMgr.getItem(
-                    new PropertyId(thisState.getNodeId(), propName));
-            // check if property has been defined by mixin type (or one of its supertypes)
-            NodeTypeImpl declaringNT = (NodeTypeImpl) prop.getDefinition().getDeclaringNodeType();
-            if (!entRemaining.includesNodeType(declaringNT.getQName())) {
-                // the remaining effective node type doesn't include the
-                // node type that declared this property, it is thus safe
-                // to remove it
-                removeChildProperty(propName);
+        // walk through properties and child nodes and remove those that have
+        // been defined by the specified mixin type
+        boolean success = false;
+        try {
+            // use temp set to avoid ConcurrentModificationException
+            HashSet set = new HashSet(thisState.getPropertyNames());
+            for (Iterator iter = set.iterator(); iter.hasNext();) {
+                Name propName = (Name) iter.next();
+                PropertyState propState = (PropertyState) stateMgr.getItemState(new PropertyId(thisState.getNodeId(), propName));
+                // check if property has been defined by mixin type (or one of its supertypes)
+                PropertyDefinition def = ntMgr.getPropertyDefinition(propState.getDefinitionId());
+                NodeTypeImpl declaringNT = (NodeTypeImpl) def.getDeclaringNodeType();
+                if (!entRemaining.includesNodeType(declaringNT.getQName())) {
+                    // the remaining effective node type doesn't include the
+                    // node type that declared this property, it is thus safe
+                    // to remove it
+                    removeChildProperty(propName);
+                }
             }
-        }
-        // use temp array to avoid ConcurrentModificationException
-        ArrayList list = new ArrayList(thisState.getChildNodeEntries());
-        // start from tail to avoid problems with same-name siblings
-        for (int i = list.size() - 1; i >= 0; i--) {
-            ChildNodeEntry entry = (ChildNodeEntry) list.get(i);
-            NodeImpl node = (NodeImpl) itemMgr.getItem(entry.getId());
-            // check if node has been defined by mixin type (or one of its supertypes)
-            NodeTypeImpl declaringNT = (NodeTypeImpl) node.getDefinition().getDeclaringNodeType();
-            if (!entRemaining.includesNodeType(declaringNT.getQName())) {
-                // the remaining effective node type doesn't include the
-                // node type that declared this child node, it is thus safe
-                // to remove it
-                removeChildNode(entry.getName(), entry.getIndex());
+            // use temp array to avoid ConcurrentModificationException
+            ArrayList list = new ArrayList(thisState.getChildNodeEntries());
+            // start from tail to avoid problems with same-name siblings
+            for (int i = list.size() - 1; i >= 0; i--) {
+                ChildNodeEntry entry = (ChildNodeEntry) list.get(i);
+                NodeState nodeState = (NodeState) stateMgr.getItemState(entry.getId());
+                NodeDefinition def = ntMgr.getNodeDefinition(nodeState.getDefinitionId());
+                // check if node has been defined by mixin type (or one of its supertypes)
+                NodeTypeImpl declaringNT = (NodeTypeImpl) def.getDeclaringNodeType();
+                if (!entRemaining.includesNodeType(declaringNT.getQName())) {
+                    // the remaining effective node type doesn't include the
+                    // node type that declared this child node, it is thus safe
+                    // to remove it
+                    removeChildNode(entry.getName(), entry.getIndex());
+                }
+            }
+            success = true;
+        } catch (ItemStateException e) {
+            throw new RepositoryException("Failed to clean up child items defined by removed mixin " + session.getJCRName(mixinName));
+        } finally {
+            if (!success) {
+                // TODO revert changes made to the jcr:mixinTypes property
             }
         }
     }
@@ -2119,6 +2147,7 @@
         if (nt.isMixin()) {
             throw new RepositoryException(nodeTypeName + ": not a primary node type");
         }
+
         return internalAddNode(relPath, nt);
     }
 
@@ -2842,6 +2871,21 @@
                     "invalid mixin type name: " + mixinName, e);
         }
 
+        // check permissions
+        Path p = getPrimaryPath();
+        AccessManager acMgr = session.getAccessManager();
+        if (!acMgr.isGranted(p, Permission.NODE_TYPE_MNGMT)) {
+            return false;
+        }
+        // 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;
+            }
+        }
+
         NodeTypeManagerImpl ntMgr = session.getNodeTypeManager();
         NodeTypeImpl mixin = ntMgr.getNodeType(ntName);
         if (!mixin.isMixin()) {
@@ -3299,12 +3343,28 @@
 
         // check lock status
         checkLock();
+        // check permission
+        session.getAccessManager().checkPermission(getPrimaryPath(), Permission.VERSION_MNGMT);
 
         Version v = session.getVersionManager().checkin(this);
-        internalSetProperty(NameConstants.JCR_ISCHECKEDOUT, InternalValue.create(false));
-        internalSetProperty(NameConstants.JCR_BASEVERSION, InternalValue.create(new UUID(v.getUUID())));
-        internalSetProperty(NameConstants.JCR_PREDECESSORS, InternalValue.EMPTY_ARRAY, PropertyType.REFERENCE);
-        save();
+        boolean success = false;
+        try {
+            internalSetProperty(NameConstants.JCR_ISCHECKEDOUT, InternalValue.create(false));
+            internalSetProperty(NameConstants.JCR_BASEVERSION, InternalValue.create(new UUID(v.getUUID())));
+            internalSetProperty(NameConstants.JCR_PREDECESSORS, InternalValue.EMPTY_ARRAY, PropertyType.REFERENCE);
+            save();
+            success = true;
+        } finally {
+            if (!success) {
+                try {
+                    // TODO: need to revert changes made within the version manager as well.
+                    refresh(false);
+                } catch (RepositoryException e) {
+                    // cleanup failed
+                    log.error("Error while cleaning up after failed Node.checkin", e);
+                }
+            }
+        }
         return v;
     }
 
@@ -3329,25 +3389,37 @@
 
         // check lock status
         checkLock();
+        // check permission
+        session.getAccessManager().checkPermission(getPrimaryPath(), Permission.VERSION_MNGMT);
 
-        boolean hasPendingChanges = session.hasPendingChanges();
-
+        boolean hasPendingChanges = hasPendingChanges();
         Property[] props = new Property[2];
-        props[0] = internalSetProperty(NameConstants.JCR_ISCHECKEDOUT, InternalValue.create(true));
-        props[1] = internalSetProperty(NameConstants.JCR_PREDECESSORS,
-                new InternalValue[]{
-                        InternalValue.create(new UUID(getBaseVersion().getUUID()))
-                });
-        if (hasPendingChanges) {
-            for (int i = 0; i < props.length; i++) {
-                props[i].save();
+        boolean success = false;
+        try {
+            props[0] = internalSetProperty(NameConstants.JCR_ISCHECKEDOUT, InternalValue.create(true));
+            props[1] = internalSetProperty(NameConstants.JCR_PREDECESSORS,
+                    new InternalValue[]{
+                            InternalValue.create(new UUID(getBaseVersion().getUUID()))
+                    });
+            if (hasPendingChanges) {
+                for (int i = 0; i < props.length; i++) {
+                    props[i].save();
+                }
+            } else {
+                save();
             }
-        } else {
-            try {
-                session.save();
-            } catch (RepositoryException e) {
-                session.refresh(false);
-                throw e;
+            success = true;
+        } finally {
+            if (!success) {
+                for (int i = 0; i < props.length; i++) {
+                    if (props[i] != null) {
+                        try {
+                            props[i].refresh(false);
+                        } catch (RepositoryException e) {
+                            log.error("Error while cleaning up after failed Node.checkout", e);
+                        }
+                    }
+                }
             }
         }
     }
@@ -3748,7 +3820,8 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Perform {@link Node#cancelMerge(Version)} or {@link Node#doneMerge(Version)}
+     * depending on the value of <code>cancel</code>.
      */
     private void internalFinishMerge(Version version, boolean cancel)
             throws VersionException, InvalidItemStateException,
@@ -3769,6 +3842,8 @@
 
         // check lock
         checkLock();
+        // check permission
+        session.getAccessManager().checkPermission(getPrimaryPath(), Permission.VERSION_MNGMT);
 
         // check if checked out
         if (!internalIsCheckedOut()) {
@@ -3787,22 +3862,33 @@
             throw new VersionException(msg);
         }
 
-        // remove version from mergeFailed list
-        internalSetMergeFailed(failed);
+        boolean success = false;
+        try {
+            // remove version from mergeFailed list
+            internalSetMergeFailed(failed);
 
-        if (!cancel) {
-            // add version to jcr:predecessors list
-            Value[] vals = getProperty(NameConstants.JCR_PREDECESSORS).getValues();
-            InternalValue[] v = new InternalValue[vals.length + 1];
-            for (int i = 0; i < vals.length; i++) {
-                v[i] = InternalValue.create(UUID.fromString(vals[i].getString()));
+            if (!cancel) {
+                // add version to jcr:predecessors list
+                Value[] vals = getProperty(NameConstants.JCR_PREDECESSORS).getValues();
+                InternalValue[] v = new InternalValue[vals.length + 1];
+                for (int i = 0; i < vals.length; i++) {
+                    v[i] = InternalValue.create(UUID.fromString(vals[i].getString()));
+                }
+                v[vals.length] = InternalValue.create(UUID.fromString(version.getUUID()));
+                internalSetProperty(NameConstants.JCR_PREDECESSORS, v);
             }
-            v[vals.length] = InternalValue.create(UUID.fromString(version.getUUID()));
-            internalSetProperty(NameConstants.JCR_PREDECESSORS, v);
-        }
 
-        // save
-        save();
+            save();
+            success = true;
+        } finally {
+            if (!success) {
+                try {
+                    refresh(false);
+                } catch (RepositoryException e) {
+                    log.error("Error while reverting changes upon failed Node.doneMerge or Node.cancelMerge, respectively.", e);
+                }
+            }
+        }
     }
 
     /**
@@ -3973,7 +4059,19 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Executes the Node#update or Node#merge call.
+     *
+     * @param srcWorkspaceName Name of the source workspace as passed to
+     * {@link Node#merge(String, boolean)} or {@link Node#update(String)}.
+     * @param failedIds List to place the failed ids or <code>null</code> if
+     * {@link Node#update(String)} should be executed.
+     * @param bestEffort Flag passed to {@link Node#merge(String, boolean)} or
+     * false if {@link Node#update(String)} should be executed.
+     * @throws NoSuchWorkspaceException
+     * @throws AccessDeniedException
+     * @throws LockException
+     * @throws InvalidItemStateException
+     * @throws RepositoryException
      */
     private void internalMerge(String srcWorkspaceName,
                                List failedIds, boolean bestEffort)
@@ -3987,6 +4085,8 @@
         // do checks
         sanityCheck();
         checkSessionHasPending();
+        // check permission
+        session.getAccessManager().checkPermission(getPrimaryPath(), Permission.VERSION_MNGMT);
 
         // if same workspace, ignore
         if (srcWorkspaceName.equals(session.getWorkspace().getName())) {
@@ -3994,22 +4094,22 @@
         }
 
         SessionImpl srcSession = null;
+        boolean success = false;
         try {
             // create session on other workspace for current subject
             // (may throw NoSuchWorkspaceException and AccessDeniedException)
             srcSession = rep.createSession(session.getSubject(), srcWorkspaceName);
-            try {
-                internalMerge(srcSession, failedIds, bestEffort, removeExisting, replaceExisting);
-            } catch (RepositoryException e) {
+            internalMerge(srcSession, failedIds, bestEffort, removeExisting, replaceExisting);
+            session.save();
+            success = true;
+        } finally {
+            if (!success) {
                 try {
                     session.refresh(false);
-                } catch (RepositoryException e1) {
-                    // ignore
+                } catch (RepositoryException e) {
+                    log.error("Error while cleaning up after failed merge/update", e);
                 }
-                throw e;
             }
-            session.save();
-        } finally {
             if (srcSession != null) {
                 // we don't need the other session anymore, logout
                 srcSession.logout();
@@ -4156,19 +4256,22 @@
     private void internalRestore(Version version, VersionSelector vsel, boolean removeExisting)
             throws UnsupportedRepositoryOperationException, RepositoryException {
 
+        boolean success = false;
         try {
             internalRestore((VersionImpl) version, vsel, removeExisting);
-        } catch (RepositoryException e) {
-            // revert session
-            try {
-                log.error("reverting changes applied during restore...");
-                session.refresh(false);
-            } catch (RepositoryException e1) {
-                // ignore this
+            session.save();
+            success = true;
+        } finally {
+            if (!success) {
+                // revert session
+                try {
+                    log.debug("reverting changes applied during restore...");
+                    session.refresh(false);
+                } catch (RepositoryException e) {
+                    log.error("Error while reverting changes applied during restore.", e);
+                }
             }
-            throw e;
         }
-        session.save();
     }
 
     /**
@@ -4189,6 +4292,9 @@
             throw new VersionException("Restore of root version not allowed.");
         }
 
+        // check permission
+        session.getAccessManager().checkPermission(getPrimaryPath(), Permission.VERSION_MNGMT);
+
         // set jcr:isCheckedOut property to true, in order to avoid any conflicts
         internalSetProperty(NameConstants.JCR_ISCHECKEDOUT, InternalValue.create(true));
 
@@ -4451,45 +4557,8 @@
             RepositoryException {
         // check state of this instance
         sanityCheck();
-
-        // check for pending changes
-        if (hasPendingChanges()) {
-            String msg = "Unable to lock node. Node has pending changes: " + this;
-            log.debug(msg);
-            throw new InvalidItemStateException(msg);
-        }
-
-        checkLockable();
-
-        LockManager lockMgr = session.getLockManager();
-        synchronized (lockMgr) {
-            Lock lock = lockMgr.lock(this, isDeep, isSessionScoped);
-
-            boolean succeeded = false;
-
-            try {
-                // add properties to content
-                internalSetProperty(NameConstants.JCR_LOCKOWNER,
-                        InternalValue.create(getSession().getUserID()));
-                internalSetProperty(NameConstants.JCR_LOCKISDEEP,
-                        InternalValue.create(isDeep));
-                save();
-                succeeded = true;
-            } finally {
-                if (!succeeded) {
-                    // failed to set lock meta-data content, cleanup
-                    try {
-                        lockMgr.unlock(this);
-                        refresh(false);
-                    } catch (RepositoryException re) {
-                        // cleanup failed
-                        log.error("error while cleaning up after failed lock attempt", re);
-                    }
-                }
-            }
-
-            return lock;
-        }
+        LockManager lockMgr = ((WorkspaceImpl) session.getWorkspace()).get283LockManager();
+        return lockMgr.lock(getPath(), isDeep, isSessionScoped, Long.MAX_VALUE, null);
     }
 
     /**
@@ -4500,11 +4569,8 @@
             AccessDeniedException, RepositoryException {
         // check state of this instance
         sanityCheck();
-
-        if (isNew()) {
-            throw new LockException("New node can not be locked: " + this);
-        }
-        return session.getLockManager().getLock(this);
+        LockManager lockMgr = ((WorkspaceImpl) session.getWorkspace()).get283LockManager();
+        return lockMgr.getLock(getPath());
     }
 
     /**
@@ -4516,28 +4582,8 @@
             RepositoryException {
         // check state of this instance
         sanityCheck();
-
-        // check for pending changes
-        if (hasPendingChanges()) {
-            String msg = "Unable to unlock node. Node has pending changes: " + this;
-            log.debug(msg);
-            throw new InvalidItemStateException(msg);
-        }
-
-        checkLockable();
-
-        LockManager lockMgr = session.getLockManager();
-        synchronized (lockMgr) {
-            if (lockMgr.isLockHolder(session, this)) {
-                // save first, and unlock later. this guards concurrent access
-
-                // remove properties in content
-                internalSetProperty(NameConstants.JCR_LOCKOWNER, (InternalValue) null);
-                internalSetProperty(NameConstants.JCR_LOCKISDEEP, (InternalValue) null);
-                save();
-            }
-            lockMgr.unlock(this);
-        }
+        LockManager lockMgr = ((WorkspaceImpl) session.getWorkspace()).get283LockManager();
+        lockMgr.unlock(getPath());
     }
 
     /**
@@ -4546,12 +4592,8 @@
     public boolean holdsLock() throws RepositoryException {
         // check state of this instance
         sanityCheck();
-
-        if (!isNodeType(NameConstants.MIX_LOCKABLE) || isNew()) {
-            // a node that is new or not lockable never holds a lock
-            return false;
-        }
-        return session.getLockManager().holdsLock(this);
+        LockManager lockMgr = ((WorkspaceImpl) session.getWorkspace()).get283LockManager();
+        return lockMgr.holdsLock(getPath());
     }
 
     /**
@@ -4560,27 +4602,8 @@
     public boolean isLocked() throws RepositoryException {
         // check state of this instance
         sanityCheck();
-
-        if (isNew()) {
-            return false;
-        }
-        return session.getLockManager().isLocked(this);
-    }
-
-    /**
-     * Checks if this node is lockable, i.e. has 'mix:lockable'.
-     *
-     * @throws LockException       if this node is not lockable
-     * @throws RepositoryException if another error occurs
-     */
-    private void checkLockable() throws LockException, RepositoryException {
-        if (!isNodeType(NameConstants.MIX_LOCKABLE)) {
-            String msg =
-                "Unable to perform a locking operation on"
-                + " a non-lockable node: " + this;
-            log.debug(msg);
-            throw new LockException(msg);
-        }
+        LockManager lockMgr = ((WorkspaceImpl) session.getWorkspace()).get283LockManager();
+        return lockMgr.isLocked(getPath());
     }
 
     /**
@@ -4682,6 +4705,8 @@
 
         // check lock status
         checkLock();
+        // check permission
+        session.getAccessManager().checkPermission(getPrimaryPath(), Permission.NODE_TYPE_MNGMT);
 
         Name ntName;
         try {
@@ -4703,13 +4728,13 @@
         // build effective node type of new primary type & existing mixin's
         // in order to detect conflicts
         NodeTypeRegistry ntReg = ntMgr.getNodeTypeRegistry();
-        EffectiveNodeType entNew, entOld;
+        EffectiveNodeType entNew, entOld, entAll;
         try {
             entNew = ntReg.getEffectiveNodeType(ntName);
             entOld = ntReg.getEffectiveNodeType(state.getNodeTypeName());
 
             // try to build new effective node type (will throw in case of conflicts)
-            ntReg.getEffectiveNodeType(ntName, state.getMixinTypeNames());
+            entAll = ntReg.getEffectiveNodeType(ntName, state.getMixinTypeNames());
         } catch (NodeTypeConflictException ntce) {
             throw new ConstraintViolationException(ntce.getMessage());
         }
@@ -4731,6 +4756,7 @@
 
         Set oldDefs = new HashSet(Arrays.asList(entOld.getAllItemDefs()));
         Set newDefs = new HashSet(Arrays.asList(entNew.getAllItemDefs()));
+        Set allDefs = new HashSet(Arrays.asList(entAll.getAllItemDefs()));
 
         // added child item definitions
         Set addedDefs = new HashSet(newDefs);
@@ -4770,14 +4796,12 @@
                 PropertyState propState =
                         (PropertyState) stateMgr.getItemState(
                                 new PropertyId(thisState.getNodeId(), propName));
-                if (!newDefs.contains(ntReg.getPropDef(propState.getDefinitionId()))) {
+                if (!allDefs.contains(ntReg.getPropDef(propState.getDefinitionId()))) {
                     // try to find new applicable definition first and
                     // redefine property if possible
-
-                    PropertyDefinitionImpl pdi = null;
                     try {
                         PropertyImpl prop = (PropertyImpl) itemMgr.getItem(propState.getId());
-                        pdi = getApplicablePropertyDefinition(
+                        PropertyDefinitionImpl pdi = getApplicablePropertyDefinition(
                                 propName, propState.getType(),
                                 propState.isMultiValued(), false);
                         if (pdi.getRequiredType() != PropertyType.UNDEFINED
@@ -4813,8 +4837,7 @@
                         // update collection of added definitions
                         addedDefs.remove(pdi.unwrap());
                     } catch (ValueFormatException vfe) {
-                        // value conversion failed,
-                        // remove it
+                        // value conversion failed, remove it
                         removeChildProperty(propName);
                     } catch (ConstraintViolationException cve) {
                         // no suitable definition found for this property,
@@ -4835,19 +4858,16 @@
         for (int i = list.size() - 1; i >= 0; i--) {
             ChildNodeEntry entry = (ChildNodeEntry) list.get(i);
             try {
-                NodeState nodeState =
-                        (NodeState) stateMgr.getItemState(entry.getId());
-                if (!newDefs.contains(ntReg.getNodeDef(nodeState.getDefinitionId()))) {
+                NodeState nodeState = (NodeState) stateMgr.getItemState(entry.getId());
+                if (!allDefs.contains(ntReg.getNodeDef(nodeState.getDefinitionId()))) {
                     // try to find new applicable definition first and
                     // redefine node if possible
-
-                    NodeDefinitionImpl ndi = null;
                     try {
-                        NodeImpl node = (NodeImpl) itemMgr.getItem(nodeState.getId());
-                        ndi = getApplicableChildNodeDefinition(
+                        NodeDefinitionImpl ndi = getApplicableChildNodeDefinition(
                                 entry.getName(),
                                 nodeState.getNodeTypeName());
-                        // redefine property
+                        // redefine node
+                        NodeImpl node = (NodeImpl) itemMgr.getItem(nodeState.getId());
                         node.onRedefine(ndi.unwrap().getId());
                         // update collection of added definitions
                         addedDefs.remove(ndi.unwrap());
@@ -4864,7 +4884,8 @@
             }
         }
 
-        // create new 'auto-create' items
+        // create items that are defined as auto-created by the new primary node
+        // type and at the same time were not present with the old nt
         for (Iterator iter = addedDefs.iterator(); iter.hasNext();) {
             ItemDef def = (ItemDef) iter.next();
             if (def.isAutoCreated()) {

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SecurityItemModifier.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SecurityItemModifier.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SecurityItemModifier.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SecurityItemModifier.java Thu Jan  8 03:52:38 2009
@@ -18,23 +18,21 @@
 
 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.spi.Name;
+import org.apache.jackrabbit.spi.Path;
 
-import javax.jcr.AccessDeniedException;
-import javax.jcr.ItemExistsException;
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.PathNotFoundException;
 import javax.jcr.Property;
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
-import javax.jcr.lock.LockException;
-import javax.jcr.nodetype.ConstraintViolationException;
-import javax.jcr.version.VersionException;
+import javax.jcr.ItemExistsException;
+import javax.jcr.AccessDeniedException;
 
 /**
  * <code>SecurityItemModifier</code>: An abstract helper class to allow classes
@@ -46,72 +44,106 @@
  */
 public abstract class SecurityItemModifier {
 
-    protected SecurityItemModifier() {
+    private final boolean checkAcPermission;
+
+    protected SecurityItemModifier(boolean checkAcPermission) {
         Class cl = getClass();
         if (!(cl.equals(UserManagerImpl.class) ||
               cl.equals(ACLEditor.class) ||
               cl.equals(org.apache.jackrabbit.core.security.authorization.principalbased.ACLEditor.class))) {
             throw new IllegalArgumentException("Only UserManagerImpl and ACLEditor may extend from the SecurityItemModifier");
         }
+        this.checkAcPermission = checkAcPermission;
     }
 
-    protected NodeImpl addSecurityNode(NodeImpl parentImpl, Name name, Name ntName) throws RepositoryException, PathNotFoundException, LockException, ConstraintViolationException, ItemExistsException, VersionException {
-        synchronized (parentImpl) {
-            // 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();
-                }
+    protected NodeImpl addSecurityNode(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);
+    }
 
-            return parentImpl.createChildNode(name, def, nodeType, null);
+    protected Property setSecurityProperty(NodeImpl parentImpl, Name name, Value value) throws RepositoryException {
+        if (!parentImpl.isNew()) {
+            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 setSecurityProperty(NodeImpl parentImpl, Name name, Value value) throws RepositoryException, PathNotFoundException, LockException, ConstraintViolationException, ItemExistsException, VersionException {
-        synchronized (parentImpl) {
-            // 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 setSecurityProperty(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 Property setSecurityProperty(NodeImpl parentImpl, Name name, Value[] values) throws RepositoryException, PathNotFoundException, LockException, ConstraintViolationException, ItemExistsException, VersionException {
-        synchronized (parentImpl) {
-            // 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 removeSecurityItem(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 {
+        SessionImpl sImpl = (SessionImpl) item.getSession();
+        AccessManager acMgr = sImpl.getAccessManager();
+
+        Path path = sImpl.getHierarchyManager().getPath(item.getId());
+        acMgr.checkPermission(path, perm);
+    }
+
+    private void checkPermission(NodeImpl node, Name childName, int perm) throws RepositoryException {
+        SessionImpl sImpl = (SessionImpl) node.getSession();
+        AccessManager acMgr = sImpl.getAccessManager();
+
+        boolean isGranted = acMgr.isGranted(node.getPrimaryPath(), childName, perm);
+        if (!isGranted) {
+            throw new AccessDeniedException("Permission denied.");
         }
     }
 
-    protected void removeSecurityItem(ItemImpl itemImpl) throws LockException, VersionException, AccessDeniedException, ItemNotFoundException, RepositoryException {
-        NodeImpl n = (itemImpl.isNode()) ? (NodeImpl) itemImpl : (NodeImpl) itemImpl.getParent();
-        synchronized (n) {
-            // validation: make sure Node is not locked or checked-in.
-            n.checkSetProperty();
-            itemImpl.internalRemove(true);
+    private int getPermission(boolean isNode, boolean isRemove) {
+        if (checkAcPermission) {
+            return Permission.MODIFY_AC;
+        } else if (isNode) {
+            return (isRemove) ? Permission.REMOVE_NODE : Permission.ADD_NODE;
+        } else {
+            return (isRemove) ? Permission.REMOVE_PROPERTY : Permission.SET_PROPERTY;
         }
     }
 }
\ No newline at end of file

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=732693&r1=732692&r2=732693&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 Thu Jan  8 03:52:38 2009
@@ -872,6 +872,28 @@
     }
 
     /**
+     * Determines if there are pending unsaved changes either on the passed
+     * item or on any item in it's subtree.
+     *
+     * @param 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)
@@ -1020,7 +1042,7 @@
         // check permissions
         AccessManager acMgr = getAccessManager();
         if (!(acMgr.isGranted(srcPath, Permission.REMOVE_NODE) &&
-                acMgr.isGranted(destPath, Permission.ADD_NODE))) {
+                acMgr.isGranted(destPath, Permission.ADD_NODE | Permission.NODE_TYPE_MNGMT))) {
             String msg = "Not allowed to move node " + srcAbsPath + " to " + destAbsPath;
             log.debug(msg);
             throw new AccessDeniedException(msg);
@@ -1324,7 +1346,7 @@
 
     //--------------------------------------------------< new JSR 283 methods >
     /**
-     * @see org.apache.jackrabbit.api.jsr283.Session#getNodeByIdentifier(String) 
+     * @see org.apache.jackrabbit.api.jsr283.Session#getNodeByIdentifier(String)
      * @since JCR 2.0
      */
     public Node getNodeByIdentifier(String id)

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java Thu Jan  8 03:52:38 2009
@@ -151,6 +151,13 @@
 
         /**
          * {@inheritDoc}
+         */
+        public void checkPermission(Path absPath, int permissions) throws AccessDeniedException, RepositoryException {
+            // allow everything
+        }
+
+        /**
+         * {@inheritDoc}
          *
          * @return always <code>true</code>
          * @throws ItemNotFoundException is never thrown
@@ -211,9 +218,9 @@
         }
 
         /**
-         * @see AbstractAccessControlManager#checkPrivileges(String, int)
+         * @see AbstractAccessControlManager#checkPermission(String,int)
          */
-        protected void checkPrivileges(String absPath, int privileges) throws
+        protected void checkPermission(String absPath, int permission) throws
                 AccessDeniedException, PathNotFoundException, RepositoryException {
             // allow everything
         }
@@ -257,7 +264,7 @@
         public Privilege[] getPrivileges(String absPath)
                 throws PathNotFoundException, RepositoryException {
             checkValidNodePath(absPath);
-            return getPrivilegeRegistry().getPrivileges(PrivilegeRegistry.ALL);
+            return new Privilege[] {getPrivilegeRegistry().getPrivilege(Privilege.JCR_ALL)};
         }
 
         /**

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=732693&r1=732692&r2=732693&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 Thu Jan  8 03:52:38 2009
@@ -20,6 +20,7 @@
 import org.apache.jackrabbit.api.jsr283.observation.EventJournal;
 import org.apache.jackrabbit.core.config.WorkspaceConfig;
 import org.apache.jackrabbit.core.lock.LockManager;
+import org.apache.jackrabbit.core.lock.SessionLockManager;
 import org.apache.jackrabbit.core.observation.EventStateCollection;
 import org.apache.jackrabbit.core.observation.EventStateCollectionFactory;
 import org.apache.jackrabbit.core.observation.ObservationManagerImpl;
@@ -118,6 +119,8 @@
      */
     protected LockManager lockMgr;
 
+    private org.apache.jackrabbit.api.jsr283.lock.LockManager jcr283LockManager;
+
     /**
      * Protected constructor.
      *
@@ -264,6 +267,21 @@
         throw new UnsupportedRepositoryOperationException("not yet implemented");
     }
 
+    /**
+     * @see org.apache.jackrabbit.api.jsr283.Workspace#getLockManager()
+     * @see org.apache.jackrabbit.api.jsr283.lock.LockManager
+     */
+    // TODO: rename to 'getLockManager'.
+    // TODO  in order not to break compatilibiy with the 1.x releases
+    // TODO  the 283 method has been tmp. renamed since it conflicts with an
+    // TODO  existing public method, exposing the internal lock manager.
+    public org.apache.jackrabbit.api.jsr283.lock.LockManager get283LockManager() throws UnsupportedRepositoryOperationException, RepositoryException {
+        if (jcr283LockManager == null) {
+            jcr283LockManager = new SessionLockManager(session, session.getLockManager());
+        }
+        return jcr283LockManager;
+    }
+
     //-------------------------------< JackrabbitWorkspace/new JSR 283 method >
     /**
      * Creates a new <code>Workspace</code> with the specified
@@ -847,6 +865,7 @@
             throw new InvalidItemStateException(msg);
         }
 
+        boolean success = false;
         try {
             // now restore all versions that have a node in the ws
             int numRestored = 0;
@@ -878,17 +897,19 @@
                     }
                 }
             }
-        } catch (RepositoryException e) {
-            // revert session
-            try {
-                log.error("reverting changes applied during restore...");
-                session.refresh(false);
-            } catch (RepositoryException e1) {
-                // ignore this
+            session.save();
+            success = true;
+        } finally {
+            if (!success) {
+                // revert session
+                try {
+                    log.debug("reverting changes applied during restore...");
+                    session.refresh(false);
+                } catch (RepositoryException e) {
+                    log.error("Error while reverting changes applied during restore.", e);
+                }
             }
-            throw e;
         }
-        session.save();
     }
 
     /**

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java Thu Jan  8 03:52:38 2009
@@ -883,7 +883,7 @@
         try {
             if (record.isLock()) {
                 listener.externalLock(record.getNodeId(), record.isDeep(),
-                        record.getUserId());
+                        record.getOwner());
             } else {
                 listener.externalUnlock(record.getNodeId());
             }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/LockEventListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/LockEventListener.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/LockEventListener.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/LockEventListener.java Thu Jan  8 03:52:38 2009
@@ -31,10 +31,10 @@
      * @param nodeId node id
      * @param isDeep <code>true</code> if the lock is deep;
      *               <code>false</code> otherwise
-     * @param userId user id
+     * @param lockOwner lock owner
      * @throws RepositoryException if the lock cannot be processed
      */
-    void externalLock(NodeId nodeId, boolean isDeep, String userId) throws RepositoryException;
+    void externalLock(NodeId nodeId, boolean isDeep, String lockOwner) throws RepositoryException;
 
     /**
      * Handle an external unlock operation.

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/LockRecord.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/LockRecord.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/LockRecord.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/LockRecord.java Thu Jan  8 03:52:38 2009
@@ -46,9 +46,9 @@
     private boolean isDeep;
 
     /**
-     * User id.
+     * Lock owner.
      */
-    private String userId;
+    private String lockOwner;
 
     /**
      * Create a new instance of this class. Used when a lock operation should
@@ -56,18 +56,18 @@
      *
      * @param nodeId node id
      * @param isDeep flag indicating whether the lock is deep
-     * @param userId user id
+     * @param lockOwner the name of the lock owner.
      * @param record journal record
      * @param workspace workspace
      */
-    public LockRecord(NodeId nodeId, boolean isDeep, String userId,
+    public LockRecord(NodeId nodeId, boolean isDeep, String lockOwner,
                       Record record, String workspace) {
         super(record, workspace);
 
         this.nodeId = nodeId;
         this.isLock = true;
         this.isDeep = isDeep;
-        this.userId = userId;
+        this.lockOwner = lockOwner;
     }
 
     /**
@@ -104,7 +104,7 @@
         isLock = record.readBoolean();
         if (isLock) {
             isDeep = record.readBoolean();
-            userId = record.readString();
+            lockOwner = record.readString();
         }
     }
 
@@ -117,7 +117,7 @@
         record.writeBoolean(isLock);
         if (isLock) {
             record.writeBoolean(isDeep);
-            record.writeString(userId);
+            record.writeString(lockOwner);
         }
     }
 
@@ -161,8 +161,18 @@
      * Return the user id associated with the lock operation.
      *
      * @return user id
+     * @deprecated User {@link #getOwner()} instead.
      */
     public String getUserId() {
-        return userId;
+        return lockOwner;
+    }
+
+    /**
+     * Return the lock owner associated with the lock operation.
+     *
+     * @return lock owner associated with the lock operation.
+     */
+    public String getOwner() {
+        return lockOwner;
     }
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/AbstractLockInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/AbstractLockInfo.java?rev=732693&r1=732692&r2=732693&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/AbstractLockInfo.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/AbstractLockInfo.java Thu Jan  8 03:52:38 2009
@@ -66,10 +66,25 @@
      */
     public AbstractLockInfo(LockToken lockToken, boolean sessionScoped, boolean deep,
                     String lockOwner) {
+        this(lockToken, sessionScoped, deep, lockOwner, Long.MAX_VALUE);
+    }
+
+    /**
+     * Create a new instance of this class.
+     *
+     * @param lockToken     lock token
+     * @param sessionScoped whether lock token is session scoped
+     * @param deep          whether lock is deep
+     * @param lockOwner     owner of lock
+     * @param timeoutHint   the timeoutHint
+     */
+    public AbstractLockInfo(LockToken lockToken, boolean sessionScoped, boolean deep,
+                            String lockOwner, long timeoutHint) {
         this.lockToken = lockToken;
         this.sessionScoped = sessionScoped;
         this.deep = deep;
         this.lockOwner = lockOwner;
+        // TODO: TOBEFIXED for 2.0 respect and deal timeout hint.
     }
 
     /**
@@ -145,6 +160,17 @@
     }
 
     /**
+     * Return the number of seconds remaining until the lock expires.
+     *
+     * @return number of seconds remaining until the lock expires.
+     */
+    public long getSecondsRemaining() {
+        // TODO: TOBEFIXED for 2.0
+        // TODO  - add support for timeout specified by the API user -> LockManager#lock
+        return Long.MAX_VALUE;
+    }
+
+    /**
      * {@inheritDoc}
      */
     public String toString() {
@@ -162,6 +188,7 @@
         } else {
             buffer.append("none");
         }
+        buffer.append("owner:").append(lockOwner);
         buffer.append(')');
         return buffer.toString();
     }



Mime
View raw message