001/* $Id: PluginDeclarationRule.java 992060 2010-09-02 19:09:47Z simonetripodi $
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
019package org.apache.commons.digester.plugins;
020
021import java.util.Properties;
022
023import org.apache.commons.digester.Digester;
024import org.apache.commons.digester.Rule;
025
026/**
027 * A Digester rule which allows the user to pre-declare a class which is to
028 * be referenced later at a plugin point by a PluginCreateRule.
029 * <p>
030 * Normally, a PluginDeclarationRule is added to a Digester instance with
031 * the pattern "{root}/plugin" or "* /plugin" where {root} is the name of 
032 * the root tag in the input document.
033 *
034 * @since 1.6
035 */
036
037public class PluginDeclarationRule extends Rule {
038
039    //------------------- constructors ---------------------------------------
040
041    /** constructor  */
042    public PluginDeclarationRule() {
043        super();
044    }
045
046    //------------------- methods --------------------------------------------
047
048    /**
049     * Invoked upon reading a tag defining a plugin declaration. The tag
050     * must have the following mandatory attributes:
051     * <ul>
052     *   <li> id </li>
053     *   <li> class </li>
054     * </ul>
055     *
056     *@param namespace The xml namespace in which the xml element which
057     * triggered this rule resides.
058     *@param name The name of the xml element which triggered this rule.
059     *@param attributes The set of attributes on the xml element which
060     * triggered this rule.
061     *@exception java.lang.Exception
062     */
063
064    @Override
065    public void begin(String namespace, String name,
066                      org.xml.sax.Attributes attributes)
067                      throws java.lang.Exception {
068                 
069        int nAttrs = attributes.getLength();
070        Properties props = new Properties();
071        for(int i=0; i<nAttrs; ++i) {
072            String key = attributes.getLocalName(i);
073            if ((key == null) || (key.length() == 0)) {
074                key = attributes.getQName(i);
075            }
076            String value = attributes.getValue(i);
077            props.setProperty(key, value);
078        }
079        
080        try {
081            declarePlugin(digester, props);
082        } catch(PluginInvalidInputException ex) {
083            throw new PluginInvalidInputException(
084                "Error on element [" + digester.getMatch() + 
085                "]: " + ex.getMessage());
086        }
087    }
088    
089    public static void declarePlugin(Digester digester, Properties props)
090    throws PluginException {
091        
092        String id = props.getProperty("id");
093        String pluginClassName = props.getProperty("class");
094        
095        if (id == null) {
096            throw new PluginInvalidInputException(
097                "mandatory attribute id not present on plugin declaration");
098        }
099
100        if (pluginClassName == null) {
101            throw new PluginInvalidInputException(
102                "mandatory attribute class not present on plugin declaration");
103        }
104
105        Declaration newDecl = new Declaration(pluginClassName);
106        newDecl.setId(id);
107        newDecl.setProperties(props);
108
109        PluginRules rc = (PluginRules) digester.getRules();
110        PluginManager pm = rc.getPluginManager();
111
112        newDecl.init(digester, pm);
113        pm.addDeclaration(newDecl);
114        
115        // Note that it is perfectly safe to redeclare a plugin, because
116        // the declaration doesn't add any rules to digester; all it does
117        // is create a RuleLoader instance whch is *capable* of adding the
118        // rules to the digester.
119    }
120}
121