Author: scheu
Date: Tue Jan 19 22:46:32 2010
New Revision: 900993

URL: http://svn.apache.org/viewvc?rev=900993&view=rev
Log:
WSCOMMONS-518
Contributor: Rich Scheuerle
Analysis: Doug Larson
Summary of Problem:
The new XMLStreamReader wrappers and delegates in Axiom prevent consumers from 
directly accessing the original
parser.  This has caused regressions for some users.
Summary of Solution:
The XMLStreamReader wrappers and delegates remain intact.  Some of them have 
been marked with a new marker interface, XMLStreamReaderContainer.  New utility 
methods are added to XMLStreamReaderUtils to allow a consumer to access the 
original XMLStreamReader.

Tests are added to verify the function.

Note that an OMStAXWRapper is not an XMLStreamReaderContainer.  An 
OMStaXWrapper actually wraps a OM tree and
adapts it to an XMLStreamReader interface (versus wrapping an actual live 
parser).

Added:
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/wrapper/XMLStreamReaderContainer.java
Modified:
    
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/builder/SafeXMLStreamReader.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/XMLStreamReaderUtils.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/wrapper/XMLStreamReaderWrapper.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPDecodingStreamReader.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamReader.java
    
webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/mtom/MTOMStAXSOAPModelBuilderTest.java

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=900993&r1=900992&r2=900993&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
 Tue Jan 19 22:46:32 2010
@@ -41,6 +41,8 @@
 
 /**
  * {...@link XMLStreamReader} implementation that generates events from a 
given Axiom tree.
+ * This class does intentionally does not implement XMLStreamReaderContainer 
because
+ * it does not wrap a parser (it wraps an OM graph).
  */
 public class OMStAXWrapper extends StreamReaderDelegate implements 
OMXMLStreamReader {
     private static final Log log = LogFactory.getLog(OMStAXWrapper.class);

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/SafeXMLStreamReader.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/SafeXMLStreamReader.java?rev=900993&r1=900992&r2=900993&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/SafeXMLStreamReader.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/SafeXMLStreamReader.java
 Tue Jan 19 22:46:32 2010
@@ -23,6 +23,8 @@
 import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.util.StreamReaderDelegate;
 
+import org.apache.axiom.util.stax.wrapper.XMLStreamReaderContainer;
+
 /**
  * XMLStreamReader wrapper that prevents access to the underlying parser
  * after the first error occurs.
@@ -55,7 +57,7 @@
  * to {...@link XMLStreamReader#next()} and similar methods on the underlying 
parser.
  * Any attempt to do so will immediately result in an error.
  */
-public class SafeXMLStreamReader extends StreamReaderDelegate {
+public class SafeXMLStreamReader extends StreamReaderDelegate implements 
XMLStreamReaderContainer {
     private boolean parserError;
 
     public SafeXMLStreamReader(XMLStreamReader reader) {

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/XMLStreamReaderUtils.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/XMLStreamReaderUtils.java?rev=900993&r1=900992&r2=900993&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/XMLStreamReaderUtils.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/XMLStreamReaderUtils.java
 Tue Jan 19 22:46:32 2010
@@ -26,12 +26,19 @@
 
 import org.apache.axiom.attachments.ByteArrayDataSource;
 import org.apache.axiom.ext.stax.datahandler.DataHandlerReader;
+import org.apache.axiom.om.OMAttachmentAccessor;
 import org.apache.axiom.om.util.Base64;
+import org.apache.axiom.util.stax.wrapper.XMLStreamReaderContainer;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
 /**
  * Contains utility methods to work with {...@link XMLStreamReader} objects.
  */
 public class XMLStreamReaderUtils {
+    
+    private static Log log = LogFactory.getLog(XMLStreamReaderUtils.class);
+   
     /**
      * Get the {...@link DataHandlerReader} extension from a given {...@link 
XMLStreamReader}.
      * 
@@ -108,4 +115,60 @@
         }
         return new DataHandler(new ByteArrayDataSource(Base64.decode(base64)));
     }
+    
+    /**
+     * getOriginalXMLStreamReader
+     * Searches the wrapper and delegate classes to find the original 
XMLStreamReader
+     * This method should only be used when a consumer of Axiom really needs 
to 
+     * access the original stream reader.
+     * @param parser XMLStreamReader used by Axiom
+     * @return original parser 
+     */
+    public static XMLStreamReader getOriginalXMLStreamReader(XMLStreamReader 
parser) {
+        if (log.isDebugEnabled()) {
+            String clsName = (parser != null) ? parser.getClass().toString() : 
"null";
+            log.debug("Entry getOriginalXMLStreamReader: " + clsName);
+        }
+        while (parser instanceof XMLStreamReaderContainer) {
+            parser = ((XMLStreamReaderContainer) parser).getParent();
+            if (log.isDebugEnabled()) {
+                String clsName = (parser != null) ? 
parser.getClass().toString() : "null";
+                log.debug("  parent: " + clsName);
+            }
+        }
+        if (log.isDebugEnabled()) {
+            String clsName = (parser != null) ? parser.getClass().toString() : 
"null";
+            log.debug("Exit getOriginalXMLStreamReader: " + clsName);
+        }
+        return parser;
+    }
+    
+    /**
+     * Searches the wrapper and delegate classes to find an XMLStreamReader
+     * that implements the OMAttachmentAccessor
+     * @param parser
+     * @return XMLStreamREader that implements OMAttachmentAccessor or null
+     */
+    public static XMLStreamReader 
getOMAttachmentAccessorXMLStreamReader(XMLStreamReader parser) {
+        if (log.isDebugEnabled()) {
+            String clsName = (parser != null) ? parser.getClass().toString() : 
"null";
+            log.debug("Entry getOMAttachmentAccessorXMLStreamReader: " + 
clsName);
+        }
+        while (!(parser instanceof OMAttachmentAccessor) &&
+                (parser instanceof XMLStreamReaderContainer)) {
+            parser = ((XMLStreamReaderContainer) parser).getParent();
+            if (log.isDebugEnabled()) {
+                String clsName = (parser != null) ? 
parser.getClass().toString() : "null";
+                log.debug("  parent: " + clsName);
+            }
+        }
+        if (!(parser instanceof OMAttachmentAccessor)) {
+            parser = null;
+        }
+        if (log.isDebugEnabled()) {
+            String clsName = (parser != null) ? parser.getClass().toString() : 
"null";
+            log.debug("Exit getOMAttachmentAccessorXMLStreamReader: " + 
clsName);
+        }
+        return parser;
+    }
 }

Added: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/wrapper/XMLStreamReaderContainer.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/wrapper/XMLStreamReaderContainer.java?rev=900993&view=auto
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/wrapper/XMLStreamReaderContainer.java
 (added)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/wrapper/XMLStreamReaderContainer.java
 Tue Jan 19 22:46:32 2010
@@ -0,0 +1,37 @@
+/*
+ * 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.axiom.util.stax.wrapper;
+
+import javax.xml.stream.XMLStreamReader;
+
+/**
+ * Marker interface for Axiom XMLStreamReader classes that
+ * wrap or delegate to another (parent) XMLStreamReader.
+ * 
+ * The marker interface is necessary so that consumers 
+ * can access the original parser.
+ * @see XMLStreamReaderUtils
+ * 
+ * Note that the only the getParent() method is applicable.
+ * Please do not add a setParent() method since that would
+ * violate the immutable characteristic of the XMLStreamReaderWrapper
+ */
+public interface XMLStreamReaderContainer {
+    XMLStreamReader getParent();
+}

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/wrapper/XMLStreamReaderWrapper.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/wrapper/XMLStreamReaderWrapper.java?rev=900993&r1=900992&r2=900993&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/wrapper/XMLStreamReaderWrapper.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/wrapper/XMLStreamReaderWrapper.java
 Tue Jan 19 22:46:32 2010
@@ -31,7 +31,7 @@
  * similar to {...@link javax.xml.stream.util.StreamReaderDelegate}, with the 
difference that it is
  * immutable.
  */
-public class XMLStreamReaderWrapper implements XMLStreamReader {
+public class XMLStreamReaderWrapper implements XMLStreamReader, 
XMLStreamReaderContainer {
     private final XMLStreamReader parent;
 
     /**
@@ -42,6 +42,15 @@
     public XMLStreamReaderWrapper(XMLStreamReader parent) {
         this.parent = parent;
     }
+    
+    /**
+     * Get Parent
+     * Note that setParent is intentionally omitted.  XMLStreamReaderWrapper 
is immutable.
+     * @return XMLStreamReader parent
+     */
+    public XMLStreamReader getParent() {
+        return parent;
+    }
 
     public void close() throws XMLStreamException {
         parent.close();

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPDecodingStreamReader.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPDecodingStreamReader.java?rev=900993&r1=900992&r2=900993&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPDecodingStreamReader.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPDecodingStreamReader.java
 Tue Jan 19 22:46:32 2010
@@ -35,6 +35,7 @@
 import org.apache.axiom.ext.stax.datahandler.DataHandlerReader;
 import org.apache.axiom.om.util.StAXUtils;
 import org.apache.axiom.util.base64.Base64Utils;
+import org.apache.axiom.util.stax.wrapper.XMLStreamReaderContainer;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -56,7 +57,8 @@
  * {...@link DataHandlerReader#getDataHandlerProvider()}, then the {...@link 
MimePartProvider} will only
  * be invoked when {...@link DataHandlerProvider#getDataHandler()} is called.
  */
-public class XOPDecodingStreamReader extends StreamReaderDelegate implements 
XMLStreamReader, DataHandlerReader {
+public class XOPDecodingStreamReader extends StreamReaderDelegate 
+    implements XMLStreamReader, DataHandlerReader, XMLStreamReaderContainer {
     private static final String SOLE_CHILD_MSG =
             "Expected xop:Include as the sole child of an element information 
item (see section " +
             "3.2 of http://www.w3.org/TR/xop10/)";

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamReader.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamReader.java?rev=900993&r1=900992&r2=900993&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamReader.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/xop/XOPEncodingStreamReader.java
 Tue Jan 19 22:46:32 2010
@@ -33,6 +33,7 @@
 import javax.xml.stream.XMLStreamReader;
 
 import org.apache.axiom.ext.stax.datahandler.DataHandlerReader;
+import org.apache.axiom.util.stax.wrapper.XMLStreamReaderContainer;
 
 /**
  * {...@link XMLStreamReader} wrapper that encodes XOP. It assumes that the 
underlying reader
@@ -52,7 +53,8 @@
  * This class defers loading of {...@link DataHandler} objects until {...@link 
#getDataHandler(String)} is
  * called, except if this is not supported by the underlying stream.
  */
-public class XOPEncodingStreamReader extends XOPEncodingStreamWrapper 
implements XMLStreamReader {
+public class XOPEncodingStreamReader extends XOPEncodingStreamWrapper 
+    implements XMLStreamReader, XMLStreamReaderContainer {
     /**
      * Wrapper that adds the XOP namespace to another namespace context.
      */
@@ -530,4 +532,8 @@
             default: return parent.isEndElement();
         }
     }
+
+    public XMLStreamReader getParent() {
+        return parent;
+    }
 }

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/mtom/MTOMStAXSOAPModelBuilderTest.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/mtom/MTOMStAXSOAPModelBuilderTest.java?rev=900993&r1=900992&r2=900993&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/mtom/MTOMStAXSOAPModelBuilderTest.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/mtom/MTOMStAXSOAPModelBuilderTest.java
 Tue Jan 19 22:46:32 2010
@@ -28,10 +28,13 @@
 import org.apache.axiom.om.OMOutputFormat;
 import org.apache.axiom.om.OMText;
 import org.apache.axiom.om.OMXMLStreamReader;
+import org.apache.axiom.om.impl.OMStAXWrapper;
+import org.apache.axiom.om.impl.builder.StAXBuilder;
 import org.apache.axiom.om.impl.traverse.OMDescendantsIterator;
 import org.apache.axiom.om.util.StAXUtils;
 import org.apache.axiom.soap.SOAP12Constants;
 import org.apache.axiom.soap.impl.builder.MTOMStAXSOAPModelBuilder;
+import org.apache.axiom.util.stax.XMLStreamReaderUtils;
 
 import javax.activation.DataHandler;
 import javax.xml.namespace.QName;
@@ -79,6 +82,7 @@
         return createBuilderForTestMTOMMessage().getDocumentElement();
     }
     
+    
     private void checkSerialization(OMElement root, boolean optimize) throws 
Exception {
         OMOutputFormat format = new OMOutputFormat();
         format.setDoOptimize(optimize);
@@ -95,6 +99,45 @@
         }
     }
     
+    public void testAccessToParser() throws Exception {
+        OMElement root = createTestMTOMMessage();
+        StAXBuilder builder = (StAXBuilder) root.getBuilder();
+        // Disable caching so that the reader can be accessed.
+        builder.setCache(false);
+        XMLStreamReader reader = (XMLStreamReader) builder.getParser();
+        
+        XMLStreamReader original = 
XMLStreamReaderUtils.getOriginalXMLStreamReader(reader);
+        
+        // The streaming parser is wrapped by a SafeXMLStreamReader and 
dialect readers.
+        // Thus the reader and original readers will not be the same.
+        assertTrue(reader != original);
+        
+        // The streaming parser will not have access to the attachments.  Thus 
this will
+        // return null
+        XMLStreamReader attachmentAccessor = 
+            
XMLStreamReaderUtils.getOMAttachmentAccessorXMLStreamReader(reader);
+        
+        assertTrue(attachmentAccessor == null);
+        
+    }
+    
+    public void testAccessToCachedParser() throws Exception {
+        OMElement root = createTestMTOMMessage();
+        XMLStreamReader reader = root.getXMLStreamReader(true);
+        
+        XMLStreamReader original = 
XMLStreamReaderUtils.getOriginalXMLStreamReader(reader);
+        
+        // The caching parser will be an OMStaXWrapper.
+        assertTrue(original instanceof OMStAXWrapper);
+        
+        XMLStreamReader attachmentAccessor = 
+            
XMLStreamReaderUtils.getOMAttachmentAccessorXMLStreamReader(reader);
+        
+        // Thus the attachmentAccessor should also be the OMStaXWrapper
+        assertTrue(attachmentAccessor instanceof OMStAXWrapper);
+        
+    }
+    
     public void testCreateOMElement() throws Exception {
         OMElement root = createTestMTOMMessage();
         OMElement body = (OMElement) root.getFirstOMChild();


Reply via email to