Index: /home/ntoper/workspace/JR/src/main/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java =================================================================== --- /home/ntoper/workspace/JR/src/main/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java (revision 441794) +++ /home/ntoper/workspace/JR/src/main/java/org/apache/jackrabbit/core/xml/WorkspaceImporter.java (working copy) @@ -16,6 +16,23 @@ */ package org.apache.jackrabbit.core.xml; +import java.util.Iterator; +import java.util.List; +import java.util.Stack; + +import javax.jcr.AccessDeniedException; +import javax.jcr.ImportUUIDBehavior; +import javax.jcr.ItemExistsException; +import javax.jcr.ItemNotFoundException; +import javax.jcr.PathNotFoundException; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.ValueFormatException; +import javax.jcr.lock.LockException; +import javax.jcr.nodetype.ConstraintViolationException; +import javax.jcr.version.VersionException; +import javax.jcr.version.VersionHistory; + import org.apache.jackrabbit.core.BatchedItemOperations; import org.apache.jackrabbit.core.HierarchyManager; import org.apache.jackrabbit.core.NodeId; @@ -39,22 +56,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.jcr.ImportUUIDBehavior; -import javax.jcr.ItemExistsException; -import javax.jcr.ItemNotFoundException; -import javax.jcr.PathNotFoundException; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.lock.LockException; -import javax.jcr.nodetype.ConstraintViolationException; -import javax.jcr.version.VersionException; -import javax.jcr.version.VersionHistory; -import java.util.Iterator; -import java.util.List; -import java.util.Stack; - /** - * WorkspaceImporter ... + * WorkspaceImporter. It imports the content submitted to it + * by the Content Handler + * */ public class WorkspaceImporter implements Importer { @@ -59,16 +64,15 @@ public class WorkspaceImporter implements Importer { private static Logger log = LoggerFactory.getLogger(WorkspaceImporter.class); - private final NodeState importTarget; - private final WorkspaceImpl wsp; private final NodeTypeRegistry ntReg; private final HierarchyManager hierMgr; private final BatchedItemOperations itemOps; - private final int uuidBehavior; - private boolean aborted; + //It is not useful anymore: we never abort: we raise an exception. + // I suggest to delete it. Do you see any issue with this? + private boolean aborted = false; private Stack parents; /** @@ -77,12 +81,31 @@ */ private final ReferenceChangeTracker refTracker; + // Unused for now. It will be used in the next iteration on JIRA + private boolean raw = false; + + /** + * True if we skip the tree with current node as root + */ + private boolean skip = false; + /** - * Creates a new WorkspaceImporter instance. + * Used to find when stopping skipping + */ + private NodeInfo skipNode; + + /** + * True if this node already exist + */ + private NodeState existing = null; + private WorkspaceImpl wsp; + + /** + * Creates a new sWorkspaceImporter instance. * * @param parentPath target path where to add the imported subtree - * @param wsp - * @param ntReg + * @param wsp the workspace we want to import content to + * @param ntReg the NodeTypeRegistry of the repository * @param uuidBehavior flag that governs how incoming UUIDs are handled * @throws PathNotFoundException if no node exists at * parentPath or if the @@ -98,12 +121,11 @@ * @throws RepositoryException if another error occurs */ public WorkspaceImporter(Path parentPath, - WorkspaceImpl wsp, - NodeTypeRegistry ntReg, - int uuidBehavior) - throws PathNotFoundException, ConstraintViolationException, - VersionException, LockException, RepositoryException { - + WorkspaceImpl wsp, + NodeTypeRegistry ntReg, + int uuidBehavior) + throws PathNotFoundException, ConstraintViolationException, + VersionException, LockException, RepositoryException { SessionImpl ses = (SessionImpl) wsp.getSession(); itemOps = new BatchedItemOperations(wsp.getItemStateManager(), ntReg, ses.getLockManager(), ses, wsp.getHierarchyManager(), @@ -108,20 +130,16 @@ itemOps = new BatchedItemOperations(wsp.getItemStateManager(), ntReg, ses.getLockManager(), ses, wsp.getHierarchyManager(), ses.getNamespaceResolver()); - hierMgr = wsp.getHierarchyManager(); - // perform preliminary checks + this.hierMgr = wsp.getHierarchyManager(); + //Perform preliminary checks itemOps.verifyCanWrite(parentPath); importTarget = itemOps.getNodeState(parentPath); - this.wsp = wsp; this.ntReg = ntReg; this.uuidBehavior = uuidBehavior; - aborted = false; - refTracker = new ReferenceChangeTracker(); - parents = new Stack(); parents.push(importTarget); } @@ -127,79 +145,171 @@ } /** - * @param parent - * @param conflicting - * @param nodeInfo - * @return - * @throws RepositoryException + * Performs some checks to know if the node is importable or not. + * If it is a serious issue, raises an exception, else return false. + * this subtree. + *
+ * Performs also if needed some remapping. + * + * @param parent the parent NodeState + * @param nodeInfo NodeInfo passed by the ContentHandler + * @param propInfo PropInfo passed by the ContentHandler + * @return true if the node is fine; else false + * @throws RepositoryException if some constraints checks are not OK + * @throws ItemExistsException if the item exist + * @throws ItemNotFoundException if some constraints checks are not OK (shouldn't happen) + * @throws LockException if some constraints checks are not OK + * @throws VersionException if some constraints checks are not OK + * @throws AccessDeniedException if some constraints checks are not OK + * @throws ConstraintViolationException if some constraints checks are not OK */ - protected NodeState resolveUUIDConflict(NodeState parent, - NodeState conflicting, - NodeInfo nodeInfo) - throws RepositoryException { + private boolean checkNode(NodeState parent, NodeInfo nodeInfo, List propInfo) + throws ConstraintViolationException, AccessDeniedException, VersionException, + LockException, ItemNotFoundException, ItemExistsException, RepositoryException { + itemOps.checkAddNode(parent, nodeInfo.getName(), nodeInfo.getNodeTypeName(), + BatchedItemOperations.CHECK_ACCESS + | BatchedItemOperations.CHECK_CONSTRAINTS + | BatchedItemOperations.CHECK_LOCK + | BatchedItemOperations.CHECK_VERSIONING); + + QName nodeName = nodeInfo.getName(); + QName ntName = nodeInfo.getNodeTypeName(); + + if (parent.hasChildNodeEntry(nodeName)) { + // a node with that name already exists... + //No need to check for more than one, since if it + //is the case we can import it. + NodeState.ChildNodeEntry entry = + parent.getChildNodeEntry(nodeName, 1); + NodeId idExisting = entry.getId(); + NodeState existing = (NodeState) itemOps.getItemState(idExisting); + NodeDef def = ntReg.getNodeDef(existing.getDefinitionId()); + if (!def.allowsSameNameSiblings()) { + // existing doesn't allow same-name siblings, + // check for potential conflicts + EffectiveNodeType entExisting = + itemOps.getEffectiveNodeType(existing); + if (!raw && def.isProtected() && entExisting.includesNodeType(ntName)) { + return false; + } - NodeState node; - if (uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW) { - // create new with new uuid: - // check if new node can be added (check access rights & - // node type constraints only, assume locking & versioning status - // has already been checked on ancestor) - itemOps.checkAddNode(parent, nodeInfo.getName(), - nodeInfo.getNodeTypeName(), - BatchedItemOperations.CHECK_ACCESS - | BatchedItemOperations.CHECK_CONSTRAINTS); - node = itemOps.createNodeState(parent, nodeInfo.getName(), - nodeInfo.getNodeTypeName(), nodeInfo.getMixinNames(), null); - // remember uuid mapping - EffectiveNodeType ent = itemOps.getEffectiveNodeType(node); - if (ent.includesNodeType(QName.MIX_REFERENCEABLE)) { - refTracker.mappedUUID(nodeInfo.getId().getUUID(), node.getNodeId().getUUID()); + if (def.isAutoCreated() && entExisting.includesNodeType(ntName)) { + // this node has already been auto-created, + // no need to create it + this.existing = existing; + } else { + throw new ItemExistsException(itemOps.safeGetJCRPath(existing.getNodeId())); + } } - } else if (uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW) { - String msg = "a node with uuid " + nodeInfo.getId() - + " already exists!"; - log.debug(msg); - throw new ItemExistsException(msg); - } else if (uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING) { - // make sure conflicting node is not importTarget or an ancestor thereof - Path p0 = hierMgr.getPath(importTarget.getNodeId()); - Path p1 = hierMgr.getPath(conflicting.getNodeId()); - try { - if (p1.equals(p0) || p1.isAncestorOf(p0)) { - String msg = "cannot remove ancestor node"; - log.debug(msg); - throw new ConstraintViolationException(msg); + } + + if (parent.hasPropertyName(nodeName)) { + /** + * a property with the same name already exists; if this property + * has been imported as well (e.g. through document view import + * where an element can have the same name as one of the attributes + * of its parent element) we have to rename the onflicting property; + * + * see http://issues.apache.org/jira/browse/JCR-61 + */ + PropertyId propId = new PropertyId(parent.getNodeId(), nodeName); + PropertyState conflicting = itemOps.getPropertyState(propId); + if (conflicting.getStatus() == ItemState.STATUS_NEW) { + // assume this property has been imported as well; + // rename conflicting property + // @todo use better reversible escaping scheme to create unique name + QName newName = new QName(nodeName.getNamespaceURI(), nodeName.getLocalName() + "_"); + if (parent.hasPropertyName(newName)) { + newName = new QName(newName.getNamespaceURI(), newName.getLocalName() + "_"); } - } 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); + PropertyState newProp = + itemOps.createPropertyState(parent, newName, + conflicting.getType(), conflicting.getValues().length); + newProp.setValues(conflicting.getValues()); + parent.removePropertyName(nodeName); + itemOps.store(parent); + itemOps.destroy(conflicting); } - // remove conflicting: - // check if conflicting can be removed - // (access rights, node type constraints, locking & versioning status) - itemOps.checkRemoveNode(conflicting, - BatchedItemOperations.CHECK_ACCESS - | BatchedItemOperations.CHECK_LOCK - | BatchedItemOperations.CHECK_VERSIONING - | BatchedItemOperations.CHECK_CONSTRAINTS); - // do remove conflicting (recursive) - itemOps.removeNodeState(conflicting); + } + + return true; + } + + /** + * Create propoerties on a specific NodeState + * @param myNode the NodeState + * @param propInfos PropInfo + * @throws ItemNotFoundException if issue in the NodeState + * @throws ItemExistsException if issue in the NodeState + * @throws ConstraintViolationException if issue in the NodeState + * @throws ValueFormatException if issue in the NodeState + * @throws RepositoryException if issue in the NodeState + */ + private void createProperties(NodeState myNode, List propInfos) + throws ItemNotFoundException, ItemExistsException, ConstraintViolationException, + ValueFormatException, RepositoryException { + // process properties + Iterator iter = propInfos.iterator(); + while (iter.hasNext()) { + PropInfo pi = (PropInfo) iter.next(); + pi.apply(myNode, itemOps, ntReg, refTracker); + } + } + + /** + * Create the specific NodeState + * @param parent NodeState + * @param nodeInfo NodeInfo + * @return newly create NodeState + * @throws ConstraintViolationException if we cannot create the NodeState + * @throws RepositoryException if we cannot create the NodeState + */ + private NodeState createNode(NodeState parent, NodeInfo nodeInfo) throws ConstraintViolationException, RepositoryException { + + NodeDef def = + itemOps.findApplicableNodeDefinition(nodeInfo.getName(), nodeInfo.getNodeTypeName(), parent); + + // potential uuid conflict + NodeState conflicting = null; + NodeState node; - // create new with given uuid: - // check if new node can be added (check access rights & - // node type constraints only, assume locking & versioning status - // has already been checked on ancestor) - itemOps.checkAddNode(parent, nodeInfo.getName(), - nodeInfo.getNodeTypeName(), - BatchedItemOperations.CHECK_ACCESS - | BatchedItemOperations.CHECK_CONSTRAINTS); + try { + if (nodeInfo.getId() != null) { + conflicting = itemOps.getNodeState(nodeInfo.getId()); + } + } catch (ItemNotFoundException infe) { + conflicting = null; + } + if (conflicting != null) { + // resolve uuid conflict + node = resolveUUIDConflict(parent, conflicting, nodeInfo); + } + else { // do create new node - node = itemOps.createNodeState(parent, nodeInfo.getName(), - nodeInfo.getNodeTypeName(), nodeInfo.getMixinNames(), - nodeInfo.getId()); - } else if (uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING) { + node = itemOps.createNodeState(parent, nodeInfo.getName(), nodeInfo.getNodeTypeName(), + nodeInfo.getMixinNames(), null, def); + } + return node; + } + + /** + * Resolve UUID conflict if any. + * + * @param parent NodeState + * @param conflicting NodeState + * @param nodeInfo NodeInfo + * @return the new conflicting NodeState + * @throws ItemExistsException + * @throws ConstraintViolationException + * @throws IllegalStateException + * @throws RepositoryException + */ + private NodeState resolveUUIDConflict(NodeState parent, NodeState conflicting, NodeInfo nodeInfo) + throws ItemExistsException, ConstraintViolationException, IllegalStateException, RepositoryException { + NodeState node = null; + switch (uuidBehavior) { + + case ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING: NodeId parentId = conflicting.getParentId(); if (parentId == null) { String msg = "root node cannot be replaced"; @@ -225,11 +335,32 @@ | BatchedItemOperations.CHECK_CONSTRAINTS); // do remove conflicting (recursive) itemOps.removeNodeState(conflicting); - // create new with given uuid at same location as conflicting: - // check if new node can be added at other location + // do create new node + node = itemOps.createNodeState(parent, nodeInfo.getName(), + nodeInfo.getNodeTypeName(), nodeInfo.getMixinNames(), + nodeInfo.getId()); + break; + + case ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING: + // make sure conflicting node is not importTarget or an ancestor thereof + Path p0 = hierMgr.getPath(importTarget.getNodeId()); + Path p1 = hierMgr.getPath(conflicting.getNodeId()); + try { + if (p1.equals(p0) || p1.isAncestorOf(p0)) { + String msg = "cannot remove ancestor node"; + log.debug(msg); + throw new ConstraintViolationException(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); + } + // remove conflicting: + // check if conflicting can be removed // (access rights, node type constraints, locking & versioning status) - itemOps.checkAddNode(parent, nodeInfo.getName(), - nodeInfo.getNodeTypeName(), + itemOps.checkRemoveNode(conflicting, BatchedItemOperations.CHECK_ACCESS | BatchedItemOperations.CHECK_LOCK | BatchedItemOperations.CHECK_VERSIONING @@ -234,6 +365,10 @@ | BatchedItemOperations.CHECK_LOCK | BatchedItemOperations.CHECK_VERSIONING | BatchedItemOperations.CHECK_CONSTRAINTS); + // do remove conflicting (recursive) + itemOps.removeNodeState(conflicting); + + // create new with given uuid: // do create new node node = itemOps.createNodeState(parent, nodeInfo.getName(), nodeInfo.getNodeTypeName(), nodeInfo.getMixinNames(), @@ -238,13 +373,37 @@ node = itemOps.createNodeState(parent, nodeInfo.getName(), nodeInfo.getNodeTypeName(), nodeInfo.getMixinNames(), nodeInfo.getId()); - } else { - String msg = "unknown uuidBehavior: " + uuidBehavior; + break; + + case ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW: + String msg = "a node with uuid " + nodeInfo.getId() + + " already exists!"; log.debug(msg); - throw new RepositoryException(msg); + throw new ItemExistsException(msg); + + case ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW: + // create new with new uuid: + // check if new node can be added (check access rights & + // node type constraints only, assume locking & versioning status + // has already been checked on ancestor) + node = itemOps.createNodeState(parent, nodeInfo.getName(), + nodeInfo.getNodeTypeName(), nodeInfo.getMixinNames(), null); + // remember uuid mapping + EffectiveNodeType ent = itemOps.getEffectiveNodeType(node); + if (ent.includesNodeType(QName.MIX_REFERENCEABLE)) { + refTracker.mappedUUID(nodeInfo.getId().getUUID(), node.getNodeId().getUUID()); + } + break; + //No need for default case. } + return node; + } - return node; + /** + * @return true if skip mode is on. + */ + protected boolean isSkipped() { + return skip; } /** @@ -251,8 +410,8 @@ * Post-process imported node (initialize properties with special * semantics etc.) * - * @param node - * @throws RepositoryException + * @param node NodeState to postprocess + * @throws RepositoryException if issue when postprocessing a node */ protected void postProcessNode(NodeState node) throws RepositoryException { /** @@ -319,6 +478,7 @@ } } + //-------------------------------------------------------------< Importer > /** * {@inheritDoc} @@ -339,178 +499,31 @@ * {@inheritDoc} */ public void startNode(NodeInfo nodeInfo, List propInfos) - throws RepositoryException { + throws RepositoryException { if (aborted) { - // the import has been aborted, get outta here... return; } - boolean succeeded = false; - NodeState parent; - try { - // check sanity of workspace/session first - wsp.sanityCheck(); - - parent = (NodeState) parents.peek(); + NodeState parent = (NodeState) parents.peek(); - // process node - - NodeState node = null; - NodeId id = nodeInfo.getId(); - QName nodeName = nodeInfo.getName(); - QName ntName = nodeInfo.getNodeTypeName(); - QName[] mixins = nodeInfo.getMixinNames(); - - if (parent == null) { - // parent node was skipped, skip this child node also - parents.push(null); // push null onto stack for skipped node - succeeded = true; - log.debug("skipping node " + nodeName); - return; - } - if (parent.hasChildNodeEntry(nodeName)) { - // a node with that name already exists... - NodeState.ChildNodeEntry entry = - parent.getChildNodeEntry(nodeName, 1); - NodeId idExisting = entry.getId(); - NodeState existing = (NodeState) itemOps.getItemState(idExisting); - NodeDef def = ntReg.getNodeDef(existing.getDefinitionId()); - - if (!def.allowsSameNameSiblings()) { - // existing doesn't allow same-name siblings, - // check for potential conflicts - EffectiveNodeType entExisting = - itemOps.getEffectiveNodeType(existing); - if (def.isProtected() && entExisting.includesNodeType(ntName)) { - // skip protected node - parents.push(null); // push null onto stack for skipped node - succeeded = true; - log.debug("skipping protected node " - + itemOps.safeGetJCRPath(existing.getNodeId())); - return; - } - if (def.isAutoCreated() && entExisting.includesNodeType(ntName)) { - // this node has already been auto-created, - // no need to create it - node = existing; - } else { - throw new ItemExistsException(itemOps.safeGetJCRPath(existing.getNodeId())); - } - } - } - - if (node == null) { - // there's no node with that name... - if (id == null) { - // no potential uuid conflict, always create new node - - NodeDef def = - itemOps.findApplicableNodeDefinition(nodeName, ntName, parent); - if (def.isProtected()) { - // skip protected node - parents.push(null); // push null onto stack for skipped node - succeeded = true; - log.debug("skipping protected node " + nodeName); - return; - } + if (raw && !checkNode(parent, nodeInfo, propInfos)) { + skip = true; + } - if (parent.hasPropertyName(nodeName)) { - /** - * a property with the same name already exists; if this property - * has been imported as well (e.g. through document view import - * where an element can have the same name as one of the attributes - * of its parent element) we have to rename the onflicting property; - * - * see http://issues.apache.org/jira/browse/JCR-61 - */ - PropertyId propId = new PropertyId(parent.getNodeId(), nodeName); - PropertyState conflicting = itemOps.getPropertyState(propId); - if (conflicting.getStatus() == ItemState.STATUS_NEW) { - // assume this property has been imported as well; - // rename conflicting property - // @todo use better reversible escaping scheme to create unique name - QName newName = new QName(nodeName.getNamespaceURI(), nodeName.getLocalName() + "_"); - if (parent.hasPropertyName(newName)) { - newName = new QName(newName.getNamespaceURI(), newName.getLocalName() + "_"); - } - PropertyState newProp = - itemOps.createPropertyState(parent, newName, - conflicting.getType(), conflicting.getValues().length); - newProp.setValues(conflicting.getValues()); - parent.removePropertyName(nodeName); - itemOps.store(parent); - itemOps.destroy(conflicting); - } - } + if (skip) { + return; + } - // check if new node can be added (check access rights & - // node type constraints only, assume locking & versioning status - // has already been checked on ancestor) - itemOps.checkAddNode(parent, nodeName, ntName, - BatchedItemOperations.CHECK_ACCESS - | BatchedItemOperations.CHECK_CONSTRAINTS); - // do create new node - node = itemOps.createNodeState(parent, nodeName, ntName, mixins, null, def); - } else { - // potential uuid conflict - NodeState conflicting; - - try { - conflicting = itemOps.getNodeState(id); - } catch (ItemNotFoundException infe) { - conflicting = null; - } - if (conflicting != null) { - // resolve uuid conflict - node = resolveUUIDConflict(parent, conflicting, nodeInfo); - } else { - // create new with given uuid - - NodeDef def = - itemOps.findApplicableNodeDefinition(nodeName, ntName, parent); - if (def.isProtected()) { - // skip protected node - parents.push(null); // push null onto stack for skipped node - succeeded = true; - log.debug("skipping protected node " + nodeName); - return; - } - - // check if new node can be added (check access rights & - // node type constraints only, assume locking & versioning status - // has already been checked on ancestor) - itemOps.checkAddNode(parent, nodeName, ntName, - BatchedItemOperations.CHECK_ACCESS - | BatchedItemOperations.CHECK_CONSTRAINTS); - // do create new node - node = itemOps.createNodeState(parent, nodeName, ntName, mixins, id, def); - } - } - } - - // process properties - - Iterator iter = propInfos.iterator(); - while (iter.hasNext()) { - PropInfo pi = (PropInfo) iter.next(); - pi.apply(node, itemOps, ntReg, refTracker); - } - - // store affected nodes - itemOps.store(node); - itemOps.store(parent); - - // push current node onto stack of parents - parents.push(node); - - succeeded = true; - } finally { - if (!succeeded) { - // update operation failed, cancel all modifications - aborted = true; - itemOps.cancel(); - } + NodeState myNode; + if (existing == null) { + myNode = createNode(parent, nodeInfo); + } + else { + myNode = existing; + existing = null; } + createProperties(myNode, propInfos); + parents.push(myNode); } /** @@ -517,35 +530,27 @@ * {@inheritDoc} */ public void endNode(NodeInfo nodeInfo) throws RepositoryException { - if (aborted) { - // the import has been aborted, get outta here... + //End of skip mode + if (skipNode != null && skipNode.equals(nodeInfo)) { + skip = false; + skipNode = null; return; } - NodeState node = (NodeState) parents.pop(); - if (node == null) { - // node was skipped, nothing to do here + + if (aborted || skip) { return; } - boolean succeeded = false; - try { - // check sanity of workspace/session first - wsp.sanityCheck(); - // post-process node (initialize properties with special semantics etc.) - postProcessNode(node); - - // make sure node is valid according to its definition - itemOps.validate(node); + try { + NodeState node = (NodeState) parents.pop(); - // we're done with that node, now store its state - itemOps.store(node); - succeeded = true; - } finally { - if (!succeeded) { - // update operation failed, cancel all modifications - aborted = true; - itemOps.cancel(); + if (!raw) { + this.postProcessNode(node); } + itemOps.store(node); + } catch (IllegalStateException e) { + itemOps.cancel(); + aborted = true; } } @@ -554,66 +559,54 @@ */ public void end() throws RepositoryException { if (aborted) { - // the import has been aborted, get outta here... + itemOps.cancel(); return; } - boolean succeeded = false; - try { - // check sanity of workspace/session first - wsp.sanityCheck(); - - /** - * adjust references that refer to uuid's which have been mapped to - * newly gererated uuid's on import - */ - 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]; - UUID original = (UUID) val.internalValue(); - UUID adjusted = refTracker.getMappedUUID(original); - if (adjusted != null) { - newVals[i] = InternalValue.create(adjusted); - modified = true; - } else { - // reference doesn't need adjusting, just copy old value - newVals[i] = val; - } - } - if (modified) { - prop.setValues(newVals); - itemOps.store(prop); + wsp.sanityCheck(); + /** + * adjust references that refer to uuid's which have been mapped to + * newly gererated uuid's on import + */ + 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]; + UUID original = (UUID) val.internalValue(); + UUID adjusted = refTracker.getMappedUUID(original); + if (adjusted != null) { + newVals[i] = InternalValue.create(adjusted); + modified = true; + } else { + // reference doesn't need adjusting, just copy old value + newVals[i] = val; } } - refTracker.clear(); + if (modified) { + prop.setValues(newVals); + itemOps.store(prop); + } + } + refTracker.clear(); - // make sure import target is valid according to its definition - itemOps.validate(importTarget); + // make sure import target is valid according to its definition + itemOps.validate(importTarget); - // finally store the state of the import target - // (the parent of the imported subtree) - itemOps.store(importTarget); - succeeded = true; - } finally { - if (!succeeded) { - // update operation failed, cancel all modifications - aborted = true; - itemOps.cancel(); - } - } + // finally store the state of the import target + // (the parent of the imported subtree) + itemOps.store(importTarget); - if (!aborted) { - // finish update - itemOps.update(); - } + // finish update + itemOps.update(); } + } +