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 {