This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-digester.git


The following commit(s) were added to refs/heads/master by this push:
     new 5a01544e Normalize Javadoc spelling
5a01544e is described below

commit 5a01544eea636989acf27d9214bc855ce65c1f81
Author: Gary Gregory <ggreg...@rocketsoftware.com>
AuthorDate: Wed Jun 15 08:22:59 2022 -0400

    Normalize Javadoc spelling
---
 .../digester3/plugins/InitializableRule.java       |   78 +-
 .../digester3/plugins/PluginCreateRule.java        | 1266 ++++++++++----------
 .../commons/digester3/plugins/PluginRules.java     |  944 +++++++--------
 3 files changed, 1144 insertions(+), 1144 deletions(-)

diff --git 
a/core/src/main/java/org/apache/commons/digester3/plugins/InitializableRule.java
 
b/core/src/main/java/org/apache/commons/digester3/plugins/InitializableRule.java
index fda1ddb5..ad78afc4 100644
--- 
a/core/src/main/java/org/apache/commons/digester3/plugins/InitializableRule.java
+++ 
b/core/src/main/java/org/apache/commons/digester3/plugins/InitializableRule.java
@@ -1,39 +1,39 @@
-package org.apache.commons.digester3.plugins;
-
-/*
- * 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.
- */
-
-/**
- * Defines an interface that a Rule class can implement if it wishes to get an 
initialisation callback after the rule
- * has been added to the set of Rules within a PluginRules instance.
- *
- * @since 1.6
- */
-public interface InitializableRule
-{
-
-    /**
-     * Called after this Rule object has been added to the list of all Rules. 
Note that if a single InitializableRule
-     * instance is associated with more than one pattern, then this method 
will be called more than once.
-     *
-     * @param pattern is the digester match pattern that will trigger this 
rule.
-     */
-    void postRegisterInit( String pattern );
-
-}
+package org.apache.commons.digester3.plugins;
+
+/*
+ * 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.
+ */
+
+/**
+ * Defines an interface that a Rule class can implement if it wishes to get an 
initialization callback after the rule
+ * has been added to the set of Rules within a PluginRules instance.
+ *
+ * @since 1.6
+ */
+public interface InitializableRule
+{
+
+    /**
+     * Called after this Rule object has been added to the list of all Rules. 
Note that if a single InitializableRule
+     * instance is associated with more than one pattern, then this method 
will be called more than once.
+     *
+     * @param pattern is the digester match pattern that will trigger this 
rule.
+     */
+    void postRegisterInit( String pattern );
+
+}
diff --git 
a/core/src/main/java/org/apache/commons/digester3/plugins/PluginCreateRule.java 
b/core/src/main/java/org/apache/commons/digester3/plugins/PluginCreateRule.java
index 599943d4..72bcc4cc 100644
--- 
a/core/src/main/java/org/apache/commons/digester3/plugins/PluginCreateRule.java
+++ 
b/core/src/main/java/org/apache/commons/digester3/plugins/PluginCreateRule.java
@@ -1,633 +1,633 @@
-package org.apache.commons.digester3.plugins;
-
-/*
- * 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 java.util.List;
-
-import org.apache.commons.digester3.Rule;
-import org.apache.commons.logging.Log;
-import org.xml.sax.Attributes;
-
-/**
- * Allows the original rules for parsing the configuration file to define 
points at which plugins are allowed, by
- * configuring a PluginCreateRule with the appropriate pattern.
- *
- * @since 1.6
- */
-public class PluginCreateRule
-    extends Rule
-    implements InitializableRule
-{
-
-    // see setPluginClassAttribute
-    private String pluginClassAttrNs = null;
-
-    private String pluginClassAttr = null;
-
-    // see setPluginIdAttribute
-    private String pluginIdAttrNs = null;
-
-    private String pluginIdAttr = null;
-
-    /**
-     * In order to invoke the addRules method on the plugin class correctly, 
we need to know the pattern which this rule
-     * is matched by.
-     */
-    private String pattern;
-
-    /** A base class that any plugin must derive from. */
-    private Class<?> baseClass = null;
-
-    /**
-     * Info about optional default plugin to be used if no plugin-id is 
specified in the input data. This can simplify
-     * the syntax where one particular plugin is usually used.
-     */
-    private Declaration defaultPlugin;
-
-    /**
-     * Currently, none of the Rules methods allow exceptions to be thrown. 
Therefore if this class cannot initialize
-     * itself properly, it cannot cause the digester to stop. Instead, we 
cache the exception and throw it the first
-     * time the begin() method is called.
-     */
-    private PluginConfigurationException initException;
-
-    // -------------------- constructors -------------------------------------
-
-    /**
-     * Create a plugin rule where the user <i>must</i> specify a plugin-class 
or plugin-id.
-     *
-     * @param baseClass is the class which any specified plugin <i>must</i> be 
descended from.
-     */
-    public PluginCreateRule( final Class<?> baseClass )
-    {
-        this.baseClass = baseClass;
-    }
-
-    /**
-     * Create a plugin rule where the user <i>may</i> specify a plugin. If the 
user doesn't specify a plugin, then the
-     * default class specified in this constructor is used.
-     *
-     * @param baseClass is the class which any specified plugin <i>must</i> be 
descended from.
-     * @param dfltPluginClass is the class which will be used if the user 
doesn't specify any plugin-class or plugin-id.
-     *            This class will have custom rules installed for it just like 
a declared plugin.
-     */
-    public PluginCreateRule( final Class<?> baseClass, final Class<?> 
dfltPluginClass )
-    {
-        this.baseClass = baseClass;
-        if ( dfltPluginClass != null )
-        {
-            defaultPlugin = new Declaration( dfltPluginClass );
-        }
-    }
-
-    /**
-     * Create a plugin rule where the user <i>may</i> specify a plugin. If the 
user doesn't specify a plugin, then the
-     * default class specified in this constructor is used.
-     *
-     * @param baseClass is the class which any specified plugin <i>must</i> be 
descended from.
-     * @param dfltPluginClass is the class which will be used if the user 
doesn't specify any plugin-class or plugin-id.
-     *            This class will have custom rules installed for it just like 
a declared plugin.
-     * @param dfltPluginRuleLoader is a RuleLoader instance which knows how to 
load the custom rules associated with
-     *            this default plugin.
-     */
-    public PluginCreateRule( final Class<?> baseClass, final Class<?> 
dfltPluginClass, final RuleLoader dfltPluginRuleLoader )
-    {
-        this.baseClass = baseClass;
-        if ( dfltPluginClass != null )
-        {
-            defaultPlugin = new Declaration( dfltPluginClass, 
dfltPluginRuleLoader );
-        }
-    }
-
-    // ------------------- properties ---------------------------------------
-
-    /**
-     * Sets the xml attribute which the input xml uses to indicate to a 
PluginCreateRule which class should be
-     * instantiated.
-     * <p>
-     * See {@link PluginRules#setPluginClassAttribute} for more info.
-     *
-     * @param namespaceUri is the namespace uri that the specified attribute 
is in. If the attribute is in no namespace,
-     *            then this should be null. Note that if a namespace is used, 
the attrName value should <i>not</i>
-     *            contain any kind of namespace-prefix. Note also that if you 
are using a non-namespace-aware parser,
-     *            this parameter <i>must</i> be null.
-     * @param attrName is the attribute whose value contains the name of the 
class to be instantiated.
-     */
-    public void setPluginClassAttribute( final String namespaceUri, final 
String attrName )
-    {
-        pluginClassAttrNs = namespaceUri;
-        pluginClassAttr = attrName;
-    }
-
-    /**
-     * Sets the xml attribute which the input xml uses to indicate to a 
PluginCreateRule which plugin declaration is
-     * being referenced.
-     * <p>
-     * See {@link PluginRules#setPluginIdAttribute} for more info.
-     *
-     * @param namespaceUri is the namespace uri that the specified attribute 
is in. If the attribute is in no namespace,
-     *            then this should be null. Note that if a namespace is used, 
the attrName value should <i>not</i>
-     *            contain any kind of namespace-prefix. Note also that if you 
are using a non-namespace-aware parser,
-     *            this parameter <i>must</i> be null.
-     * @param attrName is the attribute whose value contains the id of the 
plugin declaration to be used when
-     *            instantiating an object.
-     */
-    public void setPluginIdAttribute( final String namespaceUri, final String 
attrName )
-    {
-        pluginIdAttrNs = namespaceUri;
-        pluginIdAttr = attrName;
-    }
-
-    // ------------------- methods --------------------------------------------
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void postRegisterInit( final String matchPattern )
-    {
-        final Log log = LogUtils.getLogger( getDigester() );
-        final boolean debug = log.isDebugEnabled();
-        if ( debug )
-        {
-            log.debug( "PluginCreateRule.postRegisterInit" + ": rule 
registered for pattern [" + matchPattern + "]" );
-        }
-
-        if ( getDigester() == null )
-        {
-            // We require setDigester to be called before this method.
-            // Note that this means that PluginCreateRule cannot be added
-            // to a Rules object which has not yet been added to a
-            // Digester object.
-            initException =
-                new PluginConfigurationException( "Invalid invocation of 
postRegisterInit" + ": digester not set." );
-            throw initException;
-        }
-
-        if ( pattern != null )
-        {
-            // We have been called twice, ie a single instance has been
-            // associated with multiple patterns.
-            //
-            // Generally, Digester Rule instances can be associated with
-            // multiple patterns. However for plugins, this creates some
-            // complications. Some day this may be supported; however for
-            // now we just reject this situation.
-            initException =
-                new PluginConfigurationException( "A single PluginCreateRule 
instance has been mapped to"
-                    + " multiple patterns; this is not supported." );
-            throw initException;
-        }
-
-        if ( matchPattern.indexOf( '*' ) != -1 )
-        {
-            // having wildcards in patterns is extremely difficult to
-            // deal with. For now, we refuse to allow this.
-            //
-            // TODO: check for any chars not valid in xml element name
-            // rather than just *.
-            //
-            // Reasons include:
-            // (a) handling recursive plugins, and
-            // (b) determining whether one pattern is "below" another,
-            // as done by PluginRules. Without wildcards, "below"
-            // just means startsWith, which is easy to check.
-            initException =
-                new PluginConfigurationException( "A PluginCreateRule instance 
has been mapped to" + " pattern ["
-                    + matchPattern + "]." + " This pattern includes a wildcard 
character."
-                    + " This is not supported by the plugin architecture." );
-            throw initException;
-        }
-
-        if ( baseClass == null )
-        {
-            baseClass = Object.class;
-        }
-
-        final PluginRules rules = (PluginRules) getDigester().getRules();
-        final PluginManager pm = rules.getPluginManager();
-
-        // check default class is valid
-        if ( defaultPlugin != null )
-        {
-            if ( !baseClass.isAssignableFrom( defaultPlugin.getPluginClass() ) 
)
-            {
-                initException =
-                    new PluginConfigurationException( "Default class [" + 
defaultPlugin.getPluginClass().getName()
-                        + "] does not inherit from [" + baseClass.getName() + 
"]." );
-                throw initException;
-            }
-
-            try
-            {
-                defaultPlugin.init( getDigester(), pm );
-
-            }
-            catch ( final PluginException pwe )
-            {
-
-                throw new PluginConfigurationException( pwe.getMessage(), 
pwe.getCause() );
-            }
-        }
-
-        // remember the pattern for later
-        pattern = matchPattern;
-
-        if ( pluginClassAttr == null )
-        {
-            // the user hasn't set explicit xml attr names on this rule,
-            // so fetch the default values
-            pluginClassAttrNs = rules.getPluginClassAttrNs();
-            pluginClassAttr = rules.getPluginClassAttr();
-
-            if ( debug )
-            {
-                log.debug( "init: pluginClassAttr set to per-digester values 
[" + "ns=" + pluginClassAttrNs + ", name="
-                    + pluginClassAttr + "]" );
-            }
-        }
-        else
-        {
-            if ( debug )
-            {
-                log.debug( "init: pluginClassAttr set to rule-specific values 
[" + "ns=" + pluginClassAttrNs
-                    + ", name=" + pluginClassAttr + "]" );
-            }
-        }
-
-        if ( pluginIdAttr == null )
-        {
-            // the user hasn't set explicit xml attr names on this rule,
-            // so fetch the default values
-            pluginIdAttrNs = rules.getPluginIdAttrNs();
-            pluginIdAttr = rules.getPluginIdAttr();
-
-            if ( debug )
-            {
-                log.debug( "init: pluginIdAttr set to per-digester values [" + 
"ns=" + pluginIdAttrNs + ", name="
-                    + pluginIdAttr + "]" );
-            }
-        }
-        else
-        {
-            if ( debug )
-            {
-                log.debug( "init: pluginIdAttr set to rule-specific values [" 
+ "ns=" + pluginIdAttrNs + ", name="
-                    + pluginIdAttr + "]" );
-            }
-        }
-    }
-
-    /**
-     * Invoked when the Digester matches this rule against an xml element.
-     * <p>
-     * A new instance of the target class is created, and pushed onto the 
stack. A new "private" PluginRules object is
-     * then created and set as the digester's default Rules object. Any custom 
rules associated with the plugin class
-     * are then loaded into that new Rules object. Finally, any custom rules 
that are associated with the current
-     * pattern (such as SetPropertiesRules) have their begin methods executed.
-     *
-     * @param namespace the namespace URI of the matching element, or an empty 
string if the parser is not namespace
-     *            aware or the element has no namespace
-     * @param name the local name if the parser is namespace aware, or just 
the element name otherwise
-     * @param attributes The attribute list of this element
-     * @throws Exception if any error occurs
-     */
-    @Override
-    public void begin( final String namespace, final String name, final 
org.xml.sax.Attributes attributes )
-        throws Exception
-    {
-        final Log log = getDigester().getLogger();
-        final boolean debug = log.isDebugEnabled();
-        if ( debug )
-        {
-            log.debug( "PluginCreateRule.begin" + ": pattern=[" + pattern + 
"]" + " match=[" + getDigester().getMatch()
-                + "]" );
-        }
-
-        if ( initException != null )
-        {
-            // we had a problem during initialisation that we could
-            // not report then; report it now.
-            throw initException;
-        }
-
-        // load any custom rules associated with the plugin
-        final PluginRules oldRules = (PluginRules) getDigester().getRules();
-        final PluginManager pluginManager = oldRules.getPluginManager();
-        Declaration currDeclaration = null;
-
-        String pluginClassName;
-        if ( pluginClassAttrNs == null )
-        {
-            // Yep, this is ugly.
-            //
-            // In a namespace-aware parser, the one-param version will
-            // return attributes with no namespace.
-            //
-            // In a non-namespace-aware parser, the two-param version will
-            // never return any attributes, ever.
-            pluginClassName = attributes.getValue( pluginClassAttr );
-        }
-        else
-        {
-            pluginClassName = attributes.getValue( pluginClassAttrNs, 
pluginClassAttr );
-        }
-
-        String pluginId;
-        if ( pluginIdAttrNs == null )
-        {
-            pluginId = attributes.getValue( pluginIdAttr );
-        }
-        else
-        {
-            pluginId = attributes.getValue( pluginIdAttrNs, pluginIdAttr );
-        }
-
-        if ( pluginClassName != null )
-        {
-            // The user is using a plugin "inline", ie without a previous
-            // explicit declaration. If they have used the same plugin class
-            // before, we have already gone to the effort of creating a
-            // Declaration object, so retrieve it. If there is no existing
-            // declaration object for this class, then create one.
-
-            currDeclaration = pluginManager.getDeclarationByClass( 
pluginClassName );
-
-            if ( currDeclaration == null )
-            {
-                currDeclaration = new Declaration( pluginClassName );
-                try
-                {
-                    currDeclaration.init( getDigester(), pluginManager );
-                }
-                catch ( final PluginException pwe )
-                {
-                    throw new PluginInvalidInputException( pwe.getMessage(), 
pwe.getCause() );
-                }
-                pluginManager.addDeclaration( currDeclaration );
-            }
-        }
-        else if ( pluginId != null )
-        {
-            currDeclaration = pluginManager.getDeclarationById( pluginId );
-
-            if ( currDeclaration == null )
-            {
-                throw new PluginInvalidInputException( "Plugin id [" + 
pluginId + "] is not defined." );
-            }
-        }
-        else if ( defaultPlugin != null )
-        {
-            currDeclaration = defaultPlugin;
-        }
-        else
-        {
-            throw new PluginInvalidInputException( "No plugin class specified 
for element " + pattern );
-        }
-
-        // get the class of the user plugged-in type
-        final Class<?> pluginClass = currDeclaration.getPluginClass();
-
-        final String path = getDigester().getMatch();
-
-        // create a new Rules object and effectively push it onto a stack of
-        // rules objects. The stack is actually a linked list; using the
-        // PluginRules constructor below causes the new instance to link
-        // to the previous head-of-stack, then the Digester.setRules() makes
-        // the new instance the new head-of-stack.
-        final PluginRules newRules = new PluginRules( getDigester(), path, 
oldRules, pluginClass );
-        getDigester().setRules( newRules );
-
-        if ( debug )
-        {
-            log.debug( "PluginCreateRule.begin: installing new plugin: " + 
"oldrules=" + oldRules.toString()
-                + ", newrules=" + newRules.toString() );
-        }
-
-        // load up the custom rules
-        currDeclaration.configure( getDigester(), pattern );
-
-        // create an instance of the plugin class
-        final Object instance = pluginClass.newInstance();
-        getDigester().push( instance );
-        if ( debug )
-        {
-            log.debug( "PluginCreateRule.begin" + ": pattern=[" + pattern + 
"]" + " match=[" + getDigester().getMatch()
-                + "]" + " pushed instance of plugin [" + pluginClass.getName() 
+ "]" );
-        }
-
-        // and now we have to fire any custom rules which would have
-        // been matched by the same path that matched this rule, had
-        // they been loaded at that time.
-        final List<Rule> rules = newRules.getDecoratedRules().match( 
namespace, path, name, attributes );
-        fireBeginMethods( rules, namespace, name, attributes );
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void body( final String namespace, final String name, final String 
text )
-        throws Exception
-    {
-
-        // While this class itself has no work to do in the body method,
-        // we do need to fire the body methods of all dynamically-added
-        // rules matching the same path as this rule. During begin, we had
-        // to manually execute the dynamic rules' begin methods because they
-        // didn't exist in the digester's Rules object when the match begin.
-        // So in order to ensure consistent ordering of rule execution, the
-        // PluginRules class deliberately avoids returning any such rules
-        // in later calls to the match method, instead relying on this
-        // object to execute them at the appropriate time.
-        //
-        // Note that this applies only to rules matching exactly the path
-        // which is also matched by this PluginCreateRule.
-
-        final String path = getDigester().getMatch();
-        final PluginRules newRules = (PluginRules) getDigester().getRules();
-        final List<Rule> rules = newRules.getDecoratedRules().match( 
namespace, path, name, null );
-        fireBodyMethods( rules, namespace, name, text );
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void end( final String namespace, final String name )
-        throws Exception
-    {
-        // see body method for more info
-        final String path = getDigester().getMatch();
-        final PluginRules newRules = (PluginRules) getDigester().getRules();
-        final List<Rule> rules = newRules.getDecoratedRules().match( 
namespace, path, name, null );
-        fireEndMethods( rules, namespace, name );
-
-        // pop the stack of PluginRules instances, which
-        // discards all custom rules associated with this plugin
-        getDigester().setRules( newRules.getParent() );
-
-        // and get rid of the instance of the plugin class from the
-        // digester object stack.
-        getDigester().pop();
-    }
-
-    /**
-     * Return the pattern that this Rule is associated with.
-     * <p>
-     * In general, Rule instances <i>can</i> be associated with multiple 
patterns. A PluginCreateRule, however, will
-     * only function correctly when associated with a single pattern. It is 
possible to fix this, but I can't be
-     * bothered just now because this feature is unlikely to be used.
-     * </p>
-     *
-     * @return The pattern value
-     */
-    public String getPattern()
-    {
-        return pattern;
-    }
-
-    /**
-     * Duplicate the processing that the Digester does when firing the begin 
methods of rules. It would be really nice
-     * if the Digester class provided a way for this functionality to just be 
invoked directly.
-     *
-     * @param rules The rules which {@link Rule#begin(String, String, 
Attributes)} method has to be fired
-     * @param namespace the namespace URI of the matching element, or an empty 
string if the parser is not namespace
-     *            aware or the element has no namespace
-     * @param name the local name if the parser is namespace aware, or just 
the element name otherwise
-     * @param list The attribute list of this element
-     * @throws Exception if any error occurs
-     */
-    public void fireBeginMethods( final List<Rule> rules, final String 
namespace, final String name, final Attributes list )
-        throws Exception
-    {
-
-        if ( ( rules != null ) && ( !rules.isEmpty() ) )
-        {
-            final Log log = getDigester().getLogger();
-            final boolean debug = log.isDebugEnabled();
-            for ( final Rule rule : rules )
-            {
-                if ( debug )
-                {
-                    log.debug( "  Fire begin() for " + rule );
-                }
-                try
-                {
-                    rule.begin( namespace, name, list );
-                }
-                catch ( final Exception e )
-                {
-                    throw getDigester().createSAXException( e );
-                }
-                catch ( final Error e )
-                {
-                    throw e;
-                }
-            }
-        }
-    }
-
-    /**
-     * Duplicate the processing that the Digester does when firing the {@link 
Rule#body(String, String, String)} methods
-     * of rules.
-     *
-     * It would be really nice if the Digester class provided a way for this 
functionality to just be invoked directly.
-     *
-     * @param rules The rules which {@link Rule#body(String, String, String)} 
method has to be fired
-     * @param namespace the namespace URI of the matching element, or an empty 
string if the parser is not namespace
-     *            aware or the element has no namespace
-     * @param name the local name if the parser is namespace aware, or just 
the element name otherwise
-     * @param text The text of the body of this element
-     * @throws Exception if any error occurs
-     */
-    private void fireBodyMethods( final List<Rule> rules, final String 
namespaceURI, final String name, final String text )
-        throws Exception
-    {
-        if ( ( rules != null ) && ( !rules.isEmpty() ) )
-        {
-            final Log log = getDigester().getLogger();
-            final boolean debug = log.isDebugEnabled();
-            for ( final Rule rule : rules )
-            {
-                if ( debug )
-                {
-                    log.debug( "  Fire body() for " + rule );
-                }
-                try
-                {
-                    rule.body( namespaceURI, name, text );
-                }
-                catch ( final Exception e )
-                {
-                    throw getDigester().createSAXException( e );
-                }
-                catch ( final Error e )
-                {
-                    throw e;
-                }
-            }
-        }
-    }
-
-    /**
-     * Duplicate the processing that the Digester does when firing the end 
methods of rules.
-     *
-     * It would be really nice if the Digester class provided a way for this 
functionality to just be invoked directly.
-     *
-     * @param rules The rules which {@link Rule#end(String, String)} method 
has to be fired
-     * @param namespaceURI the namespace URI of the matching element, or an 
empty string if the parser is not namespace
-     *            aware or the element has no namespace
-     * @param name the local name if the parser is namespace aware, or just 
the element name otherwise
-     * @throws Exception if any error occurs
-     */
-    public void fireEndMethods( final List<Rule> rules, final String 
namespaceURI, final String name )
-        throws Exception
-    {
-        // Fire "end" events for all relevant rules in reverse order
-        if ( rules != null )
-        {
-            final Log log = getDigester().getLogger();
-            final boolean debug = log.isDebugEnabled();
-            for ( int i = 0; i < rules.size(); i++ )
-            {
-                final int j = ( rules.size() - i ) - 1;
-                final Rule rule = rules.get( j );
-                if ( debug )
-                {
-                    log.debug( "  Fire end() for " + rule );
-                }
-                try
-                {
-                    rule.end( namespaceURI, name );
-                }
-                catch ( final Exception e )
-                {
-                    throw getDigester().createSAXException( e );
-                }
-                catch ( final Error e )
-                {
-                    throw e;
-                }
-            }
-        }
-    }
-
-}
+package org.apache.commons.digester3.plugins;
+
+/*
+ * 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 java.util.List;
+
+import org.apache.commons.digester3.Rule;
+import org.apache.commons.logging.Log;
+import org.xml.sax.Attributes;
+
+/**
+ * Allows the original rules for parsing the configuration file to define 
points at which plugins are allowed, by
+ * configuring a PluginCreateRule with the appropriate pattern.
+ *
+ * @since 1.6
+ */
+public class PluginCreateRule
+    extends Rule
+    implements InitializableRule
+{
+
+    // see setPluginClassAttribute
+    private String pluginClassAttrNs = null;
+
+    private String pluginClassAttr = null;
+
+    // see setPluginIdAttribute
+    private String pluginIdAttrNs = null;
+
+    private String pluginIdAttr = null;
+
+    /**
+     * In order to invoke the addRules method on the plugin class correctly, 
we need to know the pattern which this rule
+     * is matched by.
+     */
+    private String pattern;
+
+    /** A base class that any plugin must derive from. */
+    private Class<?> baseClass = null;
+
+    /**
+     * Info about optional default plugin to be used if no plugin-id is 
specified in the input data. This can simplify
+     * the syntax where one particular plugin is usually used.
+     */
+    private Declaration defaultPlugin;
+
+    /**
+     * Currently, none of the Rules methods allow exceptions to be thrown. 
Therefore if this class cannot initialize
+     * itself properly, it cannot cause the digester to stop. Instead, we 
cache the exception and throw it the first
+     * time the begin() method is called.
+     */
+    private PluginConfigurationException initException;
+
+    // -------------------- constructors -------------------------------------
+
+    /**
+     * Create a plugin rule where the user <i>must</i> specify a plugin-class 
or plugin-id.
+     *
+     * @param baseClass is the class which any specified plugin <i>must</i> be 
descended from.
+     */
+    public PluginCreateRule( final Class<?> baseClass )
+    {
+        this.baseClass = baseClass;
+    }
+
+    /**
+     * Create a plugin rule where the user <i>may</i> specify a plugin. If the 
user doesn't specify a plugin, then the
+     * default class specified in this constructor is used.
+     *
+     * @param baseClass is the class which any specified plugin <i>must</i> be 
descended from.
+     * @param dfltPluginClass is the class which will be used if the user 
doesn't specify any plugin-class or plugin-id.
+     *            This class will have custom rules installed for it just like 
a declared plugin.
+     */
+    public PluginCreateRule( final Class<?> baseClass, final Class<?> 
dfltPluginClass )
+    {
+        this.baseClass = baseClass;
+        if ( dfltPluginClass != null )
+        {
+            defaultPlugin = new Declaration( dfltPluginClass );
+        }
+    }
+
+    /**
+     * Create a plugin rule where the user <i>may</i> specify a plugin. If the 
user doesn't specify a plugin, then the
+     * default class specified in this constructor is used.
+     *
+     * @param baseClass is the class which any specified plugin <i>must</i> be 
descended from.
+     * @param dfltPluginClass is the class which will be used if the user 
doesn't specify any plugin-class or plugin-id.
+     *            This class will have custom rules installed for it just like 
a declared plugin.
+     * @param dfltPluginRuleLoader is a RuleLoader instance which knows how to 
load the custom rules associated with
+     *            this default plugin.
+     */
+    public PluginCreateRule( final Class<?> baseClass, final Class<?> 
dfltPluginClass, final RuleLoader dfltPluginRuleLoader )
+    {
+        this.baseClass = baseClass;
+        if ( dfltPluginClass != null )
+        {
+            defaultPlugin = new Declaration( dfltPluginClass, 
dfltPluginRuleLoader );
+        }
+    }
+
+    // ------------------- properties ---------------------------------------
+
+    /**
+     * Sets the xml attribute which the input xml uses to indicate to a 
PluginCreateRule which class should be
+     * instantiated.
+     * <p>
+     * See {@link PluginRules#setPluginClassAttribute} for more info.
+     *
+     * @param namespaceUri is the namespace uri that the specified attribute 
is in. If the attribute is in no namespace,
+     *            then this should be null. Note that if a namespace is used, 
the attrName value should <i>not</i>
+     *            contain any kind of namespace-prefix. Note also that if you 
are using a non-namespace-aware parser,
+     *            this parameter <i>must</i> be null.
+     * @param attrName is the attribute whose value contains the name of the 
class to be instantiated.
+     */
+    public void setPluginClassAttribute( final String namespaceUri, final 
String attrName )
+    {
+        pluginClassAttrNs = namespaceUri;
+        pluginClassAttr = attrName;
+    }
+
+    /**
+     * Sets the xml attribute which the input xml uses to indicate to a 
PluginCreateRule which plugin declaration is
+     * being referenced.
+     * <p>
+     * See {@link PluginRules#setPluginIdAttribute} for more info.
+     *
+     * @param namespaceUri is the namespace uri that the specified attribute 
is in. If the attribute is in no namespace,
+     *            then this should be null. Note that if a namespace is used, 
the attrName value should <i>not</i>
+     *            contain any kind of namespace-prefix. Note also that if you 
are using a non-namespace-aware parser,
+     *            this parameter <i>must</i> be null.
+     * @param attrName is the attribute whose value contains the id of the 
plugin declaration to be used when
+     *            instantiating an object.
+     */
+    public void setPluginIdAttribute( final String namespaceUri, final String 
attrName )
+    {
+        pluginIdAttrNs = namespaceUri;
+        pluginIdAttr = attrName;
+    }
+
+    // ------------------- methods --------------------------------------------
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void postRegisterInit( final String matchPattern )
+    {
+        final Log log = LogUtils.getLogger( getDigester() );
+        final boolean debug = log.isDebugEnabled();
+        if ( debug )
+        {
+            log.debug( "PluginCreateRule.postRegisterInit" + ": rule 
registered for pattern [" + matchPattern + "]" );
+        }
+
+        if ( getDigester() == null )
+        {
+            // We require setDigester to be called before this method.
+            // Note that this means that PluginCreateRule cannot be added
+            // to a Rules object which has not yet been added to a
+            // Digester object.
+            initException =
+                new PluginConfigurationException( "Invalid invocation of 
postRegisterInit" + ": digester not set." );
+            throw initException;
+        }
+
+        if ( pattern != null )
+        {
+            // We have been called twice, ie a single instance has been
+            // associated with multiple patterns.
+            //
+            // Generally, Digester Rule instances can be associated with
+            // multiple patterns. However for plugins, this creates some
+            // complications. Some day this may be supported; however for
+            // now we just reject this situation.
+            initException =
+                new PluginConfigurationException( "A single PluginCreateRule 
instance has been mapped to"
+                    + " multiple patterns; this is not supported." );
+            throw initException;
+        }
+
+        if ( matchPattern.indexOf( '*' ) != -1 )
+        {
+            // having wildcards in patterns is extremely difficult to
+            // deal with. For now, we refuse to allow this.
+            //
+            // TODO: check for any chars not valid in xml element name
+            // rather than just *.
+            //
+            // Reasons include:
+            // (a) handling recursive plugins, and
+            // (b) determining whether one pattern is "below" another,
+            // as done by PluginRules. Without wildcards, "below"
+            // just means startsWith, which is easy to check.
+            initException =
+                new PluginConfigurationException( "A PluginCreateRule instance 
has been mapped to" + " pattern ["
+                    + matchPattern + "]." + " This pattern includes a wildcard 
character."
+                    + " This is not supported by the plugin architecture." );
+            throw initException;
+        }
+
+        if ( baseClass == null )
+        {
+            baseClass = Object.class;
+        }
+
+        final PluginRules rules = (PluginRules) getDigester().getRules();
+        final PluginManager pm = rules.getPluginManager();
+
+        // check default class is valid
+        if ( defaultPlugin != null )
+        {
+            if ( !baseClass.isAssignableFrom( defaultPlugin.getPluginClass() ) 
)
+            {
+                initException =
+                    new PluginConfigurationException( "Default class [" + 
defaultPlugin.getPluginClass().getName()
+                        + "] does not inherit from [" + baseClass.getName() + 
"]." );
+                throw initException;
+            }
+
+            try
+            {
+                defaultPlugin.init( getDigester(), pm );
+
+            }
+            catch ( final PluginException pwe )
+            {
+
+                throw new PluginConfigurationException( pwe.getMessage(), 
pwe.getCause() );
+            }
+        }
+
+        // remember the pattern for later
+        pattern = matchPattern;
+
+        if ( pluginClassAttr == null )
+        {
+            // the user hasn't set explicit xml attr names on this rule,
+            // so fetch the default values
+            pluginClassAttrNs = rules.getPluginClassAttrNs();
+            pluginClassAttr = rules.getPluginClassAttr();
+
+            if ( debug )
+            {
+                log.debug( "init: pluginClassAttr set to per-digester values 
[" + "ns=" + pluginClassAttrNs + ", name="
+                    + pluginClassAttr + "]" );
+            }
+        }
+        else
+        {
+            if ( debug )
+            {
+                log.debug( "init: pluginClassAttr set to rule-specific values 
[" + "ns=" + pluginClassAttrNs
+                    + ", name=" + pluginClassAttr + "]" );
+            }
+        }
+
+        if ( pluginIdAttr == null )
+        {
+            // the user hasn't set explicit xml attr names on this rule,
+            // so fetch the default values
+            pluginIdAttrNs = rules.getPluginIdAttrNs();
+            pluginIdAttr = rules.getPluginIdAttr();
+
+            if ( debug )
+            {
+                log.debug( "init: pluginIdAttr set to per-digester values [" + 
"ns=" + pluginIdAttrNs + ", name="
+                    + pluginIdAttr + "]" );
+            }
+        }
+        else
+        {
+            if ( debug )
+            {
+                log.debug( "init: pluginIdAttr set to rule-specific values [" 
+ "ns=" + pluginIdAttrNs + ", name="
+                    + pluginIdAttr + "]" );
+            }
+        }
+    }
+
+    /**
+     * Invoked when the Digester matches this rule against an xml element.
+     * <p>
+     * A new instance of the target class is created, and pushed onto the 
stack. A new "private" PluginRules object is
+     * then created and set as the digester's default Rules object. Any custom 
rules associated with the plugin class
+     * are then loaded into that new Rules object. Finally, any custom rules 
that are associated with the current
+     * pattern (such as SetPropertiesRules) have their begin methods executed.
+     *
+     * @param namespace the namespace URI of the matching element, or an empty 
string if the parser is not namespace
+     *            aware or the element has no namespace
+     * @param name the local name if the parser is namespace aware, or just 
the element name otherwise
+     * @param attributes The attribute list of this element
+     * @throws Exception if any error occurs
+     */
+    @Override
+    public void begin( final String namespace, final String name, final 
org.xml.sax.Attributes attributes )
+        throws Exception
+    {
+        final Log log = getDigester().getLogger();
+        final boolean debug = log.isDebugEnabled();
+        if ( debug )
+        {
+            log.debug( "PluginCreateRule.begin" + ": pattern=[" + pattern + 
"]" + " match=[" + getDigester().getMatch()
+                + "]" );
+        }
+
+        if ( initException != null )
+        {
+            // we had a problem during initialization that we could
+            // not report then; report it now.
+            throw initException;
+        }
+
+        // load any custom rules associated with the plugin
+        final PluginRules oldRules = (PluginRules) getDigester().getRules();
+        final PluginManager pluginManager = oldRules.getPluginManager();
+        Declaration currDeclaration = null;
+
+        String pluginClassName;
+        if ( pluginClassAttrNs == null )
+        {
+            // Yep, this is ugly.
+            //
+            // In a namespace-aware parser, the one-param version will
+            // return attributes with no namespace.
+            //
+            // In a non-namespace-aware parser, the two-param version will
+            // never return any attributes, ever.
+            pluginClassName = attributes.getValue( pluginClassAttr );
+        }
+        else
+        {
+            pluginClassName = attributes.getValue( pluginClassAttrNs, 
pluginClassAttr );
+        }
+
+        String pluginId;
+        if ( pluginIdAttrNs == null )
+        {
+            pluginId = attributes.getValue( pluginIdAttr );
+        }
+        else
+        {
+            pluginId = attributes.getValue( pluginIdAttrNs, pluginIdAttr );
+        }
+
+        if ( pluginClassName != null )
+        {
+            // The user is using a plugin "inline", ie without a previous
+            // explicit declaration. If they have used the same plugin class
+            // before, we have already gone to the effort of creating a
+            // Declaration object, so retrieve it. If there is no existing
+            // declaration object for this class, then create one.
+
+            currDeclaration = pluginManager.getDeclarationByClass( 
pluginClassName );
+
+            if ( currDeclaration == null )
+            {
+                currDeclaration = new Declaration( pluginClassName );
+                try
+                {
+                    currDeclaration.init( getDigester(), pluginManager );
+                }
+                catch ( final PluginException pwe )
+                {
+                    throw new PluginInvalidInputException( pwe.getMessage(), 
pwe.getCause() );
+                }
+                pluginManager.addDeclaration( currDeclaration );
+            }
+        }
+        else if ( pluginId != null )
+        {
+            currDeclaration = pluginManager.getDeclarationById( pluginId );
+
+            if ( currDeclaration == null )
+            {
+                throw new PluginInvalidInputException( "Plugin id [" + 
pluginId + "] is not defined." );
+            }
+        }
+        else if ( defaultPlugin != null )
+        {
+            currDeclaration = defaultPlugin;
+        }
+        else
+        {
+            throw new PluginInvalidInputException( "No plugin class specified 
for element " + pattern );
+        }
+
+        // get the class of the user plugged-in type
+        final Class<?> pluginClass = currDeclaration.getPluginClass();
+
+        final String path = getDigester().getMatch();
+
+        // create a new Rules object and effectively push it onto a stack of
+        // rules objects. The stack is actually a linked list; using the
+        // PluginRules constructor below causes the new instance to link
+        // to the previous head-of-stack, then the Digester.setRules() makes
+        // the new instance the new head-of-stack.
+        final PluginRules newRules = new PluginRules( getDigester(), path, 
oldRules, pluginClass );
+        getDigester().setRules( newRules );
+
+        if ( debug )
+        {
+            log.debug( "PluginCreateRule.begin: installing new plugin: " + 
"oldrules=" + oldRules.toString()
+                + ", newrules=" + newRules.toString() );
+        }
+
+        // load up the custom rules
+        currDeclaration.configure( getDigester(), pattern );
+
+        // create an instance of the plugin class
+        final Object instance = pluginClass.newInstance();
+        getDigester().push( instance );
+        if ( debug )
+        {
+            log.debug( "PluginCreateRule.begin" + ": pattern=[" + pattern + 
"]" + " match=[" + getDigester().getMatch()
+                + "]" + " pushed instance of plugin [" + pluginClass.getName() 
+ "]" );
+        }
+
+        // and now we have to fire any custom rules which would have
+        // been matched by the same path that matched this rule, had
+        // they been loaded at that time.
+        final List<Rule> rules = newRules.getDecoratedRules().match( 
namespace, path, name, attributes );
+        fireBeginMethods( rules, namespace, name, attributes );
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void body( final String namespace, final String name, final String 
text )
+        throws Exception
+    {
+
+        // While this class itself has no work to do in the body method,
+        // we do need to fire the body methods of all dynamically-added
+        // rules matching the same path as this rule. During begin, we had
+        // to manually execute the dynamic rules' begin methods because they
+        // didn't exist in the digester's Rules object when the match begin.
+        // So in order to ensure consistent ordering of rule execution, the
+        // PluginRules class deliberately avoids returning any such rules
+        // in later calls to the match method, instead relying on this
+        // object to execute them at the appropriate time.
+        //
+        // Note that this applies only to rules matching exactly the path
+        // which is also matched by this PluginCreateRule.
+
+        final String path = getDigester().getMatch();
+        final PluginRules newRules = (PluginRules) getDigester().getRules();
+        final List<Rule> rules = newRules.getDecoratedRules().match( 
namespace, path, name, null );
+        fireBodyMethods( rules, namespace, name, text );
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void end( final String namespace, final String name )
+        throws Exception
+    {
+        // see body method for more info
+        final String path = getDigester().getMatch();
+        final PluginRules newRules = (PluginRules) getDigester().getRules();
+        final List<Rule> rules = newRules.getDecoratedRules().match( 
namespace, path, name, null );
+        fireEndMethods( rules, namespace, name );
+
+        // pop the stack of PluginRules instances, which
+        // discards all custom rules associated with this plugin
+        getDigester().setRules( newRules.getParent() );
+
+        // and get rid of the instance of the plugin class from the
+        // digester object stack.
+        getDigester().pop();
+    }
+
+    /**
+     * Return the pattern that this Rule is associated with.
+     * <p>
+     * In general, Rule instances <i>can</i> be associated with multiple 
patterns. A PluginCreateRule, however, will
+     * only function correctly when associated with a single pattern. It is 
possible to fix this, but I can't be
+     * bothered just now because this feature is unlikely to be used.
+     * </p>
+     *
+     * @return The pattern value
+     */
+    public String getPattern()
+    {
+        return pattern;
+    }
+
+    /**
+     * Duplicate the processing that the Digester does when firing the begin 
methods of rules. It would be really nice
+     * if the Digester class provided a way for this functionality to just be 
invoked directly.
+     *
+     * @param rules The rules which {@link Rule#begin(String, String, 
Attributes)} method has to be fired
+     * @param namespace the namespace URI of the matching element, or an empty 
string if the parser is not namespace
+     *            aware or the element has no namespace
+     * @param name the local name if the parser is namespace aware, or just 
the element name otherwise
+     * @param list The attribute list of this element
+     * @throws Exception if any error occurs
+     */
+    public void fireBeginMethods( final List<Rule> rules, final String 
namespace, final String name, final Attributes list )
+        throws Exception
+    {
+
+        if ( ( rules != null ) && ( !rules.isEmpty() ) )
+        {
+            final Log log = getDigester().getLogger();
+            final boolean debug = log.isDebugEnabled();
+            for ( final Rule rule : rules )
+            {
+                if ( debug )
+                {
+                    log.debug( "  Fire begin() for " + rule );
+                }
+                try
+                {
+                    rule.begin( namespace, name, list );
+                }
+                catch ( final Exception e )
+                {
+                    throw getDigester().createSAXException( e );
+                }
+                catch ( final Error e )
+                {
+                    throw e;
+                }
+            }
+        }
+    }
+
+    /**
+     * Duplicate the processing that the Digester does when firing the {@link 
Rule#body(String, String, String)} methods
+     * of rules.
+     *
+     * It would be really nice if the Digester class provided a way for this 
functionality to just be invoked directly.
+     *
+     * @param rules The rules which {@link Rule#body(String, String, String)} 
method has to be fired
+     * @param namespace the namespace URI of the matching element, or an empty 
string if the parser is not namespace
+     *            aware or the element has no namespace
+     * @param name the local name if the parser is namespace aware, or just 
the element name otherwise
+     * @param text The text of the body of this element
+     * @throws Exception if any error occurs
+     */
+    private void fireBodyMethods( final List<Rule> rules, final String 
namespaceURI, final String name, final String text )
+        throws Exception
+    {
+        if ( ( rules != null ) && ( !rules.isEmpty() ) )
+        {
+            final Log log = getDigester().getLogger();
+            final boolean debug = log.isDebugEnabled();
+            for ( final Rule rule : rules )
+            {
+                if ( debug )
+                {
+                    log.debug( "  Fire body() for " + rule );
+                }
+                try
+                {
+                    rule.body( namespaceURI, name, text );
+                }
+                catch ( final Exception e )
+                {
+                    throw getDigester().createSAXException( e );
+                }
+                catch ( final Error e )
+                {
+                    throw e;
+                }
+            }
+        }
+    }
+
+    /**
+     * Duplicate the processing that the Digester does when firing the end 
methods of rules.
+     *
+     * It would be really nice if the Digester class provided a way for this 
functionality to just be invoked directly.
+     *
+     * @param rules The rules which {@link Rule#end(String, String)} method 
has to be fired
+     * @param namespaceURI the namespace URI of the matching element, or an 
empty string if the parser is not namespace
+     *            aware or the element has no namespace
+     * @param name the local name if the parser is namespace aware, or just 
the element name otherwise
+     * @throws Exception if any error occurs
+     */
+    public void fireEndMethods( final List<Rule> rules, final String 
namespaceURI, final String name )
+        throws Exception
+    {
+        // Fire "end" events for all relevant rules in reverse order
+        if ( rules != null )
+        {
+            final Log log = getDigester().getLogger();
+            final boolean debug = log.isDebugEnabled();
+            for ( int i = 0; i < rules.size(); i++ )
+            {
+                final int j = ( rules.size() - i ) - 1;
+                final Rule rule = rules.get( j );
+                if ( debug )
+                {
+                    log.debug( "  Fire end() for " + rule );
+                }
+                try
+                {
+                    rule.end( namespaceURI, name );
+                }
+                catch ( final Exception e )
+                {
+                    throw getDigester().createSAXException( e );
+                }
+                catch ( final Error e )
+                {
+                    throw e;
+                }
+            }
+        }
+    }
+
+}
diff --git 
a/core/src/main/java/org/apache/commons/digester3/plugins/PluginRules.java 
b/core/src/main/java/org/apache/commons/digester3/plugins/PluginRules.java
index b1faa0c4..f50eb916 100644
--- a/core/src/main/java/org/apache/commons/digester3/plugins/PluginRules.java
+++ b/core/src/main/java/org/apache/commons/digester3/plugins/PluginRules.java
@@ -1,472 +1,472 @@
-package org.apache.commons.digester3.plugins;
-
-/*
- * 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 java.util.List;
-
-import org.apache.commons.digester3.Digester;
-import org.apache.commons.digester3.Rule;
-import org.apache.commons.digester3.Rules;
-import org.apache.commons.digester3.RulesBase;
-import org.apache.commons.logging.Log;
-import org.xml.sax.Attributes;
-
-/**
- * A custom digester Rules manager which must be used as the Rules object when 
using the plugins module functionality.
- * <p>
- * During parsing, a linked list of PluginCreateRule instances develop, and 
this list also acts like a stack. The
- * original instance that was set before the Digester started parsing is 
always at the tail of the list, and the
- * Digester always holds a reference to the instance at the head of the list 
in the rules member. Initially, this
- * list/stack holds just one instance, ie head and tail are the same object.
- * <p>
- * When the start of an xml element causes a PluginCreateRule to fire, a new 
PluginRules instance is created and
- * inserted at the head of the list (ie pushed onto the stack of Rules 
objects). Digester.getRules() therefore returns
- * this new Rules object, and any custom rules associated with that plugin are 
added to that instance.
- * <p>
- * When the end of the xml element is encountered (and therefore the 
PluginCreateRule end method fires), the stack of
- * Rules objects is popped, so that Digester.getRules returns the previous 
Rules object.
- *
- * @since 1.6
- */
-public class PluginRules
-    implements Rules
-{
-
-    /**
-     * The Digester instance with which this Rules instance is associated.
-     */
-    protected Digester digester = null;
-
-    /**
-     * The (optional) object which generates new rules instances.
-     */
-    private RulesFactory rulesFactory;
-
-    /**
-     * The rules implementation that we are "enhancing" with plugins 
functionality, as per the Decorator pattern.
-     */
-    private final Rules decoratedRules;
-
-    /** Object which contains information about all known plugins. */
-    private final PluginManager pluginManager;
-
-    /**
-     * The path below which this rules object has responsibility. For paths 
shorter than or equal the mountpoint, the
-     * parent's match is called.
-     */
-    private String mountPoint = null;
-
-    /**
-     * The Rules object that holds rules applying "above" the mountpoint, ie 
the next Rules object down in the stack.
-     */
-    private PluginRules parent = null;
-
-    /**
-     * A reference to the object that holds all data which should only exist 
once per digester instance.
-     */
-    private PluginContext pluginContext = null;
-
-    // ------------------------------------------------------------- 
Constructor
-
-    /**
-     * Constructor for top-level Rules objects. Exactly one of these must be 
created and installed into the Digester
-     * instance as the Rules object before parsing starts.
-     */
-    public PluginRules()
-    {
-        this( new RulesBase() );
-    }
-
-    /**
-     * Constructor for top-level Rules object which handles rule-matching 
using the specified implementation.
-     *
-     * @param decoratedRules The top-level Rules object which handles 
rule-matching using the specified implementation.
-     */
-    public PluginRules( final Rules decoratedRules )
-    {
-        this.decoratedRules = decoratedRules;
-
-        pluginContext = new PluginContext();
-        pluginManager = new PluginManager( pluginContext );
-    }
-
-    /**
-     * Constructs a Rules instance which has a parent Rules object (which is 
different from having a delegate rules
-     * object).
-     * <p>
-     * One of these is created each time a PluginCreateRule's begin method 
fires, in order to manage the custom rules
-     * associated with whatever concrete plugin class the user has specified.
-     *
-     * @param digester is the object this rules will be associated with.
-     * @param mountPoint is the digester match path for the element matching a 
PluginCreateRule which caused this
-     *            "nested parsing scope" to begin. This is expected to be 
equal to digester.getMatch().
-     * @param parent must be non-null.
-     * @param pluginClass is the plugin class whose custom rules will be 
loaded into this new PluginRules object.
-     * @throws PluginException if any error occurs
-     */
-    PluginRules( final Digester digester, final String mountPoint, final 
PluginRules parent, final Class<?> pluginClass )
-        throws PluginException
-    {
-        // no need to set digester or decoratedRules.digester,
-        // because when Digester.setRules is called, the setDigester
-        // method on this object will be called.
-
-        this.digester = digester;
-        this.mountPoint = mountPoint;
-        this.parent = parent;
-        this.rulesFactory = parent.rulesFactory;
-
-        if ( rulesFactory == null )
-        {
-            decoratedRules = new RulesBase();
-        }
-        else
-        {
-            decoratedRules = rulesFactory.newRules( digester, pluginClass );
-        }
-
-        pluginContext = parent.pluginContext;
-        pluginManager = new PluginManager( parent.pluginManager );
-    }
-
-    // ------------------------------------------------------------- Properties
-
-    /**
-     * Return the parent Rules object.
-     *
-     * @return the parent Rules object.
-     */
-    public Rules getParent()
-    {
-        return parent;
-    }
-
-    /**
-     * Return the Digester instance with which this instance is associated.
-     *
-     * @return the Digester instance with which this instance is associated.
-     */
-    @Override
-    public Digester getDigester()
-    {
-        return digester;
-    }
-
-    /**
-     * Set the Digester instance with which this Rules instance is associated.
-     *
-     * @param digester The newly associated Digester instance
-     */
-    @Override
-    public void setDigester( final Digester digester )
-    {
-        this.digester = digester;
-        decoratedRules.setDigester( digester );
-    }
-
-    /**
-     * Return the namespace URI that will be applied to all subsequently added 
{@code Rule} objects.
-     *
-     * @return the namespace URI that will be applied to all subsequently 
added {@code Rule} objects.
-     */
-    @Override
-    public String getNamespaceURI()
-    {
-        return decoratedRules.getNamespaceURI();
-    }
-
-    /**
-     * Set the namespace URI that will be applied to all subsequently added 
{@code Rule} objects.
-     *
-     * @param namespaceURI Namespace URI that must match on all subsequently 
added rules, or {@code null} for
-     *            matching regardless of the current namespace URI
-     */
-    @Override
-    public void setNamespaceURI( final String namespaceURI )
-    {
-        decoratedRules.setNamespaceURI( namespaceURI );
-    }
-
-    /**
-     * Return the object which "knows" about all declared plugins.
-     *
-     * @return The pluginManager value
-     */
-    public PluginManager getPluginManager()
-    {
-        return pluginManager;
-    }
-
-    /**
-     * See {@link PluginContext#getRuleFinders}.
-     *
-     * @return the list of RuleFinder objects
-     */
-    public List<RuleFinder> getRuleFinders()
-    {
-        return pluginContext.getRuleFinders();
-    }
-
-    /**
-     * See {@link PluginContext#setRuleFinders}.
-     *
-     * @param ruleFinders the list of RuleFinder objects
-     */
-    public void setRuleFinders( final List<RuleFinder> ruleFinders )
-    {
-        pluginContext.setRuleFinders( ruleFinders );
-    }
-
-    /**
-     * Return the rules factory object (or null if one has not been specified).
-     *
-     * @return the rules factory object.
-     */
-    public RulesFactory getRulesFactory()
-    {
-        return rulesFactory;
-    }
-
-    /**
-     * Set the object which is used to generate the new Rules instances 
created to hold and process the rules associated
-     * with each plugged-in class.
-     *
-     * @param factory the rules factory object
-     */
-    public void setRulesFactory( final RulesFactory factory )
-    {
-        rulesFactory = factory;
-    }
-
-    // --------------------------------------------------------- Public Methods
-
-    /**
-     * This package-scope method is used by the PluginCreateRule class to get 
direct access to the rules that were
-     * dynamically added by the plugin. No other class should need access to 
this object.
-     *
-     * @return The decorated Rule instance
-     */
-    Rules getDecoratedRules()
-    {
-        return decoratedRules;
-    }
-
-    /**
-     * Return the list of rules registered with this object, in the order they 
were registered with this object.
-     * <p>
-     * Note that Rule objects stored in parent Rules objects are not returned 
by this method.
-     *
-     * @return list of all Rule objects known to this Rules instance.
-     */
-    @Override
-    public List<Rule> rules()
-    {
-        return decoratedRules.rules();
-    }
-
-    /**
-     * Register a new Rule instance matching the specified pattern.
-     *
-     * @param pattern Nesting pattern to be matched for this Rule. This 
parameter treats equally patterns that begin
-     *            with and without a leading slash ('/').
-     * @param rule Rule instance to be registered
-     */
-    @Override
-    public void add( String pattern, final Rule rule )
-    {
-        final Log log = LogUtils.getLogger( digester );
-        final boolean debug = log.isDebugEnabled();
-
-        if ( debug )
-        {
-            log.debug( "add entry" + ": mapping pattern [" + pattern + "]" + " 
to rule of type ["
-                + rule.getClass().getName() + "]" );
-        }
-
-        // allow patterns with a leading slash character
-        if ( pattern.startsWith( "/" ) )
-        {
-            pattern = pattern.substring( 1 );
-        }
-
-        if ( mountPoint != null && !pattern.equals( mountPoint ) && 
!pattern.startsWith( mountPoint + "/" ) )
-        {
-            // This can only occur if a plugin attempts to add a
-            // rule with a pattern that doesn't start with the
-            // prefix passed to the addRules method. Plugins mustn't
-            // add rules outside the scope of the tag they were specified
-            // on, so refuse this.
-
-            // alas, can't throw exception
-            log.warn( "An attempt was made to add a rule with a pattern that"
-                + "is not at or below the mountpoint of the current" + " 
PluginRules object." + " Rule pattern: "
-                + pattern + ", mountpoint: " + mountPoint + ", rule type: " + 
rule.getClass().getName() );
-            return;
-        }
-
-        decoratedRules.add( pattern, rule );
-
-        if ( rule instanceof InitializableRule )
-        {
-            try
-            {
-                ( (InitializableRule) rule ).postRegisterInit( pattern );
-            }
-            catch ( final PluginConfigurationException e )
-            {
-                // Currently, Digester doesn't handle exceptions well
-                // from the add method. The workaround is for the
-                // initialisable rule to remember that its initialisation
-                // failed, and to throw the exception when begin is
-                // called for the first time.
-                if ( debug )
-                {
-                    log.debug( "Rule initialisation failed", e );
-                }
-                // throw e; -- alas, can't do this
-                return;
-            }
-        }
-
-        if ( debug )
-        {
-            log.debug( "add exit" + ": mapped pattern [" + pattern + "]" + " 
to rule of type ["
-                + rule.getClass().getName() + "]" );
-        }
-    }
-
-    /**
-     * Clear all rules.
-     */
-    @Override
-    public void clear()
-    {
-        decoratedRules.clear();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public List<Rule> match( final String namespaceURI, final String path, 
final String name, final Attributes attributes )
-    {
-        final Log log = LogUtils.getLogger( digester );
-        final boolean debug = log.isDebugEnabled();
-
-        if ( debug )
-        {
-            log.debug( "Matching path [" + path + "] on rules object " + 
this.toString() );
-        }
-
-        List<Rule> matches;
-        if ( ( mountPoint != null ) && ( path.length() <= mountPoint.length() 
) )
-        {
-            if ( debug )
-            {
-                log.debug( "Path [" + path + "] delegated to parent." );
-            }
-
-            matches = parent.match( namespaceURI, path, name, attributes );
-
-            // Note that in the case where path equals mountPoint,
-            // we deliberately return only the rules from the parent,
-            // even though this object may hold some rules matching
-            // this same path. See PluginCreateRule's begin, body and end
-            // methods for the reason.
-        }
-        else
-        {
-            log.debug( "delegating to decorated rules." );
-            matches = decoratedRules.match( namespaceURI, path, name, 
attributes );
-        }
-
-        return matches;
-    }
-
-    /**
-     * See {@link PluginContext#setPluginClassAttribute}.
-     *
-     * @param namespaceUri is the namespace uri that the specified attribute 
is in. If the attribute is in no namespace,
-     *            then this should be null. Note that if a namespace is used, 
the attrName value should <i>not</i>
-     *            contain any kind of namespace-prefix. Note also that if you 
are using a non-namespace-aware parser,
-     *            this parameter <i>must</i> be null.
-     * @param attrName is the attribute whose value contains the name of the 
class to be instantiated.
-     * */
-    public void setPluginClassAttribute( final String namespaceUri, final 
String attrName )
-    {
-        pluginContext.setPluginClassAttribute( namespaceUri, attrName );
-    }
-
-    /**
-     * See {@link PluginContext#setPluginIdAttribute}.
-     *
-     * @param namespaceUri is the namespace uri that the specified attribute 
is in. If the attribute is in no namespace,
-     *            then this should be null. Note that if a namespace is used, 
the attrName value should <i>not</i>
-     *            contain any kind of namespace-prefix. Note also that if you 
are using a non-namespace-aware parser,
-     *            this parameter <i>must</i> be null.
-     * @param attrName is the attribute whose value contains the id of the 
plugin declaration to be used when
-     *            instantiating an object.
-     **/
-    public void setPluginIdAttribute( final String namespaceUri, final String 
attrName )
-    {
-        pluginContext.setPluginIdAttribute( namespaceUri, attrName );
-    }
-
-    /**
-     * See {@link PluginContext#getPluginClassAttrNs}.
-     *
-     * @return the namespace for the xml attribute which indicates which class 
is to be plugged in.
-     */
-    public String getPluginClassAttrNs()
-    {
-        return pluginContext.getPluginClassAttrNs();
-    }
-
-    /**
-     * See {@link PluginContext#getPluginClassAttr}.
-     *
-     * @return the namespace for the xml attribute which indicates which class 
is to be plugged in.
-     */
-    public String getPluginClassAttr()
-    {
-        return pluginContext.getPluginClassAttr();
-    }
-
-    /**
-     * See {@link PluginContext#getPluginIdAttrNs}.
-     *
-     * @return the namespace for the xml attribute which indicates which 
previous plugin declaration should be used.
-     */
-    public String getPluginIdAttrNs()
-    {
-        return pluginContext.getPluginIdAttrNs();
-    }
-
-    /**
-     * See {@link PluginContext#getPluginIdAttr}.
-     *
-     * @return the namespace for the xml attribute which indicates which 
previous plugin declaration should be used.
-     */
-    public String getPluginIdAttr()
-    {
-        return pluginContext.getPluginIdAttr();
-    }
-
-}
+package org.apache.commons.digester3.plugins;
+
+/*
+ * 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 java.util.List;
+
+import org.apache.commons.digester3.Digester;
+import org.apache.commons.digester3.Rule;
+import org.apache.commons.digester3.Rules;
+import org.apache.commons.digester3.RulesBase;
+import org.apache.commons.logging.Log;
+import org.xml.sax.Attributes;
+
+/**
+ * A custom digester Rules manager which must be used as the Rules object when 
using the plugins module functionality.
+ * <p>
+ * During parsing, a linked list of PluginCreateRule instances develop, and 
this list also acts like a stack. The
+ * original instance that was set before the Digester started parsing is 
always at the tail of the list, and the
+ * Digester always holds a reference to the instance at the head of the list 
in the rules member. Initially, this
+ * list/stack holds just one instance, ie head and tail are the same object.
+ * <p>
+ * When the start of an xml element causes a PluginCreateRule to fire, a new 
PluginRules instance is created and
+ * inserted at the head of the list (ie pushed onto the stack of Rules 
objects). Digester.getRules() therefore returns
+ * this new Rules object, and any custom rules associated with that plugin are 
added to that instance.
+ * <p>
+ * When the end of the xml element is encountered (and therefore the 
PluginCreateRule end method fires), the stack of
+ * Rules objects is popped, so that Digester.getRules returns the previous 
Rules object.
+ *
+ * @since 1.6
+ */
+public class PluginRules
+    implements Rules
+{
+
+    /**
+     * The Digester instance with which this Rules instance is associated.
+     */
+    protected Digester digester = null;
+
+    /**
+     * The (optional) object which generates new rules instances.
+     */
+    private RulesFactory rulesFactory;
+
+    /**
+     * The rules implementation that we are "enhancing" with plugins 
functionality, as per the Decorator pattern.
+     */
+    private final Rules decoratedRules;
+
+    /** Object which contains information about all known plugins. */
+    private final PluginManager pluginManager;
+
+    /**
+     * The path below which this rules object has responsibility. For paths 
shorter than or equal the mountpoint, the
+     * parent's match is called.
+     */
+    private String mountPoint = null;
+
+    /**
+     * The Rules object that holds rules applying "above" the mountpoint, ie 
the next Rules object down in the stack.
+     */
+    private PluginRules parent = null;
+
+    /**
+     * A reference to the object that holds all data which should only exist 
once per digester instance.
+     */
+    private PluginContext pluginContext = null;
+
+    // ------------------------------------------------------------- 
Constructor
+
+    /**
+     * Constructor for top-level Rules objects. Exactly one of these must be 
created and installed into the Digester
+     * instance as the Rules object before parsing starts.
+     */
+    public PluginRules()
+    {
+        this( new RulesBase() );
+    }
+
+    /**
+     * Constructor for top-level Rules object which handles rule-matching 
using the specified implementation.
+     *
+     * @param decoratedRules The top-level Rules object which handles 
rule-matching using the specified implementation.
+     */
+    public PluginRules( final Rules decoratedRules )
+    {
+        this.decoratedRules = decoratedRules;
+
+        pluginContext = new PluginContext();
+        pluginManager = new PluginManager( pluginContext );
+    }
+
+    /**
+     * Constructs a Rules instance which has a parent Rules object (which is 
different from having a delegate rules
+     * object).
+     * <p>
+     * One of these is created each time a PluginCreateRule's begin method 
fires, in order to manage the custom rules
+     * associated with whatever concrete plugin class the user has specified.
+     *
+     * @param digester is the object this rules will be associated with.
+     * @param mountPoint is the digester match path for the element matching a 
PluginCreateRule which caused this
+     *            "nested parsing scope" to begin. This is expected to be 
equal to digester.getMatch().
+     * @param parent must be non-null.
+     * @param pluginClass is the plugin class whose custom rules will be 
loaded into this new PluginRules object.
+     * @throws PluginException if any error occurs
+     */
+    PluginRules( final Digester digester, final String mountPoint, final 
PluginRules parent, final Class<?> pluginClass )
+        throws PluginException
+    {
+        // no need to set digester or decoratedRules.digester,
+        // because when Digester.setRules is called, the setDigester
+        // method on this object will be called.
+
+        this.digester = digester;
+        this.mountPoint = mountPoint;
+        this.parent = parent;
+        this.rulesFactory = parent.rulesFactory;
+
+        if ( rulesFactory == null )
+        {
+            decoratedRules = new RulesBase();
+        }
+        else
+        {
+            decoratedRules = rulesFactory.newRules( digester, pluginClass );
+        }
+
+        pluginContext = parent.pluginContext;
+        pluginManager = new PluginManager( parent.pluginManager );
+    }
+
+    // ------------------------------------------------------------- Properties
+
+    /**
+     * Return the parent Rules object.
+     *
+     * @return the parent Rules object.
+     */
+    public Rules getParent()
+    {
+        return parent;
+    }
+
+    /**
+     * Return the Digester instance with which this instance is associated.
+     *
+     * @return the Digester instance with which this instance is associated.
+     */
+    @Override
+    public Digester getDigester()
+    {
+        return digester;
+    }
+
+    /**
+     * Set the Digester instance with which this Rules instance is associated.
+     *
+     * @param digester The newly associated Digester instance
+     */
+    @Override
+    public void setDigester( final Digester digester )
+    {
+        this.digester = digester;
+        decoratedRules.setDigester( digester );
+    }
+
+    /**
+     * Return the namespace URI that will be applied to all subsequently added 
{@code Rule} objects.
+     *
+     * @return the namespace URI that will be applied to all subsequently 
added {@code Rule} objects.
+     */
+    @Override
+    public String getNamespaceURI()
+    {
+        return decoratedRules.getNamespaceURI();
+    }
+
+    /**
+     * Set the namespace URI that will be applied to all subsequently added 
{@code Rule} objects.
+     *
+     * @param namespaceURI Namespace URI that must match on all subsequently 
added rules, or {@code null} for
+     *            matching regardless of the current namespace URI
+     */
+    @Override
+    public void setNamespaceURI( final String namespaceURI )
+    {
+        decoratedRules.setNamespaceURI( namespaceURI );
+    }
+
+    /**
+     * Return the object which "knows" about all declared plugins.
+     *
+     * @return The pluginManager value
+     */
+    public PluginManager getPluginManager()
+    {
+        return pluginManager;
+    }
+
+    /**
+     * See {@link PluginContext#getRuleFinders}.
+     *
+     * @return the list of RuleFinder objects
+     */
+    public List<RuleFinder> getRuleFinders()
+    {
+        return pluginContext.getRuleFinders();
+    }
+
+    /**
+     * See {@link PluginContext#setRuleFinders}.
+     *
+     * @param ruleFinders the list of RuleFinder objects
+     */
+    public void setRuleFinders( final List<RuleFinder> ruleFinders )
+    {
+        pluginContext.setRuleFinders( ruleFinders );
+    }
+
+    /**
+     * Return the rules factory object (or null if one has not been specified).
+     *
+     * @return the rules factory object.
+     */
+    public RulesFactory getRulesFactory()
+    {
+        return rulesFactory;
+    }
+
+    /**
+     * Set the object which is used to generate the new Rules instances 
created to hold and process the rules associated
+     * with each plugged-in class.
+     *
+     * @param factory the rules factory object
+     */
+    public void setRulesFactory( final RulesFactory factory )
+    {
+        rulesFactory = factory;
+    }
+
+    // --------------------------------------------------------- Public Methods
+
+    /**
+     * This package-scope method is used by the PluginCreateRule class to get 
direct access to the rules that were
+     * dynamically added by the plugin. No other class should need access to 
this object.
+     *
+     * @return The decorated Rule instance
+     */
+    Rules getDecoratedRules()
+    {
+        return decoratedRules;
+    }
+
+    /**
+     * Return the list of rules registered with this object, in the order they 
were registered with this object.
+     * <p>
+     * Note that Rule objects stored in parent Rules objects are not returned 
by this method.
+     *
+     * @return list of all Rule objects known to this Rules instance.
+     */
+    @Override
+    public List<Rule> rules()
+    {
+        return decoratedRules.rules();
+    }
+
+    /**
+     * Register a new Rule instance matching the specified pattern.
+     *
+     * @param pattern Nesting pattern to be matched for this Rule. This 
parameter treats equally patterns that begin
+     *            with and without a leading slash ('/').
+     * @param rule Rule instance to be registered
+     */
+    @Override
+    public void add( String pattern, final Rule rule )
+    {
+        final Log log = LogUtils.getLogger( digester );
+        final boolean debug = log.isDebugEnabled();
+
+        if ( debug )
+        {
+            log.debug( "add entry" + ": mapping pattern [" + pattern + "]" + " 
to rule of type ["
+                + rule.getClass().getName() + "]" );
+        }
+
+        // allow patterns with a leading slash character
+        if ( pattern.startsWith( "/" ) )
+        {
+            pattern = pattern.substring( 1 );
+        }
+
+        if ( mountPoint != null && !pattern.equals( mountPoint ) && 
!pattern.startsWith( mountPoint + "/" ) )
+        {
+            // This can only occur if a plugin attempts to add a
+            // rule with a pattern that doesn't start with the
+            // prefix passed to the addRules method. Plugins mustn't
+            // add rules outside the scope of the tag they were specified
+            // on, so refuse this.
+
+            // alas, can't throw exception
+            log.warn( "An attempt was made to add a rule with a pattern that"
+                + "is not at or below the mountpoint of the current" + " 
PluginRules object." + " Rule pattern: "
+                + pattern + ", mountpoint: " + mountPoint + ", rule type: " + 
rule.getClass().getName() );
+            return;
+        }
+
+        decoratedRules.add( pattern, rule );
+
+        if ( rule instanceof InitializableRule )
+        {
+            try
+            {
+                ( (InitializableRule) rule ).postRegisterInit( pattern );
+            }
+            catch ( final PluginConfigurationException e )
+            {
+                // Currently, Digester doesn't handle exceptions well
+                // from the add method. The workaround is for the
+                // initialisable rule to remember that its initialization
+                // failed, and to throw the exception when begin is
+                // called for the first time.
+                if ( debug )
+                {
+                    log.debug( "Rule initialisation failed", e );
+                }
+                // throw e; -- alas, can't do this
+                return;
+            }
+        }
+
+        if ( debug )
+        {
+            log.debug( "add exit" + ": mapped pattern [" + pattern + "]" + " 
to rule of type ["
+                + rule.getClass().getName() + "]" );
+        }
+    }
+
+    /**
+     * Clear all rules.
+     */
+    @Override
+    public void clear()
+    {
+        decoratedRules.clear();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public List<Rule> match( final String namespaceURI, final String path, 
final String name, final Attributes attributes )
+    {
+        final Log log = LogUtils.getLogger( digester );
+        final boolean debug = log.isDebugEnabled();
+
+        if ( debug )
+        {
+            log.debug( "Matching path [" + path + "] on rules object " + 
this.toString() );
+        }
+
+        List<Rule> matches;
+        if ( ( mountPoint != null ) && ( path.length() <= mountPoint.length() 
) )
+        {
+            if ( debug )
+            {
+                log.debug( "Path [" + path + "] delegated to parent." );
+            }
+
+            matches = parent.match( namespaceURI, path, name, attributes );
+
+            // Note that in the case where path equals mountPoint,
+            // we deliberately return only the rules from the parent,
+            // even though this object may hold some rules matching
+            // this same path. See PluginCreateRule's begin, body and end
+            // methods for the reason.
+        }
+        else
+        {
+            log.debug( "delegating to decorated rules." );
+            matches = decoratedRules.match( namespaceURI, path, name, 
attributes );
+        }
+
+        return matches;
+    }
+
+    /**
+     * See {@link PluginContext#setPluginClassAttribute}.
+     *
+     * @param namespaceUri is the namespace uri that the specified attribute 
is in. If the attribute is in no namespace,
+     *            then this should be null. Note that if a namespace is used, 
the attrName value should <i>not</i>
+     *            contain any kind of namespace-prefix. Note also that if you 
are using a non-namespace-aware parser,
+     *            this parameter <i>must</i> be null.
+     * @param attrName is the attribute whose value contains the name of the 
class to be instantiated.
+     * */
+    public void setPluginClassAttribute( final String namespaceUri, final 
String attrName )
+    {
+        pluginContext.setPluginClassAttribute( namespaceUri, attrName );
+    }
+
+    /**
+     * See {@link PluginContext#setPluginIdAttribute}.
+     *
+     * @param namespaceUri is the namespace uri that the specified attribute 
is in. If the attribute is in no namespace,
+     *            then this should be null. Note that if a namespace is used, 
the attrName value should <i>not</i>
+     *            contain any kind of namespace-prefix. Note also that if you 
are using a non-namespace-aware parser,
+     *            this parameter <i>must</i> be null.
+     * @param attrName is the attribute whose value contains the id of the 
plugin declaration to be used when
+     *            instantiating an object.
+     **/
+    public void setPluginIdAttribute( final String namespaceUri, final String 
attrName )
+    {
+        pluginContext.setPluginIdAttribute( namespaceUri, attrName );
+    }
+
+    /**
+     * See {@link PluginContext#getPluginClassAttrNs}.
+     *
+     * @return the namespace for the xml attribute which indicates which class 
is to be plugged in.
+     */
+    public String getPluginClassAttrNs()
+    {
+        return pluginContext.getPluginClassAttrNs();
+    }
+
+    /**
+     * See {@link PluginContext#getPluginClassAttr}.
+     *
+     * @return the namespace for the xml attribute which indicates which class 
is to be plugged in.
+     */
+    public String getPluginClassAttr()
+    {
+        return pluginContext.getPluginClassAttr();
+    }
+
+    /**
+     * See {@link PluginContext#getPluginIdAttrNs}.
+     *
+     * @return the namespace for the xml attribute which indicates which 
previous plugin declaration should be used.
+     */
+    public String getPluginIdAttrNs()
+    {
+        return pluginContext.getPluginIdAttrNs();
+    }
+
+    /**
+     * See {@link PluginContext#getPluginIdAttr}.
+     *
+     * @return the namespace for the xml attribute which indicates which 
previous plugin declaration should be used.
+     */
+    public String getPluginIdAttr()
+    {
+        return pluginContext.getPluginIdAttr();
+    }
+
+}

Reply via email to