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