Normalize Javadoc spelling
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 fda1ddb..ad78afc 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 599943d..72bcc4c 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 b1faa0c..f50eb91 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();

+    }

+

+}