docviewimporthandler.java

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

JAVA
327
字号
/* * 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.NodeId;import org.apache.jackrabbit.name.NameException;import org.apache.jackrabbit.name.NameFormat;import org.apache.jackrabbit.name.QName;import org.apache.jackrabbit.name.IllegalNameException;import org.apache.jackrabbit.util.ISO9075;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import javax.jcr.PropertyType;import javax.jcr.RepositoryException;import java.io.IOException;import java.io.Reader;import java.util.ArrayList;import java.util.Stack;/** * <code>DocViewImportHandler</code> processes Document View XML SAX events * and 'translates' them into <code>{@link Importer}</code> method calls. */class DocViewImportHandler extends TargetImportHandler {    private static Logger log = LoggerFactory.getLogger(DocViewImportHandler.class);    /**     * stack of NodeInfo instances; an instance is pushed onto the stack     * in the startElement method and is popped from the stack in the     * endElement method.     */    private final Stack stack = new Stack();    // buffer used to merge adjacent character data    private BufferedStringValue textHandler = null;    /**     * Constructs a new <code>DocViewImportHandler</code>.     *     * @param importer     */    DocViewImportHandler(Importer importer) {        super(importer);    }    /**     * Parses the given string as a list of JCR names. Any whitespace sequence     * is supported as a names separator instead of just a single space to     * be more liberal in what we accept. The current namespace context is     * used to convert the prefixed name strings to QNames.     *     * @param value string value     * @return the parsed names     * @throws SAXException if an invalid name was encountered     */    private QName[] parseNames(String value) throws SAXException {        String[] names = value.split("\\p{Space}+");        QName[] qnames = new QName[names.length];        for (int i = 0; i < names.length; i++) {            try {                qnames[i] = NameFormat.parse(names[i], nsContext);            } catch (NameException ne) {                throw new SAXException("Invalid name: " + names[i], ne);            }        }        return qnames;    }    /**     * Appends the given character data to the internal buffer.     *     * @param ch     the characters to be appended     * @param start  the index of the first character to append     * @param length the number of characters to append     * @throws SAXException if an error occurs     * @see #characters(char[], int, int)     * @see #ignorableWhitespace(char[], int, int)     * @see #processCharacters()     */    private void appendCharacters(char[] ch, int start, int length)            throws SAXException {        if (textHandler == null) {            textHandler = new BufferedStringValue(nsContext);        }        try {            textHandler.append(ch, start, length);        } catch (IOException ioe) {            String msg = "internal error while processing internal buffer data";            log.error(msg, ioe);            throw new SAXException(msg, ioe);        }    }    /**     * Translates character data reported by the     * <code>{@link #characters(char[], int, int)}</code> &     * <code>{@link #ignorableWhitespace(char[], int, int)}</code> SAX events     * into a  <code>jcr:xmltext</code> child node with one     * <code>jcr:xmlcharacters</code> property.     *     * @throws SAXException if an error occurs     * @see #appendCharacters(char[], int, int)     */    private void processCharacters()            throws SAXException {        try {            if (textHandler != null && textHandler.length() > 0) {                // there is character data that needs to be added to                // the current node                // check for pure whitespace character data                Reader reader = textHandler.reader();                try {                    int ch;                    while ((ch = reader.read()) != -1) {                        if (ch > 0x20) {                            break;                        }                    }                    if (ch == -1) {                        // the character data consists of pure whitespace, ignore                        log.debug("ignoring pure whitespace character data...");                        // reset handler                        textHandler.dispose();                        textHandler = null;                        return;                    }                } finally {                    reader.close();                }                NodeInfo node =                        new NodeInfo(QName.JCR_XMLTEXT, null, null, null);                TextValue[] values =                        new TextValue[]{textHandler};                ArrayList props = new ArrayList();                PropInfo prop = new PropInfo(                        QName.JCR_XMLCHARACTERS, PropertyType.STRING, values);                props.add(prop);                // call Importer                importer.startNode(node, props);                importer.endNode(node);                // reset handler                textHandler.dispose();                textHandler = null;            }        } catch (IOException ioe) {            String msg = "internal error while processing internal buffer data";            log.error(msg, ioe);            throw new SAXException(msg, ioe);        } catch (RepositoryException re) {            throw new SAXException(re);        }    }    /**     * Processes the given <code>name</code>, i.e. decodes it and checks     * the format of the decoded name.     *     * @param name name to process     * @return the decoded and valid jcr name or the original name if it is     *         not encoded or if the resulting decoded name would be illegal.     */    private QName processName(QName name) {        QName decoded = ISO9075.decode(name);        if (decoded != name) {            // only need to check format of decoded name since            // an xml name is always a legal jcr name            // (http://issues.apache.org/jira/browse/JCR-821)            try {                NameFormat.checkFormat(decoded.getLocalName());                return decoded;            } catch (IllegalNameException ine) {                // decoded name would be illegal according to jsr 170,                // use encoded name as a fallback                log.warn("encountered illegal encoded name '"                        + name.getLocalName() + "': "                        + ine.getMessage());            }        }        return name;    }    //-------------------------------------------------------< ContentHandler >    /**     * {@inheritDoc}     * <p/>     * See also {@link DocViewSAXEventGenerator#leavingProperties(javax.jcr.Node, int)}     * regarding special handling of multi-valued properties on export.     */    public void startElement(String namespaceURI, String localName,                             String qName, Attributes atts)            throws SAXException {        // process buffered character data        processCharacters();        try {            QName nodeName = new QName(namespaceURI, localName);            // process node name            nodeName = processName(nodeName);            // properties            NodeId id = null;            QName nodeTypeName = null;            QName[] mixinTypes = null;            ArrayList props = new ArrayList(atts.getLength());            for (int i = 0; i < atts.getLength(); i++) {                if (atts.getURI(i).equals(QName.NS_XMLNS_URI)) {                    // skip namespace declarations reported as attributes                    // see http://issues.apache.org/jira/browse/JCR-620#action_12448164                    continue;                }                QName propName = new QName(atts.getURI(i), atts.getLocalName(i));                // process property name                propName = processName(propName);                // value(s)                String attrValue = atts.getValue(i);                TextValue[] propValues;                // always assume single-valued property for the time being                // until a way of properly serializing/detecting multi-valued                // properties on re-import is found (see JCR-325);                // see also DocViewSAXEventGenerator#leavingProperties(Node, int)                // todo proper multi-value serialization support                propValues = new TextValue[1];                propValues[0] = new StringValue(attrValue, nsContext);                if (propName.equals(QName.JCR_PRIMARYTYPE)) {                    // jcr:primaryType                    if (attrValue.length() > 0) {                        try {                            nodeTypeName = NameFormat.parse(attrValue, nsContext);                        } catch (NameException ne) {                            throw new SAXException("illegal jcr:primaryType value: "                                    + attrValue, ne);                        }                    }                } else if (propName.equals(QName.JCR_MIXINTYPES)) {                    // jcr:mixinTypes                    mixinTypes = parseNames(attrValue);                } else if (propName.equals(QName.JCR_UUID)) {                    // jcr:uuid                    if (attrValue.length() > 0) {                        id = NodeId.valueOf(attrValue);                    }                } else {                    props.add(new PropInfo(                            propName, PropertyType.UNDEFINED, propValues));                }            }            NodeInfo node =                    new NodeInfo(nodeName, nodeTypeName, mixinTypes, id);            // all information has been collected, now delegate to importer            importer.startNode(node, props);            // push current node data onto stack            stack.push(node);        } catch (RepositoryException re) {            throw new SAXException(re);        }    }    /**     * {@inheritDoc}     */    public void characters(char[] ch, int start, int length)            throws SAXException {        /**         * buffer data reported by the characters event;         * will be processed on the next endElement or startElement event.         */        appendCharacters(ch, start, length);    }    /**     * {@inheritDoc}     */    public void ignorableWhitespace(char[] ch, int start, int length)            throws SAXException {        /**         * buffer data reported by the ignorableWhitespace event;         * will be processed on the next endElement or startElement event.         */        appendCharacters(ch, start, length);    }    /**     * {@inheritDoc}     */    public void endElement(String namespaceURI, String localName, String qName)            throws SAXException {        // process buffered character data        processCharacters();        NodeInfo node = (NodeInfo) stack.peek();        try {            // call Importer            importer.endNode(node);        } catch (RepositoryException re) {            throw new SAXException(re);        }        // we're done with this node, pop it from stack        stack.pop();    }}

⌨️ 快捷键说明

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