You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commons-dev@ws.apache.org by ve...@apache.org on 2009/03/13 21:04:55 UTC

svn commit: r753373 - in /webservices/commons/trunk/modules/transport/modules/base/src: main/java/org/apache/axis2/format/ test/java/org/apache/axis2/format/

Author: veithen
Date: Fri Mar 13 20:04:50 2009
New Revision: 753373

URL: http://svn.apache.org/viewvc?rev=753373&view=rev
Log:
Consolidated the code that handles large text payloads. There is now a class ElementHelper with methods getTextAsStream and writeTextTo that can be used as alternatives to OMElement#getText() but that work with streams and guarantee constant memory usage and optimal efficiency. Note that the intention is to move these two methods to the corresponding class in Axiom, but this is not possible for the moment because of the release schedule.

Added:
    webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/ElementHelper.java   (with props)
    webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/TextFromElementReader.java   (with props)
    webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/CharacterStreamComparator.java   (with props)
    webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/ElementHelperTest.java   (with props)
    webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/RandomDataSource.java   (with props)
    webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/TextFromElementReaderTest.java   (with props)
Modified:
    webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/PlainTextFormatter.java
    webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/TextFromElementDataSource.java

Added: webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/ElementHelper.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/ElementHelper.java?rev=753373&view=auto
==============================================================================
--- webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/ElementHelper.java (added)
+++ webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/ElementHelper.java Fri Mar 13 20:04:50 2009
@@ -0,0 +1,111 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.axis2.format;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.Writer;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.OMNode;
+import org.apache.axiom.om.OMSourcedElement;
+import org.apache.axiom.om.OMText;
+
+/**
+ * Utility class with methods to work on {@link OMElement} objects.
+ * <p>
+ * NOTICE: The code in this class will be moved to Axiom (or somewhere else). Use with care!
+ */
+public class ElementHelper {
+    private ElementHelper() {}
+    
+    /**
+     * Returns a stream representing the concatenation of the text nodes that are children of a
+     * given element.
+     * The stream returned by this method produces exactly the same character sequence as the
+     * the stream created by the following expression:
+     * <pre>new StringReader(element.getText())</pre>
+     * The difference is that the stream implementation returned by this method is guaranteed
+     * to have constant memory usage and is optimized for performance.
+     * 
+     * @param element the element to read the text nodes from
+     * @param cache whether to enable caching when accessing the element
+     * @return a stream representing the concatenation of the text nodes
+     * 
+     * @see OMElement#getText()
+     */
+    public static Reader getTextAsStream(OMElement element, boolean cache) {
+        // If the element is not an OMSourcedElement and has not more than one child, then the most
+        // efficient way to get the Reader is to build a StringReader
+        if (!(element instanceof OMSourcedElement) && (!cache || element.isComplete())) {
+            OMNode child = element.getFirstOMChild();
+            if (child == null) {
+                return new StringReader("");
+            } else if (child.getNextOMSibling() == null) {
+                return new StringReader(child instanceof OMText ? ((OMText)child).getText() : "");
+            }
+        }
+        // In all other cases, extract the data from the XMLStreamReader
+        return new TextFromElementReader(cache ? element.getXMLStreamReader()
+                : element.getXMLStreamReaderWithoutCaching());
+    }
+    
+    /**
+     * Write the content of the text nodes that are children of a given element to a
+     * {@link Writer}.
+     * If <code>cache</code> is true, this method has the same effect as the following instruction:
+     * <pre>out.write(element.getText())</pre>
+     * The difference is that this method is guaranteed to have constant memory usage and is
+     * optimized for performance.
+     * 
+     * @param element the element to read the text nodes from
+     * @param out the stream to write the content to
+     * @param cache whether to enable caching when accessing the element
+     * @throws XMLStreamException if an error occurs when reading from the element
+     * @throws IOException if an error occurs when writing to the stream
+     * 
+     * @see OMElement#getText()
+     */
+    public static void writeTextTo(OMElement element, Writer out, boolean cache)
+            throws XMLStreamException, IOException {
+        
+        XMLStreamReader reader = cache ? element.getXMLStreamReader()
+                : element.getXMLStreamReaderWithoutCaching();
+        int depth = 0;
+        while (reader.hasNext()) {
+            switch (reader.next()) {
+                case XMLStreamReader.CHARACTERS:
+                case XMLStreamReader.CDATA:
+                    if (depth == 1) {
+                        out.write(reader.getText());
+                    }
+                    break;
+                case XMLStreamReader.START_ELEMENT:
+                    depth++;
+                    break;
+                case XMLStreamReader.END_ELEMENT:
+                    depth--;
+            }
+        }
+    }
+}

Propchange: webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/ElementHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/PlainTextFormatter.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/PlainTextFormatter.java?rev=753373&r1=753372&r2=753373&view=diff
==============================================================================
--- webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/PlainTextFormatter.java (original)
+++ webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/PlainTextFormatter.java Fri Mar 13 20:04:50 2009
@@ -35,7 +35,6 @@
 
 import javax.activation.DataSource;
 import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamReader;
 
 public class PlainTextFormatter implements MessageFormatterEx {
 
@@ -50,13 +49,7 @@
         if (BaseConstants.DEFAULT_TEXT_WRAPPER.equals(textElt.getQName())) {
 	        try {
 		        Writer out = new OutputStreamWriter(outputStream, format.getCharSetEncoding());
-                XMLStreamReader reader = preserve ? textElt.getXMLStreamReader() : textElt.getXMLStreamReaderWithoutCaching();
-                while (reader.hasNext()) {
-                	int eventType = reader.next();
-                    if (eventType == XMLStreamReader.CHARACTERS || eventType == XMLStreamReader.CDATA) {
-                        out.write(reader.getText());
-                    }
-                }
+		        ElementHelper.writeTextTo(textElt, out, preserve);
                 out.flush();
 	        } catch (IOException e) {
 	            throw new AxisFault("Error writing text message to stream", e);

Modified: webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/TextFromElementDataSource.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/TextFromElementDataSource.java?rev=753373&r1=753372&r2=753373&view=diff
==============================================================================
--- webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/TextFromElementDataSource.java (original)
+++ webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/TextFromElementDataSource.java Fri Mar 13 20:04:50 2009
@@ -23,10 +23,9 @@
 import java.io.OutputStream;
 
 import javax.activation.DataSource;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamReader;
 
 import org.apache.axiom.om.OMElement;
+import org.apache.axis2.transport.base.streams.ReaderInputStream;
 
 /**
  * Data source that represents the text of a given {@link OMElement}.
@@ -38,68 +37,6 @@
  * but that is more efficient.
  */
 public class TextFromElementDataSource implements DataSource {
-    private static class InputStreamImpl extends InputStream {
-        private final XMLStreamReader reader;
-        private final String charset;
-        private byte[] buffer;
-        private int offset;
-        
-        public InputStreamImpl(XMLStreamReader reader, String charset) {
-            this.reader = reader;
-            this.charset = charset;
-        }
-
-        @Override
-        public int read() throws IOException {
-            byte[] b = new byte[1];
-            return read(b) == -1 ? -1 : b[0] & 0xFF;
-        }
-
-        @Override
-        public int read(byte[] b) throws IOException {
-            return read(b, 0, b.length);
-        }
-
-        @Override
-        public int read(byte[] b, int off, int len) throws IOException {
-            try {
-                int read = 0;
-                outer: while (len > 0) {
-                    if (buffer == null || offset == buffer.length) {
-                        // Refill buffer
-                        while (true) {
-                            if (!reader.hasNext()) {
-                                break outer;
-                            }
-                            int eventType = reader.next();
-                            if (eventType == XMLStreamReader.CHARACTERS ||
-                                    eventType == XMLStreamReader.CDATA) {
-                                // Note: this is not entirely correct for encodings such as UTF-16.
-                                // Once IO-158 is implemented, we could avoid this by implementing a
-                                // Reader and using ReaderInputStream.
-                                buffer = reader.getText().getBytes(charset);
-                                offset = 0;
-                                break;
-                            }
-                        }
-                    }
-                    int c = Math.min(len, buffer.length-offset);
-                    System.arraycopy(buffer, offset, b, off, c);
-                    offset += c;
-                    off += c;
-                    len -= c;
-                    read += c;
-                }
-                return read == 0 ? -1 : read;
-            }
-            catch (XMLStreamException ex) {
-                IOException ioException = new IOException("Unable to read from XMLStreamReader");
-                ioException.initCause(ex);
-                throw ioException;
-            }
-        }
-    }
-    
     private final OMElement element;
     private final String charset;
     private final String contentType;
@@ -119,7 +56,7 @@
     }
 
     public InputStream getInputStream() throws IOException {
-        return new InputStreamImpl(element.getXMLStreamReader(), charset);
+        return new ReaderInputStream(ElementHelper.getTextAsStream(element, true), charset);
     }
 
     public OutputStream getOutputStream() throws IOException {

Added: webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/TextFromElementReader.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/TextFromElementReader.java?rev=753373&view=auto
==============================================================================
--- webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/TextFromElementReader.java (added)
+++ webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/TextFromElementReader.java Fri Mar 13 20:04:50 2009
@@ -0,0 +1,160 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.axis2.format;
+
+import java.io.IOException;
+import java.io.Reader;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.axiom.om.OMException;
+
+/**
+ * {@link Reader} implementation that extracts the text nodes from an element given by an
+ * {@link XMLStreamReader}. The expected input is a document with only a document
+ * element (as produced by {@link org.apache.axiom.om.OMElement.OMElement#getXMLStreamReader()}).
+ * The class will extract the text nodes that are direct children of that element, i.e. it uses
+ * the same conventions as {@link org.apache.axiom.om.OMElement.OMElement#getText()}.
+ * It will call {@link XMLStreamReader#close()} when the end of the document is reached or when
+ * {@link #close()} is called.
+ * <p>
+ * The main purpose of this class is to provide a convenient and efficient way to get the text
+ * content of an element without converting it first to a string, i.e. without using
+ * {@link org.apache.axiom.om.OMElement.OMElement#getText()}. This is important for potentially
+ * large contents, for which this class guarantees constant memory usage.
+ * <p>
+ * Note that this class should in general not be used directly. Instead, 
+ * {@link ElementHelper#getTextAsStream(org.apache.axiom.om.OMElement)}
+ * should be called to get the most efficient stream implementation for a given an element.
+ * <p>
+ * NOTICE: The code in this class will be moved to Axiom (or somewhere else). Use with care!
+ */
+public class TextFromElementReader extends Reader {
+    private final XMLStreamReader stream;
+    
+    /**
+     * Flag indicating that we have reached the end of the document and that the underlying
+     * parser has been closed.
+     */
+    private boolean endOfStream;
+    
+    /**
+     * The current depth relative to the document element (not the document). A value greater than
+     * 0 indicates that we are inside a nested element and that we need to skip text nodes.
+     */
+    private int skipDepth;
+    
+    /**
+     * The current position in the character data of the event, or -1 if all the character data
+     * has been consumed and a new event needs to be requested from the parser.
+     */
+    private int sourceStart = -1;
+    
+    /**
+     * Constructor.
+     * 
+     * @param stream the stream to extract the text nodes from
+     * @throws OMException if the stream doesn't start with the expected events
+     */
+    public TextFromElementReader(XMLStreamReader stream) {
+        this.stream = stream;
+        try {
+            if (stream.getEventType() != XMLStreamReader.START_DOCUMENT) {
+                throw new OMException("Expected START_DOCUMENT as first event from parser");
+            }
+            if (stream.next() != XMLStreamReader.START_ELEMENT) {
+                throw new OMException("Expected START_ELEMENT event");
+            }
+        } catch (XMLStreamException ex) {
+            throw new OMException(ex);
+        }
+    }
+
+    @Override
+    public int read(char[] cbuf, int off, int len) throws IOException {
+        if (endOfStream) {
+            return -1;
+        }
+        int read = 0;
+        try {
+            while (true) {
+                if (sourceStart == -1) {
+                    eventLoop: while (true) {
+                        int type = stream.next();
+                        switch (type) {
+                            case XMLStreamReader.CHARACTERS:
+                            case XMLStreamReader.CDATA:
+                                if (skipDepth == 0) {
+                                    sourceStart = 0;
+                                    break eventLoop;
+                                }
+                                break;
+                            case XMLStreamReader.START_ELEMENT:
+                                skipDepth++;
+                                break;
+                            case XMLStreamReader.END_ELEMENT:
+                                if (skipDepth == 0) {
+                                    if (stream.next() == XMLStreamReader.END_DOCUMENT) {
+                                        endOfStream = true;
+                                        stream.close();
+                                        return read == 0 ? -1 : read;
+                                    } else {
+                                        throw new IOException(
+                                                "End of document expected after element");
+                                    }
+                                } else {
+                                    skipDepth--;
+                                }
+                        }
+                    }
+                }
+                int c = stream.getTextCharacters(sourceStart, cbuf, off, len);
+                sourceStart += c;
+                off += c;
+                len -= c;
+                read += c;
+                if (len > 0) {
+                    sourceStart = -1;
+                } else {
+                    return read;
+                }
+            }
+        } catch (XMLStreamException ex) {
+            IOException ex2 = new IOException("Got an exception from the underlying parser " +
+            		"while reading the content of an element");
+            ex2.initCause(ex);
+            throw ex2;
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (!endOfStream) {
+            try {
+                stream.close();
+            } catch (XMLStreamException ex) {
+                IOException ex2 = new IOException("Error when trying to close underlying parser");
+                ex2.initCause(ex);
+                throw ex2;
+            }
+        }
+    }
+}

Propchange: webservices/commons/trunk/modules/transport/modules/base/src/main/java/org/apache/axis2/format/TextFromElementReader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/CharacterStreamComparator.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/CharacterStreamComparator.java?rev=753373&view=auto
==============================================================================
--- webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/CharacterStreamComparator.java (added)
+++ webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/CharacterStreamComparator.java Fri Mar 13 20:04:50 2009
@@ -0,0 +1,70 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.axis2.format;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+
+import junit.framework.Assert;
+
+/**
+ * {@link Writer} implementation that compares the data written to it with another character
+ * sequence specified by a {@link Reader}.
+ * This class is meant to be used in JUnit test cases.
+ */
+public class CharacterStreamComparator extends Writer {
+    private final Reader in;
+    private final char[] compareBuffer = new char[1024];
+    private int position;
+    
+    public CharacterStreamComparator(Reader in) {
+        this.in = in;
+    }
+
+    @Override
+    public void write(char[] buffer, int off, int len) throws IOException {
+        while (len > 0) {
+            int c = in.read(compareBuffer, 0, Math.min(compareBuffer.length, len));
+            if (c == -1) {
+                Assert.fail("The two streams have different lengths");
+            }
+            for (int i=0; i<c; i++) {
+                if (buffer[off] != compareBuffer[i]) {
+                    Assert.fail("Character mismatch at position " + position);
+                }
+                off++;
+                len--;
+                position++;
+            }
+        }
+    }
+
+    @Override
+    public void flush() throws IOException {
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (in.read() != -1) {
+            Assert.fail("The two streams have different lengths");
+        }
+    }
+}

Propchange: webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/CharacterStreamComparator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/ElementHelperTest.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/ElementHelperTest.java?rev=753373&view=auto
==============================================================================
--- webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/ElementHelperTest.java (added)
+++ webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/ElementHelperTest.java Fri Mar 13 20:04:50 2009
@@ -0,0 +1,126 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.axis2.format;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.SequenceInputStream;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.Vector;
+
+import javax.activation.DataSource;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
+
+import junit.framework.TestCase;
+
+import org.apache.axiom.om.OMAbstractFactory;
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.OMFactory;
+import org.apache.axiom.om.OMSourcedElement;
+import org.apache.axiom.om.impl.builder.StAXOMBuilder;
+import org.apache.axiom.om.impl.llom.OMSourcedElementImpl;
+import org.apache.axiom.om.impl.llom.util.AXIOMUtil;
+import org.apache.commons.io.IOUtils;
+
+public class ElementHelperTest extends TestCase {
+    private void compareStreams(Reader s1, Reader s2) throws IOException {
+        Writer comparator = new CharacterStreamComparator(s2);
+        IOUtils.copy(s1, comparator);
+        comparator.close();
+    }
+    
+    public void testGetTextAsStreamWithSingleTextNode() throws Exception {
+        OMFactory factory = OMAbstractFactory.getOMFactory();
+        OMElement element = factory.createOMElement(new QName("a"));
+        factory.createOMText(element, "test");
+        Reader in = ElementHelper.getTextAsStream(element, true);
+        assertTrue(in instanceof StringReader);
+        assertEquals(element.getText(), IOUtils.toString(in));
+    }
+    
+    public void testGetTextAsStreamWithNonTextChildren() throws Exception {
+        OMElement element = AXIOMUtil.stringToOM("<a>A<b>B</b>C</a>");
+        Reader in = new TextFromElementReader(element.getXMLStreamReader());
+        assertEquals(element.getText(), IOUtils.toString(in));
+    }
+    
+    public void testGetTextAsStreamWithOMSourcedElement() throws Exception {
+        OMFactory factory = OMAbstractFactory.getOMFactory();
+        DataSource ds = new RandomDataSource(445566, 32, 128, 20000000);
+        QName qname = new QName("a");
+        Charset cs = Charset.forName("ascii");
+        OMSourcedElement element = new OMSourcedElementImpl(qname, factory,
+                new WrappedTextNodeOMDataSource(qname, ds, cs));
+        Reader in = ElementHelper.getTextAsStream(element, true);
+        assertFalse(in instanceof StringReader);
+        compareStreams(new InputStreamReader(ds.getInputStream(), cs), in);
+    }
+    
+    public void testGetTextAsStreamWithoutCaching() throws Exception {
+        DataSource ds = new RandomDataSource(654321, 64, 128, 20000000);
+        Vector<InputStream> v = new Vector<InputStream>();
+        v.add(new ByteArrayInputStream("<a>".getBytes("ascii")));
+        v.add(ds.getInputStream());
+        v.add(new ByteArrayInputStream("</a>".getBytes("ascii")));
+        XMLInputFactory factory = XMLInputFactory.newInstance();
+        factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.FALSE);
+        XMLStreamReader reader = factory.createXMLStreamReader(
+                new SequenceInputStream(v.elements()), "ascii");
+        OMElement element = new StAXOMBuilder(reader).getDocumentElement();
+        Reader in = ElementHelper.getTextAsStream(element, false);
+        compareStreams(new InputStreamReader(ds.getInputStream(), "ascii"), in);
+    }
+    
+    public void testWriteTextTo() throws Exception {
+        OMFactory factory = OMAbstractFactory.getOMFactory();
+        OMElement element = factory.createOMElement(new QName("a"));
+        factory.createOMText(element, "test");
+        StringWriter out = new StringWriter();
+        ElementHelper.writeTextTo(element, out, true);
+        assertEquals(element.getText(), out.toString());
+    }
+    
+    public void testWriteTextToWithNonTextNodes() throws Exception {
+        OMElement element = AXIOMUtil.stringToOM("<a>A<b>B</b>C</a>");
+        StringWriter out = new StringWriter();
+        ElementHelper.writeTextTo(element, out, true);
+        assertEquals(element.getText(), out.toString());
+    }
+    
+    public void testWriteTextToWithOMSourcedElement() throws Exception {
+        OMFactory factory = OMAbstractFactory.getOMFactory();
+        DataSource ds = new RandomDataSource(665544, 32, 128, 20000000);
+        QName qname = new QName("a");
+        OMSourcedElement element = new OMSourcedElementImpl(qname, factory,
+                new WrappedTextNodeOMDataSource(qname, ds, Charset.forName("ascii")));
+        Reader in = new InputStreamReader(ds.getInputStream(), "ascii");
+        Writer out = new CharacterStreamComparator(in);
+        ElementHelper.writeTextTo(element, out, true); // cache doesn't matter here
+        out.close();
+    }
+}

Propchange: webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/ElementHelperTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/RandomDataSource.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/RandomDataSource.java?rev=753373&view=auto
==============================================================================
--- webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/RandomDataSource.java (added)
+++ webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/RandomDataSource.java Fri Mar 13 20:04:50 2009
@@ -0,0 +1,70 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.axis2.format;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Random;
+
+import javax.activation.DataSource;
+
+public class RandomDataSource implements DataSource {
+    private final long seed;
+    private final int rangeStart;
+    private final int rangeEnd;
+    private final int length;
+
+    public RandomDataSource(long seed, int rangeStart, int rangeEnd, int length) {
+        this.seed = seed;
+        this.rangeStart = rangeStart;
+        this.rangeEnd = rangeEnd;
+        this.length = length;
+    }
+
+    public String getName() {
+        return null;
+    }
+    
+    public String getContentType() {
+        return null;
+    }
+    
+    public InputStream getInputStream() throws IOException {
+        final Random random = new Random(seed);
+        return new InputStream() {
+            private int position;
+            
+            @Override
+            public int read() throws IOException {
+                if (position == length) {
+                    return -1;
+                } else {
+                    position++;
+                    return random.nextInt(rangeEnd-rangeStart) + rangeStart;
+                }
+            }
+        };
+    }
+    
+    public OutputStream getOutputStream() throws IOException {
+        throw new UnsupportedOperationException();
+    }
+}

Propchange: webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/RandomDataSource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/TextFromElementReaderTest.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/TextFromElementReaderTest.java?rev=753373&view=auto
==============================================================================
--- webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/TextFromElementReaderTest.java (added)
+++ webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/TextFromElementReaderTest.java Fri Mar 13 20:04:50 2009
@@ -0,0 +1,45 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.axis2.format;
+
+import java.io.Reader;
+import java.io.StringReader;
+
+import javax.xml.stream.XMLStreamReader;
+
+import junit.framework.TestCase;
+
+import org.apache.axiom.om.util.StAXUtils;
+import org.apache.commons.io.IOUtils;
+
+// Note: this class only contains a single test method because most aspects of TextFromElementReader
+//       are actually tested by ElementHelperTest
+public class TextFromElementReaderTest extends TestCase {
+    /**
+     * Test that TextFromElementReader works correctly with a "naked" StAX parser.
+     * 
+     * @throws Exception
+     */
+    public void testStAX() throws Exception {
+        XMLStreamReader reader = StAXUtils.createXMLStreamReader(new StringReader("<a>test</a>"));
+        Reader in = new TextFromElementReader(reader);
+        assertEquals("test", IOUtils.toString(in));
+    }
+}

Propchange: webservices/commons/trunk/modules/transport/modules/base/src/test/java/org/apache/axis2/format/TextFromElementReaderTest.java
------------------------------------------------------------------------------
    svn:mergeinfo =