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 2010/05/23 09:25:58 UTC

svn commit: r947371 - in /webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder: SafeXMLStreamReader.java StAXBuilder.java StAXOMBuilder.java

Author: veithen
Date: Sun May 23 07:25:57 2010
New Revision: 947371

URL: http://svn.apache.org/viewvc?rev=947371&view=rev
Log:
Eliminated SafeXMLStreamReader (see WSCOMMONS-372) and integrated its code into StAX(OM)Builder.

Reason: Using an XMLStreamReader wrapper is easy and robust, but has two issues:
* It is not easy to distinguish between exceptions caused by parsing errors and exceptions caused by incorrect invocations of the reader.
* The wrapper sometimes gets in the way of other features; see WSCOMMONS-518 and WSCOMMONS-540.

Removed:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/SafeXMLStreamReader.java
Modified:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXBuilder.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXBuilder.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXBuilder.java?rev=947371&r1=947370&r2=947371&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXBuilder.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXBuilder.java Sun May 23 07:25:57 2010
@@ -106,6 +106,12 @@ public abstract class StAXBuilder implem
     protected int elementLevel = 0;
     
     /**
+     * Stores exceptions thrown by the parser. Used to avoid accessing the parser
+     * again after is has thrown a parse exception.
+     */
+    protected Exception parserException;
+    
+    /**
      * Constructor StAXBuilder.
      * This constructor is used if the parser is at the beginning (START_DOCUMENT).
      *
@@ -146,7 +152,7 @@ public abstract class StAXBuilder implem
             ((BuilderAwareReader) parser).setBuilder(this);
         }
         dataHandlerReader = DataHandlerReaderUtils.getDataHandlerReader(parser);
-        this.parser = new SafeXMLStreamReader(parser);
+        this.parser = parser;
     }
 
     /**
@@ -276,7 +282,16 @@ public abstract class StAXBuilder implem
             omContainer.addChild(text);
             return text;
         } else {
-            return omfactory.createOMText(omContainer, parser.getText(), textType);
+            // Some parsers (like Woodstox) parse text nodes lazily and may throw a
+            // RuntimeException in getText()
+            String text;
+            try {
+                text = parser.getText();
+            } catch (RuntimeException ex) {
+                parserException = ex;
+                throw ex;
+            }
+            return omfactory.createOMText(omContainer, text, textType);
         }
     }
 

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java?rev=947371&r1=947370&r2=947371&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/StAXOMBuilder.java Sun May 23 07:25:57 2010
@@ -52,6 +52,32 @@ import java.io.InputStream;
  * This class supports the {@link XMLStreamReader} extension defined by
  * {@link org.apache.axiom.ext.stax.datahandler.DataHandlerReader} as well as the legacy extension mechanism
  * defined in the documentation of {@link DataHandlerReaderUtils}.
+ * <h3>Error handling</h3>
+ * Usually, code that uses StAX directly just stops processing of an XML document
+ * once the first parsing error has been reported. However, since Axiom
+ * uses deferred parsing, and client code accesses the XML infoset using
+ * an object model, things are more complicated. Indeed, if the XML
+ * document is not well formed, the corresponding error might be reported
+ * as a runtime exception by any call to a method of an OM node.
+ * <p>
+ * Typically the client code will have some error handling that will intercept
+ * runtime exceptions and take appropriate action. Very often this error handling
+ * code might want to access the object model again, for example to log the request that caused the
+ * failure. This causes no problem except if the runtime exception was caused by a
+ * parsing error, in which case Axiom would again try to pull events from the parser.
+ * <p>
+ * This would lead to a situation where Axiom accesses a parser that has reported a parsing
+ * error before. While one would expect that after a first error reported by the parser, all
+ * subsequent invocations of the parser will fail, this is not the case for all parsers
+ * (at least not in all situations). Instead, the parser might be left in an inconsistent
+ * state after the error. E.g. WSCOMMONS-372 describes a case where Woodstox
+ * encounters an error in {@link XMLStreamReader#getText()} but continues to return
+ * (incorrect) events afterwards. The explanation for this behaviour might be that
+ * the situation described here is quite uncommon when StAX is used directly (i.e. not through
+ * Axiom).
+ * <p>
+ * To avoid this, the builder remembers exceptions thrown by the parser and rethrows
+ * them during a call to {@link #next()}.
  */
 public class StAXOMBuilder extends StAXBuilder {
     /** Field document */
@@ -633,7 +659,21 @@ public class StAXOMBuilder extends StAXB
             lookAheadToken = -1; // Reset
             return token;
         } else {
-            return parser.next();
+            if (parserException != null) {
+                log.warn("Attempt to access a parser that has thrown a parse exception before; " +
+                		"rethrowing the original exception.");
+                if (parserException instanceof XMLStreamException) {
+                    throw (XMLStreamException)parserException;
+                } else {
+                    throw (RuntimeException)parserException;
+                }
+            }
+            try {
+                return parser.next();
+            } catch (XMLStreamException ex) {
+                parserException = ex;
+                throw ex;
+            }
         }
     }