001: /* $Id: Declaration.java 471661 2006-11-06 08:09:25Z skitching $
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)
143: throws PluginException {
144: Log log = digester.getLogger();
145: boolean debug = log.isDebugEnabled();
146: if (debug) {
147: log.debug("init being called!");
148: }
149:
150: if (initialized) {
151: throw new PluginAssertionFailure(
152: "Init called multiple times.");
153: }
154:
155: if ((pluginClass == null) && (pluginClassName != null)) {
156: try {
157: // load the plugin class object
158: pluginClass = digester.getClassLoader().loadClass(
159: pluginClassName);
160: } catch (ClassNotFoundException cnfe) {
161: throw new PluginException("Unable to load class "
162: + pluginClassName, cnfe);
163: }
164: }
165:
166: if (ruleLoader == null) {
167: // the caller didn't provide a ruleLoader to the constructor,
168: // so get the plugin manager to "discover" one.
169: log.debug("Searching for ruleloader...");
170: ruleLoader = pm.findLoader(digester, id, pluginClass,
171: properties);
172: } else {
173: log.debug("This declaration has an explicit ruleLoader.");
174: }
175:
176: if (debug) {
177: if (ruleLoader == null) {
178: log.debug("No ruleLoader found for plugin declaration"
179: + " id [" + id + "]" + ", class ["
180: + pluginClass.getClass().getName() + "].");
181: } else {
182: log.debug("RuleLoader of type ["
183: + ruleLoader.getClass().getName()
184: + "] associated with plugin declaration"
185: + " id [" + id + "]" + ", class ["
186: + pluginClass.getClass().getName() + "].");
187: }
188: }
189:
190: initialized = true;
191: }
192:
193: /**
194: * Attempt to load custom rules for the target class at the specified
195: * pattern.
196: * <p>
197: * On return, any custom rules associated with the plugin class have
198: * been loaded into the Rules object currently associated with the
199: * specified digester object.
200: */
201:
202: public void configure(Digester digester, String pattern)
203: throws PluginException {
204: Log log = digester.getLogger();
205: boolean debug = log.isDebugEnabled();
206: if (debug) {
207: log.debug("configure being called!");
208: }
209:
210: if (!initialized) {
211: throw new PluginAssertionFailure("Not initialized.");
212: }
213:
214: if (ruleLoader != null) {
215: ruleLoader.addRules(digester, pattern);
216: }
217: }
218: }
|