You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by ve...@apache.org on 2016/04/09 19:12:01 UTC

svn commit: r1738366 - in /webservices/axiom/trunk/aspects: core-aspects/src/main/java/org/apache/axiom/core/impl/builder/ core-aspects/src/main/java/org/apache/axiom/core/stream/dom/ om-aspects/src/main/java/org/apache/axiom/om/impl/common/factory/

Author: veithen
Date: Sat Apr  9 17:12:01 2016
New Revision: 1738366

URL: http://svn.apache.org/viewvc?rev=1738366&view=rev
Log:
Avoid unnecessary conversion to StAX when constructing a builder from a DOM node.

Added:
    webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/dom/
    webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/dom/DOMInput.java   (with props)
    webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/dom/DOMReader.java   (with props)
Removed:
    webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/factory/DOMNamespaceContext.java
    webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/factory/DOMUtils.java
    webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/factory/DOMXMLStreamReader.java
Modified:
    webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/impl/builder/BuildableContext.java
    webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/factory/AbstractOMMetaFactory.java

Modified: webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/impl/builder/BuildableContext.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/impl/builder/BuildableContext.java?rev=1738366&r1=1738365&r2=1738366&view=diff
==============================================================================
--- webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/impl/builder/BuildableContext.java (original)
+++ webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/impl/builder/BuildableContext.java Sat Apr  9 17:12:01 2016
@@ -158,8 +158,7 @@ final class BuildableContext extends Con
 
     @Override
     void startFragment() {
-        // TODO
-        throw new UnsupportedOperationException();
+        startDocument(null, "1.0", null, true);
     }
 
     void processDocumentTypeDeclaration(String rootName, String publicId, String systemId,

Added: webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/dom/DOMInput.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/dom/DOMInput.java?rev=1738366&view=auto
==============================================================================
--- webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/dom/DOMInput.java (added)
+++ webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/dom/DOMInput.java Sat Apr  9 17:12:01 2016
@@ -0,0 +1,54 @@
+/*
+ * 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.axiom.core.stream.dom;
+
+import org.apache.axiom.core.stream.XmlHandler;
+import org.apache.axiom.core.stream.XmlInput;
+import org.apache.axiom.core.stream.XmlReader;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.Node;
+
+public class DOMInput implements XmlInput {
+    private final Node node;
+    private final boolean expandEntityReferences;
+    
+    /**
+     * Constructor.
+     * 
+     * @param node
+     *            The root node of the tree from which events will be generated.
+     * @param expandEntityReferences
+     *            Determines how {@link EntityReference} nodes are handled by this instance. When
+     *            set to {@code false}, a single
+     *            {@link XmlHandler#processEntityReference(String, String)} event will be emitted
+     *            for each {@link EntityReference}. When set to {@code true}, no
+     *            {@link XmlHandler#processEntityReference(String, String)} events are generated.
+     *            Instead, the implementation will traverse the descendants of the
+     *            {@link EntityReference} nodes (which effectively expands these entity references).
+     */
+    public DOMInput(Node node, boolean expandEntityReferences) {
+        this.node = node;
+        this.expandEntityReferences = expandEntityReferences;
+    }
+
+    @Override
+    public XmlReader createReader(XmlHandler handler) {
+        return new DOMReader(handler, node, expandEntityReferences);
+    }
+}

Propchange: webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/dom/DOMInput.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/dom/DOMReader.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/dom/DOMReader.java?rev=1738366&view=auto
==============================================================================
--- webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/dom/DOMReader.java (added)
+++ webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/dom/DOMReader.java Sat Apr  9 17:12:01 2016
@@ -0,0 +1,207 @@
+/*
+ * 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.axiom.core.stream.dom;
+
+import javax.xml.XMLConstants;
+
+import org.apache.axiom.core.stream.StreamException;
+import org.apache.axiom.core.stream.XmlHandler;
+import org.apache.axiom.core.stream.XmlReader;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+
+final class DOMReader implements XmlReader {
+    private static final int START = 0;
+    private static final int NOT_VISITED = 1;
+    private static final int VISITED = 2;
+    private static final int COMPLETE = 3;
+    
+    private final XmlHandler handler;
+    private final Node rootNode;
+    private final boolean expandEntityReferences;
+    private final boolean dom3;
+    private Node currentNode;
+    private int state = START;
+    
+    DOMReader(XmlHandler handler, Node node, boolean expandEntityReferences) {
+        this.handler = handler;
+        rootNode = node;
+        this.expandEntityReferences = expandEntityReferences;
+        Document ownerDocument;
+        if (node.getNodeType() == Node.DOCUMENT_NODE) {
+            ownerDocument = (Document)node;
+        } else {
+            ownerDocument = node.getOwnerDocument();
+        }
+        dom3 = ownerDocument.getImplementation().hasFeature("XML", "3.0");
+    }
+
+    private static String nullToEmptyString(String s) {
+        return s == null ? "" : s;
+    }
+    
+    @Override
+    public boolean proceed() throws StreamException {
+        Node currentNode = this.currentNode;
+        int state = this.state;
+        loop: while (true) {
+            switch (state) {
+                case START:
+                    if (rootNode instanceof Document) {
+                        currentNode = rootNode;
+                    }
+                    state = NOT_VISITED;
+                    break;
+                case NOT_VISITED:
+                    if (currentNode == null) {
+                        currentNode = rootNode;
+                    } else {
+                        Node node = currentNode.getFirstChild();
+                        if (node == null) {
+                            state = VISITED;
+                        } else {
+                            currentNode = node;
+                        }
+                    }
+                    break;
+                case VISITED:
+                    if (currentNode == null || currentNode instanceof Document) {
+                        throw new IllegalStateException();
+                    } else if (currentNode == rootNode) {
+                        currentNode = null;
+                    } else {
+                        Node node = currentNode.getNextSibling();
+                        if (node == null) {
+                            currentNode = currentNode.getParentNode();
+                        } else {
+                            currentNode = node;
+                            state = NOT_VISITED;
+                        }
+                    }
+                    break;
+                default:
+                    throw new IllegalStateException();
+            }
+            int nodeType = currentNode == null ? Node.DOCUMENT_NODE : currentNode.getNodeType();
+            if (state == VISITED) {
+                // In the future, there may be other node types that generate events here
+                switch (nodeType) {
+                    case Node.ELEMENT_NODE:
+                        handler.endElement();
+                        break loop;
+                    case Node.DOCUMENT_NODE:
+                        handler.completed();
+                        state = COMPLETE;
+                        break loop;
+                }
+            } else {
+                switch (nodeType) {
+                    case Node.DOCUMENT_NODE:
+                        if (currentNode != null) {
+                            Document document = (Document)currentNode;
+                            if (dom3) {
+                                handler.startDocument(document.getInputEncoding(), document.getXmlVersion(), document.getXmlEncoding(), document.getXmlStandalone());
+                            } else {
+                                handler.startDocument(null, "1.0", null, true);
+                            }
+                        } else {
+                            handler.startFragment();
+                        }
+                        break;
+                    case Node.DOCUMENT_TYPE_NODE:
+                        DocumentType docType = (DocumentType)currentNode;
+                        handler.processDocumentTypeDeclaration(docType.getName(), docType.getPublicId(), docType.getSystemId(), docType.getInternalSubset());
+                        break loop;
+                    case Node.ELEMENT_NODE:
+                        Element element = (Element)currentNode;
+                        String localName = element.getLocalName();
+                        if (localName == null) {
+                            // TODO
+                            throw new UnsupportedOperationException();
+                        } else {
+                            handler.startElement(nullToEmptyString(element.getNamespaceURI()), localName, nullToEmptyString(element.getPrefix()));
+                        }
+                        NamedNodeMap attributes = element.getAttributes();
+                        // TODO: we should not push all attributes at once
+                        for (int length=attributes.getLength(), i=0; i<length; i++) {
+                            Attr attr = (Attr)attributes.item(i);
+                            String attrLocalName = attr.getLocalName();
+                            if (attrLocalName == null) {
+                                // TODO
+                                throw new UnsupportedOperationException();
+                            } else {
+                                String namespaceURI = attr.getNamespaceURI();
+                                if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI)) {
+                                    handler.processNamespaceDeclaration(attrLocalName.equals(XMLConstants.XMLNS_ATTRIBUTE) ? "" : attrLocalName, attr.getValue());
+                                } else {
+                                    handler.processAttribute(nullToEmptyString(namespaceURI), attrLocalName, nullToEmptyString(attr.getPrefix()), attr.getValue(), "CDATA", attr.getSpecified());
+                                }
+                            }
+                        }
+                        handler.attributesCompleted();
+                        break loop;
+                    case Node.TEXT_NODE:
+                        handler.processCharacterData(currentNode.getNodeValue(), dom3 && ((Text)currentNode).isElementContentWhitespace());
+                        break loop;
+                    case Node.CDATA_SECTION_NODE:
+                        handler.startCDATASection();
+                        handler.processCharacterData(currentNode.getNodeValue(), false);
+                        handler.endCDATASection();
+                        break loop;
+                    case Node.COMMENT_NODE:
+                        handler.startComment();
+                        handler.processCharacterData(currentNode.getNodeValue(), false);
+                        handler.endComment();
+                        break loop;
+                    case Node.PROCESSING_INSTRUCTION_NODE:
+                        ProcessingInstruction pi = (ProcessingInstruction)currentNode;
+                        handler.startProcessingInstruction(pi.getTarget());
+                        handler.processCharacterData(pi.getData(), false);
+                        handler.endProcessingInstruction();
+                        break loop;
+                    case Node.ENTITY_REFERENCE_NODE:
+                        if (!expandEntityReferences) {
+                            handler.processEntityReference(currentNode.getNodeName(), null);
+                            state = VISITED;
+                            break loop;
+                        } else {
+                            // No event has been generated, so loop again
+                            break;
+                        }
+                    default:
+                        // TODO
+                        throw new UnsupportedOperationException("Unsupported node type " + nodeType);
+                }
+            }
+        }
+        this.currentNode = currentNode;
+        this.state = state;
+        return state == COMPLETE;
+    }
+
+    @Override
+    public void dispose() {
+    }
+}

Propchange: webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/stream/dom/DOMReader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/factory/AbstractOMMetaFactory.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/factory/AbstractOMMetaFactory.java?rev=1738366&r1=1738365&r2=1738366&view=diff
==============================================================================
--- webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/factory/AbstractOMMetaFactory.java (original)
+++ webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/factory/AbstractOMMetaFactory.java Sat Apr  9 17:12:01 2016
@@ -40,6 +40,7 @@ import org.apache.axiom.core.impl.builde
 import org.apache.axiom.core.impl.builder.PlainXMLModel;
 import org.apache.axiom.core.stream.FilteredXmlInput;
 import org.apache.axiom.core.stream.XmlInput;
+import org.apache.axiom.core.stream.dom.DOMInput;
 import org.apache.axiom.core.stream.sax.SAXInput;
 import org.apache.axiom.om.OMException;
 import org.apache.axiom.om.OMFactory;
@@ -248,7 +249,7 @@ public abstract class AbstractOMMetaFact
     public OMXMLParserWrapper createOMBuilder(OMFactory omFactory, Node node,
             boolean expandEntityReferences) {
         return createOMBuilder(
-                new StAXPullInput(new DOMXMLStreamReader(node, expandEntityReferences), true, null),
+                new DOMInput(node, expandEntityReferences),
                 nodeFactory, PlainXMLModel.INSTANCE, null, true, null);
     }
 
@@ -283,7 +284,7 @@ public abstract class AbstractOMMetaFact
             // TODO: supporting this will require some refactoring of the builders
             throw new UnsupportedOperationException();
         } else if (source instanceof DOMSource) {
-            return createSOAPModelBuilder(new StAXPullInput(new DOMXMLStreamReader(((DOMSource)source).getNode(), true), true, null), nodeFactory, true, null);
+            return createSOAPModelBuilder(new DOMInput(((DOMSource)source).getNode(), true), nodeFactory, true, null);
         } else if (source instanceof StreamSource) {
             return createSOAPModelBuilder(StAXParserConfiguration.SOAP,
                     toInputSource((StreamSource)source));