You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by sk...@apache.org on 2005/02/09 08:24:51 UTC

svn commit: r153033 - in jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2: Context.java SAXHandler.java

Author: skitching
Date: Tue Feb  8 23:24:49 2005
New Revision: 153033

URL: http://svn.apache.org/viewcvs?view=rev&rev=153033
Log:
Move several variables that evolve during a parse from the SAXHandler to
the Context class. In most cases, the related methods that modify them 
have been moved too. In particular, the following have been moved:
 * documentLocator
 * contentHandler
 * bodyText/bodyTexts
 * namespaces 

Modified:
    jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/Context.java
    jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/SAXHandler.java

Modified: jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/Context.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/Context.java?view=diff&r1=153032&r2=153033
==============================================================================
--- jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/Context.java (original)
+++ jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/Context.java Tue Feb  8 23:24:49 2005
@@ -23,6 +23,12 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.EmptyStackException;
+import java.lang.reflect.InvocationTargetException;
+
+import org.xml.sax.Locator;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
 
 import org.apache.commons.logging.Log;
 
@@ -76,6 +82,53 @@
     private Log log;
 
     /**
+     * The Locator associated with our parser object. This object can be
+     * consulted to find out which line of the input xml document we are
+     * currently on - very useful when generating error messages.
+     */
+    private Locator documentLocator = null;
+
+    /**
+     * Registered namespaces we are currently processing.  The key is the
+     * namespace prefix that was declared in the document.  The value is an
+     * ArrayStack of the namespace URIs this prefix has been mapped to --
+     * the top Stack element is the most current one.  (This architecture
+     * is required because documents can declare nested uses of the same
+     * prefix for different Namespace URIs).
+     * <p>
+     * TODO: move this data to the Context.
+     */
+    private HashMap namespaces = new HashMap();
+
+    /**
+     * If not null, then calls to the saxHandler's characters, startElement, 
+     * endElement and processingInstruction methods are forwarded to the 
+     * specified object. This is intended to allow rules to temporarily 
+     * "take control" of the sax events. In particular, this is used by 
+     * NodeCreateAction.
+     */
+    private ContentHandler contentHandler = null;
+
+    /**
+     * The body text of the current element. As the parser reports chunks
+     * of text associated with the current element, they are appended here.
+     * When the end of the element is reported, the full text content of the
+     * current element should be here. Note that if the element has mixed
+     * content, ie text intermingled with child elements, then this buffer
+     * ends up with all the different text pieces appended to form one string.
+     */
+    private StringBuffer bodyText = new StringBuffer();
+
+    /**
+     * When processing an element with mixed content (ie text and child
+     * elements), then when we start a child element we need to store the
+     * current text seen so far, and restore it after we have finished
+     * with the child element. This stack therefore contains StringBuffer
+     * items containing the body text of "interrupted" xml elements.
+     */
+    private ArrayStack bodyTexts = new ArrayStack();
+
+    /**
      * Stack whose elements are List objects, each containing a list of
      * Action objects as returned from RuleManager.getMatchingActions().
      * As each xml element in the input is entered, the list of matching
@@ -133,9 +186,10 @@
     /**
      * Construct a new Context.
      */
-    public Context(SAXHandler saxHandler, Log log) {
+    public Context(SAXHandler saxHandler, Log log, Locator locator) {
         this.saxHandler = saxHandler;
         this.log = log;
+        this.documentLocator = locator;
     }
 
     // ---------------------------------------------------
@@ -150,6 +204,111 @@
     }
 
     /**
+     * Gets the document locator associated with our parser. This object 
+     * can be consulted to find out which line of the input xml document 
+     * we are currently on - very useful when generating error messages.
+     *
+     * @return the Locator supplied by the document parser
+     */
+    public Locator getDocumentLocator() {
+        return documentLocator;
+    }
+
+    /**
+     * Return the currently mapped namespace URI for the specified prefix,
+     * if any; otherwise return <code>null</code>.  These mappings come and
+     * go dynamically as the document is parsed.
+     *
+     * @param prefix Prefix to look up
+     */
+    public String findNamespaceURI(String prefix) {
+        ArrayStack stack = (ArrayStack) namespaces.get(prefix);
+        if (stack == null) {
+            return null;
+        }
+        try {
+            return (String) stack.peek();
+        } catch (EmptyStackException e) {
+            // This should never happen, as endPrefixMapping removes
+            // the prefix from the namespaces map when the stack becomes
+            // empty. Still, better safe than sorry..
+            return null;
+        }
+    }
+
+    /**
+     * Register the specified prefix string as being an alias for the
+     * specified namespace uri.
+     */
+    public void pushNamespace(String prefix, String namespaceURI) {
+        ArrayStack stack = (ArrayStack) namespaces.get(prefix);
+        if (stack == null) {
+            stack = new ArrayStack();
+            namespaces.put(prefix, stack);
+        }
+        stack.push(namespaceURI);
+    }
+     
+    /**
+     * Unregister the specified prefix string as being an alias for the
+     * specified namespace uri.
+     */
+    public void popNamespace(String prefix) throws SAXException {
+        ArrayStack stack = (ArrayStack) namespaces.get(prefix);
+        if (stack == null) {
+            throw createSAXException(
+                "popNamespace called for unknown" +
+                "namespace prefix '" + prefix + "'");
+        }
+
+        try {
+            stack.pop();
+            if (stack.empty())
+                namespaces.remove(prefix);
+        } catch (EmptyStackException e) {
+            // This should never happen; it would indicate a serious
+            // internal software flaw. If a prefix has no mapping, then
+            // stack should have been null, not empty.
+            throw createSAXException(
+                "popNamespace called on prefix with empty stack.");
+        }
+    }
+
+    /**
+     * Save the buffer which is currently being used to accumulate text
+     * content of the current xml element. This is expected to be called
+     * just before starting processing of a child xml element.
+     */
+    public void pushBodyText() {
+        bodyTexts.push(bodyText);
+        bodyText = new StringBuffer();
+    }
+    
+    /**
+     * Restore a saved buffer. This is expected to be called just after
+     * completing processing of a child xml element, to continue accumulating
+     * text content for its parent.
+     */
+    public StringBuffer popBodyText() {
+        StringBuffer tmp = bodyText;
+        bodyText = (StringBuffer) bodyTexts.pop();
+        return tmp;
+    }
+    
+    /**
+     * Append more text to the buffer representing the text content of the
+     * current xml element. This is called in multiple stages because:
+     * <ul>
+     * <li>A sax parser is permitted to deliver a block of contiguous text
+     *   in multiple callbacks if it wishes, and
+     * <li>The text might be intermingled with child elements.
+     * </ul>
+     */
+    public void appendToBodyText(char[] buffer, int start, int length) {
+        bodyText.append(buffer, start, length);
+    }
+    
+    /**
      * Return the path to the xml element currently being processed.
      */
     public String getMatchPath() {
@@ -222,6 +381,30 @@
         return saxHandler;
     }
 
+    /**
+     * Specify a contentHandler to forward calls to. If non-null, then
+     * whenever this object receives calls from the XMLReader to any of
+     * the following methods, the call will be forwarded on to the specified
+     * objects instead of being processed in the normal manner.
+     * <p>
+     * This allows an Action to assume complete control of input handling
+     * for a period of time. For example, this allows the NodeCreateAction
+     * to build a DOM tree representing a portion of input.
+     * <p>
+     * Passing null restores normal operation, ie this object then resumes
+     * processing of the callbacks itself.
+     */
+    public void setContentHandler(ContentHandler contentHandler) {
+        this.contentHandler = contentHandler;
+    }
+
+    /**
+     * See {@link #setContentHandler}.
+     */
+    public ContentHandler getContentHandler() {
+        return contentHandler;
+    }
+
     // --------------------------------------------------- 
     // Object Stack Methods
     // --------------------------------------------------- 
@@ -582,5 +765,72 @@
         }
         
         return null;
+    }
+
+    /**
+     * Create a SAX exception which also understands about the location in
+     * the digester file where the exception occurs. This method is expected
+     * to be called by Action classes when they detect a problem.
+     *
+     * @return the new exception
+     */
+    public SAXException createSAXException(String message, Exception e) {
+        if ((e != null) &&
+            (e instanceof InvocationTargetException)) {
+            Throwable t = ((InvocationTargetException) e).getTargetException();
+            if ((t != null) && (t instanceof Exception)) {
+                e = (Exception) t;
+            }
+        }
+
+        if (documentLocator != null) {
+            String error = 
+                "Error at line " + documentLocator.getLineNumber() 
+                + ", column " + documentLocator.getColumnNumber()
+                + ": " + message;
+
+            if (e != null) {
+                return new SAXParseException(error, documentLocator, e);
+            } else {
+                return new SAXParseException(error, documentLocator);
+            }
+        }
+
+        // The SAX parser doesn't have location info enabled, so we'll just
+        // generate the best error message we can without it.
+        log.error("No Locator!");
+        if (e != null) {
+            return new SAXException(message, e);
+        } else {
+            return new SAXException(message);
+        }
+    }
+
+    /**
+     * Create a SAX exception which also understands about the location in
+     * the digester file where the exception occurs. This method is expected
+     * to be called by Action classes when they detect a problem.
+     *
+     * @return the new exception
+     */
+    public SAXException createSAXException(Exception e) {
+        if (e instanceof InvocationTargetException) {
+            Throwable t = ((InvocationTargetException) e).getTargetException();
+            if ((t != null) && (t instanceof Exception)) {
+                e = (Exception) t;
+            }
+        }
+        return createSAXException(e.getMessage(), e);
+    }
+
+    /**
+     * Create a SAX exception which also understands about the location in
+     * the digester file where the exception occurs. This method is expected
+     * to be called by Action classes when they detect a problem.
+     *
+     * @return the new exception
+     */
+    public SAXException createSAXException(String message) {
+        return createSAXException(message, null);
     }
 }

Modified: jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/SAXHandler.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/SAXHandler.java?view=diff&r1=153032&r2=153033
==============================================================================
--- jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/SAXHandler.java (original)
+++ jakarta/commons/proper/digester/branches/digester2/src/java/org/apache/commons/digester2/SAXHandler.java Tue Feb  8 23:24:49 2005
@@ -25,7 +25,6 @@
 import java.io.Reader;
 import java.io.StringReader;
 
-import java.lang.reflect.InvocationTargetException;
 import java.util.EmptyStackException;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -92,16 +91,9 @@
 
 public class SAXHandler extends DefaultHandler implements LexicalHandler {
 
-    // --------------------------------------------------------- Constructors
-
-    /**
-     * Construct a new SAXHandler.
-     */
-    public SAXHandler() {
-        super();
-    }
-
-    // --------------------------------------------------- Instance Variables
+    // --------------------------------------------------- 
+    // Instance Variables
+    // --------------------------------------------------- 
 
     /**
      * The EntityResolver used to look up any external entities referenced
@@ -122,11 +114,6 @@
     private ErrorHandler errorHandler = null;
 
     /**
-     * The Locator associated with our parser.
-     */
-    private Locator locator = null;
-
-    /**
      * A count of the number of entities resolved. Currently, we only
      * care whether this is zero or one, so a boolean could do as well.
      * However it seems likely that a count could be useful at some time.
@@ -216,57 +203,40 @@
     // -------------------------------------------------------------------
 
     /**
-     * If null, then calls to this objects' characters, startElement, endElement
-     * and processingInstruction methods are forwarded to the specified object.
-     * This is intended to allow rules to temporarily "take control" of the
-     * sax events. In particular, this is used by NodeCreateAction.
+     * The Locator associated with our parser object. This object can be
+     * consulted to find out which line of the input xml document we are
+     * currently on - very useful when generating error messages.
      */
-    private ContentHandler contentHandler = null;
+    private Locator documentLocator = null;
 
     /**
      * The public identifier of the DTD we are currently parsing under
      * (if any). See method {@link #startDTD}.
-     *
-     * TODO: Consider if this should be moved to Context.
+     * <p>
+     * Note that this info is not on the Context because the user may
+     * access this data after the parse has completed.
      */
     private String dtdPublicId = null;
 
     /**
      * The system identifier of the DTD we are currently parsing under
      * (if any). See method {@link #startDTD}.
-     *
-     * TODO: Consider if this should be moved to Context.
+     * <p>
+     * Note that this info is not on the Context because the user may
+     * access this data after the parse has completed.
      */
     private String dtdSystemId = null;
 
-    /**
-     * The body text of the current element. As the parser reports chunks
-     * of text associated with the current element, they are appended here.
-     * When the end of the element is reported, the full text content of the
-     * current element should be here. Note that if the element has mixed
-     * content, ie text intermingled with child elements, then this buffer
-     * ends up with all the different text pieces mixed together.
-     */
-    private StringBuffer bodyText = new StringBuffer();
+    // --------------------------------------------------------- 
+    // Constructors
+    // --------------------------------------------------------- 
 
     /**
-     * When processing an element with mixed content (ie text and child
-     * elements), then when we start a child element we need to store the
-     * current text seen so far, and restore it after we have finished
-     * with the child element. This stack therefore contains StringBuffer
-     * items containing the body text of "interrupted" xml elements.
-     */
-    private ArrayStack bodyTexts = new ArrayStack();
-
-    /**
-     * Registered namespaces we are currently processing.  The key is the
-     * namespace prefix that was declared in the document.  The value is an
-     * ArrayStack of the namespace URIs this prefix has been mapped to --
-     * the top Stack element is the most current one.  (This architecture
-     * is required because documents can declare nested uses of the same
-     * prefix for different Namespace URIs).
+     * Construct a new SAXHandler.
      */
-    private HashMap namespaces = new HashMap();
+    public SAXHandler() {
+        super();
+    }
 
     // ---------------------------------------------------------------------
     // General object configuration methods
@@ -319,30 +289,6 @@
     }
 
     /**
-     * Specify a contentHandler to forward calls to. If non-null, then
-     * whenever this object receives calls from the XMLReader to any of
-     * the following methods, the call will be forwarded on to the specified
-     * objects instead of being processed in the normal manner.
-     * <p>
-     * This allows an Action to assume complete control of input handling
-     * for a period of time. For example, this allows the NodeCreateAction
-     * to build a DOM tree representing a portion of input.
-     * <p>
-     * Passing null restores normal operation, ie this object then resumes
-     * processing of the callbacks itself.
-     */
-    public void setContentHandler(ContentHandler contentHandler) {
-        this.contentHandler = contentHandler;
-    }
-
-    /**
-     * See {@link #setContentHandler}.
-     */
-    public ContentHandler getContentHandler() {
-        return contentHandler;
-    }
-
-    /**
      * Get the public identifier of the DTD associated with the document
      * currently being parsed, or most recently parsed.
      * <p>
@@ -558,7 +504,7 @@
      * @param entityResolver a class that implement the
      * <code>EntityResolver</code> interface.
      */
-    public void setEntityResolver(EntityResolver entityResolver){
+    public void setEntityResolver(EntityResolver entityResolver) {
         this.entityResolver = entityResolver;
     }
 
@@ -566,7 +512,7 @@
      * Return the Entity Resolver used by the SAX parser.
      * @return Return the Entity Resolver used by the SAX parser.
      */
-    public EntityResolver getEntityResolver(){
+    public EntityResolver getEntityResolver() {
         return entityResolver;
     }
 
@@ -712,116 +658,11 @@
      * should be called to release this member.
      */
     public void clear() {
-        namespaces.clear();
-
         // It would be nice to set
         //   context = null;
         // but currently that would stuff up the getRoot() method.
     }
 
-    /**
-     * Return the currently mapped namespace URI for the specified prefix,
-     * if any; otherwise return <code>null</code>.  These mappings come and
-     * go dynamically as the document is parsed.
-     *
-     * @param prefix Prefix to look up
-     */
-    public String findNamespaceURI(String prefix) {
-        ArrayStack stack = (ArrayStack) namespaces.get(prefix);
-        if (stack == null) {
-            return null;
-        }
-        try {
-            return (String) stack.peek();
-        } catch (EmptyStackException e) {
-            // This should never happen, as endPrefixMapping removes
-            // the prefix from the namespaces map when the stack becomes
-            // empty. Still, better safe than sorry..
-            return null;
-        }
-    }
-
-    /**
-     * Gets the document locator associated with our parser.
-     * See {@link #setDocumentLocator}.
-     *
-     * @return the Locator supplied by the document parser
-     */
-    public Locator getDocumentLocator() {
-        return locator;
-    }
-
-    // -------------------------------------------------------
-    // Package Methods
-    //
-    // These methods are intended mainly for the use of Action
-    // classes and other similar "implementation" classes.
-    // -------------------------------------------------------
-
-    /**
-     * Create a SAX exception which also understands about the location in
-     * the digester file where the exception occurs. This method is expected
-     * to be called by Action classes when they detect a problem.
-     *
-     * @return the new exception
-     */
-    public SAXException createSAXException(String message, Exception e) {
-        if ((e != null) &&
-            (e instanceof InvocationTargetException)) {
-            Throwable t = ((InvocationTargetException) e).getTargetException();
-            if ((t != null) && (t instanceof Exception)) {
-                e = (Exception) t;
-            }
-        }
-
-        if (locator != null) {
-            String error = "Error at (" + locator.getLineNumber() + ", " +
-                    locator.getColumnNumber() + ": " + message;
-            if (e != null) {
-                return new SAXParseException(error, locator, e);
-            } else {
-                return new SAXParseException(error, locator);
-            }
-        }
-
-        // The SAX parser doesn't have location info enabled, so we'll just
-        // generate the best error message we can without it.
-        log.error("No Locator!");
-        if (e != null) {
-            return new SAXException(message, e);
-        } else {
-            return new SAXException(message);
-        }
-    }
-
-    /**
-     * Create a SAX exception which also understands about the location in
-     * the digester file where the exception occurs. This method is expected
-     * to be called by Action classes when they detect a problem.
-     *
-     * @return the new exception
-     */
-    public SAXException createSAXException(Exception e) {
-        if (e instanceof InvocationTargetException) {
-            Throwable t = ((InvocationTargetException) e).getTargetException();
-            if ((t != null) && (t instanceof Exception)) {
-                e = (Exception) t;
-            }
-        }
-        return createSAXException(e.getMessage(), e);
-    }
-
-    /**
-     * Create a SAX exception which also understands about the location in
-     * the digester file where the exception occurs. This method is expected
-     * to be called by Action classes when they detect a problem.
-     *
-     * @return the new exception
-     */
-    public SAXException createSAXException(String message) {
-        return createSAXException(message, null);
-    }
-
     // -------------------------------------------------------
     // Overridable methods
     //
@@ -881,18 +722,13 @@
      * updated before each SAX event is dispatched to this class.
      *
      * @param locator The new locator
-     *
-     * TODO: Consider whether this object (and the associated createSAXException
-     * method) should be on the Context rather than this object, to make it
-     * easier for Action instances to access.
-     *
      */
     public void setDocumentLocator(Locator locator) {
         if (saxLog.isDebugEnabled()) {
             saxLog.debug("setDocumentLocator(" + locator + ")");
         }
 
-        this.locator = locator;
+        documentLocator = locator;
     }
 
     /**
@@ -913,16 +749,9 @@
         dtdPublicId = null;
         dtdSystemId = null;
 
-        // This shouldn't be necesary if a parse has completed cleanly, as
-        // endPrefixMapping should have been called for each namespace. But
-        // on error, problems can occur.
-        namespaces.clear();
-        bodyText.setLength(0);
-        bodyTexts.clear();
-
         // Create a new parsing context. This guarantees that Actions have
         // a clean slate for handling this new input document.
-        context = new Context(this, log);
+        context = new Context(this, log, documentLocator);
 
         if (initialObject != null) {
             context.setRoot(initialObject);
@@ -991,13 +820,7 @@
                 "startPrefixMapping(" + prefix + "," + namespaceURI + ")");
         }
 
-        // Register this prefix mapping
-        ArrayStack stack = (ArrayStack) namespaces.get(prefix);
-        if (stack == null) {
-            stack = new ArrayStack();
-            namespaces.put(prefix, stack);
-        }
-        stack.push(namespaceURI);
+        context.pushNamespace(prefix, namespaceURI);
     }
 
     /**
@@ -1011,21 +834,8 @@
         if (saxLog.isDebugEnabled()) {
             saxLog.debug("endPrefixMapping(" + prefix + ")");
         }
-
-        // Deregister this prefix mapping
-        ArrayStack stack = (ArrayStack) namespaces.get(prefix);
-        if (stack == null) {
-            return;
-        }
-        try {
-            stack.pop();
-            if (stack.empty())
-                namespaces.remove(prefix);
-        } catch (EmptyStackException e) {
-            // This should never happen; it would indicate a serious
-            // internal software flaw.
-            throw createSAXException("endPrefixMapping popped too many times");
-        }
+        
+        context.popNamespace(prefix);
     }
 
     /**
@@ -1041,6 +851,7 @@
      */
     public void characters(char buffer[], int start, int length)
     throws SAXException {
+        ContentHandler contentHandler = context.getContentHandler();
         if (contentHandler != null) {
             // forward calls instead of handling them here
             contentHandler.characters(buffer, start, length);
@@ -1051,7 +862,7 @@
             saxLog.debug("characters(" + new String(buffer, start, length) + ")");
         }
 
-        bodyText.append(buffer, start, length);
+        context.appendToBodyText(buffer, start, length);
     }
 
     /**
@@ -1093,6 +904,7 @@
      */
     public void processingInstruction(String target, String data)
     throws SAXException {
+        ContentHandler contentHandler = context.getContentHandler();
         if (contentHandler != null) {
             // forward calls instead of handling them here
             contentHandler.processingInstruction(target, data);
@@ -1146,6 +958,7 @@
     String qName,
     Attributes attrs)
     throws SAXException {
+        ContentHandler contentHandler = context.getContentHandler();
         if (contentHandler != null) {
             // forward calls instead of handling them here
             contentHandler.startElement(namespaceURI, localName, qName, attrs);
@@ -1161,11 +974,7 @@
         }
 
         // Save the body text accumulated for our surrounding element
-        bodyTexts.push(bodyText);
-        if (debug) {
-            log.debug("  Pushing body text '" + bodyText.toString() + "'");
-        }
-        bodyText = new StringBuffer();
+        context.pushBodyText();
 
         // the actual element name is either in localName or qName, depending
         // on whether the parser is namespace aware
@@ -1205,7 +1014,7 @@
                     action.begin(context, namespaceURI, name, attrs);
                 } catch (Exception e) {
                     log.error("Begin event threw exception", e);
-                    throw createSAXException(e);
+                    throw context.createSAXException(e);
                 } catch (Error e) {
                     log.error("Begin event threw error", e);
                     throw e;
@@ -1235,6 +1044,7 @@
     String localName,
     String qName)
     throws SAXException {
+        ContentHandler contentHandler = context.getContentHandler();
         if (contentHandler != null) {
             // forward calls instead of handling them here
             contentHandler.endElement(namespaceURI, localName, qName);
@@ -1244,6 +1054,11 @@
         boolean debug = log.isDebugEnabled();
         String matchPath = context.getMatchPath();
 
+        // Retrieve the current bodytext. Also set the current bodytext to
+        // be the text associated with the parent object, so future calls to
+        // characters(...) updates the text associated with the parent.
+        String bodyText = context.popBodyText().toString();
+
         if (debug) {
             if (saxLog.isDebugEnabled()) {
                 saxLog.debug("endElement(" + namespaceURI + "," + localName +
@@ -1265,7 +1080,6 @@
         // Fire "body" events for all relevant rules
         List actions = (List) context.peekMatchingActions();
         if ((actions != null) && (actions.size() > 0)) {
-            String bodyText = this.bodyText.toString();
             Substitutor substitutor = getSubstitutor();
             if (substitutor!= null) {
                 bodyText = substitutor.substitute(bodyText);
@@ -1279,7 +1093,7 @@
                     action.body(context, namespaceURI, name, bodyText);
                 } catch (Exception e) {
                     log.error("Body event threw exception", e);
-                    throw createSAXException(e);
+                    throw context.createSAXException(e);
                 } catch (Error e) {
                     log.error("Body event threw error", e);
                     throw e;
@@ -1291,13 +1105,6 @@
             }
         }
 
-        // Restore the body text for the parent element (now that we have
-        // finished with the body text for this current element).
-        bodyText = (StringBuffer) bodyTexts.pop();
-        if (debug) {
-            log.debug("  Popping body text '" + bodyText.toString() + "'");
-        }
-
         // Fire "end" events for all relevant rules in reverse order
         // Note that the actions list is actually an ArrayStack, so
         // out-of-order access isn't a performance problem.
@@ -1311,7 +1118,7 @@
                     action.end(context, namespaceURI, name);
                 } catch (Exception e) {
                     log.error("End event threw exception", e);
-                    throw createSAXException(e);
+                    throw context.createSAXException(e);
                 } catch (Error e) {
                     log.error("End event threw error", e);
                     throw e;
@@ -1448,7 +1255,7 @@
                 sys = "'" + systemId + "'";
             }
             
-            throw createSAXException(
+            throw context.createSAXException(
                 "The external entity with publicId = " + pub
                 + " and systemId = " + sys
                 + " has not been registered as a known entity.");
@@ -1466,7 +1273,7 @@
                 log.debug(" Cannot resolve entity: '" + entityURL + "'");
             }
             
-            throw createSAXException(
+            throw context.createSAXException(
                 "Cannot resolve entity. PublicId is null or has not been"
                 + " registered as a known entity, and systemId is null.");
         }



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org