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/02/27 00:47:46 UTC

svn commit: r1732585 - in /webservices/axiom/trunk/aspects: core-aspects/src/main/java/org/apache/axiom/core/ om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/ om-aspects/src/main/java/org/apache/axiom/om/impl/mixin/

Author: veithen
Date: Fri Feb 26 23:47:46 2016
New Revision: 1732585

URL: http://svn.apache.org/viewvc?rev=1732585&view=rev
Log:
Use a smarter way to implement serializeAndConsume.

Modified:
    webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/InputContext.java
    webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/BuilderHandler.java
    webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/Context.java
    webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/mixin/AxiomContainerSupport.aj

Modified: webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/InputContext.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/InputContext.java?rev=1732585&r1=1732584&r2=1732585&view=diff
==============================================================================
--- webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/InputContext.java (original)
+++ webservices/axiom/trunk/aspects/core-aspects/src/main/java/org/apache/axiom/core/InputContext.java Fri Feb 26 23:47:46 2016
@@ -18,6 +18,20 @@
  */
 package org.apache.axiom.core;
 
+import org.apache.axiom.core.stream.XmlHandler;
+
 public interface InputContext {
     Builder getBuilder();
+
+    /**
+     * Enables pass-through mode for this context. In this mode, events for the parent information
+     * item linked to this context (and its descendants) are passed directly to the specified
+     * handler instead of building nodes for them.
+     * 
+     * @param handler
+     *            the handler to send events to
+     * @throws IllegalStateException
+     *             if a pass-through handler has already been set for this context
+     */
+    void setPassThroughHandler(XmlHandler passThroughHandler);
 }

Modified: webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/BuilderHandler.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/BuilderHandler.java?rev=1732585&r1=1732584&r2=1732585&view=diff
==============================================================================
--- webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/BuilderHandler.java (original)
+++ webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/BuilderHandler.java Fri Feb 26 23:47:46 2016
@@ -30,6 +30,7 @@ import org.apache.axiom.core.Builder;
 import org.apache.axiom.core.CoreNode;
 import org.apache.axiom.core.CoreParentNode;
 import org.apache.axiom.core.NodeFactory;
+import org.apache.axiom.core.stream.StreamException;
 import org.apache.axiom.core.stream.XmlHandler;
 import org.apache.axiom.om.impl.intf.AxiomDocument;
 import org.apache.axiom.om.impl.intf.AxiomSourcedElement;
@@ -131,58 +132,58 @@ public final class BuilderHandler implem
     }
     
     public void processDocumentTypeDeclaration(String rootName, String publicId, String systemId,
-            String internalSubset) {
+            String internalSubset) throws StreamException {
         model.validateEventType(XMLStreamConstants.DTD);
         context.processDocumentTypeDeclaration(rootName, publicId, systemId, internalSubset);
     }
     
-    public void startElement(String namespaceURI, String localName, String prefix) {
+    public void startElement(String namespaceURI, String localName, String prefix) throws StreamException {
         depth++;
         context = context.startElement(namespaceURI, localName, prefix);
     }
     
-    public void endElement() {
+    public void endElement() throws StreamException {
         context = context.endElement();
         depth--;
     }
 
-    public void processAttribute(String namespaceURI, String localName, String prefix, String value, String type, boolean specified) {
+    public void processAttribute(String namespaceURI, String localName, String prefix, String value, String type, boolean specified) throws StreamException {
         context.processAttribute(namespaceURI, localName, prefix, value, type, specified);
     }
     
-    public void processNamespaceDeclaration(String prefix, String namespaceURI) {
+    public void processNamespaceDeclaration(String prefix, String namespaceURI) throws StreamException {
         context.processNamespaceDeclaration(prefix, namespaceURI);
     }
     
-    public void attributesCompleted() {
+    public void attributesCompleted() throws StreamException {
         context.attributesCompleted();
     }
     
-    public void processCharacterData(Object data, boolean ignorable) {
+    public void processCharacterData(Object data, boolean ignorable) throws StreamException {
         context.processCharacterData(data, ignorable);
     }
     
-    public void processProcessingInstruction(String piTarget, String piData) {
+    public void processProcessingInstruction(String piTarget, String piData) throws StreamException {
         model.validateEventType(XMLStreamConstants.PROCESSING_INSTRUCTION);
         context.processProcessingInstruction(piTarget, piData);
     }
 
-    public void processComment(String content) {
+    public void processComment(String content) throws StreamException {
         model.validateEventType(XMLStreamConstants.COMMENT);
         context.processComment(content);
     }
     
-    public void processCDATASection(String content) {
+    public void processCDATASection(String content) throws StreamException {
         model.validateEventType(XMLStreamConstants.CDATA);
         context.processCDATASection(content);
     }
     
-    public void processEntityReference(String name, String replacementText) {
+    public void processEntityReference(String name, String replacementText) throws StreamException {
         model.validateEventType(XMLStreamConstants.ENTITY_REFERENCE);
         context.processEntityReference(name, replacementText);
     }
     
-    public void endDocument() {
+    public void endDocument() throws StreamException {
         if (depth != 0) {
             throw new IllegalStateException();
         }

Modified: webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/Context.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/Context.java?rev=1732585&r1=1732584&r2=1732585&view=diff
==============================================================================
--- webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/Context.java (original)
+++ webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/Context.java Fri Feb 26 23:47:46 2016
@@ -22,6 +22,8 @@ import org.apache.axiom.core.Builder;
 import org.apache.axiom.core.CoreCharacterDataNode;
 import org.apache.axiom.core.CoreParentNode;
 import org.apache.axiom.core.InputContext;
+import org.apache.axiom.core.stream.StreamException;
+import org.apache.axiom.core.stream.XmlHandler;
 import org.apache.axiom.om.OMNamespace;
 import org.apache.axiom.om.impl.common.AxiomSemantics;
 import org.apache.axiom.om.impl.common.OMNamespaceImpl;
@@ -49,6 +51,17 @@ public final class Context implements In
     
     private Object pendingCharacterData;
     
+    /**
+     * The {@link XmlHandler} object to send events to if pass-through is enabled. See
+     * {@link InputContext#setPassThroughHandler(XmlHandler)} for more details.
+     */
+    private XmlHandler passThroughHandler;
+    
+    /**
+     * Tracks the nesting depth when pass-through is enabled.
+     */
+    private int passThroughDepth;
+
     public Context(BuilderHandler builderHandler, Context parentContext, int depth) {
         this.builderHandler = builderHandler;
         this.parentContext = parentContext;
@@ -60,14 +73,36 @@ public final class Context implements In
         return builderHandler.builder;
     }
 
+    public void setPassThroughHandler(XmlHandler passThroughHandler) {
+        if (this.passThroughHandler != null) {
+            throw new IllegalStateException("A pass-through handler has already been set for this context");
+        }
+        target.coreSetState(CoreParentNode.DISCARDED);
+        this.passThroughHandler = passThroughHandler;
+    }
+    
     private Context newContext(AxiomContainer target) {
         if (nestedContext == null) {
             nestedContext = new Context(builderHandler, this, depth+1);
         }
         nestedContext.target = target;
+        target.coreSetInputContext(nestedContext);
         return nestedContext;
     }
     
+    private Context decrementPassThroughDepth() {
+        if (passThroughDepth == 0) {
+            target.coreSetInputContext(null);
+            target.coreSetState(CoreParentNode.DISCARDED);
+            passThroughHandler = null;
+            target = null;
+            return parentContext;
+        } else {
+            passThroughDepth--;
+            return this;
+        }
+    }
+    
     private void addChild(AxiomChildNode node) {
         if (pendingCharacterData != null) {
             AxiomCharacterDataNode cdataNode = builderHandler.nodeFactory.createNode(AxiomCharacterDataNode.class);
@@ -82,73 +117,104 @@ public final class Context implements In
     }
     
     public void processDocumentTypeDeclaration(String rootName, String publicId, String systemId,
-            String internalSubset) {
-        AxiomDocType node = builderHandler.nodeFactory.createNode(AxiomDocType.class);
-        node.coreSetRootName(rootName);
-        node.coreSetPublicId(publicId);
-        node.coreSetSystemId(systemId);
-        node.coreSetInternalSubset(internalSubset);
-        addChild(node);
-    }
-    
-    public Context startElement(String namespaceURI, String localName, String prefix) {
-        AxiomElement element;
-        OMNamespace ns = builderHandler.nsCache.getOMNamespace(namespaceURI, prefix);
-        if (depth == 0 && builderHandler.root != null) {
-            builderHandler.root.validateName(prefix, localName, namespaceURI);
-            builderHandler.root.initName(localName, ns, false);
-            builderHandler.root.coreSetInputContext(this);
-            builderHandler.root.coreSetState(CoreParentNode.ATTRIBUTES_PENDING);
-            element = builderHandler.root;
-        } else {
-            element = builderHandler.nodeFactory.createNode(builderHandler.model.determineElementType(
-                    target, depth+1, namespaceURI, localName));
-            element.coreSetInputContext(this);
-            element.coreSetState(CoreParentNode.ATTRIBUTES_PENDING);
-            element.initName(localName, ns, false);
-            addChild(element);
-        }
-        return newContext(element);
-    }
-    
-    public Context endElement() {
-        target.setComplete(true);
-        target.coreSetInputContext(null);
-        if (pendingCharacterData != null) {
-            target.coreSetCharacterData(pendingCharacterData, null);
-            pendingCharacterData = null;
+            String internalSubset) throws StreamException {
+        if (passThroughHandler != null) {
+            passThroughHandler.processDocumentTypeDeclaration(rootName, publicId, systemId, internalSubset);
+        } else {
+            AxiomDocType node = builderHandler.nodeFactory.createNode(AxiomDocType.class);
+            node.coreSetRootName(rootName);
+            node.coreSetPublicId(publicId);
+            node.coreSetSystemId(systemId);
+            node.coreSetInternalSubset(internalSubset);
+            addChild(node);
+        }
+    }
+    
+    public Context startElement(String namespaceURI, String localName, String prefix) throws StreamException {
+        if (passThroughHandler != null) {
+            passThroughDepth++;
+            passThroughHandler.startElement(namespaceURI, localName, prefix);
+            return this;
+        } else {
+            AxiomElement element;
+            OMNamespace ns = builderHandler.nsCache.getOMNamespace(namespaceURI, prefix);
+            if (depth == 0 && builderHandler.root != null) {
+                builderHandler.root.validateName(prefix, localName, namespaceURI);
+                builderHandler.root.initName(localName, ns, false);
+                builderHandler.root.coreSetInputContext(this);
+                builderHandler.root.coreSetState(CoreParentNode.ATTRIBUTES_PENDING);
+                element = builderHandler.root;
+            } else {
+                element = builderHandler.nodeFactory.createNode(builderHandler.model.determineElementType(
+                        target, depth+1, namespaceURI, localName));
+                element.coreSetState(CoreParentNode.ATTRIBUTES_PENDING);
+                element.initName(localName, ns, false);
+                addChild(element);
+            }
+            return newContext(element);
+        }
+    }
+    
+    public Context endElement() throws StreamException {
+        if (passThroughHandler != null) {
+            // TODO: hack
+            if (passThroughDepth > 0) {
+                passThroughHandler.endElement();
+            }
+            return decrementPassThroughDepth();
+        } else {
+            target.setComplete(true);
+            target.coreSetInputContext(null);
+            if (pendingCharacterData != null) {
+                target.coreSetCharacterData(pendingCharacterData, null);
+                pendingCharacterData = null;
+            }
+            target = null;
+            return parentContext;
         }
-        target = null;
-        return parentContext;
     }
 
-    public void processAttribute(String namespaceURI, String localName, String prefix, String value, String type, boolean specified) {
-        OMNamespace ns = builderHandler.nsCache.getOMNamespace(namespaceURI, prefix);
-        AxiomAttribute attr = builderHandler.nodeFactory.createNode(AxiomAttribute.class);
-        attr.internalSetLocalName(localName);
-        attr.coreSetCharacterData(value, AxiomSemantics.INSTANCE);
-        attr.internalSetNamespace(ns);
-        attr.coreSetType(type);
-        attr.coreSetSpecified(specified);
-        ((AxiomElement)target).coreAppendAttribute(attr);
+    public void processAttribute(String namespaceURI, String localName, String prefix, String value, String type, boolean specified) throws StreamException {
+        if (passThroughHandler != null) {
+            passThroughHandler.processAttribute(namespaceURI, localName, prefix, value, type, specified);
+        } else {
+            OMNamespace ns = builderHandler.nsCache.getOMNamespace(namespaceURI, prefix);
+            AxiomAttribute attr = builderHandler.nodeFactory.createNode(AxiomAttribute.class);
+            attr.internalSetLocalName(localName);
+            attr.coreSetCharacterData(value, AxiomSemantics.INSTANCE);
+            attr.internalSetNamespace(ns);
+            attr.coreSetType(type);
+            attr.coreSetSpecified(specified);
+            ((AxiomElement)target).coreAppendAttribute(attr);
+        }
     }
     
-    public void processNamespaceDeclaration(String prefix, String namespaceURI) {
-        OMNamespace ns = builderHandler.nsCache.getOMNamespace(namespaceURI, prefix);
-        if (ns == null) {
-            ns = DEFAULT_NS;
+    public void processNamespaceDeclaration(String prefix, String namespaceURI) throws StreamException {
+        if (passThroughHandler != null) {
+            passThroughHandler.processNamespaceDeclaration(prefix, namespaceURI);
+        } else {
+            OMNamespace ns = builderHandler.nsCache.getOMNamespace(namespaceURI, prefix);
+            if (ns == null) {
+                ns = DEFAULT_NS;
+            }
+            AxiomNamespaceDeclaration decl = builderHandler.nodeFactory.createNode(AxiomNamespaceDeclaration.class);
+            decl.setDeclaredNamespace(ns);
+            ((AxiomElement)target).coreAppendAttribute(decl);
         }
-        AxiomNamespaceDeclaration decl = builderHandler.nodeFactory.createNode(AxiomNamespaceDeclaration.class);
-        decl.setDeclaredNamespace(ns);
-        ((AxiomElement)target).coreAppendAttribute(decl);
     }
     
-    public void attributesCompleted() {
-        target.coreSetState(CoreParentNode.INCOMPLETE);
+    public void attributesCompleted() throws StreamException {
+        if (passThroughHandler != null) {
+            passThroughHandler.attributesCompleted();
+        } else {
+            target.coreSetState(CoreParentNode.INCOMPLETE);
+        }
     }
     
-    public void processCharacterData(Object data, boolean ignorable) {
-        if (!ignorable && pendingCharacterData == null && target.coreGetFirstChildIfAvailable() == null) {
+    public void processCharacterData(Object data, boolean ignorable) throws StreamException {
+        if (passThroughHandler != null) {
+            passThroughHandler.processCharacterData(data, ignorable);
+        } else if (!ignorable && pendingCharacterData == null && target.coreGetFirstChildIfAvailable() == null) {
             pendingCharacterData = data;
         } else {
             AxiomCharacterDataNode node = builderHandler.nodeFactory.createNode(AxiomCharacterDataNode.class);
@@ -158,40 +224,64 @@ public final class Context implements In
         }
     }
     
-    public void processProcessingInstruction(String piTarget, String piData) {
-        AxiomProcessingInstruction node = builderHandler.nodeFactory.createNode(AxiomProcessingInstruction.class);
-        node.coreSetTarget(piTarget);
-        node.coreSetCharacterData(piData, AxiomSemantics.INSTANCE);
-        addChild(node);
+    public void processProcessingInstruction(String piTarget, String piData) throws StreamException {
+        if (passThroughHandler != null) {
+            passThroughHandler.processProcessingInstruction(piTarget, piData);
+        } else {
+            AxiomProcessingInstruction node = builderHandler.nodeFactory.createNode(AxiomProcessingInstruction.class);
+            node.coreSetTarget(piTarget);
+            node.coreSetCharacterData(piData, AxiomSemantics.INSTANCE);
+            addChild(node);
+        }
     }
 
-    public void processComment(String content) {
-        AxiomComment node = builderHandler.nodeFactory.createNode(AxiomComment.class);
-        node.coreSetCharacterData(content, AxiomSemantics.INSTANCE);
-        addChild(node);
+    public void processComment(String content) throws StreamException {
+        if (passThroughHandler != null) {
+            passThroughHandler.processComment(content);
+        } else {
+            AxiomComment node = builderHandler.nodeFactory.createNode(AxiomComment.class);
+            node.coreSetCharacterData(content, AxiomSemantics.INSTANCE);
+            addChild(node);
+        }
     }
     
-    public void processCDATASection(String content) {
-        AxiomCDATASection node = builderHandler.nodeFactory.createNode(AxiomCDATASection.class);
-        node.coreSetCharacterData(content, AxiomSemantics.INSTANCE);
-        addChild(node);
+    public void processCDATASection(String content) throws StreamException {
+        if (passThroughHandler != null) {
+            passThroughHandler.processCDATASection(content);
+        } else {
+            AxiomCDATASection node = builderHandler.nodeFactory.createNode(AxiomCDATASection.class);
+            node.coreSetCharacterData(content, AxiomSemantics.INSTANCE);
+            addChild(node);
+        }
     }
     
-    public void processEntityReference(String name, String replacementText) {
-        AxiomEntityReference node = builderHandler.nodeFactory.createNode(AxiomEntityReference.class);
-        node.coreSetName(name);
-        node.coreSetReplacementText(replacementText);
-        addChild(node);
+    public void processEntityReference(String name, String replacementText) throws StreamException {
+        if (passThroughHandler != null) {
+            passThroughHandler.processEntityReference(name, replacementText);
+        } else {
+            AxiomEntityReference node = builderHandler.nodeFactory.createNode(AxiomEntityReference.class);
+            node.coreSetName(name);
+            node.coreSetReplacementText(replacementText);
+            addChild(node);
+        }
     }
     
-    public void endDocument() {
-        if (depth != 0) {
-            throw new IllegalStateException();
-        }
-        if (target != null) {
-            target.setComplete(true);
-            target.coreSetInputContext(null);
+    public void endDocument() throws StreamException {
+        if (passThroughHandler != null) {
+            // TODO: hack
+            if (passThroughDepth > 0) {
+                passThroughHandler.endDocument();
+            }
+            decrementPassThroughDepth();
+        } else {
+            if (depth != 0) {
+                throw new IllegalStateException();
+            }
+            if (target != null) {
+                target.setComplete(true);
+                target.coreSetInputContext(null);
+            }
+            target = null;
         }
-        target = null;
     }
 }

Modified: webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/mixin/AxiomContainerSupport.aj
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/mixin/AxiomContainerSupport.aj?rev=1732585&r1=1732584&r2=1732585&view=diff
==============================================================================
--- webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/mixin/AxiomContainerSupport.aj (original)
+++ webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/mixin/AxiomContainerSupport.aj Fri Feb 26 23:47:46 2016
@@ -36,6 +36,7 @@ import org.apache.axiom.core.CoreModelEx
 import org.apache.axiom.core.CoreNSAwareElement;
 import org.apache.axiom.core.CoreNode;
 import org.apache.axiom.core.ElementMatcher;
+import org.apache.axiom.core.InputContext;
 import org.apache.axiom.core.Mapper;
 import org.apache.axiom.core.stream.NamespaceRepairingFilterHandler;
 import org.apache.axiom.core.stream.StreamException;
@@ -58,7 +59,6 @@ import org.apache.axiom.om.impl.common.A
 import org.apache.axiom.om.impl.common.NamespaceURIInterningXMLStreamReaderWrapper;
 import org.apache.axiom.om.impl.common.OMChildrenQNameIterator;
 import org.apache.axiom.om.impl.common.SAXResultContentHandler;
-import org.apache.axiom.om.impl.common.builder.StAXHelper;
 import org.apache.axiom.om.impl.common.serializer.pull.OMXMLStreamReaderExAdapter;
 import org.apache.axiom.om.impl.common.serializer.pull.PullSerializer;
 import org.apache.axiom.om.impl.common.serializer.push.XmlDeclarationRewriterHandler;
@@ -372,44 +372,13 @@ public aspect AxiomContainerSupport {
                 child.internalSerialize(handler, cache);
                 child = (AxiomChildNode)child.coreGetNextSiblingIfAvailable();
             }
-            // Next, if the container is incomplete, disable caching (temporarily)
-            // and serialize the nodes that have not been built yet by copying the
-            // events from the underlying XMLStreamReader.
-            if (!isComplete() && coreGetBuilder() != null) {
-                Builder builder = coreGetBuilder();
-                XMLStreamReader reader = builder.disableCaching();
-                // The reader is null in the very special case where this is an OMDocument and
-                // the current event is END_DOCUMENT (which means that auto-close is triggered
-                // and the parser is released, resulting in a null value).
-                if (reader != null) {
-                    StAXHelper helper = new StAXHelper(reader, handler);
-                    int depth = 0;
-                    loop: while (true) {
-                        switch (helper.lookahead()) {
-                            case XMLStreamReader.START_ELEMENT:
-                                depth++;
-                                break;
-                            case XMLStreamReader.END_ELEMENT:
-                                if (depth == 0) {
-                                    break loop;
-                                } else {
-                                    depth--;
-                                }
-                                break;
-                            case XMLStreamReader.END_DOCUMENT:
-                                if (depth != 0) {
-                                    // If we get here, then we have seen a START_ELEMENT event without
-                                    // a matching END_ELEMENT
-                                    throw new IllegalStateException();
-                                }
-                                break loop;
-                        }
-                        // Note that we don't copy the final END_ELEMENT/END_DOCUMENT event for
-                        // the container. This is the responsibility of the caller.
-                        helper.next();
-                    }
-                }
-                builder.reenableCaching(this);
+            InputContext context = coreGetInputContext();
+            if (context != null) {
+                context.setPassThroughHandler(handler);
+                Builder builder = context.getBuilder();
+                do {
+                    builder.next();
+                } while (coreGetInputContext() != null);
             }
         }
     }