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;
+            }
         }
     }
     


Reply via email to