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);
     }
 
     /**


Reply via email to