blob: 4482b41d9cf3f6fdde747447c344ec4518644576 [file] [log] [blame]
/* $Id: Declaration.java,v 1.17 2004/05/10 06:44:13 skitching Exp $
*
* Copyright 2003-2004 The Apache Software Foundation.
*
* Licensed 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.
*/
package org.apache.commons.digester.plugins;
import java.io.IOException;
import java.util.Properties;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.digester.Digester;
/**
* Represents a Class that can be instantiated by a PluginCreateRule, plus
* info on how to load custom digester rules for mapping xml into that
* plugged-in class.
*
* @since 1.6
*/
public class Declaration {
/** The class of the object to be instantiated. */
private Class pluginClass;
/** The name of the class of the object to be instantiated. */
private String pluginClassName;
/** See {@link #setId}. */
private String id;
/** See {@link #setProperties}. */
private Properties properties = new Properties();
/** See {@link #init}. */
private boolean initialized = false;
/**
* Class which is responsible for dynamically loading this
* plugin's rules on demand.
*/
private RuleLoader ruleLoader = null;
//---------------------- constructors ----------------------------------
/**
* Constructor.
*/
public Declaration(String pluginClassName) {
// We can't load the pluginClass at this time, because we don't
// have a digester instance yet to load it through. So just
// save the name away, and we'll load the Class object in the
// init method.
this.pluginClassName = pluginClassName;
}
/**
* Constructor.
*/
public Declaration(Class pluginClass) {
this.pluginClass = pluginClass;
this.pluginClassName = pluginClass.getName();
}
/**
* Create an instance where a fully-initialised ruleLoader instance
* is provided by the caller instead of having the PluginManager
* "discover" an appropriate one.
*/
public Declaration(Class pluginClass, RuleLoader ruleLoader) {
this.pluginClass = pluginClass;
this.pluginClassName = pluginClass.getName();
this.ruleLoader = ruleLoader;
}
//---------------------- properties -----------------------------------
/**
* The id that the user associated with a particular plugin declaration
* in the input xml. This id is later used in the input xml to refer
* back to the original declaration.
* <p>
* For plugins declared "in-line", the id is null.
*/
public void setId(String id) {
this.id = id;
}
/**
* Return the id associated with this declaration. For plugins
* declared "inline", null will be returned.
*
* @return The id value. May be null.
*/
public String getId() {
return id;
}
/**
* Copy all (key,value) pairs in the param into the properties member of
* this object.
* <p>
* The declaration properties cannot be explicit member variables,
* because the set of useful properties a user can provide on a declaration
* depends on what RuleFinder classes are available - and extra RuleFinders
* can be added by the user. So here we keep a map of the settings, and
* let the RuleFinder objects look for whatever properties they consider
* significant.
* <p>
* The "id" and "class" properties are treated differently.
*/
public void setProperties(Properties p) {
properties.putAll(p);
}
/**
* Return plugin class associated with this declaration.
*
* @return The pluginClass.
*/
public Class getPluginClass() {
return pluginClass;
}
//---------------------- methods -----------------------------------
/**
* Must be called exactly once, and must be called before any call
* to the configure method.
*/
public void init(Digester digester, PluginManager pm) throws PluginException {
Log log = digester.getLogger();
boolean debug = log.isDebugEnabled();
if (debug) {
log.debug("init being called!");
}
if (initialized) {
throw new PluginAssertionFailure("Init called multiple times.");
}
if ((pluginClass == null) && (pluginClassName != null)) {
try {
// load the plugin class object
pluginClass =
digester.getClassLoader().loadClass(pluginClassName);
} catch(ClassNotFoundException cnfe) {
throw new PluginException(
"Unable to load class " + pluginClassName, cnfe);
}
}
if (ruleLoader == null) {
// the caller didn't provide a ruleLoader to the constructor,
// so get the plugin manager to "discover" one.
log.debug("Searching for ruleloader...");
ruleLoader = pm.findLoader(digester, id, pluginClass, properties);
} else {
log.debug("This declaration has an explicit ruleLoader.");
}
if (debug) {
if (ruleLoader == null) {
log.debug(
"No ruleLoader found for plugin declaration"
+ " id [" + id + "]"
+ ", class [" + pluginClass.getClass().getName() + "].");
} else {
log.debug(
"RuleLoader of type [" + ruleLoader.getClass().getName()
+ "] associated with plugin declaration"
+ " id [" + id + "]"
+ ", class [" + pluginClass.getClass().getName() + "].");
}
}
initialized = true;
}
/**
* Attempt to load custom rules for the target class at the specified
* pattern.
* <p>
* On return, any custom rules associated with the plugin class have
* been loaded into the Rules object currently associated with the
* specified digester object.
*/
public void configure(Digester digester, String pattern)
throws PluginException {
Log log = digester.getLogger();
boolean debug = log.isDebugEnabled();
if (debug) {
log.debug("configure being called!");
}
if (!initialized) {
throw new PluginAssertionFailure("Not initialized.");
}
if (ruleLoader != null) {
ruleLoader.addRules(digester, pattern);
}
}
}