package org.apache.commons.digester3;

/*
 * 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.
 */

import static java.lang.String.format;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.validation.Schema;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

/**
 * <p>
 * A <strong>Digester</strong> processes an XML input stream by matching a series of element nesting patterns to execute
 * Rules that have been added prior to the start of parsing.
 * </p>
 * <p>
 * See the <a href="package-summary.html#package_description">Digester Developer Guide</a> for more information.
 * </p>
 * <p>
 * <strong>IMPLEMENTATION NOTE</strong> - A single Digester instance may only be used within the context of a single
 * thread at a time, and a call to <code>parse()</code> must be completed before another can be initiated even from the
 * same thread.
 * </p>
 * <p>
 * A Digester instance should not be used for parsing more than one input document. The problem is that the Digester
 * class has quite a few member variables whose values "evolve" as SAX events are received during a parse. When reusing
 * the Digester instance, all these members must be reset back to their initial states before the second parse begins.
 * The "clear()" method makes a stab at resetting these, but it is actually rather a difficult problem. If you are
 * determined to reuse Digester instances, then at the least you should call the clear() method before each parse, and
 * must call it if the Digester parse terminates due to an exception during a parse.
 * </p>
 * <p>
 * <strong>LEGACY IMPLEMENTATION NOTE</strong> - When using the legacy XML schema support (instead of using the
 * {@link Schema} class), a bug in Xerces 2.0.2 prevents the support of XML schema. You need Xerces 2.1/2.3 and up to
 * make this class work with the legacy XML schema support.
 * </p>
 * <p>
 * This package was inspired by the <code>XmlMapper</code> class that was part of Tomcat 3.0 and 3.1, but is organized
 * somewhat differently.
 * </p>
 */
public class Digester
    extends DefaultHandler
{

    // --------------------------------------------------------- Constructors

    /**
     * Construct a new Digester with default properties.
     */
    public Digester()
    {
    }

    /**
     * Construct a new Digester, allowing a SAXParser to be passed in. This allows Digester to be used in environments
     * which are unfriendly to JAXP1.1 (such as WebLogic 6.0). This may help in places where you are able to load JAXP
     * 1.1 classes yourself.
     *
     * @param parser The SAXParser used to parse XML streams
     */
    public Digester( final SAXParser parser )
    {
        this.parser = parser;
    }

    /**
     * Construct a new Digester, allowing an XMLReader to be passed in. This allows Digester to be used in environments
     * which are unfriendly to JAXP1.1 (such as WebLogic 6.0). Note that if you use this option you have to configure
     * namespace and validation support yourself, as these properties only affect the SAXParser and emtpy constructor.
     *
     * @param reader The XMLReader used to parse XML streams
     */
    public Digester( final XMLReader reader )
    {
        this.reader = reader;
    }

    // --------------------------------------------------- Instance Variables

    /**
     * The body text of the current element.
     */
    private StringBuilder bodyText = new StringBuilder();

    /**
     * The stack of body text string buffers for surrounding elements.
     */
    private final Stack<StringBuilder> bodyTexts = new Stack<StringBuilder>();

    /**
     * Stack whose elements are List objects, each containing a list of Rule objects as returned from Rules.getMatch().
     * As each xml element in the input is entered, the matching rules are pushed onto this stack. After the end tag is
     * reached, the matches are popped again. The depth of is stack is therefore exactly the same as the current
     * "nesting" level of the input xml.
     *
     * @since 1.6
     */
    private final Stack<List<Rule>> matches = new Stack<List<Rule>>();

    /**
     * The class loader to use for instantiating application objects. If not specified, the context class loader, or the
     * class loader used to load Digester itself, is used, based on the value of the <code>useContextClassLoader</code>
     * variable.
     */
    private ClassLoader classLoader = null;

    /**
     * Has this Digester been configured yet.
     */
    private boolean configured = false;

    /**
     * The EntityResolver used by the SAX parser. By default it use this class
     */
    private EntityResolver entityResolver;

    /**
     * The URLs of entityValidator that have been registered, keyed by the public identifier that corresponds.
     */
    private final HashMap<String, URL> entityValidator = new HashMap<String, URL>();

    /**
     * The application-supplied error handler that is notified when parsing warnings, errors, or fatal errors occur.
     */
    private ErrorHandler errorHandler = null;

    /**
     * The SAXParserFactory that is created the first time we need it.
     */
    private SAXParserFactory factory = null;

    /**
     * The Locator associated with our parser.
     */
    private Locator locator = null;

    /**
     * The current match pattern for nested element processing.
     */
    private String match = "";

    /**
     * Do we want a "namespace aware" parser.
     */
    private boolean namespaceAware = false;

    /**
     * The executor service to run asynchronous parse method.
     * @since 3.1
     */
    private ExecutorService executorService;

    /**
     * Registered namespaces we are currently processing. The key is the namespace prefix that was declared in the
     * document. The value is an Stack 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).
     */
    private final HashMap<String, Stack<String>> namespaces = new HashMap<String, Stack<String>>();

    /**
     * Do we want a "XInclude aware" parser.
     */
    private boolean xincludeAware = false;

    /**
     * The parameters stack being utilized by CallMethodRule and CallParamRule rules.
     *
     * @since 2.0
     */
    private final Stack<Object[]> params = new Stack<Object[]>();

    /**
     * The SAXParser we will use to parse the input stream.
     */
    private SAXParser parser = null;

    /**
     * The public identifier of the DTD we are currently parsing under (if any).
     */
    private String publicId = null;

    /**
     * The XMLReader used to parse digester rules.
     */
    private XMLReader reader = null;

    /**
     * The "root" element of the stack (in other words, the last object that was popped.
     */
    private Object root = null;

    /**
     * The <code>Rules</code> implementation containing our collection of <code>Rule</code> instances and associated
     * matching policy. If not established before the first rule is added, a default implementation will be provided.
     */
    private Rules rules = null;

    /**
     * The XML schema to use for validating an XML instance.
     *
     * @since 2.0
     */
    private Schema schema = null;

    /**
     * The object stack being constructed.
     */
    private final Stack<Object> stack = new Stack<Object>();

    /**
     * Do we want to use the Context ClassLoader when loading classes for instantiating new objects. Default is
     * <code>true</code>.
     */
    private boolean useContextClassLoader = true;

    /**
     * Do we want to use a validating parser.
     */
    private boolean validating = false;

    /**
     * The Log to which most logging calls will be made.
     */
    private Log log = LogFactory.getLog( "org.apache.commons.digester3.Digester" );

    /**
     * The Log to which all SAX event related logging calls will be made.
     */
    private Log saxLog = LogFactory.getLog( "org.apache.commons.digester3.Digester.sax" );

    /**
     * The schema language supported. By default, we use this one.
     */
    protected static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";

    /**
     * An optional class that substitutes values in attributes and body text. This may be null and so a null check is
     * always required before use.
     */
    private Substitutor substitutor;

    /** Stacks used for interrule communication, indexed by name String */
    private final HashMap<String, Stack<Object>> stacksByName = new HashMap<String, Stack<Object>>();

    /**
     * If not null, then calls by the parser to this object'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 NodeCreateRule.
     * <p>
     * See setCustomContentHandler.
     */
    private ContentHandler customContentHandler = null;

    /**
     * Object which will receive callbacks for every pop/push action on the default stack or named stacks.
     */
    private StackAction stackAction = null;

    // ------------------------------------------------------------- Properties

    /**
     * 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
     * @return the currently mapped namespace URI for the specified prefix
     */
    public String findNamespaceURI( final String prefix )
    {
        final Stack<String> nsStack = namespaces.get( prefix );
        if ( nsStack == null )
        {
            return null;
        }
        try
        {
            return ( nsStack.peek() );
        }
        catch ( final EmptyStackException e )
        {
            return null;
        }
    }

    /**
     * Return the class loader to be used for instantiating application objects when required. This is determined based
     * upon the following rules:
     * <ul>
     * <li>The class loader set by <code>setClassLoader()</code>, if any</li>
     * <li>The thread context class loader, if it exists and the <code>useContextClassLoader</code> property is set to
     * true</li>
     * <li>The class loader used to load the Digester class itself.
     * </ul>
     *
     * @return the class loader to be used for instantiating application objects.
     */
    public ClassLoader getClassLoader()
    {
        if ( this.classLoader != null )
        {
            return ( this.classLoader );
        }
        if ( this.useContextClassLoader )
        {
            final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            if ( classLoader != null )
            {
                return ( classLoader );
            }
        }
        return ( this.getClass().getClassLoader() );
    }

    /**
     * Set the class loader to be used for instantiating application objects when required.
     *
     * @param classLoader The new class loader to use, or <code>null</code> to revert to the standard rules
     */
    public void setClassLoader( final ClassLoader classLoader )
    {
        this.classLoader = classLoader;
    }

    /**
     * Return the current depth of the element stack.
     *
     * @return the current depth of the element stack.
     */
    public int getCount()
    {
        return ( stack.size() );
    }

    /**
     * Return the name of the XML element that is currently being processed.
     *
     * @return the name of the XML element that is currently being processed.
     */
    public String getCurrentElementName()
    {
        String elementName = match;
        final int lastSlash = elementName.lastIndexOf( '/' );
        if ( lastSlash >= 0 )
        {
            elementName = elementName.substring( lastSlash + 1 );
        }
        return ( elementName );
    }

    /**
     * Return the error handler for this Digester.
     *
     * @return the error handler for this Digester.
     */
    public ErrorHandler getErrorHandler()
    {
        return ( this.errorHandler );
    }

    /**
     * Set the error handler for this Digester.
     *
     * @param errorHandler The new error handler
     */
    public void setErrorHandler( final ErrorHandler errorHandler )
    {
        this.errorHandler = errorHandler;
    }

    /**
     * Return the SAXParserFactory we will use, creating one if necessary.
     *
     * @return the SAXParserFactory we will use, creating one if necessary.
     */
    public SAXParserFactory getFactory()
    {
        if ( factory == null )
        {
            factory = SAXParserFactory.newInstance();
            factory.setNamespaceAware( namespaceAware );
            factory.setXIncludeAware( xincludeAware );
            factory.setValidating( validating );
            factory.setSchema( schema );
        }
        return ( factory );
    }

    /**
     * Returns a flag indicating whether the requested feature is supported by the underlying implementation of
     * <code>org.xml.sax.XMLReader</code>. See <a href="http://www.saxproject.org">the saxproject website</a> for
     * information about the standard SAX2 feature flags.
     *
     * @param feature Name of the feature to inquire about
     * @return true, if the requested feature is supported by the underlying implementation of
     *         <code>org.xml.sax.XMLReader</code>, false otherwise
     * @throws ParserConfigurationException if a parser configuration error occurs
     * @throws SAXNotRecognizedException if the property name is not recognized
     * @throws SAXNotSupportedException if the property name is recognized but not supported
     */
    public boolean getFeature( final String feature )
        throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException
    {
        return ( getFactory().getFeature( feature ) );
    }

    /**
     * Sets a flag indicating whether the requested feature is supported by the underlying implementation of
     * <code>org.xml.sax.XMLReader</code>. See <a href="http://www.saxproject.org">the saxproject website</a> for
     * information about the standard SAX2 feature flags. In order to be effective, this method must be called
     * <strong>before</strong> the <code>getParser()</code> method is called for the first time, either directly or
     * indirectly.
     *
     * @param feature Name of the feature to set the status for
     * @param value The new value for this feature
     * @throws ParserConfigurationException if a parser configuration error occurs
     * @throws SAXNotRecognizedException if the property name is not recognized
     * @throws SAXNotSupportedException if the property name is recognized but not supported
     */
    public void setFeature( final String feature, final boolean value )
        throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException
    {
        getFactory().setFeature( feature, value );
    }

    /**
     * Return the current Logger associated with this instance of the Digester
     *
     * @return the current Logger associated with this instance of the Digester
     */
    public Log getLogger()
    {
        return log;
    }

    /**
     * Set the current logger for this Digester.
     *
     * @param log the current logger for this Digester.
     */
    public void setLogger( final Log log )
    {
        this.log = log;
    }

    /**
     * Gets the logger used for logging SAX-related information. <strong>Note</strong> the output is finely grained.
     *
     * @return the logger used for logging SAX-related information
     * @since 1.6
     */
    public Log getSAXLogger()
    {
        return saxLog;
    }

    /**
     * Sets the logger used for logging SAX-related information. <strong>Note</strong> the output is finely grained.
     *
     * @param saxLog the logger used for logging SAX-related information, not null
     * @since 1.6
     */
    public void setSAXLogger( final Log saxLog )
    {
        this.saxLog = saxLog;
    }

    /**
     * Return the current rule match path
     *
     * @return the current rule match path
     */
    public String getMatch()
    {
        return match;
    }

    /**
     * Return a Stack whose elements are List objects, each containing a list of
     * Rule objects as returned from Rules.getMatch().
     *
     * @return a Stack whose elements are List objects, each containing a list of
     *         Rule objects as returned from Rules.getMatch().
     * @since 3.0
     */
    public Stack<List<Rule>> getMatches()
    {
        return matches;
    }

    /**
     * Return the "namespace aware" flag for parsers we create.
     *
     * @return the "namespace aware" flag for parsers we create.
     */
    public boolean getNamespaceAware()
    {
        return ( this.namespaceAware );
    }

    /**
     * Set the "namespace aware" flag for parsers we create.
     *
     * @param namespaceAware The new "namespace aware" flag
     */
    public void setNamespaceAware( final boolean namespaceAware )
    {
        this.namespaceAware = namespaceAware;
    }

    /**
     * Return the XInclude-aware flag for parsers we create. XInclude functionality additionally requires
     * namespace-awareness.
     *
     * @return The XInclude-aware flag
     * @see #getNamespaceAware()
     * @since 2.0
     */
    public boolean getXIncludeAware()
    {
        return ( this.xincludeAware );
    }

    /**
     * Set the XInclude-aware flag for parsers we create. This additionally requires namespace-awareness.
     *
     * @param xincludeAware The new XInclude-aware flag
     * @see #setNamespaceAware(boolean)
     * @since 2.0
     */
    public void setXIncludeAware( final boolean xincludeAware )
    {
        this.xincludeAware = xincludeAware;
    }

    /**
     * Set the public id of the current file being parse.
     *
     * @param publicId the DTD/Schema public's id.
     */
    public void setPublicId( final String publicId )
    {
        this.publicId = publicId;
    }

    /**
     * Return the public identifier of the DTD we are currently parsing under, if any.
     *
     * @return the public identifier of the DTD we are currently parsing under, if any.
     */
    public String getPublicId()
    {
        return ( this.publicId );
    }

    /**
     * Return the namespace URI that will be applied to all subsequently added <code>Rule</code> objects.
     *
     * @return the namespace URI that will be applied to all subsequently added <code>Rule</code> objects.
     */
    public String getRuleNamespaceURI()
    {
        return ( getRules().getNamespaceURI() );
    }

    /**
     * Set the namespace URI that will be applied to all subsequently added <code>Rule</code> objects.
     *
     * @param ruleNamespaceURI Namespace URI that must match on all subsequently added rules, or <code>null</code> for
     *            matching regardless of the current namespace URI
     */
    public void setRuleNamespaceURI( final String ruleNamespaceURI )
    {
        getRules().setNamespaceURI( ruleNamespaceURI );
    }

    /**
     * Return the SAXParser we will use to parse the input stream.
     *
     * If there is a problem creating the parser, return <code>null</code>.
     *
     * @return the SAXParser we will use to parse the input stream
     */
    public SAXParser getParser()
    {
        // Return the parser we already created (if any)
        if ( parser != null )
        {
            return ( parser );
        }

        // Create a new parser
        try
        {
            parser = getFactory().newSAXParser();
        }
        catch ( final Exception e )
        {
            log.error( "Digester.getParser: ", e );
            return ( null );
        }

        return ( parser );
    }

    /**
     * Return the current value of the specified property for the underlying <code>XMLReader</code> implementation.
     *
     * See <a href="http://www.saxproject.org">the saxproject website</a> for information about the standard SAX2
     * properties.
     *
     * @param property Property name to be retrieved
     * @return the current value of the specified property for the underlying <code>XMLReader</code> implementation.
     * @throws SAXNotRecognizedException if the property name is not recognized
     * @throws SAXNotSupportedException if the property name is recognized but not supported
     */
    public Object getProperty( final String property )
        throws SAXNotRecognizedException, SAXNotSupportedException
    {
        return ( getParser().getProperty( property ) );
    }

    /**
     * Set the current value of the specified property for the underlying <code>XMLReader</code> implementation. See <a
     * href="http://www.saxproject.org">the saxproject website</a> for information about the standard SAX2 properties.
     *
     * @param property Property name to be set
     * @param value Property value to be set
     * @throws SAXNotRecognizedException if the property name is not recognized
     * @throws SAXNotSupportedException if the property name is recognized but not supported
     */
    public void setProperty( final String property, final Object value )
        throws SAXNotRecognizedException, SAXNotSupportedException
    {
        getParser().setProperty( property, value );
    }

    /**
     * Return the <code>Rules</code> implementation object containing our rules collection and associated matching
     * policy. If none has been established, a default implementation will be created and returned.
     *
     * @return the <code>Rules</code> implementation object.
     */
    public Rules getRules()
    {
        if ( this.rules == null )
        {
            this.rules = new RulesBase();
            this.rules.setDigester( this );
        }
        return ( this.rules );
    }

    /**
     * Set the <code>Rules</code> implementation object containing our rules collection and associated matching policy.
     *
     * @param rules New Rules implementation
     */
    public void setRules( final Rules rules )
    {
        this.rules = rules;
        this.rules.setDigester( this );
    }

    /**
     * Return the XML Schema used when parsing.
     *
     * @return The {@link Schema} instance in use.
     * @since 2.0
     */
    public Schema getXMLSchema()
    {
        return ( this.schema );
    }

    /**
     * Set the XML Schema to be used when parsing.
     *
     * @param schema The {@link Schema} instance to use.
     * @since 2.0
     */
    public void setXMLSchema( final Schema schema )
    {
        this.schema = schema;
    }

    /**
     * Return the boolean as to whether the context ClassLoader should be used.
     *
     * @return true, if the context ClassLoader should be used, false otherwise.
     */
    public boolean getUseContextClassLoader()
    {
        return useContextClassLoader;
    }

    /**
     * Determine whether to use the Context ClassLoader (the one found by calling
     * <code>Thread.currentThread().getContextClassLoader()</code>) to resolve/load classes that are defined in various
     * rules. If not using Context ClassLoader, then the class-loading defaults to using the calling-class' ClassLoader.
     *
     * @param use determines whether to use Context ClassLoader.
     */
    public void setUseContextClassLoader( final boolean use )
    {
        useContextClassLoader = use;
    }

    /**
     * Return the validating parser flag.
     *
     * @return the validating parser flag.
     */
    public boolean getValidating()
    {
        return ( this.validating );
    }

    /**
     * Set the validating parser flag. This must be called before <code>parse()</code> is called the first time. 
     * By default the value of this is set to false.
     * 
     * It essentially just controls the DTD validation. To use modern schema languages use the 
     * {@link #setXMLSchema(Schema)} method to associate a schema to a parser.
     *
     * @param validating The new validating parser flag.
     * @see javax.xml.parsers.SAXParserFactory#setValidating(boolean) for more detail.
     */
    public void setValidating( final boolean validating )
    {
        this.validating = validating;
    }

    /**
     * Return the XMLReader to be used for parsing the input document.
     *
     * FIXME: there is a bug in JAXP/XERCES that prevent the use of a parser that contains a schema with a DTD.
     *
     * @return the XMLReader to be used for parsing the input document.
     * @throws SAXException if no XMLReader can be instantiated
     */
    public XMLReader getXMLReader()
        throws SAXException
    {
        if ( reader == null )
        {
            reader = getParser().getXMLReader();
        }

        reader.setDTDHandler( this );
        reader.setContentHandler( this );

        if ( entityResolver == null )
        {
            reader.setEntityResolver( this );
        }
        else
        {
            reader.setEntityResolver( entityResolver );
        }

        if ( this.errorHandler != null )
        {
            reader.setErrorHandler( this.errorHandler );
        }
        else
        {
            reader.setErrorHandler( this );
        }

        return reader;
    }

    /**
     * Gets the <code>Substitutor</code> used to convert attributes and body text.
     *
     * @return the <code>Substitutor</code> used to convert attributes and body text,
     *         null if not substitutions are to be performed.
     */
    public Substitutor getSubstitutor()
    {
        return substitutor;
    }

    /**
     * Sets the <code>Substitutor</code> to be used to convert attributes and body text.
     *
     * @param substitutor the Substitutor to be used to convert attributes and body text or null if not substitution of
     *            these values is to be performed.
     */
    public void setSubstitutor( final Substitutor substitutor )
    {
        this.substitutor = substitutor;
    }

    /**
     * returns the custom SAX ContentHandler where events are redirected.
     *
     * @return the custom SAX ContentHandler where events are redirected.
     * @see #setCustomContentHandler(ContentHandler)
     * @since 1.7
     */
    public ContentHandler getCustomContentHandler()
    {
        return customContentHandler;
    }

    /**
     * Redirects (or cancels redirecting) of SAX ContentHandler events to an external object.
     * <p>
     * When this object's customContentHandler is non-null, any SAX events received from the parser will simply be
     * passed on to the specified object instead of this object handling them. This allows Rule classes to take control
     * of the SAX event stream for a while in order to do custom processing. Such a rule should save the old value
     * before setting a new one, and restore the old value in order to resume normal digester processing.
     * <p>
     * An example of a Rule which needs this feature is NodeCreateRule.
     * <p>
     * Note that saving the old value is probably not needed as it should always be null; a custom rule that wants to
     * take control could only have been called when there was no custom content handler. But it seems cleaner to
     * properly save/restore the value and maybe some day this will come in useful.
     * <p>
     * Note also that this is not quite equivalent to
     *
     * <pre>
     * digester.getXMLReader().setContentHandler( handler )
     * </pre>
     *
     * for these reasons:
     * <ul>
     * <li>Some xml parsers don't like having setContentHandler called after parsing has started. The Aelfred parser is
     * one example.</li>
     * <li>Directing the events via the Digester object potentially allows us to log information about those SAX events
     * at the digester level.</li>
     * </ul>
     *
     * @param handler the custom SAX ContentHandler where events are redirected.
     * @since 1.7
     */
    public void setCustomContentHandler( final ContentHandler handler )
    {
        customContentHandler = handler;
    }

    /**
     * Define a callback object which is invoked whenever an object is pushed onto a digester object stack,
     * or popped off one.
     *
     * @param stackAction the callback object which is invoked whenever an object is pushed onto a digester
     *        object stack, or popped off one.
     * @since 1.8
     */
    public void setStackAction( final StackAction stackAction )
    {
        this.stackAction = stackAction;
    }

    /**
     * Return the callback object which is invoked whenever an object is pushed onto a digester object stack,
     * or popped off one.
     *
     * @return the callback object which is invoked whenever an object is pushed onto a digester object stack,
     *         or popped off one.
     * @see #setStackAction(StackAction)
     * @since 1.8
     */
    public StackAction getStackAction()
    {
        return stackAction;
    }

    /**
     * Get the most current namespaces for all prefixes.
     *
     * @return Map A map with namespace prefixes as keys and most current namespace URIs for the corresponding prefixes
     *         as values
     * @since 1.8
     */
    public Map<String, String> getCurrentNamespaces()
    {
        if ( !namespaceAware )
        {
            log.warn( "Digester is not namespace aware" );
        }
        final Map<String, String> currentNamespaces = new HashMap<String, String>();
        for ( final Map.Entry<String, Stack<String>> nsEntry : namespaces.entrySet() )
        {
            try
            {
                currentNamespaces.put( nsEntry.getKey(), nsEntry.getValue().peek() );
            }
            catch ( final RuntimeException e )
            {
                // rethrow, after logging
                log.error( e.getMessage(), e );
                throw e;
            }
        }
        return currentNamespaces;
    }

    /**
     * Returns the executor service used to run asynchronous parse method.
     *
     * @return the executor service used to run asynchronous parse method
     * @since 3.1
     */
    public ExecutorService getExecutorService()
    {
        return executorService;
    }

    /**
     * Sets the executor service to run asynchronous parse method.
     *
     * @param executorService the executor service to run asynchronous parse method
     * @since 3.1
     */
    public void setExecutorService( final ExecutorService executorService )
    {
        this.executorService = executorService;
    }

    // ------------------------------------------------- ContentHandler Methods

    /**
     * {@inheritDoc}
     */
    @Override
    public void characters( final char buffer[], final int start, final int length )
        throws SAXException
    {
        if ( customContentHandler != null )
        {
            // forward calls instead of handling them here
            customContentHandler.characters( buffer, start, length );
            return;
        }

        if ( saxLog.isDebugEnabled() )
        {
            saxLog.debug( "characters(" + new String( buffer, start, length ) + ")" );
        }

        bodyText.append( buffer, start, length );
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void endDocument()
        throws SAXException
    {
        if ( saxLog.isDebugEnabled() )
        {
            if ( getCount() > 1 )
            {
                saxLog.debug( "endDocument():  " + getCount() + " elements left" );
            }
            else
            {
                saxLog.debug( "endDocument()" );
            }
        }

        // Fire "finish" events for all defined rules
        for ( final Rule rule : getRules().rules() )
        {
            try
            {
                rule.finish();
            }
            catch ( final Exception e )
            {
                log.error( "Finish event threw exception", e );
                throw createSAXException( e );
            }
            catch ( final Error e )
            {
                log.error( "Finish event threw error", e );
                throw e;
            }
        }

        // Perform final cleanup
        clear();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void endElement( final String namespaceURI, final String localName, final String qName )
        throws SAXException
    {
        if ( customContentHandler != null )
        {
            // forward calls instead of handling them here
            customContentHandler.endElement( namespaceURI, localName, qName );
            return;
        }

        final boolean debug = log.isDebugEnabled();

        if ( debug )
        {
            if ( saxLog.isDebugEnabled() )
            {
                saxLog.debug( "endElement(" + namespaceURI + "," + localName + "," + qName + ")" );
            }
            log.debug( "  match='" + match + "'" );
            log.debug( "  bodyText='" + bodyText + "'" );
        }

        // the actual element name is either in localName or qName, depending
        // on whether the parser is namespace aware
        String name = localName;
        if ( ( name == null ) || ( name.length() < 1 ) )
        {
            name = qName;
        }

        // Fire "body" events for all relevant rules
        final List<Rule> rules = matches.pop();
        if ( ( rules != null ) && ( !rules.isEmpty() ) )
        {
            String bodyText = this.bodyText.toString();
            final Substitutor substitutor = getSubstitutor();
            if ( substitutor != null )
            {
                bodyText = substitutor.substitute( bodyText );
            }
            for (final Rule rule : rules) {
                try
                {
                    if ( debug )
                    {
                        log.debug( "  Fire body() for " + rule );
                    }
                    rule.body( namespaceURI, name, bodyText );
                }
                catch ( final Exception e )
                {
                    log.error( "Body event threw exception", e );
                    throw createSAXException( e );
                }
                catch ( final Error e )
                {
                    log.error( "Body event threw error", e );
                    throw e;
                }
            }
        }
        else
        {
            if ( debug )
            {
                log.debug( "  No rules found matching '" + match + "'." );
            }
        }

        // Recover the body text from the surrounding element
        bodyText = bodyTexts.pop();
        if ( debug )
        {
            log.debug( "  Popping body text '" + bodyText.toString() + "'" );
        }

        // Fire "end" events for all relevant rules in reverse order
        if ( rules != null )
        {
            for ( int i = 0; i < rules.size(); i++ )
            {
                final int j = ( rules.size() - i ) - 1;
                try
                {
                    final Rule rule = rules.get( j );
                    if ( debug )
                    {
                        log.debug( "  Fire end() for " + rule );
                    }
                    rule.end( namespaceURI, name );
                }
                catch ( final Exception e )
                {
                    log.error( "End event threw exception", e );
                    throw createSAXException( e );
                }
                catch ( final Error e )
                {
                    log.error( "End event threw error", e );
                    throw e;
                }
            }
        }

        // Recover the previous match expression
        final int slash = match.lastIndexOf( '/' );
        if ( slash >= 0 )
        {
            match = match.substring( 0, slash );
        }
        else
        {
            match = "";
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void endPrefixMapping( final String prefix )
        throws SAXException
    {
        if ( saxLog.isDebugEnabled() )
        {
            saxLog.debug( "endPrefixMapping(" + prefix + ")" );
        }

        // Deregister this prefix mapping
        final Stack<String> stack = namespaces.get( prefix );
        if ( stack == null )
        {
            return;
        }
        try
        {
            stack.pop();
            if ( stack.empty() )
            {
                namespaces.remove( prefix );
            }
        }
        catch ( final EmptyStackException e )
        {
            throw createSAXException( "endPrefixMapping popped too many times" );
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void ignorableWhitespace( final char buffer[], final int start, final int len )
        throws SAXException
    {
        if ( saxLog.isDebugEnabled() )
        {
            saxLog.debug( "ignorableWhitespace(" + new String( buffer, start, len ) + ")" );
        }

        // No processing required
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void processingInstruction( final String target, final String data )
        throws SAXException
    {
        if ( customContentHandler != null )
        {
            // forward calls instead of handling them here
            customContentHandler.processingInstruction( target, data );
            return;
        }

        if ( saxLog.isDebugEnabled() )
        {
            saxLog.debug( "processingInstruction('" + target + "','" + data + "')" );
        }

        // No processing is required
    }

    /**
     * Gets the document locator associated with our parser.
     *
     * @return the Locator supplied by the document parser
     */
    public Locator getDocumentLocator()
    {
        return locator;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setDocumentLocator( final Locator locator )
    {
        if ( saxLog.isDebugEnabled() )
        {
            saxLog.debug( "setDocumentLocator(" + locator + ")" );
        }

        this.locator = locator;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void skippedEntity( final String name )
        throws SAXException
    {
        if ( saxLog.isDebugEnabled() )
        {
            saxLog.debug( "skippedEntity(" + name + ")" );
        }

        // No processing required
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void startDocument()
        throws SAXException
    {
        if ( saxLog.isDebugEnabled() )
        {
            saxLog.debug( "startDocument()" );
        }

        // ensure that the digester is properly configured, as
        // the digester could be used as a SAX ContentHandler
        // rather than via the parse() methods.
        configure();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void startElement( final String namespaceURI, final String localName, final String qName, Attributes list )
        throws SAXException
    {
        final boolean debug = log.isDebugEnabled();

        if ( customContentHandler != null )
        {
            // forward calls instead of handling them here
            customContentHandler.startElement( namespaceURI, localName, qName, list );
            return;
        }

        if ( saxLog.isDebugEnabled() )
        {
            saxLog.debug( "startElement(" + namespaceURI + "," + localName + "," + qName + ")" );
        }

        // Save the body text accumulated for our surrounding element
        bodyTexts.push( bodyText );
        if ( debug )
        {
            log.debug( "  Pushing body text '" + bodyText.toString() + "'" );
        }
        bodyText = new StringBuilder();

        // the actual element name is either in localName or qName, depending
        // on whether the parser is namespace aware
        String name = localName;
        if ( ( name == null ) || ( name.length() < 1 ) )
        {
            name = qName;
        }

        // Compute the current matching rule
        final StringBuilder sb = new StringBuilder( match );
        if ( match.length() > 0 )
        {
            sb.append( '/' );
        }
        sb.append( name );
        match = sb.toString();
        if ( debug )
        {
            log.debug( "  New match='" + match + "'" );
        }

        // Fire "begin" events for all relevant rules
        final List<Rule> rules = getRules().match( namespaceURI, match, localName, list );
        matches.push( rules );
        if ( ( rules != null ) && ( !rules.isEmpty() ) )
        {
            final Substitutor substitutor = getSubstitutor();
            if ( substitutor != null )
            {
                list = substitutor.substitute( list );
            }
            for (final Rule rule : rules) {
                try
                {
                    if ( debug )
                    {
                        log.debug( "  Fire begin() for " + rule );
                    }
                    rule.begin( namespaceURI, name, list );
                }
                catch ( final Exception e )
                {
                    log.error( "Begin event threw exception", e );
                    throw createSAXException( e );
                }
                catch ( final Error e )
                {
                    log.error( "Begin event threw error", e );
                    throw e;
                }
            }
        }
        else
        {
            if ( debug )
            {
                log.debug( "  No rules found matching '" + match + "'." );
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void startPrefixMapping( final String prefix, final String namespaceURI )
        throws SAXException
    {
        if ( saxLog.isDebugEnabled() )
        {
            saxLog.debug( "startPrefixMapping(" + prefix + "," + namespaceURI + ")" );
        }

        // Register this prefix mapping
        Stack<String> stack = namespaces.get( prefix );
        if ( stack == null )
        {
            stack = new Stack<String>();
            namespaces.put( prefix, stack );
        }
        stack.push( namespaceURI );
    }

    // ----------------------------------------------------- DTDHandler Methods

    /**
     * {@inheritDoc}
     */
    @Override
    public void notationDecl( final String name, final String publicId, final String systemId )
    {
        if ( saxLog.isDebugEnabled() )
        {
            saxLog.debug( "notationDecl(" + name + "," + publicId + "," + systemId + ")" );
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void unparsedEntityDecl( final String name, final String publicId, final String systemId, final String notation )
    {
        if ( saxLog.isDebugEnabled() )
        {
            saxLog.debug( "unparsedEntityDecl(" + name + "," + publicId + "," + systemId + "," + notation + ")" );
        }
    }

    // ----------------------------------------------- EntityResolver Methods

    /**
     * Set the <code>EntityResolver</code> used by SAX when resolving public id and system id. This must be called
     * before the first call to <code>parse()</code>.
     *
     * @param entityResolver a class that implement the <code>EntityResolver</code> interface.
     */
    public void setEntityResolver( final EntityResolver entityResolver )
    {
        this.entityResolver = entityResolver;
    }

    /**
     * Return the Entity Resolver used by the SAX parser.
     *
     * @return the Entity Resolver used by the SAX parser.
     */
    public EntityResolver getEntityResolver()
    {
        return entityResolver;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public InputSource resolveEntity( final String publicId, final String systemId )
        throws SAXException
    {
        if ( saxLog.isDebugEnabled() )
        {
            saxLog.debug( "resolveEntity('" + publicId + "', '" + systemId + "')" );
        }

        if ( publicId != null )
        {
            this.publicId = publicId;
        }

        // Has this system identifier been registered?
        URL entityURL = null;
        if ( publicId != null )
        {
            entityURL = entityValidator.get( publicId );
        }

        // Redirect the schema location to a local destination
        if ( entityURL == null && systemId != null )
        {
            entityURL = entityValidator.get( systemId );
        }

        if ( entityURL == null )
        {
            if ( systemId == null )
            {
                // cannot resolve
                if ( log.isDebugEnabled() )
                {
                    log.debug( " Cannot resolve null entity, returning null InputSource" );
                }
                return ( null );

            }
            // try to resolve using system ID
            if ( log.isDebugEnabled() )
            {
                log.debug( " Trying to resolve using system ID '" + systemId + "'" );
            }
            try
            {
                entityURL = new URL( systemId );
            }
            catch ( final MalformedURLException e )
            {
                throw new IllegalArgumentException( "Malformed URL '" + systemId + "' : " + e.getMessage() );
            }
        }

        // Return an input source to our alternative URL
        if ( log.isDebugEnabled() )
        {
            log.debug( " Resolving to alternate DTD '" + entityURL + "'" );
        }

        try
        {
            return createInputSourceFromURL( entityURL );
        }
        catch ( final Exception e )
        {
            throw createSAXException( e );
        }
    }

    // ------------------------------------------------- ErrorHandler Methods

    /**
     * {@inheritDoc}
     */
    @Override
    public void error( final SAXParseException exception )
        throws SAXException
    {
    	log.error( "Parse Error at line " + exception.getLineNumber() + " column " + exception.getColumnNumber() + ": "
                + exception.getMessage(), exception );
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void fatalError( final SAXParseException exception )
        throws SAXException
    {
        log.error( "Parse Fatal Error at line " + exception.getLineNumber() + " column " + exception.getColumnNumber()
                + ": " + exception.getMessage(), exception );
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void warning( final SAXParseException exception )
        throws SAXException
    {
        log.warn( "Parse Warning Error at line " + exception.getLineNumber() + " column "
                + exception.getColumnNumber() + ": " + exception.getMessage(), exception );
    }

    // ------------------------------------------------------- Public Methods

    /**
     * Parse the content of the specified file using this Digester. Returns the root element from the object stack (if
     * any).
     *
     * @param <T> the type used to auto-cast the returned object to the assigned variable type
     * @param file File containing the XML data to be parsed
     * @return the root element from the object stack (if any)
     * @throws IOException if an input/output error occurs
     * @throws SAXException if a parsing exception occurs
     */
    public <T> T parse( final File file )
        throws IOException, SAXException
    {
        if ( file == null )
        {
            throw new IllegalArgumentException( "File to parse is null" );
        }

        final InputSource input = new InputSource( new FileInputStream( file ) );
        input.setSystemId( file.toURI().toURL().toString() );

        return ( this.<T> parse( input ) );
    }

    /**
     * Creates a Callable instance that parse the content of the specified reader using this Digester.
     *
     * @param <T> The result type returned by the returned Future's {@code get} method
     * @param file File containing the XML data to be parsed
     * @return a Future that can be used to track when the parse has been fully processed.
     * @see Digester#parse(File)
     * @since 3.1
     */
    public <T> Future<T> asyncParse( final File file )
    {
        return asyncParse( new Callable<T>()
        {

            @Override
            public T call()
                throws Exception
            {
                return Digester.this.<T> parse( file );
            }

        } );
    }

    /**
     * Parse the content of the specified input source using this Digester. Returns the root element from the object
     * stack (if any).
     *
     * @param <T> the type used to auto-cast the returned object to the assigned variable type
     * @param input Input source containing the XML data to be parsed
     * @return the root element from the object stack (if any)
     * @throws IOException if an input/output error occurs
     * @throws SAXException if a parsing exception occurs
     */
    public <T> T parse( final InputSource input )
        throws IOException, SAXException
    {
        if ( input == null )
        {
            throw new IllegalArgumentException( "InputSource to parse is null" );
        }

        configure();

        String systemId = input.getSystemId();
        if ( systemId == null )
        {
            systemId = "(already loaded from stream)";
        }

        try
        {
            getXMLReader().parse( input );
        }
        catch ( final IOException e )
        {
            log.error( format( "An error occurred while reading stream from '%s', see nested exceptions", systemId ),
                       e );
            throw e;
        }
        cleanup();
        return this.<T> getRoot();
    }

    /**
     * Creates a Callable instance that parse the content of the specified reader using this Digester.
     *
     * @param <T> The result type returned by the returned Future's {@code get} method
     * @param input Input source containing the XML data to be parsed
     * @return a Future that can be used to track when the parse has been fully processed.
     * @see Digester#parse(InputSource)
     * @since 3.1
     */
    public <T> Future<T> asyncParse( final InputSource input )
    {
        return asyncParse( new Callable<T>()
        {

            @Override
            public T call()
                throws Exception
            {
                return Digester.this.<T> parse( input );
            }

        } );
    }

    /**
     * Parse the content of the specified input stream using this Digester. Returns the root element from the object
     * stack (if any).
     *
     * @param <T> the type used to auto-cast the returned object to the assigned variable type
     * @param input Input stream containing the XML data to be parsed
     * @return the root element from the object stack (if any)
     * @throws IOException if an input/output error occurs
     * @throws SAXException if a parsing exception occurs
     */
    public <T> T parse( final InputStream input )
        throws IOException, SAXException
    {
        if ( input == null )
        {
            throw new IllegalArgumentException( "InputStream to parse is null" );
        }

        return ( this.<T> parse( new InputSource( input ) ) );
    }

    /**
     * Creates a Callable instance that parse the content of the specified reader using this Digester.
     *
     * @param <T> The result type returned by the returned Future's {@code get} method
     * @param input Input stream containing the XML data to be parsed
     * @return a Future that can be used to track when the parse has been fully processed.
     * @see Digester#parse(InputStream)
     * @since 3.1
     */
    public <T> Future<T> asyncParse( final InputStream input )
    {
        return asyncParse( new Callable<T>()
        {

            @Override
            public T call()
                throws Exception
            {
                return Digester.this.<T> parse( input );
            }

        } );
    }

    /**
     * Parse the content of the specified reader using this Digester. Returns the root element from the object stack (if
     * any).
     *
     * @param <T> the type used to auto-cast the returned object to the assigned variable type
     * @param reader Reader containing the XML data to be parsed
     * @return the root element from the object stack (if any)
     * @throws IOException if an input/output error occurs
     * @throws SAXException if a parsing exception occurs
     */
    public <T> T parse( final Reader reader )
        throws IOException, SAXException
    {
        if ( reader == null )
        {
            throw new IllegalArgumentException( "Reader to parse is null" );
        }

        return ( this.<T> parse( new InputSource( reader ) ) );
    }

    /**
     * Creates a Callable instance that parse the content of the specified reader using this Digester.
     *
     * @param <T> The result type returned by the returned Future's {@code get} method
     * @param reader Reader containing the XML data to be parsed
     * @return a Future that can be used to track when the parse has been fully processed.
     * @see Digester#parse(Reader)
     * @since 3.1
     */
    public <T> Future<T> asyncParse( final Reader reader )
    {
        return asyncParse( new Callable<T>()
        {

            @Override
            public T call()
                throws Exception
            {
                return Digester.this.<T> parse( reader );
            }

        } );
    }

    /**
     * Parse the content of the specified URI using this Digester. Returns the root element from the object stack (if
     * any).
     *
     * @param <T> the type used to auto-cast the returned object to the assigned variable type
     * @param uri URI containing the XML data to be parsed
     * @return the root element from the object stack (if any)
     * @throws IOException if an input/output error occurs
     * @throws SAXException if a parsing exception occurs
     */
    public <T> T parse( final String uri )
        throws IOException, SAXException
    {
        if ( uri == null )
        {
            throw new IllegalArgumentException( "String URI to parse is null" );
        }

        return ( this.<T> parse( createInputSourceFromURL( uri ) ) );
    }

    /**
     * Creates a Callable instance that parse the content of the specified reader using this Digester.
     *
     * @param <T> The result type returned by the returned Future's {@code get} method
     * @param uri URI containing the XML data to be parsed
     * @return a Future that can be used to track when the parse has been fully processed.
     * @see Digester#parse(String)
     * @since 3.1
     */
    public <T> Future<T> asyncParse( final String uri )
    {
        return asyncParse( new Callable<T>()
        {

            @Override
            public T call()
                throws Exception
            {
                return Digester.this.<T> parse( uri );
            }

        } );
    }

    /**
     * Parse the content of the specified URL using this Digester. Returns the root element from the object stack (if
     * any).
     *
     * @param <T> the type used to auto-cast the returned object to the assigned variable type
     * @param url URL containing the XML data to be parsed
     * @return the root element from the object stack (if any)
     * @throws IOException if an input/output error occurs
     * @throws SAXException if a parsing exception occurs
     * @since 1.8
     */
    public <T> T parse( final URL url )
        throws IOException, SAXException
    {
        if ( url == null )
        {
            throw new IllegalArgumentException( "URL to parse is null" );
        }

        return ( this.<T> parse( createInputSourceFromURL( url ) ) );
    }

    /**
     * Creates a Callable instance that parse the content of the specified reader using this Digester.
     *
     * @param <T> The result type returned by the returned Future's {@code get} method
     * @param url URL containing the XML data to be parsed
     * @return a Future that can be used to track when the parse has been fully processed.
     * @see Digester#parse(URL)
     * @since 3.1
     */
    public <T> Future<T> asyncParse( final URL url )
    {
        return asyncParse( new Callable<T>()
        {

            @Override
            public T call()
                throws Exception
            {
                return Digester.this.<T> parse( url );
            }

        } );
    }

    /**
     * Execute the parse in async mode.
     *
     * @param <T> the type used to auto-cast the returned object to the assigned variable type
     * @param callable
     * @return a Future that can be used to track when the parse has been fully processed.
     * @since 3.1
     */
    private <T> Future<T> asyncParse( final Callable<T> callable )
    {
        if ( executorService == null )
        {
            throw new IllegalStateException( "ExecutorService not set" );
        }

        return executorService.submit( callable );
    }

    /**
     * <p>
     * Register the specified DTD URL for the specified public identifier. This must be called before the first call to
     * <code>parse()</code>.
     * </p>
     * <p>
     * <code>Digester</code> contains an internal <code>EntityResolver</code> implementation. This maps
     * <code>PUBLICID</code>'s to URLs (from which the resource will be loaded). A common use case for this method is to
     * register local URLs (possibly computed at runtime by a classloader) for DTDs. This allows the performance
     * advantage of using a local version without having to ensure every <code>SYSTEM</code> URI on every processed xml
     * document is local. This implementation provides only basic functionality. If more sophisticated features are
     * required, using {@link #setEntityResolver} to set a custom resolver is recommended.
     * </p>
     * <p>
     * <strong>Note:</strong> This method will have no effect when a custom <code>EntityResolver</code> has been set.
     * (Setting a custom <code>EntityResolver</code> overrides the internal implementation.)
     * </p>
     *
     * @param publicId Public identifier of the DTD to be resolved
     * @param entityURL The URL to use for reading this DTD
     * @since 1.8
     */
    public void register( final String publicId, final URL entityURL )
    {
        if ( log.isDebugEnabled() )
        {
            log.debug( "register('" + publicId + "', '" + entityURL + "'" );
        }
        entityValidator.put( publicId, entityURL );
    }

    /**
     * <p>
     * Convenience method that registers the string version of an entity URL instead of a URL version.
     * </p>
     *
     * @param publicId Public identifier of the entity to be resolved
     * @param entityURL The URL to use for reading this entity
     */
    public void register( final String publicId, final String entityURL )
    {
        if ( log.isDebugEnabled() )
        {
            log.debug( "register('" + publicId + "', '" + entityURL + "'" );
        }
        try
        {
            entityValidator.put( publicId, new URL( entityURL ) );
        }
        catch ( final MalformedURLException e )
        {
            throw new IllegalArgumentException( "Malformed URL '" + entityURL + "' : " + e.getMessage() );
        }
    }

    /**
     * Convenience method that registers DTD URLs for the specified public identifiers.
     *
     * @param entityValidator The URLs of entityValidator that have been registered, keyed by the public
     *                        identifier that corresponds.
     * @since 3.0
     */
    public void registerAll( final Map<String, URL> entityValidator )
    {
        this.entityValidator.putAll( entityValidator );
    }

    /**
     * <p>
     * <code>List</code> of <code>InputSource</code> instances created by a <code>createInputSourceFromURL()</code>
     * method call. These represent open input streams that need to be closed to avoid resource leaks, as well as
     * potentially locked JAR files on Windows.
     * </p>
     */
    protected List<InputSource> inputSources = new ArrayList<InputSource>( 5 );

    /**
     * Given a URL, return an InputSource that reads from that URL.
     * <p>
     * Ideally this function would not be needed and code could just use <code>new InputSource(entityURL)</code>.
     * Unfortunately it appears that when the entityURL points to a file within a jar archive a caching mechanism inside
     * the InputSource implementation causes a file-handle to the jar file to remain open. On Windows systems this then
     * causes the jar archive file to be locked on disk ("in use") which makes it impossible to delete the jar file -
     * and that really stuffs up "undeploy" in webapps in particular.
     * <p>
     * In JDK1.4 and later, Apache XercesJ is used as the xml parser. The InputSource object provided is converted into
     * an XMLInputSource, and eventually passed to an instance of XMLDocumentScannerImpl to specify the source data to
     * be converted into tokens for the rest of the XMLReader code to handle. XMLDocumentScannerImpl calls
     * fEntityManager.startDocumentEntity(source), where fEntityManager is declared in ancestor class XMLScanner to be
     * an XMLEntityManager. In that class, if the input source stream is null, then:
     *
     * <pre>
     * URL location = new URL( expandedSystemId );
     * URLConnection connect = location.openConnection();
     * if ( connect instanceof HttpURLConnection )
     * {
     *     setHttpProperties( connect, xmlInputSource );
     * }
     * stream = connect.getInputStream();
     * </pre>
     *
     * This method pretty much duplicates the standard behavior, except that it calls URLConnection.setUseCaches(false)
     * before opening the connection.
     *
     * @param url The URL has to be read
     * @return The InputSource that reads from the input URL
     * @throws IOException if any error occurs while reading the input URL
     * @since 1.8
     */
    public InputSource createInputSourceFromURL( final URL url )
        throws IOException
    {
        final URLConnection connection = url.openConnection();
        connection.setUseCaches( false );
        final InputStream stream = connection.getInputStream();
        final InputSource source = new InputSource( stream );
        source.setSystemId( url.toExternalForm() );
        inputSources.add( source );
        return source;
    }

    /**
     * <p>
     * Convenience method that creates an <code>InputSource</code> from the string version of a URL.
     * </p>
     *
     * @param url URL for which to create an <code>InputSource</code>
     * @return The InputSource that reads from the input URL
     * @throws IOException if any error occurs while reading the input URL
     * @since 1.8
     */
    public InputSource createInputSourceFromURL( final String url )
        throws IOException
    {
        return createInputSourceFromURL( new URL( url ) );
    }

    // --------------------------------------------------------- Rule Methods

    /**
     * <p>
     * Register a new Rule matching the specified pattern. This method sets the <code>Digester</code> property on the
     * rule.
     * </p>
     *
     * @param pattern Element matching pattern
     * @param rule Rule to be registered
     */
    public void addRule( final String pattern, final Rule rule )
    {
        rule.setDigester( this );
        getRules().add( pattern, rule );
    }

    /**
     * Register a set of Rule instances defined in a RuleSet.
     *
     * @param ruleSet The RuleSet instance to configure from
     */
    public void addRuleSet( final RuleSet ruleSet )
    {
        final String oldNamespaceURI = getRuleNamespaceURI();
        final String newNamespaceURI = ruleSet.getNamespaceURI();
        if ( log.isDebugEnabled() )
        {
            if ( newNamespaceURI == null )
            {
                log.debug( "addRuleSet() with no namespace URI" );
            }
            else
            {
                log.debug( "addRuleSet() with namespace URI " + newNamespaceURI );
            }
        }
        setRuleNamespaceURI( newNamespaceURI );
        ruleSet.addRuleInstances( this );
        setRuleNamespaceURI( oldNamespaceURI );
    }

    /**
     * Add a "bean property setter" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @see BeanPropertySetterRule
     */
    public void addBeanPropertySetter( final String pattern )
    {
        addRule( pattern, new BeanPropertySetterRule() );
    }

    /**
     * Add a "bean property setter" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param propertyName Name of property to set
     * @see BeanPropertySetterRule
     */
    public void addBeanPropertySetter( final String pattern, final String propertyName )
    {
        addRule( pattern, new BeanPropertySetterRule( propertyName ) );
    }

    /**
     * Add an "call method" rule for a method which accepts no arguments.
     *
     * @param pattern Element matching pattern
     * @param methodName Method name to be called
     * @see CallMethodRule
     */
    public void addCallMethod( final String pattern, final String methodName )
    {
        addRule( pattern, new CallMethodRule( methodName ) );
    }

    /**
     * Add an "call method" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param methodName Method name to be called
     * @param paramCount Number of expected parameters (or zero for a single parameter from the body of this element)
     * @see CallMethodRule
     */
    public void addCallMethod( final String pattern, final String methodName, final int paramCount )
    {
        addRule( pattern, new CallMethodRule( methodName, paramCount ) );
    }

    /**
     * Add an "call method" rule for the specified parameters. If <code>paramCount</code> is set to zero the rule will
     * use the body of the matched element as the single argument of the method, unless <code>paramTypes</code> is null
     * or empty, in this case the rule will call the specified method with no arguments.
     *
     * @param pattern Element matching pattern
     * @param methodName Method name to be called
     * @param paramCount Number of expected parameters (or zero for a single parameter from the body of this element)
     * @param paramTypes Set of Java class names for the types of the expected parameters (if you wish to use a
     *            primitive type, specify the corresonding Java wrapper class instead, such as
     *            <code>java.lang.Boolean</code> for a <code>boolean</code> parameter)
     * @see CallMethodRule
     */
    public void addCallMethod( final String pattern, final String methodName, final int paramCount, final String paramTypes[] )
    {
        addRule( pattern, new CallMethodRule( methodName, paramCount, paramTypes ) );
    }

    /**
     * Add an "call method" rule for the specified parameters. If <code>paramCount</code> is set to zero the rule will
     * use the body of the matched element as the single argument of the method, unless <code>paramTypes</code> is null
     * or empty, in this case the rule will call the specified method with no arguments.
     *
     * @param pattern Element matching pattern
     * @param methodName Method name to be called
     * @param paramCount Number of expected parameters (or zero for a single parameter from the body of this element)
     * @param paramTypes The Java class names of the arguments (if you wish to use a primitive type, specify the
     *            corresonding Java wrapper class instead, such as <code>java.lang.Boolean</code> for a
     *            <code>boolean</code> parameter)
     * @see CallMethodRule
     */
    public void addCallMethod( final String pattern, final String methodName, final int paramCount, final Class<?> paramTypes[] )
    {
        addRule( pattern, new CallMethodRule( methodName, paramCount, paramTypes ) );
    }

    /**
     * Add a "call parameter" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param paramIndex Zero-relative parameter index to set (from the body of this element)
     * @see CallParamRule
     */
    public void addCallParam( final String pattern, final int paramIndex )
    {
        addRule( pattern, new CallParamRule( paramIndex ) );
    }

    /**
     * Add a "call parameter" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param paramIndex Zero-relative parameter index to set (from the specified attribute)
     * @param attributeName Attribute whose value is used as the parameter value
     * @see CallParamRule
     */
    public void addCallParam( final String pattern, final int paramIndex, final String attributeName )
    {
        addRule( pattern, new CallParamRule( paramIndex, attributeName ) );
    }

    /**
     * Add a "call parameter" rule. This will either take a parameter from the stack or from the current element body
     * text.
     *
     * @param pattern Element matching pattern
     * @param paramIndex The zero-relative parameter number
     * @param fromStack Should the call parameter be taken from the top of the stack?
     * @see CallParamRule
     */
    public void addCallParam( final String pattern, final int paramIndex, final boolean fromStack )
    {
        addRule( pattern, new CallParamRule( paramIndex, fromStack ) );
    }

    /**
     * Add a "call parameter" rule that sets a parameter from the stack. This takes a parameter from the given position
     * on the stack.
     *
     * @param pattern Element matching pattern
     * @param paramIndex The zero-relative parameter number
     * @param stackIndex set the call parameter to the stackIndex'th object down the stack, where 0 is the top of the
     *            stack, 1 the next element down and so on
     * @see CallMethodRule
     */
    public void addCallParam( final String pattern, final int paramIndex, final int stackIndex )
    {
        addRule( pattern, new CallParamRule( paramIndex, stackIndex ) );
    }

    /**
     * Add a "call parameter" rule that sets a parameter from the current <code>Digester</code> matching path. This is
     * sometimes useful when using rules that support wildcards.
     *
     * @param pattern the pattern that this rule should match
     * @param paramIndex The zero-relative parameter number
     * @see CallMethodRule
     */
    public void addCallParamPath( final String pattern, final int paramIndex )
    {
        addRule( pattern, new PathCallParamRule( paramIndex ) );
    }

    /**
     * Add a "call parameter" rule that sets a parameter from a caller-provided object. This can be used to pass
     * constants such as strings to methods; it can also be used to pass mutable objects, providing ways for objects to
     * do things like "register" themselves with some shared object.
     * <p>
     * Note that when attempting to locate a matching method to invoke, the true type of the paramObj is used, so that
     * despite the paramObj being passed in here as type Object, the target method can declare its parameters as being
     * the true type of the object (or some ancestor type, according to the usual type-conversion rules).
     *
     * @param pattern Element matching pattern
     * @param paramIndex The zero-relative parameter number
     * @param paramObj Any arbitrary object to be passed to the target method.
     * @see CallMethodRule
     * @since 1.6
     */
    public void addObjectParam( final String pattern, final int paramIndex, final Object paramObj )
    {
        addRule( pattern, new ObjectParamRule( paramIndex, paramObj ) );
    }

    /**
     * Add a "factory create" rule for the specified parameters. Exceptions thrown during the object creation process
     * will be propagated.
     *
     * @param pattern Element matching pattern
     * @param className Java class name of the object creation factory class
     * @see FactoryCreateRule
     */
    public void addFactoryCreate( final String pattern, final String className )
    {
        addFactoryCreate( pattern, className, false );
    }

    /**
     * Add a "factory create" rule for the specified parameters. Exceptions thrown during the object creation process
     * will be propagated.
     *
     * @param pattern Element matching pattern
     * @param clazz Java class of the object creation factory class
     * @see FactoryCreateRule
     */
    public void addFactoryCreate( final String pattern, final Class<? extends ObjectCreationFactory<?>> clazz )
    {
        addFactoryCreate( pattern, clazz, false );
    }

    /**
     * Add a "factory create" rule for the specified parameters. Exceptions thrown during the object creation process
     * will be propagated.
     *
     * @param pattern Element matching pattern
     * @param className Java class name of the object creation factory class
     * @param attributeName Attribute name which, if present, overrides the value specified by <code>className</code>
     * @see FactoryCreateRule
     */
    public void addFactoryCreate( final String pattern, final String className, final String attributeName )
    {
        addFactoryCreate( pattern, className, attributeName, false );
    }

    /**
     * Add a "factory create" rule for the specified parameters. Exceptions thrown during the object creation process
     * will be propagated.
     *
     * @param pattern Element matching pattern
     * @param clazz Java class of the object creation factory class
     * @param attributeName Attribute name which, if present, overrides the value specified by <code>className</code>
     * @see FactoryCreateRule
     */
    public void addFactoryCreate( final String pattern, final Class<? extends ObjectCreationFactory<?>> clazz,
                                  final String attributeName )
    {
        addFactoryCreate( pattern, clazz, attributeName, false );
    }

    /**
     * Add a "factory create" rule for the specified parameters. Exceptions thrown during the object creation process
     * will be propagated.
     *
     * @param pattern Element matching pattern
     * @param creationFactory Previously instantiated ObjectCreationFactory to be utilized
     * @see FactoryCreateRule
     */
    public void addFactoryCreate( final String pattern, final ObjectCreationFactory<?> creationFactory )
    {
        addFactoryCreate( pattern, creationFactory, false );
    }

    /**
     * Add a "factory create" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param className Java class name of the object creation factory class
     * @param ignoreCreateExceptions when <code>true</code> any exceptions thrown during object creation will be
     *            ignored.
     * @see FactoryCreateRule
     */
    public void addFactoryCreate( final String pattern, final String className, final boolean ignoreCreateExceptions )
    {
        addRule( pattern, new FactoryCreateRule( className, ignoreCreateExceptions ) );
    }

    /**
     * Add a "factory create" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param clazz Java class of the object creation factory class
     * @param ignoreCreateExceptions when <code>true</code> any exceptions thrown during object creation will be
     *            ignored.
     * @see FactoryCreateRule
     */
    public void addFactoryCreate( final String pattern, final Class<? extends ObjectCreationFactory<?>> clazz,
                                  final boolean ignoreCreateExceptions )
    {
        addRule( pattern, new FactoryCreateRule( clazz, ignoreCreateExceptions ) );
    }

    /**
     * Add a "factory create" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param className Java class name of the object creation factory class
     * @param attributeName Attribute name which, if present, overrides the value specified by <code>className</code>
     * @param ignoreCreateExceptions when <code>true</code> any exceptions thrown during object creation will be
     *            ignored.
     * @see FactoryCreateRule
     */
    public void addFactoryCreate( final String pattern, final String className, final String attributeName,
                                  final boolean ignoreCreateExceptions )
    {
        addRule( pattern, new FactoryCreateRule( className, attributeName, ignoreCreateExceptions ) );
    }

    /**
     * Add a "factory create" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param clazz Java class of the object creation factory class
     * @param attributeName Attribute name which, if present, overrides the value specified by <code>className</code>
     * @param ignoreCreateExceptions when <code>true</code> any exceptions thrown during object creation will be
     *            ignored.
     * @see FactoryCreateRule
     */
    public void addFactoryCreate( final String pattern, final Class<? extends ObjectCreationFactory<?>> clazz,
                                  final String attributeName, final boolean ignoreCreateExceptions )
    {
        addRule( pattern, new FactoryCreateRule( clazz, attributeName, ignoreCreateExceptions ) );
    }

    /**
     * Add a "factory create" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param creationFactory Previously instantiated ObjectCreationFactory to be utilized
     * @param ignoreCreateExceptions when <code>true</code> any exceptions thrown during object creation will be
     *            ignored.
     * @see FactoryCreateRule
     */
    public void addFactoryCreate( final String pattern, final ObjectCreationFactory<?> creationFactory,
                                  final boolean ignoreCreateExceptions )
    {
        creationFactory.setDigester( this );
        addRule( pattern, new FactoryCreateRule( creationFactory, ignoreCreateExceptions ) );
    }

    /**
     * Add an "object create" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param className Java class name to be created
     * @see ObjectCreateRule
     */
    public void addObjectCreate( final String pattern, final String className )
    {
        addRule( pattern, new ObjectCreateRule( className ) );
    }

    /**
     * Add an "object create" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param clazz Java class to be created
     * @see ObjectCreateRule
     */
    public void addObjectCreate( final String pattern, final Class<?> clazz )
    {
        addRule( pattern, new ObjectCreateRule( clazz ) );
    }

    /**
     * Add an "object create" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param className Default Java class name to be created
     * @param attributeName Attribute name that optionally overrides the default Java class name to be created
     * @see ObjectCreateRule
     */
    public void addObjectCreate( final String pattern, final String className, final String attributeName )
    {
        addRule( pattern, new ObjectCreateRule( className, attributeName ) );
    }

    /**
     * Add an "object create" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param attributeName Attribute name that optionally overrides
     * @param clazz Default Java class to be created the default Java class name to be created
     * @see ObjectCreateRule
     */
    public void addObjectCreate( final String pattern, final String attributeName, final Class<?> clazz )
    {
        addRule( pattern, new ObjectCreateRule( attributeName, clazz ) );
    }

    /**
     * Adds an {@link SetNestedPropertiesRule}.
     *
     * @param pattern register the rule with this pattern
     * @since 1.6
     */
    public void addSetNestedProperties( final String pattern )
    {
        addRule( pattern, new SetNestedPropertiesRule() );
    }

    /**
     * Adds an {@link SetNestedPropertiesRule}.
     *
     * @param pattern register the rule with this pattern
     * @param elementName elment name that a property maps to
     * @param propertyName property name of the element mapped from
     * @since 1.6
     */
    public void addSetNestedProperties( final String pattern, final String elementName, final String propertyName )
    {
        addRule( pattern, new SetNestedPropertiesRule( elementName, propertyName ) );
    }

    /**
     * Adds an {@link SetNestedPropertiesRule}.
     *
     * @param pattern register the rule with this pattern
     * @param elementNames elment names that (in order) map to properties
     * @param propertyNames property names that (in order) elements are mapped to
     * @since 1.6
     */
    public void addSetNestedProperties( final String pattern, final String[] elementNames, final String[] propertyNames )
    {
        addRule( pattern, new SetNestedPropertiesRule( elementNames, propertyNames ) );
    }

    /**
     * Add a "set next" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param methodName Method name to call on the parent element
     * @see SetNextRule
     */
    public void addSetNext( final String pattern, final String methodName )
    {
        addRule( pattern, new SetNextRule( methodName ) );
    }

    /**
     * Add a "set next" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param methodName Method name to call on the parent element
     * @param paramType Java class name of the expected parameter type (if you wish to use a primitive type, specify the
     *            corresonding Java wrapper class instead, such as <code>java.lang.Boolean</code> for a
     *            <code>boolean</code> parameter)
     * @see SetNextRule
     */
    public void addSetNext( final String pattern, final String methodName, final String paramType )
    {
        addRule( pattern, new SetNextRule( methodName, paramType ) );
    }

    /**
     * Add {@link SetRootRule} with the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param methodName Method name to call on the root object
     * @see SetRootRule
     */
    public void addSetRoot( final String pattern, final String methodName )
    {
        addRule( pattern, new SetRootRule( methodName ) );
    }

    /**
     * Add {@link SetRootRule} with the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param methodName Method name to call on the root object
     * @param paramType Java class name of the expected parameter type
     * @see SetRootRule
     */
    public void addSetRoot( final String pattern, final String methodName, final String paramType )
    {
        addRule( pattern, new SetRootRule( methodName, paramType ) );
    }

    /**
     * Add a "set properties" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @see SetPropertiesRule
     */
    public void addSetProperties( final String pattern )
    {
        addRule( pattern, new SetPropertiesRule() );
    }

    /**
     * Add a "set properties" rule with a single overridden parameter. See
     * {@link SetPropertiesRule#SetPropertiesRule(String attributeName, String propertyName)}
     *
     * @param pattern Element matching pattern
     * @param attributeName map this attribute
     * @param propertyName to this property
     * @see SetPropertiesRule
     */
    public void addSetProperties( final String pattern, final String attributeName, final String propertyName )
    {
        addRule( pattern, new SetPropertiesRule( attributeName, propertyName ) );
    }

    /**
     * Add a "set properties" rule with overridden parameters. See
     * {@link SetPropertiesRule#SetPropertiesRule(String [] attributeNames, String [] propertyNames)}
     *
     * @param pattern Element matching pattern
     * @param attributeNames names of attributes with custom mappings
     * @param propertyNames property names these attributes map to
     * @see SetPropertiesRule
     */
    public void addSetProperties( final String pattern, final String[] attributeNames, final String[] propertyNames )
    {
        addRule( pattern, new SetPropertiesRule( attributeNames, propertyNames ) );
    }

    /**
     * Add a "set property" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param name Attribute name containing the property name to be set
     * @param value Attribute name containing the property value to set
     * @see SetPropertyRule
     */
    public void addSetProperty( final String pattern, final String name, final String value )
    {
        addRule( pattern, new SetPropertyRule( name, value ) );
    }

    /**
     * Add a "set top" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param methodName Method name to call on the parent element
     * @see SetTopRule
     */
    public void addSetTop( final String pattern, final String methodName )
    {
        addRule( pattern, new SetTopRule( methodName ) );
    }

    /**
     * Add a "set top" rule for the specified parameters.
     *
     * @param pattern Element matching pattern
     * @param methodName Method name to call on the parent element
     * @param paramType Java class name of the expected parameter type (if you wish to use a primitive type, specify the
     *            corresonding Java wrapper class instead, such as <code>java.lang.Boolean</code> for a
     *            <code>boolean</code> parameter)
     * @see SetTopRule
     */
    public void addSetTop( final String pattern, final String methodName, final String paramType )
    {
        addRule( pattern, new SetTopRule( methodName, paramType ) );
    }

    // --------------------------------------------------- Object Stack Methods

    /**
     * Clear the current contents of the default object stack, the param stack, all named stacks, and other internal
     * variables.
     * <p>
     * Calling this method <i>might</i> allow another document of the same type to be correctly parsed. However this
     * method was not intended for this purpose (just to tidy up memory usage). In general, a separate Digester object
     * should be created for each document to be parsed.
     * <p>
     * Note that this method is called automatically after a document has been successfully parsed by a Digester
     * instance. However it is not invoked automatically when a parse fails, so when reusing a Digester instance (which
     * is not recommended) this method <i>must</i> be called manually after a parse failure.
     */
    public void clear()
    {
        match = "";
        bodyTexts.clear();
        params.clear();
        publicId = null;
        stack.clear();
        stacksByName.clear();
        customContentHandler = null;
    }

    /**
     * Return the top object on the stack without removing it.
     *
     * If there are no objects on the stack, return <code>null</code>.
     *
     * @param <T> the type used to auto-cast the returned object to the assigned variable type
     * @return the top object on the stack without removing it.
     */
    public <T> T peek()
    {
        try
        {
            return this.<T> npeSafeCast( stack.peek() );
        }
        catch ( final EmptyStackException e )
        {
            log.warn( "Empty stack (returning null)" );
            return ( null );
        }
    }

    /**
     * Return the n'th object down the stack, where 0 is the top element and [getCount()-1] is the bottom element. If
     * the specified index is out of range, return <code>null</code>.
     *
     * @param <T> the type used to auto-cast the returned object to the assigned variable type
     * @param n Index of the desired element, where 0 is the top of the stack, 1 is the next element down, and so on.
     * @return the n'th object down the stack
     */
    public <T> T peek( final int n )
    {
        final int index = ( stack.size() - 1 ) - n;
        if ( index < 0 )
        {
            log.warn( "Empty stack (returning null)" );
            return ( null );
        }
        try
        {
            return this.<T> npeSafeCast( stack.get( index ) );
        }
        catch ( final EmptyStackException e )
        {
            log.warn( "Empty stack (returning null)" );
            return ( null );
        }
    }

    /**
     * Pop the top object off of the stack, and return it. If there are no objects on the stack, return
     * <code>null</code>.
     *
     * @param <T> the type used to auto-cast the returned object to the assigned variable type
     * @return the top object popped off of the stack
     */
    public <T> T pop()
    {
        try
        {
            T popped = this.<T> npeSafeCast( stack.pop() );
            if ( stackAction != null )
            {
                popped = stackAction.onPop( this, null, popped );
            }
            return popped;
        }
        catch ( final EmptyStackException e )
        {
            log.warn( "Empty stack (returning null)" );
            return ( null );
        }
    }

    /**
     * Push a new object onto the top of the object stack.
     *
     * @param <T> any type of the pushed object
     * @param object The new object
     */
    public <T> void push( T object )
    {
        if ( stackAction != null )
        {
            object = stackAction.onPush( this, null, object );
        }

        if ( stack.isEmpty() )
        {
            root = object;
        }
        stack.push( object );
    }

    /**
     * Pushes the given object onto the stack with the given name. If no stack already exists with the given name then
     * one will be created.
     *
     * @param <T> any type of the pushed object
     * @param stackName the name of the stack onto which the object should be pushed
     * @param value the Object to be pushed onto the named stack.
     * @since 1.6
     */
    public <T> void push( final String stackName, T value )
    {
        if ( stackAction != null )
        {
            value = stackAction.onPush( this, stackName, value );
        }

        Stack<Object> namedStack = stacksByName.get( stackName );
        if ( namedStack == null )
        {
            namedStack = new Stack<Object>();
            stacksByName.put( stackName, namedStack );
        }
        namedStack.push( value );
    }

    /**
     * <p>
     * Pops (gets and removes) the top object from the stack with the given name.
     * </p>
     * <p>
     * <strong>Note:</strong> a stack is considered empty if no objects have been pushed onto it yet.
     * </p>
     *
     * @param <T> the type used to auto-cast the returned object to the assigned variable type
     * @param stackName the name of the stack from which the top value is to be popped.
     * @return the top <code>Object</code> on the stack or throws {@code EmptyStackException}
     *         if the stack is either empty or has not been created yet
     * @since 1.6
     */
    public <T> T pop( final String stackName )
    {
        final Stack<Object> namedStack = stacksByName.get( stackName );
        if ( namedStack == null )
        {
            if ( log.isDebugEnabled() )
            {
                log.debug( "Stack '" + stackName + "' is empty" );
            }
            throw new EmptyStackException();
        }

        T result = this.<T> npeSafeCast( namedStack.pop() );

        if ( stackAction != null )
        {
            result = stackAction.onPop( this, stackName, result );
        }

        return result;
    }

    /**
     * <p>
     * Gets the top object from the stack with the given name. This method does not remove the object from the stack.
     * </p>
     * <p>
     * <strong>Note:</strong> a stack is considered empty if no objects have been pushed onto it yet.
     * </p>
     *
     * @param <T> the type used to auto-cast the returned object to the assigned variable type
     * @param stackName the name of the stack to be peeked
     * @return the top <code>Object</code> on the stack or null if the stack is either empty or has not been created yet
     * @since 1.6
     */
    public <T> T peek( final String stackName )
    {
        return this.<T> npeSafeCast( peek( stackName, 0 ) );
    }

    /**
     * <p>
     * Gets the top object from the stack with the given name. This method does not remove the object from the stack.
     * </p>
     * <p>
     * <strong>Note:</strong> a stack is considered empty if no objects have been pushed onto it yet.
     * </p>
     *
     * @param <T> the type used to auto-cast the returned object to the assigned variable type
     * @param stackName the name of the stack to be peeked
     * @param n Index of the desired element, where 0 is the top of the stack, 1 is the next element down, and so on.
     * @return the specified <code>Object</code> on the stack.
     * @since 1.6
     */
    public <T> T peek( final String stackName, final int n )
    {
        T result;
        final Stack<Object> namedStack = stacksByName.get( stackName );
        if ( namedStack == null )
        {
            if ( log.isDebugEnabled() )
            {
                log.debug( "Stack '" + stackName + "' is empty" );
            }
            throw new EmptyStackException();
        }

        final int index = ( namedStack.size() - 1 ) - n;
        if ( index < 0 )
        {
            throw new EmptyStackException();
        }
        result = this.<T> npeSafeCast( namedStack.get( index ) );

        return result;
    }

    /**
     * <p>
     * Is the stack with the given name empty?
     * </p>
     * <p>
     * <strong>Note:</strong> a stack is considered empty if no objects have been pushed onto it yet.
     * </p>
     *
     * @param stackName the name of the stack whose emptiness should be evaluated
     * @return true if the given stack if empty
     * @since 1.6
     */
    public boolean isEmpty( final String stackName )
    {
        boolean result = true;
        final Stack<Object> namedStack = stacksByName.get( stackName );
        if ( namedStack != null )
        {
            result = namedStack.isEmpty();
        }
        return result;
    }

    /**
     * Returns the root element of the tree of objects created as a result of applying the rule objects to the input
     * XML.
     * <p>
     * If the digester stack was "primed" by explicitly pushing a root object onto the stack before parsing started,
     * then that root object is returned here.
     * <p>
     * Alternatively, if a Rule which creates an object (eg ObjectCreateRule) matched the root element of the xml, then
     * the object created will be returned here.
     * <p>
     * In other cases, the object most recently pushed onto an empty digester stack is returned. This would be a most
     * unusual use of digester, however; one of the previous configurations is much more likely.
     * <p>
     * Note that when using one of the Digester.parse methods, the return value from the parse method is exactly the
     * same as the return value from this method. However when the Digester is being used as a SAXContentHandler, no
     * such return value is available; in this case, this method allows you to access the root object that has been
     * created after parsing has completed.
     *
     * @param <T> the type used to auto-cast the returned object to the assigned variable type
     * @return the root object that has been created after parsing or null if the digester has not parsed any XML yet.
     */
    public <T> T getRoot()
    {
        return this.<T> npeSafeCast( root );
    }

    /**
     * This method allows the "root" variable to be reset to null.
     * <p>
     * It is not considered safe for a digester instance to be reused to parse multiple xml documents. However if you
     * are determined to do so, then you should call both clear() and resetRoot() before each parse.
     *
     * @since 1.7
     */
    public void resetRoot()
    {
        root = null;
    }

    // ------------------------------------------------ Parameter Stack Methods

    // ------------------------------------------------------ Protected Methods

    /**
     * <p>
     * Clean up allocated resources after parsing is complete. The default method closes input streams that have been
     * created by Digester itself. If you override this method in a subclass, be sure to call
     * <code>super.cleanup()</code> to invoke this logic.
     * </p>
     *
     * @since 1.8
     */
    protected void cleanup()
    {
        // If we created any InputSource objects in this instance,
        // they each have an input stream that should be closed
        for ( final InputSource source : inputSources )
        {
            try
            {
                source.getByteStream().close();
            }
            catch ( final IOException e )
            {
                // Fall through so we get them all
                if ( log.isWarnEnabled() )
                {
                    log.warn( format( "An error occurred while closing resource %s (%s)",
                                      source.getPublicId(),
                                      source.getSystemId() ), e );
                }
            }
        }
        inputSources.clear();
    }

    /**
     * <p>
     * Provide a hook for lazy configuration of this <code>Digester</code> instance. The default implementation does
     * nothing, but subclasses can override as needed.
     * </p>
     * <p>
     * <strong>Note</strong> This method may be called more than once. Once only initialization code should be placed in
     * {@link #initialize} or the code should take responsibility by checking and setting the {@link #configured} flag.
     * </p>
     */
    protected void configure()
    {
        // Do not configure more than once
        if ( configured )
        {
            return;
        }

        // Perform lazy configuration as needed
        initialize(); // call hook method for subclasses that want to be initialized once only
        // Nothing else required by default

        // Set the configuration flag to avoid repeating
        configured = true;
    }

    /**
     * Checks the Digester instance has been configured.
     *
     * @return true, if the Digester instance has been configured, false otherwise
     * @since 3.0
     */
    public boolean isConfigured()
    {
        return configured;
    }

    /**
     * <p>
     * Provides a hook for lazy initialization of this <code>Digester</code> instance. The default implementation does
     * nothing, but subclasses can override as needed. Digester (by default) only calls this method once.
     * </p>
     * <p>
     * <strong>Note</strong> This method will be called by {@link #configure} only when the {@link #configured} flag is
     * false. Subclasses that override <code>configure</code> or who set <code>configured</code> may find that this
     * method may be called more than once.
     * </p>
     *
     * @since 1.6
     */
    protected void initialize()
    {
        // Perform lazy initialization as needed
        // Nothing required by default
    }

    // -------------------------------------------------------- Package Methods

    /**
     * Return the set of DTD URL registrations, keyed by public identifier. NOTE: the returned map is in read-only mode.
     *
     * @return the read-only Map of DTD URL registrations.
     */
    Map<String, URL> getRegistrations()
    {
        return Collections.unmodifiableMap( entityValidator );
    }

    /**
     * <p>
     * Return the top object on the parameters stack without removing it. If there are no objects on the stack, return
     * <code>null</code>.
     * </p>
     * <p>
     * The parameters stack is used to store <code>CallMethodRule</code> parameters. See {@link #params}.
     * </p>
     *
     * @return the top object on the parameters stack without removing it.
     */
    public Object[] peekParams()
    {
        try
        {
            return ( params.peek() );
        }
        catch ( final EmptyStackException e )
        {
            log.warn( "Empty stack (returning null)" );
            return ( null );
        }
    }

    /**
     * <p>
     * Return the n'th object down the parameters stack, where 0 is the top element and [getCount()-1] is the bottom
     * element. If the specified index is out of range, return <code>null</code>.
     * </p>
     * <p>
     * The parameters stack is used to store <code>CallMethodRule</code> parameters. See {@link #params}.
     * </p>
     *
     * @param n Index of the desired element, where 0 is the top of the stack, 1 is the next element down, and so on.
     * @return the n'th object down the parameters stack
     */
    public Object[] peekParams( final int n )
    {
        final int index = ( params.size() - 1 ) - n;
        if ( index < 0 )
        {
            log.warn( "Empty stack (returning null)" );
            return ( null );
        }
        try
        {
            return ( params.get( index ) );
        }
        catch ( final EmptyStackException e )
        {
            log.warn( "Empty stack (returning null)" );
            return ( null );
        }
    }

    /**
     * <p>
     * Pop the top object off of the parameters stack, and return it. If there are no objects on the stack, return
     * <code>null</code>.
     * </p>
     * <p>
     * The parameters stack is used to store <code>CallMethodRule</code> parameters. See {@link #params}.
     * </p>
     *
     * @return the top object popped off of the parameters stack
     */
    public Object[] popParams()
    {
        try
        {
            if ( log.isTraceEnabled() )
            {
                log.trace( "Popping params" );
            }
            return ( params.pop() );
        }
        catch ( final EmptyStackException e )
        {
            log.warn( "Empty stack (returning null)" );
            return ( null );
        }
    }

    /**
     * <p>
     * Push a new object onto the top of the parameters stack.
     * </p>
     * <p>
     * The parameters stack is used to store <code>CallMethodRule</code> parameters. See {@link #params}.
     * </p>
     *
     * @param object The new object
     */
    public void pushParams( final Object... object )
    {
        if ( log.isTraceEnabled() )
        {
            log.trace( "Pushing params" );
        }
        params.push( object );
    }

    /**
     * Create a SAX exception which also understands about the location in the digester file where the exception occurs
     *
     * @param message the custom SAX exception message
     * @param e the exception cause
     * @return the new SAX exception
     */
    public SAXException createSAXException( final String message, Exception e )
    {
        if ( ( e != null ) && ( e instanceof InvocationTargetException ) )
        {
            final Throwable t = ( (InvocationTargetException) e ).getTargetException();
            if ( ( t != null ) && ( t instanceof Exception ) )
            {
                e = (Exception) t;
            }
        }
        if ( locator != null )
        {
            final String error =
                "Error at line " + locator.getLineNumber() + " char " + locator.getColumnNumber() + ": " + message;
            if ( e != null )
            {
                return new SAXParseException( error, locator, e );
            }
            return new SAXParseException( error, locator );
        }
        log.error( "No Locator!" );
        if ( e != null )
        {
            return new SAXException( message, e );
        }
        return new SAXException( message );
    }

    /**
     * Create a SAX exception which also understands about the location in the digester file where the exception occurs
     *
     * @param e the exception cause
     * @return the new SAX exception
     */
    public SAXException createSAXException( Exception e )
    {
        if ( e instanceof InvocationTargetException )
        {
            final 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
     *
     * @param message the custom SAX exception message
     * @return the new SAX exception
     */
    public SAXException createSAXException( final String message )
    {
        return createSAXException( message, null );
    }

    /**
     * Helps casting the input object to given type, avoiding NPEs.
     *
     * @since 3.0
     * @param <T> the type the input object has to be cast.
     * @param obj the object has to be cast.
     * @return the casted object, if input object is not null, null otherwise.
     */
    private <T> T npeSafeCast( final Object obj )
    {
        if ( obj == null )
        {
            return null;
        }

        @SuppressWarnings( "unchecked" )
        final
        T result = (T) obj;
        return result;
    }

}
