jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ju...@apache.org
Subject svn commit: r957589 - in /jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core: BatchedItemOperations.java ItemValidator.java SessionImpl.java SessionMoveOperation.java session/SessionContext.java
Date Thu, 24 Jun 2010 15:53:51 GMT
Author: jukka
Date: Thu Jun 24 15:53:50 2010
New Revision: 957589

URL: http://svn.apache.org/viewvc?rev=957589&view=rev
Log:
JCR-890: concurrent read-only access to a session

Turn Session.move() into a SessionOperation

Added:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionMoveOperation.java
  (with props)
Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemValidator.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/session/SessionContext.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/BatchedItemOperations.java?rev=957589&r1=957588&r2=957589&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 Jun 24 15:53:50 2010
@@ -39,6 +39,7 @@ import org.apache.jackrabbit.core.id.Nod
 import org.apache.jackrabbit.core.id.PropertyId;
 import org.apache.jackrabbit.core.nodetype.EffectiveNodeType;
 import org.apache.jackrabbit.core.nodetype.NodeTypeConflictException;
+import org.apache.jackrabbit.core.retention.RetentionRegistry;
 import org.apache.jackrabbit.core.security.AccessManager;
 import org.apache.jackrabbit.core.security.authorization.Permission;
 import org.apache.jackrabbit.core.session.SessionContext;
@@ -89,6 +90,8 @@ public class BatchedItemOperations exten
      */
     protected final SessionImpl session;
 
+    private final HierarchyManager hierMgr;
+
     /**
      * Creates a new <code>BatchedItemOperations</code> instance.
      *
@@ -105,6 +108,7 @@ public class BatchedItemOperations exten
         super(sessionContext);
         this.stateMgr = stateMgr;
         this.session = sessionContext.getSessionImpl();
+        this.hierMgr = sessionContext.getHierarchyManager();
     }
 
     //-----------------------------------------< controlling batch operations >
@@ -749,6 +753,8 @@ public class BatchedItemOperations exten
             }
         }
 
+        RetentionRegistry retentionReg =
+            sessionContext.getSessionImpl().getRetentionRegistry();
         if ((options & CHECK_HOLD) == CHECK_HOLD) {
             if (retentionReg.hasEffectiveHold(parentPath, false)) {
                 throw new RepositoryException("Unable to add node. Parent is affected by
a hold.");
@@ -922,6 +928,8 @@ public class BatchedItemOperations exten
             }
         }
 
+        RetentionRegistry retentionReg =
+            sessionContext.getSessionImpl().getRetentionRegistry();
         if ((options & CHECK_HOLD) == CHECK_HOLD) {
             if (retentionReg.hasEffectiveHold(targetPath, true)) {
                 throw new RepositoryException("Unable to perform removal. Node is affected
by a hold.");
@@ -989,6 +997,8 @@ public class BatchedItemOperations exten
         // versioning status
         verifyCheckedOut(nodePath);
 
+        RetentionRegistry retentionReg =
+            sessionContext.getSessionImpl().getRetentionRegistry();
         if (retentionReg.hasEffectiveHold(nodePath, false)) {
             throw new RepositoryException("Unable to write. Node is affected by a hold.");
         }
@@ -1409,7 +1419,7 @@ public class BatchedItemOperations exten
     protected void verifyUnlocked(Path nodePath)
             throws LockException, RepositoryException {
         // make sure there's no foreign lock on node at nodePath
-        lockMgr.checkLock(nodePath, session);
+        sessionContext.getSessionImpl().getLockManager().checkLock(nodePath, session);
     }
 
     /**

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=957589&r1=957588&r2=957589&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 Jun 24 15:53:50 2010
@@ -29,11 +29,9 @@ import javax.jcr.nodetype.ItemDefinition
 import javax.jcr.version.VersionException;
 
 import org.apache.jackrabbit.core.id.ItemId;
-import org.apache.jackrabbit.core.lock.LockManager;
 import org.apache.jackrabbit.core.nodetype.EffectiveNodeType;
 import org.apache.jackrabbit.core.nodetype.NodeTypeConflictException;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
-import org.apache.jackrabbit.core.retention.RetentionRegistry;
 import org.apache.jackrabbit.core.security.authorization.Permission;
 import org.apache.jackrabbit.core.session.SessionContext;
 import org.apache.jackrabbit.core.state.NodeState;
@@ -115,26 +113,11 @@ public class ItemValidator {
     protected final NodeTypeRegistry ntReg;
 
     /**
-     * hierarchy manager used for generating error msg's
-     * that contain human readable paths
-     *
-     * @see #safeGetJCRPath(ItemId)
-     */
-    protected final HierarchyManager hierMgr;
-
-    /**
      * Path resolver for outputting user-friendly error messages.
      */
     protected final PathResolver resolver;
 
     /**
-     *
-     */
-    protected final LockManager lockMgr;
-
-    protected final RetentionRegistry retentionReg;
-
-    /**
      * Creates a new <code>ItemValidator</code> instance.
      *
      * @param sessionContext component context of this session
@@ -142,10 +125,7 @@ public class ItemValidator {
     public ItemValidator(SessionContext sessionContext) throws RepositoryException {
         this.sessionContext = sessionContext;
         this.ntReg = sessionContext.getRepositoryContext().getNodeTypeRegistry();
-        this.hierMgr = sessionContext.getHierarchyManager();
         this.resolver = sessionContext.getSessionImpl();
-        this.lockMgr = sessionContext.getSessionImpl().getLockManager();
-        this.retentionReg = sessionContext.getSessionImpl().getRetentionRegistry();
     }
 
     /**
@@ -359,7 +339,7 @@ public class ItemValidator {
             return;
         }
         NodeImpl node = (item.isNode()) ? (NodeImpl) item : (NodeImpl) item.getParent();
-        lockMgr.checkLock(node);
+        sessionContext.getSessionImpl().getLockManager().checkLock(node);
     }
 
     private boolean isProtected(ItemImpl item) throws RepositoryException {
@@ -381,7 +361,7 @@ public class ItemValidator {
             path = path.getAncestor(1);
         }
         boolean checkParent = (item.isNode() && isRemoval);
-        return retentionReg.hasEffectiveHold(path, checkParent);
+        return sessionContext.getSessionImpl().getRetentionRegistry().hasEffectiveHold(path,
checkParent);
     }
 
     private boolean hasRetention(ItemImpl item, boolean isRemoval) throws RepositoryException
{
@@ -393,7 +373,7 @@ public class ItemValidator {
             path = path.getAncestor(1);
         }
         boolean checkParent = (item.isNode() && isRemoval);
-        return retentionReg.hasEffectiveRetention(path, checkParent);
+        return sessionContext.getSessionImpl().getRetentionRegistry().hasEffectiveRetention(path,
checkParent);
     }
 
 
@@ -527,7 +507,8 @@ public class ItemValidator {
      */
     public String safeGetJCRPath(ItemId id) {
         try {
-            return safeGetJCRPath(hierMgr.getPath(id));
+            return safeGetJCRPath(
+                    sessionContext.getHierarchyManager().getPath(id));
         } catch (ItemNotFoundException e) {
             // return string representation of id as a fallback
             return id.toString();

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=957589&r1=957588&r2=957589&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 Jun 24 15:53:50 2010
@@ -26,7 +26,6 @@ import org.apache.jackrabbit.core.config
 import org.apache.jackrabbit.core.data.GarbageCollector;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.lock.LockManager;
-import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
 import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
 import org.apache.jackrabbit.core.retention.RetentionManagerImpl;
 import org.apache.jackrabbit.core.retention.RetentionRegistry;
@@ -41,7 +40,6 @@ import org.apache.jackrabbit.core.sessio
 import org.apache.jackrabbit.core.session.SessionOperation;
 import org.apache.jackrabbit.core.session.SessionRefreshOperation;
 import org.apache.jackrabbit.core.session.SessionSaveOperation;
-import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.state.SessionItemStateManager;
 import org.apache.jackrabbit.core.util.Dumpable;
 import org.apache.jackrabbit.core.value.ValueFactoryImpl;
@@ -66,7 +64,6 @@ import org.xml.sax.InputSource;
 import javax.jcr.AccessDeniedException;
 import javax.jcr.Credentials;
 import javax.jcr.Item;
-import javax.jcr.ItemExistsException;
 import javax.jcr.ItemNotFoundException;
 import javax.jcr.LoginException;
 import javax.jcr.NamespaceException;
@@ -213,12 +210,6 @@ public class SessionImpl extends Abstrac
     private Exception openStackTrace = new Exception("Stack Trace");
 
     /**
-     * Internal helper class for common validation checks (lock status, checkout
-     * status, protection etc. etc.)
-     */
-    private ItemValidator validator;
-
-    /**
      * Protected constructor.
      *
      * @param repositoryContext repository context
@@ -265,6 +256,7 @@ public class SessionImpl extends Abstrac
         wsp = createWorkspaceInstance(wspConfig);
         context.setItemStateManager(createSessionItemStateManager());
         context.setItemManager(createItemManager());
+        context.setItemValidator(new ItemValidator(context));
         context.setAccessManager(createAccessManager(subject));
         versionMgr = createVersionManager();
         ntInstanceHandler = new NodeTypeInstanceHandler(userId);
@@ -369,13 +361,9 @@ public class SessionImpl extends Abstrac
 
     /**
      * @return ItemValidator instance for this session.
-     * @throws RepositoryException If an error occurs.
      */
-    public synchronized ItemValidator getValidator() throws RepositoryException {
-        if (validator == null) {
-            validator = new ItemValidator(context);
-        }
-        return validator;
+    public ItemValidator getValidator() {
+        return context.getItemValidator();
     }
 
     /**
@@ -903,167 +891,8 @@ public class SessionImpl extends Abstrac
      * {@inheritDoc}
      */
     public void move(String srcAbsPath, String destAbsPath)
-            throws ItemExistsException, PathNotFoundException,
-            VersionException, ConstraintViolationException, LockException,
-            RepositoryException {
-        // check sanity of this session
-        sanityCheck();
-
-        // check paths & get node instances
-
-        Path srcPath;
-        Path.Element srcName;
-        Path srcParentPath;
-        NodeImpl targetNode;
-        NodeImpl srcParentNode;
-        try {
-            srcPath = getQPath(srcAbsPath).getNormalizedPath();
-            if (!srcPath.isAbsolute()) {
-                throw new RepositoryException("not an absolute path: " + srcAbsPath);
-            }
-            srcName = srcPath.getNameElement();
-            srcParentPath = srcPath.getAncestor(1);
-            targetNode = getItemManager().getNode(srcPath);
-            srcParentNode = getItemManager().getNode(srcParentPath);
-        } catch (AccessDeniedException ade) {
-            throw new PathNotFoundException(srcAbsPath);
-        } catch (NameException e) {
-            String msg = srcAbsPath + ": invalid path";
-            log.debug(msg);
-            throw new RepositoryException(msg, e);
-        }
-
-        Path destPath;
-        Path.Element destName;
-        Path destParentPath;
-        NodeImpl destParentNode;
-        try {
-            destPath = getQPath(destAbsPath).getNormalizedPath();
-            if (!destPath.isAbsolute()) {
-                throw new RepositoryException("not an absolute path: " + destAbsPath);
-            }
-            if (srcPath.isAncestorOf(destPath)) {
-                String msg = destAbsPath + ": invalid destination path (cannot be descendant
of source path)";
-                log.debug(msg);
-                throw new RepositoryException(msg);
-            }
-            destName = destPath.getNameElement();
-            destParentPath = destPath.getAncestor(1);
-            destParentNode = getItemManager().getNode(destParentPath);
-        } catch (AccessDeniedException ade) {
-            throw new PathNotFoundException(destAbsPath);
-        } catch (NameException e) {
-            String msg = destAbsPath + ": invalid path";
-            log.debug(msg);
-            throw new RepositoryException(msg, e);
-        }
-
-        if (context.getHierarchyManager().isShareAncestor(targetNode.getNodeId(), destParentNode.getNodeId()))
{
-            String msg = destAbsPath + ": invalid destination path (share cycle detected)";
-            log.debug(msg);
-            throw new RepositoryException(msg);
-        }
-
-        int ind = destName.getIndex();
-        if (ind > 0) {
-            // subscript in name element
-            String msg = destAbsPath + ": invalid destination path (subscript in name element
is not allowed)";
-            log.debug(msg);
-            throw new RepositoryException(msg);
-        }
-
-        // check for name collisions
-        NodeImpl existing = null;
-        try {
-            existing = getItemManager().getNode(destPath);
-            // there's already a node with that name:
-            // check same-name sibling setting of existing node
-            if (!existing.getDefinition().allowsSameNameSiblings()) {
-                throw new ItemExistsException(
-                        "Same name siblings are not allowed: " + existing);
-            }
-        } catch (AccessDeniedException ade) {
-            // FIXME by throwing ItemExistsException we're disclosing too much information
-            throw new ItemExistsException(destAbsPath);
-        } catch (PathNotFoundException pnfe) {
-            // no name collision, fall through
-        }
-
-        // 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_CHECKED_OUT | 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();
-        org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl newTargetDef;
-        try {
-            newTargetDef = destParentNode.getApplicableChildNodeDefinition(destName.getName(),
nt.getQName());
-        } catch (RepositoryException re) {
-            String msg = destAbsPath + ": no definition found in parent node's node type
for new node";
-            log.debug(msg);
-            throw new ConstraintViolationException(msg, re);
-        }
-        // if there's already a node with that name also check same-name sibling
-        // setting of new node; just checking same-name sibling setting on
-        // existing node is not sufficient since same-name sibling nodes don't
-        // necessarily have identical definitions
-        if (existing != null && !newTargetDef.allowsSameNameSiblings()) {
-            throw new ItemExistsException(
-                    "Same name siblings not allowed: " + existing);
-        }
-
-        NodeId targetId = targetNode.getNodeId();
-        int index = srcName.getIndex();
-        if (index == 0) {
-            index = 1;
-        }
-
-        // check permissions
-        AccessManager acMgr = context.getAccessManager();
-        if (!(acMgr.isGranted(srcPath, Permission.REMOVE_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);
-        }
-
-        if (srcParentNode.isSame(destParentNode)) {
-            // change definition of target
-            targetNode.onRedefine(newTargetDef.unwrap());
-            // do rename
-            destParentNode.renameChildNode(srcName.getName(), index, targetId, destName.getName());
-        } else {
-            // check shareable case
-            if (targetNode.getNodeState().isShareable()) {
-                String msg = "Moving a shareable node is not supported.";
-                log.debug(msg);
-                throw new UnsupportedRepositoryOperationException(msg);
-            }
-            // change definition of target
-            targetNode.onRedefine(newTargetDef.unwrap());
-
-            // Get the transient states
-            NodeState srcParentState =
-                    (NodeState) srcParentNode.getOrCreateTransientItemState();
-            NodeState targetState =
-                    (NodeState) targetNode.getOrCreateTransientItemState();
-            NodeState destParentState =
-                    (NodeState) destParentNode.getOrCreateTransientItemState();
-
-            // do move:
-            // 1. remove child node entry from old parent
-            if (srcParentState.removeChildNodeEntry(targetId)) {
-                // 2. re-parent target node
-                targetState.setParentId(destParentNode.getNodeId());
-                // 3. add child node entry to new parent
-                destParentState.addChildNodeEntry(destName.getName(), targetId);
-            }
-        }
+            throws RepositoryException {
+        perform(new SessionMoveOperation(this, srcAbsPath, destAbsPath));
     }
 
     /**

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionMoveOperation.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionMoveOperation.java?rev=957589&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionMoveOperation.java
(added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionMoveOperation.java
Thu Jun 24 15:53:50 2010
@@ -0,0 +1,216 @@
+/*
+ * 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 javax.jcr.AccessDeniedException;
+import javax.jcr.ItemExistsException;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.nodetype.ConstraintViolationException;
+
+import org.apache.jackrabbit.core.id.NodeId;
+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.session.SessionContext;
+import org.apache.jackrabbit.core.session.SessionOperation;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.commons.conversion.NameException;
+import org.apache.jackrabbit.spi.commons.conversion.PathResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SessionMoveOperation extends SessionOperation {
+
+    private final Logger log =
+        LoggerFactory.getLogger(SessionMoveOperation.class);
+
+    private final String srcAbsPath;
+
+    private final Path srcPath;
+
+    private final Path.Element srcName;
+
+    private final String destAbsPath;
+
+    private final Path destPath;
+
+    private final Path.Element destName;
+
+    public SessionMoveOperation(
+            PathResolver resolver, String srcAbsPath, String destAbsPath)
+            throws RepositoryException {
+        super("move");
+
+        this.srcAbsPath = srcAbsPath;
+        this.srcPath = getAbsolutePath(resolver, srcAbsPath);
+        this.srcName = srcPath.getNameElement();
+
+        this.destAbsPath = destAbsPath;
+        this.destPath = getAbsolutePath(resolver, destAbsPath);
+        this.destName = destPath.getNameElement();
+        if (destName.getIndex() > 0) {
+            // subscript in name element
+            String msg = destAbsPath + ": invalid destination path (subscript in name element
is not allowed)";
+            log.debug(msg);
+            throw new RepositoryException(msg);
+        }
+
+
+        if (srcPath.isAncestorOf(destPath)) {
+            throw new RepositoryException(
+                    "Destination path " + destAbsPath
+                    + " cannot be descendant of source path " + srcAbsPath
+                    + " in a move operation.");
+        }
+    }
+
+    private Path getAbsolutePath(PathResolver resolver, String path)
+            throws RepositoryException {
+        try {
+            Path qpath = resolver.getQPath(path).getNormalizedPath();
+            if (!qpath.isAbsolute()) {
+                throw new RepositoryException("Path is not absolute: " + path);
+            }
+            return qpath;
+        } catch (NameException e) {
+            throw new RepositoryException("Path is invalid: " + path, e);
+        }
+    }
+
+    private NodeImpl getNode(
+            SessionContext context, Path path, String absPath)
+            throws RepositoryException {
+        try {
+            return context.getItemManager().getNode(path);
+        } catch (AccessDeniedException e) {
+            throw new PathNotFoundException("Path not found: " + absPath);
+        }
+    }
+
+    public void perform(SessionContext context) throws RepositoryException {
+        // Get node instances
+        NodeImpl targetNode = getNode(context, srcPath, srcAbsPath);
+        NodeImpl srcParentNode =
+            getNode(context, srcPath.getAncestor(1), srcAbsPath);
+        NodeImpl destParentNode =
+            getNode(context, destPath.getAncestor(1), destAbsPath);
+
+        if (context.getHierarchyManager().isShareAncestor(
+                targetNode.getNodeId(), destParentNode.getNodeId())) {
+            throw new RepositoryException(
+                    "Move not possible because of a share cycle between "
+                    + srcAbsPath + " and " + destAbsPath);
+        }
+
+        // check for name collisions
+        NodeImpl existing = null;
+        try {
+            existing = context.getItemManager().getNode(destPath);
+            // there's already a node with that name:
+            // check same-name sibling setting of existing node
+            if (!existing.getDefinition().allowsSameNameSiblings()) {
+                throw new ItemExistsException(
+                        "Same name siblings are not allowed: " + existing);
+            }
+        } catch (AccessDeniedException ade) {
+            // FIXME by throwing ItemExistsException we're disclosing too much information
+            throw new ItemExistsException(destAbsPath);
+        } catch (PathNotFoundException pnfe) {
+            // no name collision, fall through
+        }
+
+        // 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_CHECKED_OUT | ItemValidator.CHECK_LOCK |
+        ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD | ItemValidator.CHECK_RETENTION;
+        context.getItemValidator().checkRemove(srcParentNode, options, Permission.NONE);
+        context.getItemValidator().checkModify(destParentNode, options, Permission.NONE);
+
+        // check constraints
+        // get applicable definition of target node at new location
+        NodeTypeImpl nt = (NodeTypeImpl) targetNode.getPrimaryNodeType();
+        org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl newTargetDef;
+        try {
+            newTargetDef = destParentNode.getApplicableChildNodeDefinition(destName.getName(),
nt.getQName());
+        } catch (RepositoryException re) {
+            String msg = destAbsPath + ": no definition found in parent node's node type
for new node";
+            log.debug(msg);
+            throw new ConstraintViolationException(msg, re);
+        }
+        // if there's already a node with that name also check same-name sibling
+        // setting of new node; just checking same-name sibling setting on
+        // existing node is not sufficient since same-name sibling nodes don't
+        // necessarily have identical definitions
+        if (existing != null && !newTargetDef.allowsSameNameSiblings()) {
+            throw new ItemExistsException(
+                    "Same name siblings not allowed: " + existing);
+        }
+
+        NodeId targetId = targetNode.getNodeId();
+        int index = srcName.getIndex();
+        if (index == 0) {
+            index = 1;
+        }
+
+        // check permissions
+        AccessManager acMgr = context.getAccessManager();
+        if (!(acMgr.isGranted(srcPath, Permission.REMOVE_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);
+        }
+
+        if (srcParentNode.isSame(destParentNode)) {
+            // change definition of target
+            targetNode.onRedefine(newTargetDef.unwrap());
+            // do rename
+            destParentNode.renameChildNode(srcName.getName(), index, targetId, destName.getName());
+        } else {
+            // check shareable case
+            if (targetNode.getNodeState().isShareable()) {
+                String msg = "Moving a shareable node is not supported.";
+                log.debug(msg);
+                throw new UnsupportedRepositoryOperationException(msg);
+            }
+            // change definition of target
+            targetNode.onRedefine(newTargetDef.unwrap());
+
+            // Get the transient states
+            NodeState srcParentState =
+                (NodeState) srcParentNode.getOrCreateTransientItemState();
+            NodeState targetState =
+                (NodeState) targetNode.getOrCreateTransientItemState();
+            NodeState destParentState =
+                (NodeState) destParentNode.getOrCreateTransientItemState();
+
+            // do move:
+            // 1. remove child node entry from old parent
+            if (srcParentState.removeChildNodeEntry(targetId)) {
+                // 2. re-parent target node
+                targetState.setParentId(destParentNode.getNodeId());
+                // 3. add child node entry to new parent
+                destParentState.addChildNodeEntry(destName.getName(), targetId);
+            }
+        }
+    }
+
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionMoveOperation.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionContext.java?rev=957589&r1=957588&r2=957589&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionContext.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/session/SessionContext.java
Thu Jun 24 15:53:50 2010
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.core.sessi
 
 import org.apache.jackrabbit.core.HierarchyManager;
 import org.apache.jackrabbit.core.ItemManager;
+import org.apache.jackrabbit.core.ItemValidator;
 import org.apache.jackrabbit.core.RepositoryContext;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.data.DataStore;
@@ -44,6 +45,11 @@ public class SessionContext {
     private volatile ItemManager itemManager;
 
     /**
+     * The item validator of this session
+     */
+    private volatile ItemValidator itemValidator;
+
+    /**
      * The access manager of this session
      */
     private volatile AccessManager accessManager;
@@ -116,6 +122,16 @@ public class SessionContext {
         this.itemManager = itemManager;
     }
 
+    public ItemValidator getItemValidator() {
+        assert itemValidator != null;
+        return itemValidator;
+    }
+
+    public void setItemValidator(ItemValidator itemValidator) {
+        assert itemValidator != null;
+        this.itemValidator = itemValidator;
+    }
+
     public AccessManager getAccessManager() {
         assert accessManager != null;
         return accessManager;



Mime
View raw message