    001    /* $Id: Declaration.java 729120 2008-12-23 21:11:38Z rahul $
    002     *
    003     * Licensed to the Apache Software Foundation (ASF) under one or more
    004     * contributor license agreements.  See the NOTICE file distributed with
    005     * this work for additional information regarding copyright ownership.
    006     * The ASF licenses this file to You under the Apache License, Version 2.0
    007     * (the "License"); you may not use this file except in compliance with
    008     * the License.  You may obtain a copy of the License at
    009     *
    010     *      http://www.apache.org/licenses/LICENSE-2.0
    011     *
    012     * Unless required by applicable law or agreed to in writing, software
    013     * distributed under the License is distributed on an "AS IS" BASIS,
    014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    015     * See the License for the specific language governing permissions and
    016     * limitations under the License.
    017     */
    018    package org.apache.commons.digester.plugins;
    019
    020    import java.util.Properties;
    021
    022    import org.apache.commons.logging.Log;
    023    import org.apache.commons.digester.Digester;
    024
    025    /**
    026     * Represents a Class that can be instantiated by a PluginCreateRule, plus
    027     * info on how to load custom digester rules for mapping xml into that
    028     * plugged-in class.
    029     *
    030     * @since 1.6
    031     */
    032    public class Declaration {
    033
    034        /** The class of the object to be instantiated. */
    035        private Class<?> pluginClass;
    036
    037        /** The name of the class of the object to be instantiated. */
    038        private String pluginClassName;
    039
    040        /** See {@link #setId}. */
    041        private String id;
    042
    043        /** See {@link #setProperties}. */
    044        private Properties properties = new Properties();
    045
    046        /** See {@link #init}. */
    047        private boolean initialized = false;
    048
    049        /**
    050         * Class which is responsible for dynamically loading this
    051         * plugin's rules on demand.
    052         */
    053        private RuleLoader ruleLoader = null;
    054
    055        //---------------------- constructors ----------------------------------
    056
    057        /**
    058         * Constructor.
    059         */
    060        public Declaration(String pluginClassName) {
    061            // We can't load the pluginClass at this time, because we don't
    062            // have a digester instance yet to load it through. So just
    063            // save the name away, and we'll load the Class object in the
    064            // init method.
    065            this.pluginClassName = pluginClassName;
    066        }
    067
    068        /**
    069         * Constructor.
    070         */
    071        public Declaration(Class<?> pluginClass) {
    072            this.pluginClass = pluginClass;
    073            this.pluginClassName = pluginClass.getName();
    074        }
    075
    076        /**
    077         * Create an instance where a fully-initialised ruleLoader instance
    078         * is provided by the caller instead of having the PluginManager
    079         * "discover" an appropriate one.
    080         */
    081        public Declaration(Class<?> pluginClass, RuleLoader ruleLoader) {
    082            this.pluginClass = pluginClass;
    083            this.pluginClassName = pluginClass.getName();
    084            this.ruleLoader = ruleLoader;
    085        }
    086
    087        //---------------------- properties -----------------------------------
    088
    089        /**
    090         * The id that the user associated with a particular plugin declaration
    091         * in the input xml. This id is later used in the input xml to refer
    092         * back to the original declaration.
    093         * <p>
    094         * For plugins declared "in-line", the id is null.
    095         */
    096        public void setId(String id) {
    097            this.id = id;
    098        }
    099
    100        /**
    101         * Return the id associated with this declaration. For plugins
    102         * declared "inline", null will be returned.
    103         *
    104         * @return The id value. May be null.
    105         */
    106        public String getId() {
    107            return id;
    108        }
    109
    110        /**
    111         * Copy all (key,value) pairs in the param into the properties member of
    112         * this object.
    113         * <p>
    114         * The declaration properties cannot be explicit member variables,
    115         * because the set of useful properties a user can provide on a declaration
    116         * depends on what RuleFinder classes are available - and extra RuleFinders
    117         * can be added by the user. So here we keep a map of the settings, and
    118         * let the RuleFinder objects look for whatever properties they consider
    119         * significant.
    120         * <p>
    121         * The "id" and "class" properties are treated differently.
    122         */
    123        public void setProperties(Properties p) {
    124            properties.putAll(p);
    125        }
    126
    127        /**
    128         * Return plugin class associated with this declaration.
    129         *
    130         * @return The pluginClass.
    131         */
    132        public Class<?> getPluginClass() {
    133            return pluginClass;
    134        }
    135
    136        //---------------------- methods -----------------------------------
    137
    138        /**
    139         * Must be called exactly once, and must be called before any call
    140         * to the configure method.
    141         */
    142        public void init(Digester digester, PluginManager pm) throws PluginException {
    143            Log log = digester.getLogger();
    144            boolean debug = log.isDebugEnabled();
    145            if (debug) {
    146                log.debug("init being called!");
    147            }
    148
    149            if (initialized) {
    150                throw new PluginAssertionFailure("Init called multiple times.");
    151            }
    152
    153            if ((pluginClass == null) && (pluginClassName != null)) {
    154                try {
    155                    // load the plugin class object
    156                    pluginClass =
    157                        digester.getClassLoader().loadClass(pluginClassName);
    158                } catch(ClassNotFoundException cnfe) {
    159                    throw new PluginException(
    160                        "Unable to load class " + pluginClassName, cnfe);
    161                }
    162            }
    163
    164            if (ruleLoader == null) {
    165                // the caller didn't provide a ruleLoader to the constructor,
    166                // so get the plugin manager to "discover" one.
    167                log.debug("Searching for ruleloader...");
    168                ruleLoader = pm.findLoader(digester, id, pluginClass, properties);
    169            } else {
    170                log.debug("This declaration has an explicit ruleLoader.");
    171            }
    172
    173            if (debug) {
    174                if (ruleLoader == null) {
    175                    log.debug(
    176                        "No ruleLoader found for plugin declaration"
    177                        + " id [" + id + "]"
    178                        + ", class [" + pluginClass.getClass().getName() + "].");
    179                } else {
    180                    log.debug(
    181                        "RuleLoader of type [" + ruleLoader.getClass().getName()
    182                        + "] associated with plugin declaration"
    183                        + " id [" + id + "]"
    184                        + ", class [" + pluginClass.getClass().getName() + "].");
    185                }
    186            }
    187
    188            initialized = true;
    189        }
    190
    191        /**
    192         * Attempt to load custom rules for the target class at the specified
    193         * pattern.
    194         * <p>
    195         * On return, any custom rules associated with the plugin class have
    196         * been loaded into the Rules object currently associated with the
    197         * specified digester object.
    198         */
    199
    200        public void configure(Digester digester, String pattern)
    201                              throws PluginException {
    202            Log log = digester.getLogger();
    203            boolean debug = log.isDebugEnabled();
    204            if (debug) {
    205                log.debug("configure being called!");
    206            }
    207
    208            if (!initialized) {
    209                throw new PluginAssertionFailure("Not initialized.");
    210            }
    211
    212            if (ruleLoader != null) {
    213                ruleLoader.addRules(digester, pattern);
    214            }
    215        }
    216    }