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 sc...@apache.org on 2006/10/18 02:16:41 UTC

svn commit: r465107 - in /webservices/commons/trunk/modules/axiom/modules: axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/ axiom-tests/src/test/java/org/apache/axiom/om/impl/llom/

Author: scheu
Date: Tue Oct 17 17:16:39 2006
New Revision: 465107

URL: http://svn.apache.org/viewvc?view=rev&rev=465107
Log:
WSCOMMONS-71
Contributor: Rich Scheuerle
Changes and Tests for errors found embedding OMSourcedElementImpl in an OM tree.

Modified:
    webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMNavigator.java
    webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMSourcedElementImpl.java
    webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/llom/OMSourcedElementTest.java

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMNavigator.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMNavigator.java?view=diff&rev=465107&r1=465106&r2=465107
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMNavigator.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMNavigator.java Tue Oct 17 17:16:39 2006
@@ -22,7 +22,7 @@
 import org.apache.axiom.om.OMNode;
 
 /**
- * Refer to the testClass to find out how to use
+ * Refer to the test, org.apache.axiom.om.OMNavigatorTest, to find out how to use
  * features like isNavigable, isComplete and step.
  */
 public class OMNavigator {
@@ -123,28 +123,63 @@
      * Private method to encapsulate the searching logic.
      */
     private void updateNextNode() {
-        if ((next instanceof OMElement) && !visited) {
-            OMElementImpl e = (OMElementImpl) next;
-            if (e.firstChild != null) {
-                next = e.firstChild;
-            } else if (e.isComplete()) {
-                backtracked = true;
-            } else {
-                next = null;
-            }
-        } else {
-            OMNode nextSibling = ((OMNodeImpl) next).nextSibling;
-            //OMNode parent = next.getParent();
-            OMContainer parent = next.getParent();
-            if (nextSibling != null) {
-                next = nextSibling;
-            } else if ((parent != null) && parent.isComplete() && !(parent instanceof OMDocument)) {
-                next = (OMNodeImpl) parent;
-                backtracked = true;
-            } else {
-                next = null;
-            }
-        }
+    	
+    	if ((next instanceof OMElement) && !visited) {
+    		OMNode firstChild = _getFirstChild((OMElement) next);
+    		if (firstChild != null) {
+    			next = firstChild;
+    		} else if (next.isComplete()) {
+    			backtracked = true;
+    		} else {
+    			next = null;
+    		}
+    	} else {
+    		OMContainer parent = next.getParent();
+    		OMNode nextSibling = _getNextSibling(next);
+    		if (nextSibling != null) {
+    			next = nextSibling;
+    		} else if ((parent != null) && parent.isComplete() && !(parent instanceof OMDocument)) {
+    			next = (OMNodeImpl) parent;
+    			backtracked = true;
+    		} else {
+    			next = null;
+    		}
+    	}
+    }
+    
+    /**
+     * @param node
+     * @return first child or null
+     */
+    private OMNode _getFirstChild(OMElement node) {
+    	if (node instanceof OMSourcedElementImpl) {
+    		OMNode first = node.getFirstOMChild();
+    		OMNode sibling = first;
+    		while (sibling != null) {
+    			sibling = sibling.getNextOMSibling();
+    		}
+    		return first;
+    	} else {
+    		// Field access is used to prevent advancing the parser.
+    		// Some tests fail if the following is used
+    		// return node.getFirstOMChild()
+    		return ((OMElementImpl)node).firstChild;
+    	}
+    }
+    
+    /**
+     * @param node
+     * @return next sibling or null
+     */
+    private OMNode _getNextSibling(OMNode node) {
+    	if (node instanceof OMSourcedElementImpl) {
+    		return node.getNextOMSibling();
+    	} else {
+    		// Field access is used to prevent advancing the parser.
+    		// Some tests fail if the following is used
+    		// return node.getNextOMSibling()
+    		return ((OMNodeImpl)node).nextSibling;
+    	}
     }
 
     /**

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMSourcedElementImpl.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMSourcedElementImpl.java?view=diff&rev=465107&r1=465106&r2=465107
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMSourcedElementImpl.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-impl/src/main/java/org/apache/axiom/om/impl/llom/OMSourcedElementImpl.java Tue Oct 17 17:16:39 2006
@@ -109,7 +109,13 @@
      */
     private XMLStreamReader getDirectReader() {
         try {
-            return dataSource.getReader();
+        	// If expansion has occurred, then the reader from the datasource is consumed or stale.
+        	// In such cases use the stream reader from the OMElementImpl
+        	if (isDataSourceConsumed()) {
+        		return super.getXMLStreamReader();
+        	} else {
+        		return dataSource.getReader();
+        	}
         } catch (XMLStreamException e) {
             log.error("Could not get parser from data source for element " +
                 getPrintableName(), e);
@@ -150,12 +156,14 @@
                 throw new RuntimeException("Element name from data source is " +
                     reader.getLocalName() + ", not the expected " + getLocalName());
             }
-            if (!reader.getNamespaceURI().equals(getNamespace().getNamespaceURI())) {
-                String uri = getNamespace().getNamespaceURI();
+            String readerURI = reader.getNamespaceURI();
+            readerURI = (readerURI == null) ? "" : readerURI;
+            String uri = getNamespace().getNamespaceURI();
+            if (!readerURI.equals(uri)) {
                 log.error("forceExpand: expected element namespace " +
                     getLocalName() + ", found " + uri);
                 throw new RuntimeException("Element namespace from data source is " +
-                    reader.getNamespaceURI() + ", not the expected " + uri);
+                    readerURI + ", not the expected " + uri);
             }
             
             // set the builder for this element
@@ -173,6 +181,16 @@
     public boolean isExpanded() {
         return isParserSet;
     }
+    
+    /**
+     * Returns whether the datasource is consumed
+     */
+    private boolean isDataSourceConsumed() {
+    	// The datasource might be consumed when it is touched/read.  
+    	// For now I am going to assume that it is since the OMDataSource currently has
+    	// no way to convey this information.
+    	return isExpanded();
+    }
 
     /* (non-Javadoc)
      * @see org.apache.axiom.om.OMElement#getChildElements()
@@ -421,7 +439,7 @@
      * @see org.apache.axiom.om.OMElement#getQName()
      */
     public QName getQName() {
-        if (isParserSet) {
+        if (isExpanded()) {
             return super.getQName();
         } else if (definedNamespace != null) {
             // always ignore prefix on name from sourced element
@@ -436,9 +454,13 @@
      * @see org.apache.axiom.om.OMElement#toStringWithConsume()
      */
     public String toStringWithConsume() throws XMLStreamException {
-        StringWriter writer = new StringWriter();
-        dataSource.serialize(writer, null);
-        return writer.toString();
+    	if (isDataSourceConsumed()) {
+        	return super.toStringWithConsume();
+        } else {
+        	StringWriter writer = new StringWriter();
+        	dataSource.serialize(writer, null);
+        	return writer.toString();
+        }
     }
 
     /* (non-Javadoc)
@@ -494,14 +516,22 @@
      * @see org.apache.axiom.om.OMNode#internalSerialize(javax.xml.stream.XMLStreamWriter)
      */
     public void internalSerialize(javax.xml.stream.XMLStreamWriter writer) throws XMLStreamException {
-        internalSerializeAndConsume(writer);
+    	if (isDataSourceConsumed()) {
+    		super.internalSerialize(writer);
+    	} else {
+    		internalSerializeAndConsume(writer);
+    	}
     }
 
     /* (non-Javadoc)
      * @see org.apache.axiom.om.impl.llom.OMElementImpl#internalSerialize(javax.xml.stream.XMLStreamWriter, boolean)
      */
     protected void internalSerialize(XMLStreamWriter writer, boolean cache) throws XMLStreamException {
-        internalSerializeAndConsume(writer);
+    	if (isDataSourceConsumed()) {
+    		super.internalSerialize(writer, cache);
+    	} else {
+    		internalSerializeAndConsume(writer);
+    	}
     }
 
     /* (non-Javadoc)
@@ -511,7 +541,11 @@
         if (log.isDebugEnabled()) {
             log.debug("serialize " + getPrintableName() + " to XMLStreamWriter");
         }
-        dataSource.serialize(writer);
+        if (isDataSourceConsumed()) {
+        	super.internalSerializeAndConsume(writer);
+        } else {
+        	dataSource.serialize(writer);
+        }
     }
 
     /* (non-Javadoc)
@@ -563,7 +597,11 @@
         if (log.isDebugEnabled()) {
             log.debug("serialize " + getPrintableName() + " to output stream");
         }
-        dataSource.serialize(output, null);
+        if (isDataSourceConsumed()) {
+        	super.serializeAndConsume(output, null);
+        } else {
+        	dataSource.serialize(output, null);
+        }
     }
 
     /* (non-Javadoc)
@@ -573,7 +611,11 @@
         if (log.isDebugEnabled()) {
             log.debug("serialize " + getPrintableName() + " to writer");
         }
-        dataSource.serialize(writer, null);
+        if (isDataSourceConsumed()) {
+        	super.serializeAndConsume(writer);
+        } else {
+        	dataSource.serialize(writer, null);
+        }
     }
 
     /* (non-Javadoc)
@@ -584,7 +626,11 @@
             log.debug("serialize formatted " + getPrintableName() +
                 " to output stream");
         }
-        dataSource.serialize(output, format);
+        if (isDataSourceConsumed()) {
+        	super.serializeAndConsume(output, format);
+        } else {
+        	dataSource.serialize(output, format);
+        }
     }
 
     /* (non-Javadoc)
@@ -595,7 +641,11 @@
             log.debug("serialize formatted " + getPrintableName() +
                 " to writer");
         }
-        dataSource.serialize(writer, format);
+        if (isDataSourceConsumed()) {
+        	super.serializeAndConsume(writer, format);
+    	} else {
+    		dataSource.serialize(writer, format);
+    	}
     }
 
     /* (non-Javadoc)

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/llom/OMSourcedElementTest.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/llom/OMSourcedElementTest.java?view=diff&rev=465107&r1=465106&r2=465107
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/llom/OMSourcedElementTest.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/llom/OMSourcedElementTest.java Tue Oct 17 17:16:39 2006
@@ -18,10 +18,14 @@
 
 import org.apache.axiom.om.AbstractTestCase;
 import org.apache.axiom.om.OMDataSource;
+import org.apache.axiom.om.OMDocument;
 import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.OMFactory;
+import org.apache.axiom.om.OMNamespace;
 import org.apache.axiom.om.OMNode;
 import org.apache.axiom.om.OMOutputFormat;
 import org.apache.axiom.om.impl.OMNamespaceImpl;
+import org.apache.axiom.om.impl.builder.StAXOMBuilder;
 import org.apache.axiom.om.impl.llom.factory.OMLinkedListImplFactory;
 import org.apache.axiom.om.impl.serialize.StreamingOMSerializer;
 
@@ -31,6 +35,8 @@
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.XMLStreamWriter;
+
+import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -42,6 +48,9 @@
 import java.util.Arrays;
 import java.util.Iterator;
 
+/**
+ * Tests the characteristics of OMSourcedElementImpl.
+ */
 public class OMSourcedElementTest extends AbstractTestCase {
     private static String testDocument =
         "<library xmlns='http://www.sosnoski.com/uwjws/library' books='1'>" +
@@ -53,6 +62,7 @@
         "<price>29.95</price></book></library>";
     
     private OMSourcedElementImpl element;
+    private OMElement root;
 
     /**
      * @param testName
@@ -62,11 +72,17 @@
     }
 
     protected void setUp() throws Exception {
-        element = new OMSourcedElementImpl("library",
-            new OMNamespaceImpl("http://www.sosnoski.com/uwjws/library", ""),
-                new OMLinkedListImplFactory(), new TestDataSource(testDocument));
+        OMFactory f = new OMLinkedListImplFactory();
+        OMNamespace ns = new OMNamespaceImpl("http://www.sosnoski.com/uwjws/library", "");
+        OMNamespace rootNS = new OMNamespaceImpl("http://sampleroot", "rootPrefix");
+        element = new OMSourcedElementImpl("library", ns, f, new TestDataSource(testDocument));
+        root = f.createOMElement("root", rootNS);
+        root.addChild(element);
     }
     
+    /**
+     * Ensure that each method of OMElementImpl is overridden in OMSourcedElementImpl
+     */
     public void testMethodOverrides() {
         Method[] submeths = OMSourcedElementImpl.class.getDeclaredMethods();
         Method[] supmeths = OMElementImpl.class.getDeclaredMethods();
@@ -97,6 +113,10 @@
         return count;
     }
     
+    /**
+     * Test serialization of OMSourcedElementImpl to a Stream
+     * @throws Exception
+     */
     public void testSerializeToStream() throws Exception {
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
         element.serialize(bos);
@@ -105,13 +125,22 @@
         assertFalse("Element expansion when serializing", element.isExpanded());
     }
     
+    /**
+     * Test serialization of OMSourcedElementImpl to a Writer
+     * @throws Exception
+     */
     public void testSerializeToWriter() throws Exception {
         StringWriter writer = new StringWriter();
         element.serialize(writer);
-        assertEquals("Serialized text error", testDocument, writer.toString());
+        String result = writer.toString();
+        assertEquals("Serialized text error", testDocument, result);
         assertFalse("Element expansion when serializing", element.isExpanded());
     }
     
+    /**
+     * Test serialization of OMSourcedElementImpl to an XMLWriter
+     * @throws Exception
+     */
     public void testSerializeToXMLWriter() throws Exception {
         StringWriter writer = new StringWriter();
         XMLStreamWriter xmlwriter = XMLOutputFactory.newInstance().createXMLStreamWriter(writer);
@@ -120,7 +149,76 @@
         assertEquals("Serialized text error", testDocument, writer.toString());
         assertFalse("Element expansion when serializing", element.isExpanded());
     }
+    
+    /**
+     * Tests OMSourcedElement serialization when the root (parent) is serialized.
+     * @throws Exception
+     */
+    public void testSerializeToXMLWriterEmbedded() throws Exception {
+        StringWriter writer = new StringWriter();
+        XMLStreamWriter xmlwriter = XMLOutputFactory.newInstance().createXMLStreamWriter(writer);
+        root.serialize(writer);
+        xmlwriter.flush();
+        String result = writer.toString();
+        // We can't test for equivalence because the underlying OMSourceElement is 
+        // streamed as it is serialized.  So I am testing for an internal value.
+        assertTrue("Serialized text error" + result, result.indexOf("1930110111") > 0);
+        assertFalse("Element expansion when serializing", element.isExpanded());
+    }
+    
+    /**
+     * Tests OMSourcedElement getReader support
+     * @throws Exception
+     */
+    public void testSerializeToXMLWriterFromReader() throws Exception {
+        StringWriter writer = new StringWriter();
+        XMLStreamWriter xmlwriter = XMLOutputFactory.newInstance().createXMLStreamWriter(writer);
+        
+        StAXOMBuilder builder = new StAXOMBuilder(element.getXMLStreamReader());  
+        OMDocument omDocument = builder.getDocument();
+        Iterator it = omDocument.getChildren();
+        while(it.hasNext()) {
+            OMNode omNode = (OMNode) it.next();
+            omNode.serializeAndConsume(xmlwriter);
+        }
+        
+        xmlwriter.flush();
+        String result = writer.toString();
+        // We can't test for equivalence because the underlying OMSourceElement is 
+        // changed as it is serialized.  So I am testing for an internal value.
+        assertTrue("Serialized text error" + result, result.indexOf("1930110111") > 0);
+        assertFalse("Element expansion when serializing", element.isExpanded());
+    }
+    
+    /**
+     * Tests OMSourcedElement processing when the getReader() of the parent is accessed.
+     * @throws Exception
+     */
+    public void testSerializeToXMLWriterFromReaderEmbedded() throws Exception {
+        StringWriter writer = new StringWriter();
+        XMLStreamWriter xmlwriter = XMLOutputFactory.newInstance().createXMLStreamWriter(writer);
+        
+        StAXOMBuilder builder = new StAXOMBuilder(root.getXMLStreamReader());  
+        OMDocument omDocument = builder.getDocument();
+        Iterator it = omDocument.getChildren();
+        while(it.hasNext()) {
+            OMNode omNode = (OMNode) it.next();
+            omNode.serializeAndConsume(xmlwriter);
+        }
+        xmlwriter.flush();
+        String result = writer.toString();
+        // We can't test for equivalence because the underlying OMSourceElement is 
+        // changed as it is serialized.  So I am testing for an internal value.
+        assertTrue("Serialized text error" + result, result.indexOf("1930110111") > 0);
+        // The implementation uses OMNavigator to walk the tree.  Currently OMNavigator must 
+        // expand the OMSourcedElement to correctly walk the elements. (See OMNavigator._getFirstChild)
+        //assertFalse("Element expansion when serializing", element.isExpanded());
+    }
 
+    /**
+     * Make sure the expanded OMSourcedElement behaves like a normal OMElement.
+     * @throws Exception
+     */
     public void testExpand() throws Exception {
         element.getAllDeclaredNamespaces();
         assertEquals("Expanded namespace count error", 1,
@@ -146,10 +244,13 @@
     }
     
     private static class TestDataSource implements OMDataSource {
-        private final String data;
+        // The data source is a ByteArrayInputStream so that we can verify that the datasource 
+        // is only accessed once.  Currently there is no way to identify a destructive vs. non-destructive OMDataSource.
+        private final ByteArrayInputStream data;
         
         private TestDataSource(String data) {
-            this.data = data;
+            this.data = new ByteArrayInputStream(data.getBytes());
+            this.data.mark(0);
         }
 
         /* (non-Javadoc)
@@ -157,7 +258,7 @@
          */
         public void serialize(OutputStream output, OMOutputFormat format) throws XMLStreamException {
             try {
-                output.write(data.getBytes());
+                output.write(getBytes());
             } catch (IOException e) {
                 throw new XMLStreamException(e);
             }
@@ -168,7 +269,7 @@
          */
         public void serialize(Writer writer, OMOutputFormat format) throws XMLStreamException {
             try {
-                writer.write(data);
+                writer.write(getString());
             } catch (IOException e) {
                 throw new XMLStreamException(e);
             }
@@ -187,7 +288,24 @@
          */
         public XMLStreamReader getReader() throws XMLStreamException {
             XMLInputFactory inputFactory = XMLInputFactory.newInstance();
-            return inputFactory.createXMLStreamReader(new StringReader(data));
+            return inputFactory.createXMLStreamReader(new StringReader(getString()));
+        }
+        
+        private byte[] getBytes() throws XMLStreamException {
+            try {
+                // The data from the data source should only be accessed once
+                //data.reset();
+                byte[] rc = new byte[data.available()];
+                data.read(rc);
+                return rc;
+            } catch (IOException io) {
+                throw new XMLStreamException(io);
+            }
+        }
+        
+        private String getString() throws XMLStreamException {
+            String text = new String(getBytes());
+            return text;
         }
     }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: commons-dev-help@ws.apache.org