jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ste...@apache.org
Subject svn commit: r164983 [2/3] - in /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core: BatchedItemOperations.java ItemValidator.java WorkspaceImpl.java xml/WorkspaceImporter.java
Date Wed, 27 Apr 2005 14:10:54 GMT
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java?rev=164983&r1=164982&r2=164983&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java Wed Apr 27 07:10:54 2005
@@ -18,27 +18,11 @@
 
 import org.apache.jackrabbit.core.config.WorkspaceConfig;
 import org.apache.jackrabbit.core.lock.LockManager;
-import org.apache.jackrabbit.core.nodetype.EffectiveNodeType;
-import org.apache.jackrabbit.core.nodetype.NodeDef;
-import org.apache.jackrabbit.core.nodetype.NodeTypeConflictException;
-import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
-import org.apache.jackrabbit.core.nodetype.PropDef;
-import org.apache.jackrabbit.core.nodetype.PropDefId;
 import org.apache.jackrabbit.core.observation.ObservationManagerFactory;
 import org.apache.jackrabbit.core.observation.ObservationManagerImpl;
 import org.apache.jackrabbit.core.query.QueryManagerImpl;
-import org.apache.jackrabbit.core.security.AccessManager;
-import org.apache.jackrabbit.core.state.ItemStateException;
-import org.apache.jackrabbit.core.state.ItemStateManager;
-import org.apache.jackrabbit.core.state.NoSuchItemStateException;
-import org.apache.jackrabbit.core.state.NodeReferences;
-import org.apache.jackrabbit.core.state.NodeReferencesId;
-import org.apache.jackrabbit.core.state.NodeState;
-import org.apache.jackrabbit.core.state.PropertyState;
 import org.apache.jackrabbit.core.state.SharedItemStateManager;
 import org.apache.jackrabbit.core.state.TransactionalItemStateManager;
-import org.apache.jackrabbit.core.util.ReferenceChangeTracker;
-import org.apache.jackrabbit.core.util.uuid.UUID;
 import org.apache.jackrabbit.core.version.GenericVersionSelector;
 import org.apache.jackrabbit.core.version.InternalVersion;
 import org.apache.jackrabbit.core.version.VersionImpl;
@@ -61,8 +45,6 @@
 import javax.jcr.NamespaceRegistry;
 import javax.jcr.NoSuchWorkspaceException;
 import javax.jcr.PathNotFoundException;
-import javax.jcr.PropertyType;
-import javax.jcr.ReferentialIntegrityException;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.UnsupportedRepositoryOperationException;
@@ -78,11 +60,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintStream;
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
-import java.util.List;
 
 /**
  * A <code>WorkspaceImpl</code> ...
@@ -91,41 +70,6 @@
 
     private static Logger log = Logger.getLogger(WorkspaceImpl.class);
 
-    // flags used by private internalCopy() method
-    private static final int COPY = 0;
-    private static final int CLONE = 1;
-    private static final int CLONE_REMOVE_EXISTING = 2;
-
-    /**
-     * option for <code>{@link #checkAddNode}</code> and
-     * <code>{@link #checkRemoveNode}</code> methods:<p/>
-     * check access rights
-     */
-    public static final int CHECK_ACCESS = 1;
-    /**
-     * option for <code>{@link #checkAddNode}</code> and
-     * <code>{@link #checkRemoveNode}</code> methods:<p/>
-     * check lock status
-     */
-    public static final int CHECK_LOCK = 2;
-    /**
-     * option for <code>{@link #checkAddNode}</code> and
-     * <code>{@link #checkRemoveNode}</code> methods:<p/>
-     * check checked-out status
-     */
-    public static final int CHECK_VERSIONING = 4;
-    /**
-     * option for <code>{@link #checkAddNode}</code> and
-     * <code>{@link #checkRemoveNode}</code> methods:<p/>
-     * check constraints defined in node type
-     */
-    public static final int CHECK_CONSTRAINTS = 16;
-    /**
-     * option for <code>{@link #checkRemoveNode}</code> method:<p/>
-     * check that target node is not being referenced
-     */
-    public static final int CHECK_REFERENCES = 8;
-
     /**
      * The configuration of this <code>Workspace</code>
      */
@@ -263,876 +207,6 @@
     }
 
     /**
-     * Checks whether the given node state satisfies the constraints implied by
-     * its primary and mixin node types. The following validations/checks are
-     * performed:
-     * <ul>
-     * <li>check if its node type satisfies the 'required node types' constraint
-     * specified in its definition</li>
-     * <li>check if all 'mandatory' child items exist</li>
-     * <li>for every property: check if the property value satisfies the
-     * value constraints specified in the property's definition</li>
-     * </ul>
-     *
-     * @param nodeState node state to be validated
-     * @throws ConstraintViolationException if any of the validations fail
-     * @throws RepositoryException          if another error occurs
-     */
-    public void validate(NodeState nodeState)
-            throws ConstraintViolationException, RepositoryException {
-        // effective node type (primary type incl. mixins)
-        EffectiveNodeType ent = getEffectiveNodeType(nodeState);
-        NodeTypeRegistry ntReg = rep.getNodeTypeRegistry();
-        NodeDef def = ntReg.getNodeDef(nodeState.getDefinitionId());
-
-        // check if primary type satisfies the 'required node types' constraint
-        QName[] requiredPrimaryTypes = def.getRequiredPrimaryTypes();
-        for (int i = 0; i < requiredPrimaryTypes.length; i++) {
-            if (!ent.includesNodeType(requiredPrimaryTypes[i])) {
-                String msg = hierMgr.safeGetJCRPath(nodeState.getId())
-                        + ": missing required primary type "
-                        + requiredPrimaryTypes[i];
-                log.debug(msg);
-                throw new ConstraintViolationException(msg);
-            }
-        }
-        // mandatory properties
-        PropDef[] pda = ent.getMandatoryPropDefs();
-        for (int i = 0; i < pda.length; i++) {
-            PropDef pd = pda[i];
-            if (!nodeState.hasPropertyEntry(pd.getName())) {
-                String msg = hierMgr.safeGetJCRPath(nodeState.getId())
-                        + ": mandatory property " + pd.getName()
-                        + " does not exist";
-                log.debug(msg);
-                throw new ConstraintViolationException(msg);
-            }
-        }
-        // mandatory child nodes
-        NodeDef[] cnda = ent.getMandatoryNodeDefs();
-        for (int i = 0; i < cnda.length; i++) {
-            NodeDef cnd = cnda[i];
-            if (!nodeState.hasChildNodeEntry(cnd.getName())) {
-                String msg = hierMgr.safeGetJCRPath(nodeState.getId())
-                        + ": mandatory child node " + cnd.getName()
-                        + " does not exist";
-                log.debug(msg);
-                throw new ConstraintViolationException(msg);
-            }
-        }
-    }
-
-    /**
-     * Checks whether the given property state satisfies the constraints
-     * implied by its definition. The following validations/checks are
-     * performed:
-     * <ul>
-     * <li>check if the type of the property values does comply with the
-     * requiredType specified in the property's definition</li>
-     * <li>check if the property values satisfy the value constraints
-     * specified in the property's definition</li>
-     * </ul>
-     *
-     * @param propState property state to be validated
-     * @throws ConstraintViolationException if any of the validations fail
-     * @throws RepositoryException          if another error occurs
-     */
-    public void validate(PropertyState propState)
-            throws ConstraintViolationException, RepositoryException {
-        NodeTypeRegistry ntReg = rep.getNodeTypeRegistry();
-        PropDef def = ntReg.getPropDef(propState.getDefinitionId());
-        InternalValue[] values = propState.getValues();
-        int type = PropertyType.UNDEFINED;
-        for (int i = 0; i < values.length; i++) {
-            if (type == PropertyType.UNDEFINED) {
-                type = values[i].getType();
-            } else if (type != values[i].getType()) {
-                throw new ConstraintViolationException(hierMgr.safeGetJCRPath(propState.getId())
-                        + ": inconsistent value types");
-            }
-            if (def.getRequiredType() != PropertyType.UNDEFINED
-                    && def.getRequiredType() != type) {
-                throw new ConstraintViolationException(hierMgr.safeGetJCRPath(propState.getId())
-                        + ": requiredType constraint is not satisfied");
-            }
-        }
-        EffectiveNodeType.checkSetPropertyValueConstraints(def, values);
-    }
-
-    /**
-     * Checks if adding if adding a child node called <code>nodeName</code> of
-     * node type <code>nodeTypeName</code> to the given parent node is allowed
-     * in the current context.
-     *
-     * @param parentState
-     * @param nodeName
-     * @param nodeTypeName
-     * @param options      bit-wise OR'ed flags specifying the checks that should be
-     *                     performed; any combination of the following constants:
-     *                     <ul>
-     *                     <li><code>{@link #CHECK_ACCESS}</code>: make sure
-     *                     current session is granted read & write access on
-     *                     parent node</li>
-     *                     <li><code>{@link #CHECK_LOCK}</code>: make sure
-     *                     there's no foreign lock on parent node</li>
-     *                     <li><code>{@link #CHECK_VERSIONING}</code>: make sure
-     *                     parent node is checked-out</li>
-     *                     <li><code>{@link #CHECK_CONSTRAINTS}</code>:
-     *                     make sure no node type constraints would be violated</li>
-     *                     <li><code>{@link #CHECK_REFERENCES}</code></li>
-     *                     </ul>
-     * @throws ConstraintViolationException
-     * @throws AccessDeniedException
-     * @throws VersionException
-     * @throws LockException
-     * @throws ItemNotFoundException
-     * @throws ItemExistsException
-     * @throws RepositoryException
-     */
-    public void checkAddNode(NodeState parentState, QName nodeName,
-                             QName nodeTypeName, int options)
-            throws ConstraintViolationException, AccessDeniedException,
-            VersionException, LockException, ItemNotFoundException,
-            ItemExistsException, RepositoryException {
-
-        Path parentPath = hierMgr.getPath(parentState.getId());
-
-        // 1. locking
-
-        if ((options & CHECK_LOCK) == CHECK_LOCK) {
-            // make sure there's no foreign lock on parent node
-            getLockManager().checkLock(parentPath, session);
-        }
-
-        // 2. versioning status
-
-        if ((options & CHECK_VERSIONING) == CHECK_VERSIONING) {
-            // make sure parent node is checked-out
-            verifyCheckedOut(parentPath);
-        }
-
-        // 3. access rights
-
-        if ((options & CHECK_ACCESS) == CHECK_ACCESS) {
-            AccessManager accessMgr = session.getAccessManager();
-            // make sure current session is granted read access on parent node
-            if (!accessMgr.isGranted(parentState.getId(), AccessManager.READ)) {
-                throw new ItemNotFoundException(hierMgr.safeGetJCRPath(parentState.getId()));
-            }
-            // make sure current session is granted write access on parent node
-            if (!accessMgr.isGranted(parentState.getId(), AccessManager.WRITE)) {
-                throw new AccessDeniedException(hierMgr.safeGetJCRPath(parentState.getId())
-                        + ": not allowed to add child node");
-            }
-        }
-
-        // 4. node type constraints
-
-        if ((options & CHECK_CONSTRAINTS) == CHECK_CONSTRAINTS) {
-            NodeTypeRegistry ntReg = rep.getNodeTypeRegistry();
-            NodeDef parentDef = ntReg.getNodeDef(parentState.getDefinitionId());
-            // make sure parent node is not protected
-            if (parentDef.isProtected()) {
-                throw new ConstraintViolationException(hierMgr.safeGetJCRPath(parentState.getId())
-                        + ": cannot add child node to protected parent node");
-            }
-            // make sure there's an applicable definition for new child node
-            EffectiveNodeType entParent = getEffectiveNodeType(parentState);
-            entParent.checkAddNodeConstraints(nodeName, nodeTypeName);
-            NodeDef newNodeDef =
-                    findApplicableNodeDefinition(nodeName, nodeTypeName,
-                            parentState);
-
-            // check for name collisions
-            if (parentState.hasPropertyEntry(nodeName)) {
-                // there's already a property with that name
-                throw new ItemExistsException("cannot add child node '"
-                        + nodeName.getLocalName() + "' to "
-                        + hierMgr.safeGetJCRPath(parentState.getId())
-                        + ": colliding with same-named existing property");
-            }
-            if (parentState.hasChildNodeEntry(nodeName)) {
-                // there's already a node with that name...
-
-                // get definition of existing conflicting node
-                NodeState.ChildNodeEntry entry = parentState.getChildNodeEntry(nodeName, 1);
-                NodeState conflictingState;
-                NodeId conflictingId = new NodeId(entry.getUUID());
-                try {
-                    conflictingState = (NodeState) stateMgr.getItemState(conflictingId);
-                } catch (ItemStateException ise) {
-                    String msg = "internal error: failed to retrieve state of "
-                            + hierMgr.safeGetJCRPath(conflictingId);
-                    log.debug(msg);
-                    throw new RepositoryException(msg, ise);
-                }
-                NodeDef conflictingTargetDef =
-                        ntReg.getNodeDef(conflictingState.getDefinitionId());
-                // check same-name sibling setting of both target and existing node
-                if (!conflictingTargetDef.allowsSameNameSiblings()
-                        || !newNodeDef.allowsSameNameSiblings()) {
-                    throw new ItemExistsException("cannot add child node '"
-                            + nodeName.getLocalName() + "' to "
-                            + hierMgr.safeGetJCRPath(parentState.getId())
-                            + ": colliding with same-named existing node");
-                }
-            }
-        }
-    }
-
-    /**
-     * Checks if removing the given target node entirely (i.e. unlinking from
-     * all its parents) is allowed in the current context.
-     *
-     * @param targetState
-     * @param options     bit-wise OR'ed flags specifying the checks that should be
-     *                    performed; any combination of the following constants:
-     *                    <ul>
-     *                    <li><code>{@link #CHECK_ACCESS}</code>: make sure
-     *                    current session is granted read access on parent
-     *                    and remove privilege on target node</li>
-     *                    <li><code>{@link #CHECK_LOCK}</code>: make sure
-     *                    there's no foreign lock on parent node</li>
-     *                    <li><code>{@link #CHECK_VERSIONING}</code>: make sure
-     *                    parent node is checked-out</li>
-     *                    <li><code>{@link #CHECK_CONSTRAINTS}</code>:
-     *                    make sure no node type constraints would be violated</li>
-     *                    <li><code>{@link #CHECK_REFERENCES}</code>:
-     *                    make sure no references exist on target node</li>
-     *                    </ul>
-     * @throws ConstraintViolationException
-     * @throws AccessDeniedException
-     * @throws VersionException
-     * @throws LockException
-     * @throws ItemNotFoundException
-     * @throws ReferentialIntegrityException
-     * @throws RepositoryException
-     */
-    public void checkRemoveNode(NodeState targetState, int options)
-            throws ConstraintViolationException, AccessDeniedException,
-            VersionException, LockException, ItemNotFoundException,
-            ReferentialIntegrityException, RepositoryException {
-        List parentUUIDs = targetState.getParentUUIDs();
-        Iterator iter = parentUUIDs.iterator();
-        while (iter.hasNext()) {
-            NodeId parentId = new NodeId((String) iter.next());
-            checkRemoveNode(targetState, parentId, options);
-        }
-    }
-
-    /**
-     * Checks if removing the given target node from the specifed parent
-     * is allowed in the current context.
-     *
-     * @param targetState
-     * @param parentId
-     * @param options     bit-wise OR'ed flags specifying the checks that should be
-     *                    performed; any combination of the following constants:
-     *                    <ul>
-     *                    <li><code>{@link #CHECK_ACCESS}</code>: make sure
-     *                    current session is granted read access on parent
-     *                    and remove privilege on target node</li>
-     *                    <li><code>{@link #CHECK_LOCK}</code>: make sure
-     *                    there's no foreign lock on parent node</li>
-     *                    <li><code>{@link #CHECK_VERSIONING}</code>: make sure
-     *                    parent node is checked-out</li>
-     *                    <li><code>{@link #CHECK_CONSTRAINTS}</code>:
-     *                    make sure no node type constraints would be violated</li>
-     *                    <li><code>{@link #CHECK_REFERENCES}</code>:
-     *                    make sure no references exist on target node</li>
-     *                    </ul>
-     * @throws ConstraintViolationException
-     * @throws AccessDeniedException
-     * @throws VersionException
-     * @throws LockException
-     * @throws ItemNotFoundException
-     * @throws ReferentialIntegrityException
-     * @throws RepositoryException
-     */
-    public void checkRemoveNode(NodeState targetState, NodeId parentId,
-                                int options)
-            throws ConstraintViolationException, AccessDeniedException,
-            VersionException, LockException, ItemNotFoundException,
-            ReferentialIntegrityException, RepositoryException {
-
-        if (targetState.getParentUUID() == null) {
-            // root or orphaned node
-            throw new ConstraintViolationException("cannot remove root node");
-        }
-        NodeId targetId = (NodeId) targetState.getId();
-        NodeState parentState = getNodeState(parentId);
-        Path parentPath = hierMgr.getPath(parentId);
-
-        // 1. locking
-
-        if ((options & CHECK_LOCK) == CHECK_LOCK) {
-            // make sure there's no foreign lock on parent node
-            getLockManager().checkLock(parentPath, session);
-        }
-
-        // 2. versioning status
-
-        if ((options & CHECK_VERSIONING) == CHECK_VERSIONING) {
-            // make sure parent node is checked-out
-            verifyCheckedOut(parentPath);
-        }
-
-        // 3. access rights
-
-        if ((options & CHECK_ACCESS) == CHECK_ACCESS) {
-            AccessManager accessMgr = session.getAccessManager();
-            try {
-                // make sure current session is granted read access on parent node
-                if (!accessMgr.isGranted(targetId, AccessManager.READ)) {
-                    throw new PathNotFoundException(hierMgr.safeGetJCRPath(targetId));
-                }
-                // make sure current session is allowed to remove target node
-                if (!accessMgr.isGranted(targetId, AccessManager.REMOVE)) {
-                    throw new AccessDeniedException(hierMgr.safeGetJCRPath(targetId)
-                            + ": not allowed to remove node");
-                }
-            } catch (ItemNotFoundException infe) {
-                String msg = "internal error: failed to check access rights for "
-                        + hierMgr.safeGetJCRPath(targetId);
-                log.debug(msg);
-                throw new RepositoryException(msg, infe);
-            }
-        }
-
-        // 4. node type constraints
-
-        if ((options & CHECK_CONSTRAINTS) == CHECK_CONSTRAINTS) {
-            NodeTypeRegistry ntReg = rep.getNodeTypeRegistry();
-            NodeDef parentDef = ntReg.getNodeDef(parentState.getDefinitionId());
-            if (parentDef.isProtected()) {
-                throw new ConstraintViolationException(hierMgr.safeGetJCRPath(parentId)
-                        + ": cannot remove child node of protected parent node");
-            }
-            NodeDef targetDef = ntReg.getNodeDef(targetState.getDefinitionId());
-            if (targetDef.isMandatory()) {
-                throw new ConstraintViolationException(hierMgr.safeGetJCRPath(targetId)
-                        + ": cannot remove mandatory node");
-            }
-            if (targetDef.isProtected()) {
-                throw new ConstraintViolationException(hierMgr.safeGetJCRPath(targetId)
-                        + ": cannot remove protected node");
-            }
-        }
-
-        // 5. referential integrity
-
-        if ((options & CHECK_REFERENCES) == CHECK_REFERENCES) {
-            EffectiveNodeType ent = getEffectiveNodeType(targetState);
-            if (ent.includesNodeType(MIX_REFERENCEABLE)) {
-                NodeReferencesId refsId = new NodeReferencesId(targetState.getUUID());
-                if (stateMgr.hasNodeReferences(refsId)) {
-                    try {
-                        NodeReferences refs = stateMgr.getNodeReferences(refsId);
-                        if (refs.hasReferences()) {
-                            throw new ReferentialIntegrityException(
-                                    hierMgr.safeGetJCRPath(targetId)
-                                    + ": cannot remove node with references");
-                        }
-                    } catch (ItemStateException ise) {
-                        String msg = "internal error: failed to check references on "
-                                + hierMgr.safeGetJCRPath(targetId);
-                        log.error(msg, ise);
-                        throw new RepositoryException(msg, ise);
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Verifies that the node at <code>nodePath</code> is checked-out; throws a
-     * <code>VersionException</code> if that's not the case.
-     * <p/>
-     * A node is considered <i>checked-out</i> if it is versionable and
-     * checked-out, or is non-versionable but its nearest versionable ancestor
-     * is checked-out, or is non-versionable and there are no versionable
-     * ancestors.
-     *
-     * @param nodePath
-     * @throws VersionException
-     * @throws RepositoryException
-     */
-    protected void verifyCheckedOut(Path nodePath)
-            throws VersionException, RepositoryException {
-        // search nearest ancestor that is versionable, start with node at nodePath
-        /**
-         * FIXME should not only rely on existence of jcr:isCheckedOut property
-         * but also verify that node.isNodeType("mix:versionable")==true;
-         * this would have a negative impact on performance though...
-         */
-        NodeState nodeState = getNodeState(nodePath);
-        while (!nodeState.hasPropertyEntry(JCR_ISCHECKEDOUT)) {
-            if (nodePath.denotesRoot()) {
-                return;
-            }
-            nodePath = nodePath.getAncestor(1);
-            nodeState = getNodeState(nodePath);
-        }
-        PropertyId propId =
-                new PropertyId(nodeState.getUUID(), JCR_ISCHECKEDOUT);
-        PropertyState propState;
-        try {
-            propState = (PropertyState) stateMgr.getItemState(propId);
-        } catch (ItemStateException ise) {
-            String msg = "internal error: failed to retrieve state of "
-                    + hierMgr.safeGetJCRPath(propId);
-            log.debug(msg);
-            throw new RepositoryException(msg, ise);
-        }
-        boolean checkedOut = ((Boolean) propState.getValues()[0].internalValue()).booleanValue();
-        if (!checkedOut) {
-            throw new VersionException(hierMgr.safeGetJCRPath(nodePath) + " is checked-in");
-        }
-    }
-
-    /**
-     * @param nodePath
-     * @return
-     * @throws PathNotFoundException
-     * @throws RepositoryException
-     */
-    protected NodeState getNodeState(Path nodePath)
-            throws PathNotFoundException, RepositoryException {
-        try {
-            ItemId id = hierMgr.resolvePath(nodePath);
-            if (!id.denotesNode()) {
-                throw new PathNotFoundException(hierMgr.safeGetJCRPath(nodePath));
-            }
-            return (NodeState) stateMgr.getItemState(id);
-        } catch (NoSuchItemStateException nsise) {
-            throw new PathNotFoundException(hierMgr.safeGetJCRPath(nodePath));
-        } catch (ItemStateException ise) {
-            String msg = "internal error: failed to retrieve state of "
-                    + hierMgr.safeGetJCRPath(nodePath);
-            log.debug(msg);
-            throw new RepositoryException(msg, ise);
-        }
-    }
-
-    /**
-     * @param id
-     * @return
-     * @throws ItemNotFoundException
-     * @throws RepositoryException
-     */
-    protected NodeState getNodeState(NodeId id)
-            throws ItemNotFoundException, RepositoryException {
-        try {
-            return (NodeState) stateMgr.getItemState(id);
-        } catch (NoSuchItemStateException nsise) {
-            throw new ItemNotFoundException(hierMgr.safeGetJCRPath(id));
-        } catch (ItemStateException ise) {
-            String msg = "internal error: failed to retrieve state of "
-                    + hierMgr.safeGetJCRPath(id);
-            log.debug(msg);
-            throw new RepositoryException(msg, ise);
-        }
-    }
-
-    /**
-     * Helper method that builds the effective (i.e. merged and resolved)
-     * node type representation of the specified node's primary and mixin
-     * node types.
-     *
-     * @param state
-     * @return the effective node type
-     * @throws RepositoryException
-     */
-    public EffectiveNodeType getEffectiveNodeType(NodeState state)
-            throws RepositoryException {
-        // build effective node type of mixins & primary type:
-        // existing mixin's
-        HashSet set = new HashSet(state.getMixinTypeNames());
-        // primary type
-        set.add(state.getNodeTypeName());
-        NodeTypeRegistry ntReg = rep.getNodeTypeRegistry();
-        try {
-            return ntReg.getEffectiveNodeType((QName[]) set.toArray(new QName[set.size()]));
-        } catch (NodeTypeConflictException ntce) {
-            String msg =
-                    "internal error: failed to build effective node type for node "
-                    + state.getUUID();
-            log.debug(msg);
-            throw new RepositoryException(msg, ntce);
-        }
-    }
-
-    /**
-     * 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(QName name,
-                                                QName nodeTypeName,
-                                                NodeState parentState)
-            throws RepositoryException, ConstraintViolationException {
-        EffectiveNodeType entParent = getEffectiveNodeType(parentState);
-        return entParent.getApplicableChildNodeDef(name, nodeTypeName);
-    }
-
-    /**
-     * 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.
-     *
-     * @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(QName name,
-                                                    int type,
-                                                    boolean multiValued,
-                                                    NodeState parentState)
-            throws RepositoryException, ConstraintViolationException {
-        EffectiveNodeType entParent = getEffectiveNodeType(parentState);
-        return entParent.getApplicablePropertyDef(name, type, multiValued);
-    }
-
-    /**
-     * Unlinks the specified node state from all its parents and recursively
-     * removes it including its properties and child nodes.
-     * <p/>
-     * <b>Precondition:</b> the state manager of this workspace needs to be in
-     * edit mode.
-     * todo duplicate code in WorkspaceImporter; consolidate in WorkspaceOperations class
-     *
-     * @param targetState
-     * @throws RepositoryException if an error occurs
-     */
-    private void removeNodeState(NodeState targetState)
-            throws RepositoryException {
-
-        // copy list to avoid ConcurrentModificationException
-        ArrayList parentUUIDs = new ArrayList(targetState.getParentUUIDs());
-        Iterator iter = parentUUIDs.iterator();
-        while (iter.hasNext()) {
-            String parentUUID = (String) iter.next();
-            NodeId parentId = new NodeId(parentUUID);
-
-            // unlink node state from this parent
-            unlinkNodeState(targetState, parentUUID);
-
-            // remove child node entries
-            NodeState parent = getNodeState(parentId);
-            // use temp array to avoid ConcurrentModificationException
-            ArrayList tmp =
-                    new ArrayList(parent.getChildNodeEntries(targetState.getUUID()));
-            // remove from tail to avoid problems with same-name siblings
-            for (int i = tmp.size() - 1; i >= 0; i--) {
-                NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) tmp.get(i);
-                parent.removeChildNodeEntry(entry.getName(), entry.getIndex());
-            }
-            // store parent
-            stateMgr.store(parent);
-        }
-    }
-
-    /**
-     * Unlinks the given node state from the specified parent i.e. removes
-     * <code>parentUUID</code> from its list of parents. If as a result
-     * the given node state would be orphaned it will be recursively removed
-     * including its properties and child nodes.
-     * <p/>
-     * Note that the child node entry refering to <code>targetState</code> is
-     * <b><i>not</i></b> automatically removed from <code>targetState</code>'s
-     * parent denoted by <code>parentUUID</code>.
-     * <p/>
-     * <b>Precondition:</b> the state manager of this workspace needs to be in
-     * edit mode.
-     * todo duplicate code in WorkspaceImporter; consolidate in WorkspaceOperations class
-     *
-     * @param targetState
-     * @param parentUUID
-     * @throws RepositoryException if an error occurs
-     */
-    private void unlinkNodeState(NodeState targetState, String parentUUID)
-            throws RepositoryException {
-
-        // check if this node state would be orphaned after unlinking it from parent
-        ArrayList parentUUIDs = new ArrayList(targetState.getParentUUIDs());
-        parentUUIDs.remove(parentUUID);
-        boolean orphaned = parentUUIDs.isEmpty();
-
-        if (orphaned) {
-            // remove child nodes
-            // use temp array to avoid ConcurrentModificationException
-            ArrayList tmp = new ArrayList(targetState.getChildNodeEntries());
-            // remove from tail to avoid problems with same-name siblings
-            for (int i = tmp.size() - 1; i >= 0; i--) {
-                NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) tmp.get(i);
-                NodeId nodeId = new NodeId(entry.getUUID());
-                try {
-                    NodeState nodeState = (NodeState) stateMgr.getItemState(nodeId);
-                    // check if child node can be removed
-                    // (access rights, locking & versioning status)
-                    checkRemoveNode(nodeState, (NodeId) targetState.getId(),
-                            CHECK_ACCESS | CHECK_LOCK | CHECK_VERSIONING);
-                    // unlink child node (recursive)
-                    unlinkNodeState(nodeState, targetState.getUUID());
-                } catch (ItemStateException ise) {
-                    String msg = "internal error: failed to retrieve state of "
-                            + nodeId;
-                    log.debug(msg);
-                    throw new RepositoryException(msg, ise);
-                }
-                // remove child node entry
-                targetState.removeChildNodeEntry(entry.getName(), entry.getIndex());
-            }
-
-            // remove properties
-            // use temp array to avoid ConcurrentModificationException
-            tmp = new ArrayList(targetState.getPropertyEntries());
-            for (int i = 0; i < tmp.size(); i++) {
-                NodeState.PropertyEntry entry = (NodeState.PropertyEntry) tmp.get(i);
-                PropertyId propId =
-                        new PropertyId(targetState.getUUID(), entry.getName());
-                try {
-                    PropertyState propState =
-                            (PropertyState) stateMgr.getItemState(propId);
-                    // remove property entry
-                    targetState.removePropertyEntry(propId.getName());
-                    // destroy property state
-                    stateMgr.destroy(propState);
-                } catch (ItemStateException ise) {
-                    String msg = "internal error: failed to retrieve state of "
-                            + propId;
-                    log.debug(msg);
-                    throw new RepositoryException(msg, ise);
-                }
-            }
-        }
-
-        // now actually do unlink target state from specified parent state
-        // (i.e. remove uuid of parent state from target state's parent list)
-        targetState.removeParentUUID(parentUUID);
-
-        if (orphaned) {
-            // destroy target state (pass overlayed state since target state
-            // might have been modified during unlinking)
-            stateMgr.destroy(targetState.getOverlayedState());
-        } else {
-            // store target state
-            stateMgr.store(targetState);
-        }
-    }
-
-    /**
-     * Recursively copies the specified node state including its properties and
-     * child nodes.
-     * <p/>
-     * <b>Precondition:</b> the state manager of <code>this</code> workspace
-     * needs to be in edit mode.
-     *
-     * @param srcState
-     * @param parentUUID
-     * @param srcStateMgr
-     * @param srcAccessMgr
-     * @param flag         one of
-     *                     <ul>
-     *                     <li><code>COPY</code></li>
-     *                     <li><code>CLONE</code></li>
-     *                     <li><code>CLONE_REMOVE_EXISTING</code></li>
-     *                     </ul>
-     * @param refTracker   tracks uuid mappings and processed reference properties
-     * @return a deep copy of the given node state and its children
-     * @throws RepositoryException if an error occurs
-     */
-    private NodeState copyNodeState(NodeState srcState,
-                                    String parentUUID,
-                                    ItemStateManager srcStateMgr,
-                                    AccessManager srcAccessMgr,
-                                    int flag,
-                                    ReferenceChangeTracker refTracker)
-            throws RepositoryException {
-
-        NodeState newState;
-        try {
-            String uuid;
-            NodeId id;
-            EffectiveNodeType ent = getEffectiveNodeType(srcState);
-            boolean referenceable = ent.includesNodeType(MIX_REFERENCEABLE);
-            switch (flag) {
-                case COPY:
-                    // always create new uuid
-                    uuid = UUID.randomUUID().toString();    // create new version 4 uuid
-                    if (referenceable) {
-                        // remember uuid mapping
-                        refTracker.mappedUUID(srcState.getUUID(), uuid);
-                    }
-                    break;
-                case CLONE:
-                    if (!referenceable) {
-                        // non-referenceable node: always create new uuid
-                        uuid = UUID.randomUUID().toString();    // create new version 4 uuid
-                        break;
-                    }
-                    // use same uuid as source node
-                    uuid = srcState.getUUID();
-                    id = new NodeId(uuid);
-                    if (stateMgr.hasItemState(id)) {
-                        // node with this uuid already exists
-                        throw new ItemExistsException(hierMgr.safeGetJCRPath(id));
-                    }
-                    break;
-                case CLONE_REMOVE_EXISTING:
-                    if (!referenceable) {
-                        // non-referenceable node: always create new uuid
-                        uuid = UUID.randomUUID().toString();    // create new version 4 uuid
-                        break;
-                    }
-                    // use same uuid as source node
-                    uuid = srcState.getUUID();
-                    id = new NodeId(uuid);
-                    if (stateMgr.hasItemState(id)) {
-                        NodeState existingState = (NodeState) stateMgr.getItemState(id);
-                        // make sure existing node is not the parent
-                        // or an ancestor thereof
-                        NodeId newParentId = new NodeId(parentUUID);
-                        Path p0 = hierMgr.getPath(newParentId);
-                        Path p1 = hierMgr.getPath(id);
-                        try {
-                            if (p1.equals(p0) || p1.isAncestorOf(p0)) {
-                                String msg = "cannot remove ancestor node";
-                                log.debug(msg);
-                                throw new RepositoryException(msg);
-                            }
-                        } catch (MalformedPathException mpe) {
-                            // should never get here...
-                            String msg = "internal error: failed to determine degree of relationship";
-                            log.error(msg, mpe);
-                            throw new RepositoryException(msg, mpe);
-                        }
-
-                        // check if existing can be removed
-                        checkRemoveNode(existingState, CHECK_ACCESS | CHECK_LOCK
-                                | CHECK_VERSIONING | CHECK_CONSTRAINTS);
-
-                        // do remove existing
-                        removeNodeState(existingState);
-                    }
-                    break;
-                default:
-                    throw new IllegalArgumentException("unknown flag");
-            }
-            newState = stateMgr.createNew(uuid, srcState.getNodeTypeName(), parentUUID);
-            // copy node state
-            // @todo special handling required for nodes with special semantics (e.g. those defined by mix:versionable, et.al.)
-            // FIXME delegate to 'node type instance handler'
-            newState.setMixinTypeNames(srcState.getMixinTypeNames());
-            newState.setDefinitionId(srcState.getDefinitionId());
-            // copy child nodes
-            Iterator iter = srcState.getChildNodeEntries().iterator();
-            while (iter.hasNext()) {
-                NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) iter.next();
-                NodeId nodeId = new NodeId(entry.getUUID());
-                if (!srcAccessMgr.isGranted(nodeId, AccessManager.READ)) {
-                    continue;
-                }
-                NodeState srcChildState = (NodeState) srcStateMgr.getItemState(nodeId);
-                // recursive copying of child node
-                NodeState newChildState = copyNodeState(srcChildState, uuid,
-                        srcStateMgr, srcAccessMgr, flag, refTracker);
-                // store new child node
-                stateMgr.store(newChildState);
-                // add new child node entry to new node
-                newState.addChildNodeEntry(entry.getName(), newChildState.getUUID());
-            }
-            // copy properties
-            iter = srcState.getPropertyEntries().iterator();
-            while (iter.hasNext()) {
-                NodeState.PropertyEntry entry = (NodeState.PropertyEntry) iter.next();
-                PropertyId propId = new PropertyId(srcState.getUUID(), entry.getName());
-                if (!srcAccessMgr.isGranted(propId, AccessManager.READ)) {
-                    continue;
-                }
-                PropertyState srcChildState =
-                        (PropertyState) srcStateMgr.getItemState(propId);
-                PropertyState newChildState =
-                        copyPropertyState(srcChildState, uuid, entry.getName());
-                if (newChildState.getType() == PropertyType.REFERENCE) {
-                    refTracker.processedReference(newChildState);
-                }
-                // store new property
-                stateMgr.store(newChildState);
-                // add new property entry to new node
-                newState.addPropertyEntry(entry.getName());
-            }
-            return newState;
-        } catch (ItemStateException ise) {
-            String msg = "internal error: failed to copy state of " + srcState.getId();
-            log.debug(msg);
-            throw new RepositoryException(msg, ise);
-        }
-    }
-
-    /**
-     * Copies the specified property state.
-     * <p/>
-     * <b>Precondition:</b> the state manager of this workspace needs to be in
-     * edit mode.
-     *
-     * @param srcState
-     * @param parentUUID
-     * @param propName
-     * @return
-     * @throws RepositoryException
-     */
-    private PropertyState copyPropertyState(PropertyState srcState,
-                                            String parentUUID,
-                                            QName propName)
-            throws RepositoryException {
-
-        // @todo special handling required for properties with special semantics
-        // (e.g. those defined by mix:versionable, mix:lockable, et.al.)
-        PropertyState newState = stateMgr.createNew(propName, parentUUID);
-        PropDefId defId = srcState.getDefinitionId();
-        newState.setDefinitionId(defId);
-        newState.setType(srcState.getType());
-        newState.setMultiValued(srcState.isMultiValued());
-        InternalValue[] values = srcState.getValues();
-        if (values != null) {
-            InternalValue[] newValues = new InternalValue[values.length];
-            for (int i = 0; i < values.length; i++) {
-                if (values[i] != null) {
-                    newValues[i] = values[i].createCopy();
-                } else {
-                    newValues[i] = null;
-                }
-            }
-            newState.setValues(values);
-            // FIXME delegate to 'node type instance handler'
-            if (defId != null) {
-                PropDef def = rep.getNodeTypeRegistry().getPropDef(defId);
-                if (def.getDeclaringNodeType().equals(MIX_REFERENCEABLE)) {
-                    if (propName.equals(JCR_UUID)) {
-                        // set correct value of jcr:uuid property
-                        newState.setValues(new InternalValue[]{InternalValue.create(parentUUID)});
-                    }
-                }
-            }
-        }
-        return newState;
-    }
-
-    /**
      * @param srcAbsPath
      * @param srcWsp
      * @param destAbsPath
@@ -1158,13 +232,9 @@
             VersionException, PathNotFoundException, ItemExistsException,
             LockException, RepositoryException {
 
-        // 1. check paths & retrieve state
-
         Path srcPath;
-        NodeState srcState;
         try {
             srcPath = Path.create(srcAbsPath, session.getNamespaceResolver(), true);
-            srcState = srcWsp.getNodeState(srcPath);
         } catch (MalformedPathException mpe) {
             String msg = "invalid path: " + srcAbsPath;
             log.debug(msg);
@@ -1172,115 +242,31 @@
         }
 
         Path destPath;
-        Path.PathElement destName;
-        Path destParentPath;
-        NodeState destParentState;
         try {
             destPath = Path.create(destAbsPath, session.getNamespaceResolver(), true);
-            destName = destPath.getNameElement();
-            destParentPath = destPath.getAncestor(1);
-            destParentState = getNodeState(destParentPath);
         } catch (MalformedPathException mpe) {
             String msg = "invalid path: " + destAbsPath;
             log.debug(msg);
             throw new RepositoryException(msg, mpe);
         }
-        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);
-        }
-
-        // 2. check access rights, lock status, node type constraints, etc.
-
-        checkAddNode(destParentState, destName.getName(),
-                srcState.getNodeTypeName(), CHECK_ACCESS | CHECK_LOCK
-                | CHECK_VERSIONING | CHECK_CONSTRAINTS);
-        // check read access right on source node
-        // use access manager of source workspace/session
-        AccessManager srcAccessMgr =
-                ((SessionImpl) srcWsp.getSession()).getAccessManager();
-        try {
-            if (!srcAccessMgr.isGranted(srcState.getId(), AccessManager.READ)) {
-                throw new PathNotFoundException(srcAbsPath);
-            }
-        } catch (ItemNotFoundException infe) {
-            String msg = "internal error: failed to check access rights for "
-                    + srcAbsPath;
-            log.debug(msg);
-            throw new RepositoryException(msg, infe);
-        }
-
-        // 3. do copy operation (modify and persist affected states)
 
         boolean succeeded = false;
-        try {
-            stateMgr.edit();
-
-            ReferenceChangeTracker refTracker = new ReferenceChangeTracker();
-
-            // create deep copy of source node state
-            NodeState newState = copyNodeState(srcState, destParentState.getUUID(),
-                    srcWsp.getItemStateManager(), srcAccessMgr, flag, refTracker);
-
-            // add to new parent
-            destParentState.addChildNodeEntry(destName.getName(), newState.getUUID());
-
-            // change definition (id) of new node
-            NodeDef newNodeDef =
-                    findApplicableNodeDefinition(destName.getName(),
-                            srcState.getNodeTypeName(), destParentState);
-            newState.setDefinitionId(newNodeDef.getId());
-
-            // adjust references that refer to uuid's which have been mapped to
-            // newly generated uuid's on copy/clone
-            Iterator iter = refTracker.getProcessedReferences();
-            while (iter.hasNext()) {
-                PropertyState prop = (PropertyState) iter.next();
-                // being paranoid...
-                if (prop.getType() != PropertyType.REFERENCE) {
-                    continue;
-                }
-                boolean modified = false;
-                InternalValue[] values = prop.getValues();
-                InternalValue[] newVals = new InternalValue[values.length];
-                for (int i = 0; i < values.length; i++) {
-                    InternalValue val = values[i];
-                    String original = ((UUID) val.internalValue()).toString();
-                    String adjusted = refTracker.getMappedUUID(original);
-                    if (adjusted != null) {
-                        newVals[i] = InternalValue.create(UUID.fromString(adjusted));
-                        modified = true;
-                    } else {
-                        // reference doesn't need adjusting, just copy old value
-                        newVals[i] = val;
-                    }
-                }
-                if (modified) {
-                    prop.setValues(newVals);
-                    stateMgr.store(prop);
-                }
-            }
-            refTracker.clear();
-
-            // store states
-            stateMgr.store(newState);
-            stateMgr.store(destParentState);
-
-            // finish update operations
-            stateMgr.update();
+        BatchedItemOperations ops =
+                new BatchedItemOperations(stateMgr, rep.getNodeTypeRegistry(),
+                        getLockManager(), session, hierMgr,
+                        session.getNamespaceResolver());
+        try {
+            ops.edit();
+            ops.copy(srcPath, srcWsp.getItemStateManager(),
+                    srcWsp.getHierarchyManager(),
+                    ((SessionImpl) srcWsp.getSession()).getAccessManager(),
+                    destPath, flag);
+            ops.update();
             succeeded = true;
-        } catch (ItemStateException ise) {
-            String msg = "internal error: failed to persist state of " + destAbsPath;
-            log.debug(msg);
-            throw new RepositoryException(msg, ise);
         } finally {
             if (!succeeded) {
                 // update operation failed, cancel all modifications
-                stateMgr.cancel();
+                ops.cancel();
             }
         }
     }
@@ -1374,9 +360,9 @@
             WorkspaceImpl srcWsp = (WorkspaceImpl) srcSession.getWorkspace();
 
             // do cross-workspace copy
-            int mode = CLONE;
+            int mode = BatchedItemOperations.CLONE;
             if (removeExisting) {
-                mode = CLONE_REMOVE_EXISTING;
+                mode = BatchedItemOperations.CLONE_REMOVE_EXISTING;
             }
             internalCopy(srcAbsPath, srcWsp, destAbsPath, mode);
         } finally {
@@ -1399,7 +385,7 @@
         sanityCheck();
 
         // do intra-workspace copy
-        internalCopy(srcAbsPath, this, destAbsPath, COPY);
+        internalCopy(srcAbsPath, this, destAbsPath, BatchedItemOperations.COPY);
     }
 
     /**
@@ -1436,7 +422,7 @@
             WorkspaceImpl srcWsp = (WorkspaceImpl) srcSession.getWorkspace();
 
             // do cross-workspace copy
-            internalCopy(srcAbsPath, srcWsp, destAbsPath, COPY);
+            internalCopy(srcAbsPath, srcWsp, destAbsPath, BatchedItemOperations.COPY);
         } finally {
             if (srcSession != null) {
                 // we don't need the other session anymore, logout
@@ -1458,20 +444,9 @@
 
         // intra-workspace move...
 
-        // 1. check paths & retrieve state
-
         Path srcPath;
-        Path.PathElement srcName;
-        Path srcParentPath;
-        NodeState targetState;
-        NodeState srcParentState;
-
         try {
             srcPath = Path.create(srcAbsPath, session.getNamespaceResolver(), true);
-            srcName = srcPath.getNameElement();
-            srcParentPath = srcPath.getAncestor(1);
-            targetState = getNodeState(srcPath);
-            srcParentState = getNodeState(srcParentPath);
         } catch (MalformedPathException mpe) {
             String msg = "invalid path: " + srcAbsPath;
             log.debug(msg);
@@ -1479,92 +454,28 @@
         }
 
         Path destPath;
-        Path.PathElement destName;
-        Path destParentPath;
-        NodeState destParentState;
-
         try {
             destPath = Path.create(destAbsPath, session.getNamespaceResolver(), true);
-            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);
-            destParentState = getNodeState(destParentPath);
         } catch (MalformedPathException mpe) {
             String msg = "invalid path: " + destAbsPath;
             log.debug(msg);
             throw new RepositoryException(msg, mpe);
         }
 
-        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);
-        }
-
-        // 2. check if target state can be removed from old/added to new parent
-
-        checkRemoveNode(targetState, (NodeId) srcParentState.getId(),
-                CHECK_ACCESS | CHECK_LOCK | CHECK_VERSIONING | CHECK_CONSTRAINTS);
-        checkAddNode(destParentState, destName.getName(),
-                targetState.getNodeTypeName(), CHECK_ACCESS | CHECK_LOCK
-                | CHECK_VERSIONING | CHECK_CONSTRAINTS);
-
-        // 3. do move operation (modify and persist affected states)
-
         boolean succeeded = false;
-        try {
-            stateMgr.edit();
-            boolean renameOnly = srcParentState.getUUID().equals(destParentState.getUUID());
-
-            // add to new parent
-            if (!renameOnly) {
-                targetState.addParentUUID(destParentState.getUUID());
-            }
-            destParentState.addChildNodeEntry(destName.getName(), targetState.getUUID());
-
-            // change definition (id) of target node
-            NodeDef newTargetDef =
-                    findApplicableNodeDefinition(destName.getName(),
-                            targetState.getNodeTypeName(), destParentState);
-            targetState.setDefinitionId(newTargetDef.getId());
-
-            // remove from old parent
-            if (!renameOnly) {
-                targetState.removeParentUUID(srcParentState.getUUID());
-            }
-
-            int srcNameIndex = srcName.getIndex();
-            if (srcNameIndex == 0) {
-                srcNameIndex = 1;
-            }
-            srcParentState.removeChildNodeEntry(srcName.getName(), srcNameIndex);
-
-            // store states
-            stateMgr.store(targetState);
-            if (renameOnly) {
-                stateMgr.store(srcParentState);
-            } else {
-                stateMgr.store(destParentState);
-                stateMgr.store(srcParentState);
-            }
-
-            // finish update
-            stateMgr.update();
+        BatchedItemOperations ops =
+                new BatchedItemOperations(stateMgr, rep.getNodeTypeRegistry(),
+                        getLockManager(), session, hierMgr,
+                        session.getNamespaceResolver());
+        try {
+            ops.edit();
+            ops.move(srcPath, destPath);
+            ops.update();
             succeeded = true;
-        } catch (ItemStateException ise) {
-            String msg = "internal error: failed to persist state of " + destAbsPath;
-            log.debug(msg);
-            throw new RepositoryException(msg, ise);
         } finally {
             if (!succeeded) {
                 // update operation failed, cancel all modifications
-                stateMgr.cancel();
+                ops.cancel();
             }
         }
     }
@@ -1580,7 +491,7 @@
         if (obsMgr == null) {
             try {
                 ObservationManagerFactory factory =
-                    rep.getObservationManagerFactory(wspConfig.getName());
+                        rep.getObservationManagerFactory(wspConfig.getName());
                 obsMgr = factory.createObservationManager(session, session.getItemManager());
             } catch (NoSuchWorkspaceException nswe) {
                 // should never get here
@@ -1688,12 +599,10 @@
                 }
                 if (restored == null) {
                     if (numRestored == 0) {
-                        throw new VersionException(
-                                "Unable to restore. At least one version needs"
+                        throw new VersionException("Unable to restore. At least one version needs"
                                 + " existing versionable node in workspace.");
                     } else {
-                        throw new VersionException(
-                                "Unable to restore. All versions with non"
+                        throw new VersionException("Unable to restore. All versions with non"
                                 + " existing versionable nodes need parent.");
                     }
                 }
@@ -1732,26 +641,16 @@
         // check state of this instance
         sanityCheck();
 
-        // check path & retrieve state
         Path parentPath;
-        NodeState parentState;
-
         try {
             parentPath = Path.create(parentAbsPath, session.getNamespaceResolver(), true);
-            parentState = getNodeState(parentPath);
         } catch (MalformedPathException mpe) {
             String msg = "invalid path: " + parentAbsPath;
             log.debug(msg);
             throw new RepositoryException(msg, mpe);
         }
 
-        // make sure import target node is checked-out
-        verifyCheckedOut(parentPath);
-
-        // check locked-status
-        getLockManager().checkLock(parentPath, session);
-
-        Importer importer = new WorkspaceImporter(parentState, this,
+        Importer importer = new WorkspaceImporter(parentPath, this,
                 rep.getNodeTypeRegistry(), uuidBehavior);
         return new ImportHandler(importer, session.getNamespaceResolver(),
                 rep.getNamespaceRegistry());



Mime
View raw message