📄 plugincreaterule.java
字号:
/* $Id: PluginCreateRule.java,v 1.19 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.util.Iterator;
import java.util.ListIterator;
import java.util.List;
import java.io.File;
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.Rule;
import org.apache.commons.digester.Rules;
import org.apache.commons.logging.Log;
/**
* 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 initialise 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(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(Class baseClass, 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(Class baseClass, Class dfltPluginClass,
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.
*/
public void setPluginClassAttribute(String namespaceUri, 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.
*/
public void setPluginIdAttribute(String namespaceUri, String attrName) {
pluginIdAttrNs = namespaceUri;
pluginIdAttr = attrName;
}
//------------------- methods --------------------------------------------
/**
* Invoked after this rule has been added to the set of digester rules,
* associated with the specified pattern. Check all configuration data is
* valid and remember the pattern for later.
*
* @param matchPattern is the digester match pattern that is associated
* with this rule instance, eg "root/widget".
* @exception PluginConfigurationException
*/
public void postRegisterInit(String matchPattern)
throws PluginConfigurationException {
Log log = LogUtils.getLogger(digester);
boolean debug = log.isDebugEnabled();
if (debug) {
log.debug("PluginCreateRule.postRegisterInit" +
": rule registered for pattern [" + matchPattern + "]");
}
if (digester == 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;
}
PluginRules rules = (PluginRules) digester.getRules();
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(digester, pm);
} catch(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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -