Author: scheu
Date: Mon Dec 14 18:43:09 2009
New Revision: 890433

URL: http://svn.apache.org/viewvc?rev=890433&view=rev
Log:
WSCOMMONS-512
Contributor:Rich Scheuerle
Avoid OMSourcedElement expansion during StreamingOMSerializer usage.
Also added 3 validation tests

Added:
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/resources/soap/noprettyprint.xml
Modified:
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMNavigator.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMStAXWrapper.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/SwitchingWrapper.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/serialize/StreamingOMSerializer.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/serializer/OMSerializerTest.java

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMNavigator.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMNavigator.java?rev=890433&r1=890432&r2=890433&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMNavigator.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMNavigator.java
 Mon Dec 14 18:43:09 2009
@@ -20,6 +20,7 @@
 package org.apache.axiom.om.impl;
 
 import org.apache.axiom.om.OMContainer;
+import org.apache.axiom.om.OMDataSource;
 import org.apache.axiom.om.OMDocument;
 import org.apache.axiom.om.OMElement;
 import org.apache.axiom.om.OMNode;
@@ -55,6 +56,10 @@
 
     /** Field start */
     private boolean start = true;
+    
+    // Indicates if an OMSourcedElement with an OMDataSource should
+    // be considered as an interior node or a leaf node.
+    private boolean isDataSourceALeaf = false;
 
     /** Constructor OMNavigator. */
     public OMNavigator() {
@@ -79,6 +84,16 @@
         root = node;
         backtracked = false;
     }
+    
+    /**
+     * Indicate if an OMSourcedElement with a OMDataSource
+     * should be considered as an interior element node or as
+     * a leaf.  
+     * @param value boolean
+     */
+    public void setDataSourceIsLeaf(boolean value) {
+        isDataSourceALeaf = value;
+    }
 
     /**
      * Gets the next node.
@@ -109,7 +124,7 @@
 
     /** Private method to encapsulate the searching logic. */
     private void updateNextNode() {
-        if ((next instanceof OMElement) && !visited) {
+        if (!isLeaf(next) && !visited) {
             OMNode firstChild = _getFirstChild((OMElement) next);
             if (firstChild != null) {
                 next = firstChild;
@@ -131,6 +146,29 @@
             }
         }
     }
+    
+    /**
+     * @param n OMNode
+     * @return true if this OMNode should be considered a leaf node
+     */
+    private boolean isLeaf(OMNode n) {
+        if (n instanceof OMElement) {
+            if (this.isDataSourceALeaf && (n instanceof OMSourcedElement)) {
+                OMDataSource ds = null;
+                try {
+                    ds = ((OMSourcedElement) n).getDataSource();
+                } catch (UnsupportedOperationException e) {
+                    ; // Operation unsupported for DOM impl
+                }
+                if (ds != null) {
+                    return true;
+                }
+            }
+            return false;
+        } else {
+            return true;
+        }
+    }
 
     /**
      * @param node

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMStAXWrapper.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMStAXWrapper.java?rev=890433&r1=890432&r2=890433&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMStAXWrapper.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMStAXWrapper.java
 Mon Dec 14 18:43:09 2009
@@ -27,6 +27,7 @@
 import javax.xml.stream.util.StreamReaderDelegate;
 
 import org.apache.axiom.om.OMAttachmentAccessor;
+import org.apache.axiom.om.OMDataSource;
 import org.apache.axiom.om.OMElement;
 import org.apache.axiom.om.OMException;
 import org.apache.axiom.om.OMXMLParserWrapper;
@@ -171,4 +172,23 @@
     public void setNamespaceURIInterning(boolean b) {
         switchingWrapper.setNamespaceURIInterning(b);
     }
+    
+    
+    /**
+     * @return OMDataSource if available
+     */
+    public OMDataSource getDataSource() {
+        return switchingWrapper.getDataSource();
+    }
+    
+    /**
+     * If enabled, treat OMSourcedElements that have
+     * a OMDataSource as leaf nodes.  The caller
+     * should use the getDataSource method to obtain
+     * the OMDataSource for these events.
+     * @param value boolean
+     */
+    public void enableDataSourceEvents(boolean value) {
+        switchingWrapper.enableDataSourceEvents(value);
+    }
 }

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/SwitchingWrapper.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/SwitchingWrapper.java?rev=890433&r1=890432&r2=890433&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/SwitchingWrapper.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/SwitchingWrapper.java
 Mon Dec 14 18:43:09 2009
@@ -39,6 +39,7 @@
 import org.apache.axiom.om.OMAttribute;
 import org.apache.axiom.om.OMComment;
 import org.apache.axiom.om.OMContainer;
+import org.apache.axiom.om.OMDataSource;
 import org.apache.axiom.om.OMDocument;
 import org.apache.axiom.om.OMElement;
 import org.apache.axiom.om.OMNamespace;
@@ -1552,4 +1553,37 @@
         }
         
     }
+    
+    /**
+     * @return OMDataSource associated with the current node or Null
+     */
+    public OMDataSource getDataSource() {
+        OMDataSource ds = null;
+        if (lastNode != null &&
+            lastNode instanceof OMSourcedElement) {
+            try {
+                ds = ((OMSourcedElement) lastNode).getDataSource();
+            } catch (UnsupportedOperationException e) {
+                ds =null;
+            }
+            if (log.isDebugEnabled()) {
+                if (ds != null) {
+                    log.debug("OMSourcedElement exposed an OMDataSource." + 
ds);
+                } else {
+                    log.debug("OMSourcedElement does not have a 
OMDataSource.");
+                }
+            }
+        }
+        return ds;
+    }
+    
+    /**
+     * Enable if an OMSourcedElement with an OMDataSource should be treated as 
a
+     * leaf node.  Disable (the default) if the OMDataSource should be parsed 
and
+     * converted into events.
+     * @param value boolean
+     */
+    public void enableDataSourceEvents(boolean value) {
+        navigator.setDataSourceIsLeaf(value);
+    }
 }

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/serialize/StreamingOMSerializer.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/serialize/StreamingOMSerializer.java?rev=890433&r1=890432&r2=890433&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/serialize/StreamingOMSerializer.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/serialize/StreamingOMSerializer.java
 Mon Dec 14 18:43:09 2009
@@ -21,7 +21,10 @@
 
 import org.apache.axiom.ext.stax.datahandler.DataHandlerReader;
 import org.apache.axiom.ext.stax.datahandler.DataHandlerWriter;
+import org.apache.axiom.om.OMDataSource;
 import org.apache.axiom.om.OMSerializer;
+import org.apache.axiom.om.impl.MTOMXMLStreamWriter;
+import org.apache.axiom.om.impl.OMStAXWrapper;
 import org.apache.axiom.om.impl.builder.DataHandlerReaderUtils;
 import org.apache.axiom.om.impl.util.OMSerializerUtil;
 import org.apache.axiom.util.stax.XMLStreamWriterUtils;
@@ -35,6 +38,7 @@
 import javax.xml.stream.XMLStreamWriter;
 
 import java.io.IOException;
+import java.io.OutputStream;
 import java.util.ArrayList;
 
 /** Class StreamingOMSerializer */
@@ -85,7 +89,29 @@
         dataHandlerReader = 
DataHandlerReaderUtils.getDataHandlerReader(reader);
         dataHandlerWriter = XMLStreamWriterUtils.getDataHandlerWriter(writer);
         
-        serializeNode(reader, writer, startAtNext);
+        if (reader instanceof OMStAXWrapper) {
+            int event = reader.getEventType();
+            if (event <= 0 ||
+                event == XMLStreamReader.PROCESSING_INSTRUCTION ||
+                event == XMLStreamReader.START_DOCUMENT) {
+                // Since we are serializing an entire document,
+                // enable the the optimized DataSource events.
+                // This will allow OMDataSource elements to be serialized
+                // directly without expansion.
+                if (log.isDebugEnabled()) {
+                    log.debug("Enable OMDataSource events while serializing 
this document");
+                }
+                ((OMStAXWrapper) reader).enableDataSourceEvents(true);
+            }
+        }
+        try {
+            serializeNode(reader, writer, startAtNext);
+        } finally {
+            if (reader instanceof OMStAXWrapper) {
+                ((OMStAXWrapper) reader).enableDataSourceEvents(false);
+            }
+        }
+        
     }
 
     /**
@@ -112,15 +138,25 @@
         boolean useCurrentEvent = !startAtNext;
         
         while (reader.hasNext() || useCurrentEvent) {
-            int event;
+            int event = 0;
+            OMDataSource ds = null;
             if (useCurrentEvent) {
                 event = reader.getEventType();
                 useCurrentEvent = false;
             } else {
-                event = reader.next();
+                event = reader.next(); 
             }
             
-            switch (event) {
+            // If the reader is exposing a DataSourc
+            // for this event, then simply serialize the
+            // DataSource
+            if (reader instanceof OMStAXWrapper) {
+                ds = ((OMStAXWrapper) reader).getDataSource();
+            }
+            if (ds != null) {
+                ds.serialize(writer);
+            } else {
+                switch (event) {
                 case START_ELEMENT:
                     serializeElement(reader, writer);
                     depth++;
@@ -160,6 +196,7 @@
                     } catch (Exception e) {
                         //TODO: log exceptions
                     }
+                }
             }
             if (depth == 0) {
                 break;

Added: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/resources/soap/noprettyprint.xml
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/resources/soap/noprettyprint.xml?rev=890433&view=auto
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/resources/soap/noprettyprint.xml
 (added)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/resources/soap/noprettyprint.xml
 Mon Dec 14 18:43:09 2009
@@ -0,0 +1 @@
+<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns:usr="http://ws.apache.org/axis2/user";><soapenv:Header 
/><soapenv:Body><axis2:echoMyData 
xmlns:axis2="http://ws.apache.org/axis2";><data xsi:type="usr:myData">Hello 
World</data></axis2:echoMyData></soapenv:Body></soapenv:Envelope>
\ No newline at end of file

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/serializer/OMSerializerTest.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/serializer/OMSerializerTest.java?rev=890433&r1=890432&r2=890433&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/serializer/OMSerializerTest.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/serializer/OMSerializerTest.java
 Mon Dec 14 18:43:09 2009
@@ -21,9 +21,12 @@
 
 import org.apache.axiom.om.AbstractTestCase;
 import org.apache.axiom.om.OMAbstractFactory;
+import org.apache.axiom.om.OMSourcedElement;
 import org.apache.axiom.om.OMXMLParserWrapper;
 import org.apache.axiom.om.OMConstants;
 import org.apache.axiom.om.TestConstants;
+import org.apache.axiom.om.ds.custombuilder.ByteArrayCustomBuilder;
+import org.apache.axiom.om.impl.builder.StAXBuilder;
 import org.apache.axiom.om.impl.builder.StAXOMBuilder;
 import org.apache.axiom.om.impl.llom.factory.OMXMLBuilderFactory;
 import org.apache.axiom.om.impl.serialize.StreamingOMSerializer;
@@ -142,6 +145,166 @@
         String outputString = new String(byteArrayOutputStream.toByteArray());
         assertTrue(outputString != null && !"".equals(outputString) && 
outputString.length() > 1);
     }
+    
+    /**
+     * Scenario:
+     *    A) Builder reads a soap message.
+     *    B) The payload of the message is created by a customer builder
+     *    C) The resulting OM is serialized (pulled) prior to completion of 
the intial read.
+     *    D) The payload of the message should not be expanded into OM.
+     *    
+     *    Expansion of the message results in both a time and space penalty.
+     * @throws Exception
+     */
+    public void testElementPullStreamAndOMExpansion() throws Exception {
+        // Create a reader sourced from a message containing an interesting 
payload
+        reader = 
StAXUtils.createXMLStreamReader(getTestResource("soap/OMElementTest.xml"));
+        
+        // Create a builder connected to the reader
+        StAXBuilder builder = OMXMLBuilderFactory.createStAXSOAPModelBuilder(
+                OMAbstractFactory.getSOAP11Factory(),
+                reader);
+        
+        // Create a custom builder to store the sub trees as a byte array 
instead of a full tree
+        ByteArrayCustomBuilder customBuilder = new 
ByteArrayCustomBuilder("utf-8");
+        
+        // Register the custom builder on the builder so that they body 
payload is stored as bytes
+        builder.registerCustomBuilderForPayload(customBuilder);
+        
+        
+        // Create an output stream
+        ByteArrayOutputStream byteArrayOutputStream = new 
ByteArrayOutputStream();
+        writer = StAXUtils.createXMLStreamWriter(byteArrayOutputStream);
+
+        // Now use StreamingOMSerializer to write the input stream to the 
output stream
+        SOAPEnvelope env = (SOAPEnvelope) builder.getDocumentElement();
+        SOAPBody body = env.getBody();
+        OMSourcedElement omse = (OMSourcedElement) body.getFirstElement();
+        
+        StreamingOMSerializer serializer = new StreamingOMSerializer();
+        serializer.serialize(env.getXMLStreamReaderWithoutCaching(),
+                             writer);
+        writer.flush();
+
+        String outputString = new String(byteArrayOutputStream.toByteArray());
+        assertTrue("Expected output was incorrect.  Received:" + outputString,
+                outputString != null && !"".equals(outputString) && 
outputString.length() > 1);
+        assertTrue("Expected output was incorrect.  Received:" + outputString,
+                outputString.contains("axis2:input"));
+        assertTrue("Expected output was incorrect.  Received:" + outputString,
+                outputString.contains("This is some text"));
+        assertTrue("Expected output was incorrect.  Received:" + outputString,
+                outputString.contains("Some Other Text"));
+        
+        assertTrue("Expectation is that an OMSourcedElement was created for 
the payload", 
+                omse != null);
+        assertTrue("Expectation is that the OMSourcedElement was not expanded 
by serialization ", 
+                !omse.isExpanded());
+    }
+    
+    /**
+     * Scenario:
+     *    A) Builder reads a soap message.
+     *    B) The payload of the message is created by a customer builder
+     *    C) The resulting OM is serialized (pulled) prior to completion of 
the intial read.
+     *    D) The payload of the message should not be expanded into OM.
+     *    
+     *    Expansion of the message results in both a time and space penalty.
+     * @throws Exception
+     */
+    public void testElementPullStreamAndOMExpansion2() throws Exception {
+        // Create a reader sourced from a message containing an interesting 
payload
+        reader = 
StAXUtils.createXMLStreamReader(getTestResource("soap/soapmessageWithXSI.xml"));
+        
+        // Create a builder connected to the reader
+        StAXBuilder builder = OMXMLBuilderFactory.createStAXSOAPModelBuilder(
+                OMAbstractFactory.getSOAP11Factory(),
+                reader);
+        
+        // Create a custom builder to store the sub trees as a byte array 
instead of a full tree
+        ByteArrayCustomBuilder customBuilder = new 
ByteArrayCustomBuilder("utf-8");
+        
+        // Register the custom builder on the builder so that they body 
payload is stored as bytes
+        builder.registerCustomBuilderForPayload(customBuilder);
+        
+        
+        // Create an output stream
+        ByteArrayOutputStream byteArrayOutputStream = new 
ByteArrayOutputStream();
+        writer = StAXUtils.createXMLStreamWriter(byteArrayOutputStream);
+
+        // Now use StreamingOMSerializer to write the input stream to the 
output stream
+        SOAPEnvelope env = (SOAPEnvelope) builder.getDocumentElement();
+        SOAPBody body = env.getBody();
+        OMSourcedElement omse = (OMSourcedElement) body.getFirstElement();
+        
+        StreamingOMSerializer serializer = new StreamingOMSerializer();
+        serializer.serialize(env.getXMLStreamReaderWithoutCaching(),
+                             writer);
+        writer.flush();
+
+        String outputString = new String(byteArrayOutputStream.toByteArray());
+        assertTrue("Expected output was incorrect.  Received:" + outputString,
+                outputString != null && !"".equals(outputString) && 
outputString.length() > 1);
+        assertTrue("Expected output was incorrect.  Received:" + outputString,
+                outputString.contains("Hello World"));
+        
+        assertTrue("Expectation is that an OMSourcedElement was created for 
the payload", 
+                omse != null);
+        assertTrue("Expectation is that the OMSourcedElement was not expanded 
by serialization ", 
+                !omse.isExpanded());
+    }
+    
+    /**
+     * Scenario:
+     *    A) Builder reads a soap message.
+     *    B) The payload of the message is created by a customer builder
+     *    C) The resulting OM is serialized (pulled) prior to completion of 
the intial read.
+     *    D) The payload of the message should not be expanded into OM.
+     *    
+     *    Expansion of the message results in both a time and space penalty.
+     * @throws Exception
+     */
+    public void testElementPullStreamAndOMExpansion3() throws Exception {
+        // Create a reader sourced from a message containing an interesting 
payload
+        reader = 
StAXUtils.createXMLStreamReader(getTestResource("soap/noprettyprint.xml"));
+        
+        // Create a builder connected to the reader
+        StAXBuilder builder = OMXMLBuilderFactory.createStAXSOAPModelBuilder(
+                OMAbstractFactory.getSOAP11Factory(),
+                reader);
+        
+        // Create a custom builder to store the sub trees as a byte array 
instead of a full tree
+        ByteArrayCustomBuilder customBuilder = new 
ByteArrayCustomBuilder("utf-8");
+        
+        // Register the custom builder on the builder so that they body 
payload is stored as bytes
+        builder.registerCustomBuilderForPayload(customBuilder);
+        
+        
+        // Create an output stream
+        ByteArrayOutputStream byteArrayOutputStream = new 
ByteArrayOutputStream();
+        writer = StAXUtils.createXMLStreamWriter(byteArrayOutputStream);
+
+        // Now use StreamingOMSerializer to write the input stream to the 
output stream
+        SOAPEnvelope env = (SOAPEnvelope) builder.getDocumentElement();
+        SOAPBody body = env.getBody();
+        OMSourcedElement omse = (OMSourcedElement) body.getFirstElement();
+        
+        StreamingOMSerializer serializer = new StreamingOMSerializer();
+        serializer.serialize(env.getXMLStreamReaderWithoutCaching(),
+                             writer);
+        writer.flush();
+
+        String outputString = new String(byteArrayOutputStream.toByteArray());
+        assertTrue("Expected output was incorrect.  Received:" + outputString,
+                outputString != null && !"".equals(outputString) && 
outputString.length() > 1);
+        assertTrue("Expected output was incorrect.  Received:" + outputString,
+                outputString.contains("Hello World"));
+        
+        assertTrue("Expectation is that an OMSourcedElement was created for 
the payload", 
+                omse != null);
+        assertTrue("Expectation is that the OMSourcedElement was not expanded 
by serialization ", 
+                !omse.isExpanded());
+    }
 
     public void testDefaultNsSerialization() {
         try {


Reply via email to