Author: veithen
Date: Tue Dec 16 02:39:23 2008
New Revision: 727013
URL: http://svn.apache.org/viewvc?rev=727013&view=rev
Log:
WSCOMMONS-372: Added a mechanism that prevents Axiom from requesting new events
from a parser that has reported a parsing error before. This avoids problems
with parsers that are left in an inconsistent state after a parsing error and
continue to return (incorrect) events.
Added:
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
Added:
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=727013&view=auto
==============================================================================
---
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/SafeXMLStreamReader.java
(added)
+++
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/builder/SafeXMLStreamReader.java
Tue Dec 16 02:39:23 2008
@@ -0,0 +1,211 @@
+/*
+ * 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.om.impl.builder;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.util.StreamReaderDelegate;
+
+/**
+ * XMLStreamReader wrapper that prevents access to the underlying parser
+ * after the first error occurs.
+ * <p>
+ * 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>
+ * This class provides a simple way to prevent this type of issue by wrapping
the underlying
+ * parser implementation. After the first parsing error occurs, the wrapper
prevents any call
+ * 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 {
+ private boolean parserError;
+
+ public SafeXMLStreamReader(XMLStreamReader reader) {
+ super(reader);
+ }
+
+ private void checkError() throws XMLStreamException {
+ if (parserError) {
+ throw new XMLStreamException(
+ "Trying to read events from a parser that already reported
an error before");
+ }
+ }
+
+ public String getElementText() throws XMLStreamException {
+ try {
+ return super.getElementText();
+ } catch (XMLStreamException ex) {
+ parserError = true;
+ throw ex;
+ } catch (RuntimeException ex) {
+ parserError = true;
+ throw ex;
+ } catch (Error ex) {
+ parserError = true;
+ throw ex;
+ }
+ }
+
+ public String getPIData() {
+ try {
+ return super.getPIData();
+ } catch (RuntimeException ex) {
+ parserError = true;
+ throw ex;
+ } catch (Error ex) {
+ parserError = true;
+ throw ex;
+ }
+ }
+
+ public String getText() {
+ try {
+ return super.getText();
+ } catch (RuntimeException ex) {
+ parserError = true;
+ throw ex;
+ } catch (Error ex) {
+ parserError = true;
+ throw ex;
+ }
+ }
+
+ public char[] getTextCharacters() {
+ try {
+ return super.getTextCharacters();
+ } catch (RuntimeException ex) {
+ parserError = true;
+ throw ex;
+ } catch (Error ex) {
+ parserError = true;
+ throw ex;
+ }
+ }
+
+ public int getTextCharacters(int sourceStart, char[] target, int
targetStart, int length)
+ throws XMLStreamException {
+ checkError();
+ try {
+ return super.getTextCharacters(sourceStart, target, targetStart,
length);
+ } catch (XMLStreamException ex) {
+ parserError = true;
+ throw ex;
+ } catch (RuntimeException ex) {
+ parserError = true;
+ throw ex;
+ } catch (Error ex) {
+ parserError = true;
+ throw ex;
+ }
+ }
+
+ public int getTextLength() {
+ try {
+ return super.getTextLength();
+ } catch (RuntimeException ex) {
+ parserError = true;
+ throw ex;
+ } catch (Error ex) {
+ parserError = true;
+ throw ex;
+ }
+ }
+
+ public int getTextStart() {
+ try {
+ return super.getTextStart();
+ } catch (RuntimeException ex) {
+ parserError = true;
+ throw ex;
+ } catch (Error ex) {
+ parserError = true;
+ throw ex;
+ }
+ }
+
+ public boolean hasNext() throws XMLStreamException {
+ checkError();
+ try {
+ return super.hasNext();
+ } catch (XMLStreamException ex) {
+ parserError = true;
+ throw ex;
+ } catch (RuntimeException ex) {
+ parserError = true;
+ throw ex;
+ } catch (Error ex) {
+ parserError = true;
+ throw ex;
+ }
+ }
+
+ public int next() throws XMLStreamException {
+ checkError();
+ try {
+ return super.next();
+ } catch (XMLStreamException ex) {
+ parserError = true;
+ throw ex;
+ } catch (RuntimeException ex) {
+ parserError = true;
+ throw ex;
+ } catch (Error ex) {
+ parserError = true;
+ throw ex;
+ }
+ }
+
+ public int nextTag() throws XMLStreamException {
+ checkError();
+ try {
+ return super.nextTag();
+ } catch (XMLStreamException ex) {
+ parserError = true;
+ throw ex;
+ } catch (RuntimeException ex) {
+ parserError = true;
+ throw ex;
+ } catch (Error ex) {
+ parserError = true;
+ throw ex;
+ }
+ }
+}
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=727013&r1=727012&r2=727013&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
Tue Dec 16 02:39:23 2008
@@ -116,7 +116,6 @@
* @param parser
*/
protected StAXBuilder(OMFactory ombuilderFactory, XMLStreamReader parser) {
- this.parser = parser;
omfactory = ombuilderFactory;
// The getCharacterEncodingScheme and getEncoding information are
@@ -126,9 +125,7 @@
charEncoding = parser.getEncoding();
}
- if (parser instanceof BuilderAwareReader) {
- ((BuilderAwareReader) parser).setBuilder(this);
- }
+ initParser(parser);
}
/**
@@ -142,13 +139,16 @@
protected StAXBuilder(OMFactory ombuilderFactory,
XMLStreamReader parser,
String characterEncoding) {
- this.parser = parser;
omfactory = ombuilderFactory;
charEncoding = characterEncoding;
-
+ initParser(parser);
+ }
+
+ private void initParser(XMLStreamReader parser) {
if (parser instanceof BuilderAwareReader) {
((BuilderAwareReader) parser).setBuilder(this);
}
+ this.parser = new SafeXMLStreamReader(parser);
}
/**