Author: scheu
Date: Tue Feb 26 09:28:29 2008
New Revision: 631309

URL: http://svn.apache.org/viewvc?rev=631309&view=rev
Log:
WSCOMMONS-303
Contributor:Rich Scheuerle
It is necessary to get minimal information about the SOAP payload (the name and 
namespace
of the first element in the SOAP body) without building the OM.
This small change and verification test adds support for "looking ahead" in the 
StAXOMBuilder
to get this information.

This is the first part of a two part change.  The second part of WSCOMMONS-303 
will expose
a property that a parser can use to communicate the qname of the first element 
in the SOAPBody.

Modified:
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXBuilder.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/SOAPBody.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/StAXSOAPModelBuilder.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/soap/impl/dom/SOAPBodyImpl.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/soap/impl/llom/SOAPBodyImpl.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/builder/CustomBuilderTest.java

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXBuilder.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXBuilder.java?rev=631309&r1=631308&r2=631309&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXBuilder.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXBuilder.java
 Tue Feb 26 09:28:29 2008
@@ -416,6 +416,13 @@
         }
         cache = b;
     }
+    
+    /**
+     * @return true if caching
+     */
+    public boolean isCache() {
+        return cache;
+    }
 
     /**
      * Method getName.

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java?rev=631309&r1=631308&r2=631309&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java
 Tue Feb 26 09:28:29 2008
@@ -59,6 +59,8 @@
     // on an OMElement is interned.
     boolean namespaceURIInterning = false;
     
+    int lookAheadToken = -1;
+    
     /**
      * Constructor StAXOMBuilder.
      *
@@ -156,7 +158,7 @@
             if (done) {
                 throw new OMException();
             }
-            int token = parser.next();
+            int token = parserNext();
             if (!cache) {
                 return token;
             }
@@ -487,5 +489,47 @@
      */
     public boolean isNamespaceURIInterning() {
         return this.namespaceURIInterning;
+    }
+    
+    /**
+     * Pushes the virtual parser ahead one token.
+     * If a look ahead token was calculated it is returned.
+     * @return next token
+     * @throws XMLStreamException
+     */
+    private int parserNext() throws XMLStreamException {
+        if (lookAheadToken >= 0) {
+            int token = lookAheadToken;
+            lookAheadToken = -1; // Reset
+            return token;
+        } else {
+            return parser.next();
+        }
+    }
+    
+    /**
+     * This method looks ahead to the next start element.
+     * @return true if successful
+     */
+    public boolean lookahead()  {
+        try {
+            while (true) {
+                if (lookAheadToken < 0) {
+                    lookAheadToken = parserNext();
+                }
+                if (lookAheadToken == XMLStreamConstants.START_ELEMENT) {
+                    return true;
+                } else if (lookAheadToken == XMLStreamConstants.END_ELEMENT ||
+                        lookAheadToken == XMLStreamConstants.START_DOCUMENT ||
+                        lookAheadToken == XMLStreamConstants.END_DOCUMENT) {
+                    next();
+                    return false;  // leaving scope...start element not found
+                } else {
+                    next();  // continue looking past whitespace etc.
+                }
+            }
+        } catch (XMLStreamException e) {
+            throw new OMException(e);
+        }
     }
 }

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/SOAPBody.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/SOAPBody.java?rev=631309&r1=631308&r2=631309&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/SOAPBody.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/SOAPBody.java
 Tue Feb 26 09:28:29 2008
@@ -21,6 +21,7 @@
 
 import org.apache.axiom.om.OMElement;
 import org.apache.axiom.om.OMException;
+import org.apache.axiom.om.OMNamespace;
 
 /**
  * An object that represents the contents of the SOAP body element in a SOAP 
message. B SOAP body
@@ -66,5 +67,23 @@
      */
     void addFault(SOAPFault soapFault) throws OMException;
 
-
+    /**
+     * Retrieves the OMNamespace of the first element in the body.
+     * The implementation might build the OMElement or it may
+     * obtain this information from the builder/parser without building
+     * the OMElement.  Use this method in the situations where you need
+     * to know the OMNamespace, but don't necessarily need the OMElement.
+     * @return OMNamespace of first element in the body or null
+     */
+    public OMNamespace getFirstElementNS();
+    
+    /**
+     * Retrieves the local name of the first element in the body.
+     * The implementation might build the OMElement or it may
+     * obtain this information from the builder/parser without building
+     * the OMElement.  Use this method in the situations where you need
+     * to know the name, but don't necessarily need the OMElement.
+     * @return local name of first element in the body or null
+     */
+    public String getFirstElementLocalName();
 }

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/StAXSOAPModelBuilder.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/StAXSOAPModelBuilder.java?rev=631309&r1=631308&r2=631309&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/StAXSOAPModelBuilder.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/soap/impl/builder/StAXSOAPModelBuilder.java
 Tue Feb 26 09:28:29 2008
@@ -20,7 +20,6 @@
 package org.apache.axiom.soap.impl.builder;
 
 import org.apache.axiom.om.OMAbstractFactory;
-import org.apache.axiom.om.OMContainer;
 import org.apache.axiom.om.OMDocument;
 import org.apache.axiom.om.OMElement;
 import org.apache.axiom.om.OMException;
@@ -77,7 +76,7 @@
 
     private String parserVersion = null;
     private static final boolean isDebugEnabled = log.isDebugEnabled();
-
+    
     /**
      * Constructor StAXSOAPModelBuilder soapVersion parameter is to give the 
soap version from the
      * transport. For example, in HTTP case you can identify the version of 
the soap message u have
@@ -166,6 +165,7 @@
      */
     protected OMNode createNextOMElement() {
         OMNode newElement = null;
+        
         if (elementLevel == 3 && 
             customBuilderForPayload != null) {
             
@@ -328,7 +328,6 @@
 
                 processNamespaceData(element, true);
                 processAttributes(element);
-
             } else {
                 throw new SOAPProcessingException(elementName
                         +

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/soap/impl/dom/SOAPBodyImpl.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/soap/impl/dom/SOAPBodyImpl.java?rev=631309&r1=631308&r2=631309&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/soap/impl/dom/SOAPBodyImpl.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/soap/impl/dom/SOAPBodyImpl.java
 Tue Feb 26 09:28:29 2008
@@ -22,6 +22,7 @@
 import org.apache.axiom.om.OMConstants;
 import org.apache.axiom.om.OMElement;
 import org.apache.axiom.om.OMException;
+import org.apache.axiom.om.OMNamespace;
 import org.apache.axiom.om.OMXMLParserWrapper;
 import org.apache.axiom.soap.SOAP11Constants;
 import org.apache.axiom.soap.SOAP12Constants;
@@ -144,4 +145,24 @@
          throw new SOAPProcessingException(
                  "Can not detach SOAP Body, SOAP Envelope must have a Body 
!!");
      }*/
+    
+    public OMNamespace getFirstElementNS() {
+        OMElement element = this.getFirstElement();
+        if (element == null) {
+            return null;
+        } else {
+            return element.getNamespace();
+        } 
+
+    }
+
+    public String getFirstElementLocalName() {
+        OMElement element = this.getFirstElement();
+        if (element == null) {
+            return null;
+        } else {
+            return element.getLocalName();
+        } 
+
+    }
 }

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/soap/impl/llom/SOAPBodyImpl.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/soap/impl/llom/SOAPBodyImpl.java?rev=631309&r1=631308&r2=631309&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/soap/impl/llom/SOAPBodyImpl.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/soap/impl/llom/SOAPBodyImpl.java
 Tue Feb 26 09:28:29 2008
@@ -33,12 +33,21 @@
 import org.apache.axiom.soap.SOAPFactory;
 import org.apache.axiom.soap.SOAPFault;
 import org.apache.axiom.soap.SOAPProcessingException;
+import org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder;
+
+import javax.xml.stream.XMLStreamConstants;
 
 /** Class SOAPBodyImpl */
 public abstract class SOAPBodyImpl extends SOAPElement
         implements SOAPBody, OMConstants {
     /** Field hasSOAPFault */
     private boolean hasSOAPFault = false;
+    
+    private boolean enableLookAhead = true;
+    private boolean lookAheadAttempted = false;
+    private boolean lookAheadSuccessful = false;
+    private String lookAheadLocalName = null;
+    private OMNamespace lookAheadNS = null;
 
     protected SOAPBodyImpl(String localName, OMNamespace ns,
                            SOAPFactory factory) {
@@ -86,22 +95,17 @@
         if (hasSOAPFault) {
             return true;
         } else {
-            OMElement element = getFirstElement();
-            if (element != null
-                    &&
-                    SOAPConstants.SOAPFAULT_LOCAL_NAME.equals(
-                            element.getLocalName())
-                    &&
-                    (SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(
-                            element.getNamespace().getNamespaceURI())
-                            ||
-                            SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(
-                                    
element.getNamespace().getNamespaceURI()))) {  //added this line
-                hasSOAPFault = true;
-                return true;
-            } else {
-                return false;
-            }
+            // Set hasSOAPFault if it matches the name matches a SOAP Fault
+            String name = this.getFirstElementLocalName();
+            if (SOAPConstants.SOAPFAULT_LOCAL_NAME.equals(name)) {
+                OMNamespace ns = this.getFirstElementNS();
+                if (ns != null &&
+                    
(SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(ns.getNamespaceURI()) ||
+                     
SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(ns.getNamespaceURI()))) {
+                    hasSOAPFault = true;
+                }                                                             
+            } 
+            return hasSOAPFault;
         }
     }
 
@@ -158,4 +162,72 @@
         throw new SOAPProcessingException(
                 "Can not detach SOAP Body, SOAP Envelope must have a Body !!");
     }
+
+    /* 
+     * Overridden so that we can detect when a child element is built
+     */
+    public void buildNext() {
+        if (builder != null) {
+            int token = builder.next();
+            if (token == XMLStreamConstants.START_ELEMENT) {
+                enableLookAhead = false;
+            }
+        }
+    }
+    
+    private boolean hasLookahead() {
+        if (!enableLookAhead) {
+           return false; 
+        }
+        if (lookAheadAttempted) {
+            return lookAheadSuccessful;
+        }
+        lookAheadAttempted = true;
+        StAXSOAPModelBuilder soapBuilder = (StAXSOAPModelBuilder) this.builder;
+        if (soapBuilder != null &&
+            soapBuilder.isCache() &&
+            !soapBuilder.isCompleted() &&
+            !soapBuilder.isClosed()) {
+            lookAheadSuccessful = soapBuilder.lookahead();
+            if (lookAheadSuccessful) {
+                this.lookAheadLocalName = soapBuilder.getName();
+                this.lookAheadNS = 
factory.createOMNamespace(soapBuilder.getNamespace(), 
+                                                             
soapBuilder.getPrefix());
+            }
+        }
+        return lookAheadSuccessful;
+    }
+    
+    public OMNamespace getFirstElementNS() {
+        if (hasLookahead()) {
+            return this.lookAheadNS;
+        } else {
+            OMElement element = this.getFirstElement();
+            if (element == null) {
+                return null;
+            } else {
+                return element.getNamespace();
+            } 
+        }
+    }
+    
+    public String getFirstElementLocalName() {
+        if (hasLookahead()) {
+            return this.lookAheadLocalName;
+        } else {
+            OMElement element = this.getFirstElement();
+            if (element == null) {
+                return null;
+            } else {
+                return element.getLocalName();
+            } 
+        }
+    }
+
+    public void addChild(OMNode child) {
+        this.enableLookAhead = false;
+        super.addChild(child);
+    }
+    
+    
 }

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/builder/CustomBuilderTest.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/builder/CustomBuilderTest.java?rev=631309&r1=631308&r2=631309&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/builder/CustomBuilderTest.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/builder/CustomBuilderTest.java
 Tue Feb 26 09:28:29 2008
@@ -20,7 +20,6 @@
 import org.apache.axiom.om.OMNamespace;
 import org.apache.axiom.om.OMNode;
 import org.apache.axiom.om.OMSourcedElement;
-import org.apache.axiom.om.OMXMLParserWrapper;
 import org.apache.axiom.om.TestConstants;
 import org.apache.axiom.om.ds.ByteArrayDataSource;
 import org.apache.axiom.om.ds.custombuilder.ByteArrayCustomBuilder;
@@ -56,9 +55,10 @@
     
     public void testSample1() throws Exception {
         File file = getTestResourceFile(TestConstants.SAMPLE1);
-        copyAndCheck(createEnvelope(file), true);
+        copyAndCheck(createEnvelope(file, false), true);
     }
     
+    
     public void testHeaderCustomBuilder() throws Exception{
         XMLStreamReader parser =
             XMLInputFactory.newInstance().createXMLStreamReader(new
@@ -78,28 +78,38 @@
         }
     }
     
+    /**
+     * Test OMSE with SOAPMessage
+     * @throws Exception
+     */
     public void testSOAPMESSAGE() throws Exception {
         File file = getTestResourceFile(TestConstants.SOAP_SOAPMESSAGE);
-        copyAndCheck(createEnvelope(file), true);
+        copyAndCheck(createEnvelope(file, false), true);
     }
     
-    public void testSOAPMESSAGE1() throws Exception {
-        File file = getTestResourceFile(TestConstants.SOAP_SOAPMESSAGE1);
-        copyAndCheck(createEnvelope(file), false);  // Ignore the 
serialization comparison
+    
+    /** 
+     * Same as testSOAPMessage, except that the a fault check is done too.
+     * (The fault check simulates what happens in the engine.)
+     * @throws Exception
+     */
+    public void testSOAPMESSAGE2() throws Exception {
+        File file = getTestResourceFile(TestConstants.SOAP_SOAPMESSAGE);
+        copyAndCheck(createEnvelope(file, true), true);
     }
     
     public void testWHITESPACE_MESSAGE() throws Exception {
         File file = getTestResourceFile(TestConstants.WHITESPACE_MESSAGE);
-        copyAndCheck(createEnvelope(file), true);
+        copyAndCheck(createEnvelope(file, false), true);
     }
     
     public void testREALLY_BIG_MESSAGE() throws Exception {
         File file = getTestResourceFile(TestConstants.REALLY_BIG_MESSAGE);
-        copyAndCheck(createEnvelope(file), false);  // Ignore the 
serialization comparison
+        copyAndCheck(createEnvelope(file, false), false);  // Ignore the 
serialization comparison
     }
     public void testOMSE() throws Exception {
         File file = getTestResourceFile(TestConstants.EMPTY_BODY_MESSAGE);
-        SOAPEnvelope sourceEnv = createEnvelope(file);
+        SOAPEnvelope sourceEnv = createEnvelope(file, false);
         SOAPBody body = sourceEnv.getBody();
         
         // Create a payload
@@ -114,7 +124,7 @@
     
     public void testOMSE2() throws Exception {
         File file = getTestResourceFile(TestConstants.EMPTY_BODY_MESSAGE);
-        SOAPEnvelope sourceEnv = createEnvelope(file);
+        SOAPEnvelope sourceEnv = createEnvelope(file, false);
         SOAPBody body = sourceEnv.getBody();
         SOAPHeader header = sourceEnv.getHeader();
         String encoding = "UTF-8";
@@ -149,12 +159,22 @@
      * @return
      * @throws Exception
      */
-    protected SOAPEnvelope createEnvelope(File file) throws Exception {
+    protected SOAPEnvelope createEnvelope(File file, boolean doFaultCheck) 
throws Exception {
         XMLStreamReader parser =
             XMLInputFactory.newInstance().createXMLStreamReader(new 
FileReader(file));
         StAXSOAPModelBuilder builder = new StAXSOAPModelBuilder(parser, null);
-        builder.registerCustomBuilderForPayload(new 
ByteArrayCustomBuilder("utf-8"));
+        
         SOAPEnvelope sourceEnv = (SOAPEnvelope) builder.getDocumentElement();
+        
+        // Do a fault check.  This is normally done in the engine (Axiom) and 
should
+        // not cause inteference with the custom builder processing
+        if (doFaultCheck) {
+            sourceEnv.getBody().hasFault();
+        }
+        
+        // Do the registration here...this simulates when it could occure in 
the engine
+        // (After the fault check and during phase processing...probably 
dispatch phase)
+        builder.registerCustomBuilderForPayload(new 
ByteArrayCustomBuilder("utf-8"));
         return sourceEnv;
     }
     



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to