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/03/09 22:26:09 UTC

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

Author: veithen
Date: Wed Mar  9 21:26:09 2016
New Revision: 1734317

URL: http://svn.apache.org/viewvc?rev=1734317&view=rev
Log:
Use a different approach to implement AXIOM-282: instead of using lookahead, allow newly registered custom builders to be applied to the last created node. Since we don't allow direct access to the underlying parser anymore, this approach basically has the same effect but allows to simplify the design of the builder.

Modified:
    webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/CustomBuilderManager.java
    webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/StAXHelper.java
    webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/StAXOMBuilder.java
    webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/soap/impl/mixin/AxiomSOAPBodySupport.aj

Modified: webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/CustomBuilderManager.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/CustomBuilderManager.java?rev=1734317&r1=1734316&r2=1734317&view=diff
==============================================================================
--- webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/CustomBuilderManager.java (original)
+++ webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/CustomBuilderManager.java Wed Mar  9 21:26:09 2016
@@ -41,64 +41,92 @@ import org.apache.commons.logging.LogFac
 final class CustomBuilderManager implements BuilderListener {
     private static final Log log = LogFactory.getLog(CustomBuilderManager.class);
     
-    private final ArrayList<CustomBuilderRegistration> registrations = new ArrayList<CustomBuilderRegistration>();
+    private ArrayList<CustomBuilderRegistration> registrations;
+    private AxiomElement lastCandidateElement;
+    private int lastCandidateDepth = -1;
     
     void register(CustomBuilder.Selector selector, CustomBuilder customBuilder) {
+        if (registrations == null) {
+            registrations = new ArrayList<CustomBuilderRegistration>();
+        }
         registrations.add(new CustomBuilderRegistration(selector, customBuilder));
+        // Try to apply the new custom builder to the element currently being built (unless it has
+        // already been processed by another custom builder). This is important for custom builders
+        // used to process the payload of a SOAP message: by the time the custom builder is
+        // registered the payload root element may already have been created (e.g. because code
+        // executed before the custom builder registration may have checked if the payload is a
+        // SOAP fault).
+        if (lastCandidateElement != null) {
+            Runnable action = getAction(lastCandidateElement, lastCandidateDepth, registrations.size()-1);
+            if (action != null) {
+                action.run();
+            }
+        }
     }
     
     @Override
     public Runnable nodeAdded(CoreNode node, int depth) {
+        return getAction(node, depth, 0);
+    }
+    
+    private Runnable getAction(CoreNode node, int depth, int firstCustomBuilder) {
+        lastCandidateElement = null;
+        lastCandidateDepth = -1;
         if (node instanceof AxiomElement && (node instanceof AxiomSOAPHeaderBlock || !(node instanceof AxiomSOAPElement))) {
             final AxiomElement element = (AxiomElement)node;
-            for (int i=0; i<registrations.size(); i++) {
-                CustomBuilderRegistration registration = registrations.get(i);
-                final String namespaceURI = element.coreGetNamespaceURI();
-                final String localName = element.coreGetLocalName();
-                if (registration.getSelector().accepts(element.getParent(), depth, namespaceURI, localName)) {
-                    final CustomBuilder customBuilder = registration.getCustomBuilder();
-                    if (log.isDebugEnabled()) {
-                        log.debug("Custom builder " + customBuilder + " accepted element {" + namespaceURI + "}" + localName + " at depth " + depth);
-                    }
-                    return new Runnable() {
-                        @Override
-                        public void run() {
-                            if (log.isDebugEnabled()) {
-                                log.debug("Invoking custom builder " + customBuilder);
-                            }
-                            XMLStreamReader reader = element.getXMLStreamReader(false);
-                            // Advance the reader to the START_ELEMENT event of the root element
-                            try {
-                                reader.next();
-                            } catch (XMLStreamException ex) {
-                                // We should never get here
-                                throw new OMException(ex);
-                            }
-                            OMDataSource dataSource = customBuilder.create(reader);
-                            try {
-                                reader.close();
-                            } catch (XMLStreamException ex) {
-                                // We should never get here
-                                throw new OMException(ex);
-                            }
-                            Class<? extends AxiomSourcedElement> type;
-                            if (element instanceof AxiomSOAP11HeaderBlock) {
-                                type = AxiomSOAP11HeaderBlock.class;
-                            } else if (element instanceof AxiomSOAP12HeaderBlock) {
-                                type = AxiomSOAP12HeaderBlock.class;
-                            } else {
-                                type = AxiomSourcedElement.class;
-                            }
-                            if (log.isDebugEnabled()) {
-                                log.debug("Replacing element with new sourced element of type " + type);
-                            }
-                            AxiomSourcedElement newElement = element.coreCreateNode(type);
-                            newElement.init(localName, new OMNamespaceImpl(namespaceURI, null), dataSource);
-                            element.coreReplaceWith(newElement, AxiomSemantics.INSTANCE);
+            if (registrations != null) {
+                for (int i=firstCustomBuilder; i<registrations.size(); i++) {
+                    CustomBuilderRegistration registration = registrations.get(i);
+                    final String namespaceURI = element.coreGetNamespaceURI();
+                    final String localName = element.coreGetLocalName();
+                    if (registration.getSelector().accepts(element.getParent(), depth, namespaceURI, localName)) {
+                        final CustomBuilder customBuilder = registration.getCustomBuilder();
+                        if (log.isDebugEnabled()) {
+                            log.debug("Custom builder " + customBuilder + " accepted element {" + namespaceURI + "}" + localName + " at depth " + depth);
                         }
-                    };
+                        return new Runnable() {
+                            @Override
+                            public void run() {
+                                if (log.isDebugEnabled()) {
+                                    log.debug("Invoking custom builder " + customBuilder);
+                                }
+                                XMLStreamReader reader = element.getXMLStreamReader(false);
+                                // Advance the reader to the START_ELEMENT event of the root element
+                                try {
+                                    reader.next();
+                                } catch (XMLStreamException ex) {
+                                    // We should never get here
+                                    throw new OMException(ex);
+                                }
+                                OMDataSource dataSource = customBuilder.create(reader);
+                                try {
+                                    reader.close();
+                                } catch (XMLStreamException ex) {
+                                    // We should never get here
+                                    throw new OMException(ex);
+                                }
+                                Class<? extends AxiomSourcedElement> type;
+                                if (element instanceof AxiomSOAP11HeaderBlock) {
+                                    type = AxiomSOAP11HeaderBlock.class;
+                                } else if (element instanceof AxiomSOAP12HeaderBlock) {
+                                    type = AxiomSOAP12HeaderBlock.class;
+                                } else {
+                                    type = AxiomSourcedElement.class;
+                                }
+                                if (log.isDebugEnabled()) {
+                                    log.debug("Replacing element with new sourced element of type " + type);
+                                }
+                                AxiomSourcedElement newElement = element.coreCreateNode(type);
+                                newElement.init(localName, new OMNamespaceImpl(namespaceURI, null), dataSource);
+                                element.coreReplaceWith(newElement, AxiomSemantics.INSTANCE);
+                            }
+                        };
+                    }
                 }
             }
+            // Save a reference to the element so that we can process it when another custom builder is registered
+            lastCandidateElement = element;
+            lastCandidateDepth = depth;
         }
         return null;
     }

Modified: webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/StAXHelper.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/StAXHelper.java?rev=1734317&r1=1734316&r2=1734317&view=diff
==============================================================================
--- webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/StAXHelper.java (original)
+++ webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/StAXHelper.java Wed Mar  9 21:26:09 2016
@@ -27,7 +27,6 @@ import org.apache.axiom.ext.stax.datahan
 import org.apache.axiom.om.DeferredParsingException;
 import org.apache.axiom.om.OMException;
 import org.apache.axiom.om.impl.intf.TextContent;
-import org.apache.axiom.util.stax.XMLEventUtils;
 import org.apache.axiom.util.stax.XMLStreamReaderUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -72,7 +71,7 @@ public class StAXHelper implements XmlRe
     private static final Log log = LogFactory.getLog(StAXHelper.class);
     
     /** Field parser */
-    public XMLStreamReader parser;
+    private XMLStreamReader parser;
 
     private final XmlHandler handler;
     private final Closeable closeable;
@@ -97,7 +96,7 @@ public class StAXHelper implements XmlRe
      */
     private Exception parserException;
     
-    private int lookAheadToken;
+    private boolean start = true;
     
     public StAXHelper(XMLStreamReader parser, XmlHandler handler,
             Closeable closeable, boolean autoClose) {
@@ -106,7 +105,6 @@ public class StAXHelper implements XmlRe
         this.closeable = closeable;
         this.autoClose = autoClose;
         dataHandlerReader = XMLStreamReaderUtils.getDataHandlerReader(parser);
-        lookAheadToken = parser.getEventType();
     }
     
     public StAXHelper(XMLStreamReader parser, XmlHandler handler) {
@@ -342,13 +340,9 @@ public class StAXHelper implements XmlRe
      * @throws DeferredParsingException
      */
     public int parserNext() {
-        if (lookAheadToken >= 0) {
-            if (log.isDebugEnabled()) {
-                log.debug("Consuming look-ahead token " + XMLEventUtils.getEventTypeString(lookAheadToken));
-            }
-            int token = lookAheadToken;
-            lookAheadToken = -1; // Reset
-            return token;
+        if (start) {
+            start = false;
+            return parser.getEventType();
         } else {
             try {
                 if (parserException != null) {
@@ -377,22 +371,6 @@ public class StAXHelper implements XmlRe
         }
     }
     
-    /**
-     * Look ahead to the next event. This method advanced the parser to the next event, but defers
-     * creation of the corresponding node to the next call of {@link #next()}.
-     * 
-     * @return The type of the next event. If the return value is
-     *         {@link XMLStreamConstants#START_ELEMENT START_ELEMENT}, then the information related
-     *         to that element can be obtained by calls to {@link #getLocalName()},
-     *         {@link #getNamespaceURI()} and {@link #getPrefix()}.
-     */
-    public final int lookahead() {
-        if (lookAheadToken < 0) {
-            lookAheadToken = parserNext();
-        }
-        return lookAheadToken;
-    }
-
     @Override
     public void dispose() {
         close();

Modified: webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/StAXOMBuilder.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/StAXOMBuilder.java?rev=1734317&r1=1734316&r2=1734317&view=diff
==============================================================================
--- webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/StAXOMBuilder.java (original)
+++ webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/om/impl/common/builder/StAXOMBuilder.java Wed Mar  9 21:26:09 2016
@@ -41,7 +41,7 @@ public class StAXOMBuilder extends Abstr
     
     private String charEncoding = null;
     
-    private CustomBuilderManager customBuilderManager;
+    private final CustomBuilderManager customBuilderManager = new CustomBuilderManager();
     
     protected StAXOMBuilder(NodeFactory nodeFactory, XMLStreamReader parser,
             boolean autoClose, Detachable detachable, Closeable closeable, Model model,
@@ -54,6 +54,7 @@ public class StAXOMBuilder extends Abstr
         helper = new StAXHelper(parser, handler, closeable, autoClose);
         this.detachable = detachable;
         charEncoding = parser.getEncoding();
+        builderHandler.addListener(customBuilderManager);
     }
     
     public StAXOMBuilder(NodeFactory nodeFactory, XMLStreamReader parser, boolean autoClose,
@@ -67,24 +68,8 @@ public class StAXOMBuilder extends Abstr
         this(nodeFactory, parser, true, null, null, PlainXMLModel.INSTANCE, element);
     }
     
-    public final String getNamespaceURI() {
-        return helper.parser.getNamespaceURI();
-    }
-
-    public final String getLocalName() {
-        return helper.parser.getLocalName();
-    }
-
-    public final String getPrefix() {
-        return helper.parser.getPrefix();
-    }
-
     @Override
     public void registerCustomBuilder(Selector selector, CustomBuilder customBuilder) {
-        if (customBuilderManager == null) {
-            customBuilderManager = new CustomBuilderManager();
-            builderHandler.addListener(customBuilderManager);
-        }
         customBuilderManager.register(selector, customBuilder);
     }
     
@@ -176,17 +161,4 @@ public class StAXOMBuilder extends Abstr
         }
         return element;
     }
-
-    /**
-     * Look ahead to the next event. This method advanced the parser to the next event, but defers
-     * creation of the corresponding node to the next call of {@link #next()}.
-     * 
-     * @return The type of the next event. If the return value is
-     *         {@link XMLStreamConstants#START_ELEMENT START_ELEMENT}, then the information related
-     *         to that element can be obtained by calls to {@link #getLocalName()},
-     *         {@link #getNamespaceURI()} and {@link #getPrefix()}.
-     */
-    public final int lookahead() {
-        return helper.lookahead();
-    }
 }

Modified: webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/soap/impl/mixin/AxiomSOAPBodySupport.aj
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/soap/impl/mixin/AxiomSOAPBodySupport.aj?rev=1734317&r1=1734316&r2=1734317&view=diff
==============================================================================
--- webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/soap/impl/mixin/AxiomSOAPBodySupport.aj (original)
+++ webservices/axiom/trunk/aspects/om-aspects/src/main/java/org/apache/axiom/soap/impl/mixin/AxiomSOAPBodySupport.aj Wed Mar  9 21:26:09 2016
@@ -18,15 +18,9 @@
  */
 package org.apache.axiom.soap.impl.mixin;
 
-import javax.xml.stream.XMLStreamReader;
-
-import org.apache.axiom.core.CoreChildNode;
-import org.apache.axiom.core.InputContext;
 import org.apache.axiom.om.OMElement;
 import org.apache.axiom.om.OMException;
 import org.apache.axiom.om.OMNamespace;
-import org.apache.axiom.om.impl.common.builder.StAXOMBuilder;
-import org.apache.axiom.soap.SOAPConstants;
 import org.apache.axiom.soap.SOAPFactory;
 import org.apache.axiom.soap.SOAPFault;
 import org.apache.axiom.soap.impl.intf.AxiomSOAPBody;
@@ -41,69 +35,18 @@ public aspect AxiomSOAPBodySupport {
         return ((SOAPFactory)getOMFactory()).createSOAPFault(this, e);
     }
 
-    private boolean AxiomSOAPBody.hasLookahead() {
-        InputContext context = coreGetInputContext();
-        if (context != null) {
-            CoreChildNode child = coreGetFirstChildIfAvailable();
-            while (child != null) {
-                if (child instanceof OMElement) {
-                    return false;
-                }
-                child = child.coreGetNextSiblingIfAvailable();
-            }
-            StAXOMBuilder builder = (StAXOMBuilder)context.getBuilder();
-            do {
-                if (builder.lookahead() == XMLStreamReader.START_ELEMENT) {
-                    return true;
-                }
-                builder.next();
-            } while (coreGetInputContext() != null);
-        }
-        return false;
-    }
-    
     public final boolean AxiomSOAPBody.hasFault() {
-        // Set hasSOAPFault if it matches the name matches a SOAP Fault
-        if (hasLookahead()) {
-            StAXOMBuilder builder = (StAXOMBuilder)coreGetBuilder();
-            return SOAPConstants.SOAPFAULT_LOCAL_NAME.equals(builder.getLocalName())
-                    && getSOAPHelper().getEnvelopeURI().equals(builder.getNamespaceURI());
-        } else {
-            return getFirstElement() instanceof SOAPFault;
-        }
+        return getFirstElement() instanceof SOAPFault;
     }
 
     public final OMNamespace AxiomSOAPBody.getFirstElementNS() {
-        if (hasLookahead()) {
-            StAXOMBuilder builder = (StAXOMBuilder)coreGetBuilder();
-            String ns = builder.getNamespaceURI();
-            if (ns == null) {
-                return null;
-            } else {
-                String prefix = builder.getPrefix();
-                return getOMFactory().createOMNamespace(ns, prefix == null ? "" : prefix);
-            }
-        } else {
-            OMElement element = getFirstElement();
-            if (element == null) {
-                return null;
-            } else {
-                return element.getNamespace();
-            } 
-        }
+        OMElement element = getFirstElement();
+        return element == null ? null : element.getNamespace();
     }
     
     public final String AxiomSOAPBody.getFirstElementLocalName() {
-        if (hasLookahead()) {
-            return ((StAXOMBuilder)coreGetBuilder()).getLocalName();
-        } else {
-            OMElement element = getFirstElement();
-            if (element == null) {
-                return null;
-            } else {
-                return element.getLocalName();
-            } 
-        }
+        OMElement element = getFirstElement();
+        return element == null ? null : element.getLocalName();
     }
 
     public final SOAPFault AxiomSOAPBody.getFault() {