sessionimporter.java

来自「jsr170接口的java实现。是个apache的开源项目。」· Java 代码 · 共 322 行

JAVA
322
字号
/* * 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.xml;import org.apache.jackrabbit.core.NodeImpl;import org.apache.jackrabbit.core.SessionImpl;import org.apache.jackrabbit.core.NodeId;import org.apache.jackrabbit.core.util.ReferenceChangeTracker;import org.apache.jackrabbit.name.QName;import org.apache.jackrabbit.value.ReferenceValue;import org.apache.jackrabbit.uuid.UUID;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.jcr.ImportUUIDBehavior;import javax.jcr.ItemExistsException;import javax.jcr.ItemNotFoundException;import javax.jcr.Property;import javax.jcr.PropertyType;import javax.jcr.RepositoryException;import javax.jcr.Value;import javax.jcr.nodetype.ConstraintViolationException;import javax.jcr.nodetype.NodeDefinition;import java.util.Iterator;import java.util.List;import java.util.Stack;/** * <code>SessionImporter</code> ... */public class SessionImporter implements Importer {    private static Logger log = LoggerFactory.getLogger(SessionImporter.class);    private final SessionImpl session;    private final NodeImpl importTargetNode;    private final int uuidBehavior;    private Stack parents;    /**     * helper object that keeps track of remapped uuid's and imported reference     * properties that might need correcting depending on the uuid mappings     */    private final ReferenceChangeTracker refTracker;    /**     * Creates a new <code>SessionImporter</code> instance.     *     * @param importTargetNode     * @param session     * @param uuidBehavior     any of the constants declared by     *                         {@link ImportUUIDBehavior}     */    public SessionImporter(NodeImpl importTargetNode,                           SessionImpl session,                           int uuidBehavior) {        this.importTargetNode = importTargetNode;        this.session = session;        this.uuidBehavior = uuidBehavior;        refTracker = new ReferenceChangeTracker();        parents = new Stack();        parents.push(importTargetNode);    }    protected NodeImpl createNode(NodeImpl parent,                                  QName nodeName,                                  QName nodeTypeName,                                  QName[] mixinNames,                                  NodeId id)            throws RepositoryException {        NodeImpl node;        if (parent.hasProperty(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             */            Property conflicting = parent.getProperty(nodeName);            if (conflicting.isNew()) {                // 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.hasProperty(newName)) {                    newName = new QName(newName.getNamespaceURI(), newName.getLocalName() + "_");                }                if (conflicting.getDefinition().isMultiple()) {                    parent.setProperty(newName, conflicting.getValues());                } else {                    parent.setProperty(newName, conflicting.getValue());                }                conflicting.remove();            }        }        // add node        UUID uuid = (id == null) ? null : id.getUUID();        node = parent.addNode(nodeName, nodeTypeName, uuid);        // add mixins        if (mixinNames != null) {            for (int i = 0; i < mixinNames.length; i++) {                node.addMixin(mixinNames[i]);            }        }        return node;    }    protected NodeImpl resolveUUIDConflict(NodeImpl parent,                                           NodeImpl conflicting,                                           NodeInfo nodeInfo)            throws RepositoryException {        NodeImpl node;        if (uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW) {            // create new with new uuid            node = createNode(parent, nodeInfo.getName(),                    nodeInfo.getNodeTypeName(), nodeInfo.getMixinNames(), null);            // remember uuid mapping            if (node.isNodeType(QName.MIX_REFERENCEABLE)) {                refTracker.mappedUUID(nodeInfo.getId().getUUID(), node.getNodeId().getUUID());            }        } 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 importTargetNode or an ancestor thereof            if (importTargetNode.getPath().startsWith(conflicting.getPath())) {                String msg = "cannot remove ancestor node";                log.debug(msg);                throw new ConstraintViolationException (msg);            }            // remove conflicting            conflicting.remove();            // create new with given uuid            node = createNode(parent, nodeInfo.getName(),                    nodeInfo.getNodeTypeName(), nodeInfo.getMixinNames(),                    nodeInfo.getId());        } else if (uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING) {            if (conflicting.getDepth() == 0) {                String msg = "root node cannot be replaced";                log.debug(msg);                throw new RepositoryException(msg);            }            // 'replace' current parent with parent of conflicting            parent = (NodeImpl) conflicting.getParent();            // replace child node            node = parent.replaceChildNode(nodeInfo.getId(), nodeInfo.getName(),                    nodeInfo.getNodeTypeName(), nodeInfo.getMixinNames());        } else {            String msg = "unknown uuidBehavior: " + uuidBehavior;            log.debug(msg);            throw new RepositoryException(msg);        }        return node;    }    //-------------------------------------------------------------< Importer >    /**     * {@inheritDoc}     */    public void start() throws RepositoryException {        // nop    }    /**     * {@inheritDoc}     */    public void startNode(NodeInfo nodeInfo, List propInfos)            throws RepositoryException {        NodeImpl parent = (NodeImpl) parents.peek();        // process node        NodeImpl 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 too            parents.push(null); // push null onto stack for skipped node            log.debug("skipping node " + nodeName);            return;        }        if (parent.hasNode(nodeName)) {            // a node with that name already exists...            NodeImpl existing = parent.getNode(nodeName);            NodeDefinition def = existing.getDefinition();            if (!def.allowsSameNameSiblings()) {                // existing doesn't allow same-name siblings,                // check for potential conflicts                if (def.isProtected() && existing.isNodeType(ntName)) {                    // skip protected node                    parents.push(null); // push null onto stack for skipped node                    log.debug("skipping protected node " + existing.safeGetJCRPath());                    return;                }                if (def.isAutoCreated() && existing.isNodeType(ntName)) {                    // this node has already been auto-created, no need to create it                    node = existing;                } else {                    // edge case: colliding node does have same uuid                    // (see http://issues.apache.org/jira/browse/JCR-1128)                    if (! (existing.getId().equals(id)                            && (uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING                            || uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING))) {                        throw new ItemExistsException(existing.safeGetJCRPath());                    }                    // fall through                }            }        }        if (node == null) {            // create node            if (id == null) {                // no potential uuid conflict, always add new node                node = createNode(parent, nodeName, ntName, mixins, null);            } else {                // potential uuid conflict                NodeImpl conflicting;                try {                    conflicting = session.getNodeById(id);                } catch (ItemNotFoundException infe) {                    conflicting = null;                }                if (conflicting != null) {                    // resolve uuid conflict                    node = resolveUUIDConflict(parent, conflicting, nodeInfo);                } else {                    // create new with given uuid                    node = createNode(parent, nodeName, ntName, mixins, id);                }            }        }        // process properties        Iterator iter = propInfos.iterator();        while (iter.hasNext()) {            PropInfo pi = (PropInfo) iter.next();            pi.apply(node, session.getNamespaceResolver(), refTracker);        }        parents.push(node);    }    /**     * {@inheritDoc}     */    public void endNode(NodeInfo nodeInfo) throws RepositoryException {        parents.pop();    }    /**     * {@inheritDoc}     */    public void end() throws RepositoryException {        /**         * adjust references that refer to uuid's which have been mapped to         * newly generated uuid's on import         */        Iterator iter = refTracker.getProcessedReferences();        while (iter.hasNext()) {            Property prop = (Property) iter.next();            // being paranoid...            if (prop.getType() != PropertyType.REFERENCE) {                continue;            }            if (prop.getDefinition().isMultiple()) {                Value[] values = prop.getValues();                Value[] newVals = new Value[values.length];                for (int i = 0; i < values.length; i++) {                    Value val = values[i];                    UUID original = UUID.fromString(val.getString());                    UUID adjusted = refTracker.getMappedUUID(original);                    if (adjusted != null) {                        newVals[i] = new ReferenceValue(session.getNodeByUUID(adjusted));                    } else {                        // reference doesn't need adjusting, just copy old value                        newVals[i] = val;                    }                }                prop.setValue(newVals);            } else {                Value val = prop.getValue();                UUID original = UUID.fromString(val.getString());                UUID adjusted = refTracker.getMappedUUID(original);                if (adjusted != null) {                    prop.setValue(session.getNodeByUUID(adjusted));                }            }        }        refTracker.clear();    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?