1. /* $Id: Declaration.java,v 1.17 2004/05/10 06:44:13 skitching Exp $
  2. *
  3. * Copyright 2003-2004 The Apache Software Foundation.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package org.apache.commons.digester.plugins;
  18. import java.io.IOException;
  19. import java.util.Properties;
  20. import java.util.List;
  21. import org.apache.commons.logging.Log;
  22. import org.apache.commons.digester.Digester;
  23. /**
  24. * Represents a Class that can be instantiated by a PluginCreateRule, plus
  25. * info on how to load custom digester rules for mapping xml into that
  26. * plugged-in class.
  27. *
  28. * @since 1.6
  29. */
  30. public class Declaration {
  31. /** The class of the object to be instantiated. */
  32. private Class pluginClass;
  33. /** The name of the class of the object to be instantiated. */
  34. private String pluginClassName;
  35. /** See {@link #setId}. */
  36. private String id;
  37. /** See {@link #setProperties}. */
  38. private Properties properties = new Properties();
  39. /** See {@link #init}. */
  40. private boolean initialized = false;
  41. /**
  42. * Class which is responsible for dynamically loading this
  43. * plugin's rules on demand.
  44. */
  45. private RuleLoader ruleLoader = null;
  46. //---------------------- constructors ----------------------------------
  47. /**
  48. * Constructor.
  49. */
  50. public Declaration(String pluginClassName) {
  51. // We can't load the pluginClass at this time, because we don't
  52. // have a digester instance yet to load it through. So just
  53. // save the name away, and we'll load the Class object in the
  54. // init method.
  55. this.pluginClassName = pluginClassName;
  56. }
  57. /**
  58. * Constructor.
  59. */
  60. public Declaration(Class pluginClass) {
  61. this.pluginClass = pluginClass;
  62. this.pluginClassName = pluginClass.getName();
  63. }
  64. /**
  65. * Create an instance where a fully-initialised ruleLoader instance
  66. * is provided by the caller instead of having the PluginManager
  67. * "discover" an appropriate one.
  68. */
  69. public Declaration(Class pluginClass, RuleLoader ruleLoader) {
  70. this.pluginClass = pluginClass;
  71. this.pluginClassName = pluginClass.getName();
  72. this.ruleLoader = ruleLoader;
  73. }
  74. //---------------------- properties -----------------------------------
  75. /**
  76. * The id that the user associated with a particular plugin declaration
  77. * in the input xml. This id is later used in the input xml to refer
  78. * back to the original declaration.
  79. * <p>
  80. * For plugins declared "in-line", the id is null.
  81. */
  82. public void setId(String id) {
  83. this.id = id;
  84. }
  85. /**
  86. * Return the id associated with this declaration. For plugins
  87. * declared "inline", null will be returned.
  88. *
  89. * @return The id value. May be null.
  90. */
  91. public String getId() {
  92. return id;
  93. }
  94. /**
  95. * Copy all (key,value) pairs in the param into the properties member of
  96. * this object.
  97. * <p>
  98. * The declaration properties cannot be explicit member variables,
  99. * because the set of useful properties a user can provide on a declaration
  100. * depends on what RuleFinder classes are available - and extra RuleFinders
  101. * can be added by the user. So here we keep a map of the settings, and
  102. * let the RuleFinder objects look for whatever properties they consider
  103. * significant.
  104. * <p>
  105. * The "id" and "class" properties are treated differently.
  106. */
  107. public void setProperties(Properties p) {
  108. properties.putAll(p);
  109. }
  110. /**
  111. * Return plugin class associated with this declaration.
  112. *
  113. * @return The pluginClass.
  114. */
  115. public Class getPluginClass() {
  116. return pluginClass;
  117. }
  118. //---------------------- methods -----------------------------------
  119. /**
  120. * Must be called exactly once, and must be called before any call
  121. * to the configure method.
  122. */
  123. public void init(Digester digester, PluginManager pm) throws PluginException {
  124. Log log = digester.getLogger();
  125. boolean debug = log.isDebugEnabled();
  126. if (debug) {
  127. log.debug("init being called!");
  128. }
  129. if (initialized) {
  130. throw new PluginAssertionFailure("Init called multiple times.");
  131. }
  132. if ((pluginClass == null) && (pluginClassName != null)) {
  133. try {
  134. // load the plugin class object
  135. pluginClass =
  136. digester.getClassLoader().loadClass(pluginClassName);
  137. } catch(ClassNotFoundException cnfe) {
  138. throw new PluginException(
  139. "Unable to load class " + pluginClassName, cnfe);
  140. }
  141. }
  142. if (ruleLoader == null) {
  143. // the caller didn't provide a ruleLoader to the constructor,
  144. // so get the plugin manager to "discover" one.
  145. log.debug("Searching for ruleloader...");
  146. ruleLoader = pm.findLoader(digester, id, pluginClass, properties);
  147. } else {
  148. log.debug("This declaration has an explicit ruleLoader.");
  149. }
  150. if (debug) {
  151. if (ruleLoader == null) {
  152. log.debug(
  153. "No ruleLoader found for plugin declaration"
  154. + " id [" + id + "]"
  155. + ", class [" + pluginClass.getClass().getName() + "].");
  156. } else {
  157. log.debug(
  158. "RuleLoader of type [" + ruleLoader.getClass().getName()
  159. + "] associated with plugin declaration"
  160. + " id [" + id + "]"
  161. + ", class [" + pluginClass.getClass().getName() + "].");
  162. }
  163. }
  164. initialized = true;
  165. }
  166. /**
  167. * Attempt to load custom rules for the target class at the specified
  168. * pattern.
  169. * <p>
  170. * On return, any custom rules associated with the plugin class have
  171. * been loaded into the Rules object currently associated with the
  172. * specified digester object.
  173. */
  174. public void configure(Digester digester, String pattern)
  175. throws PluginException {
  176. Log log = digester.getLogger();
  177. boolean debug = log.isDebugEnabled();
  178. if (debug) {
  179. log.debug("configure being called!");
  180. }
  181. if (!initialized) {
  182. throw new PluginAssertionFailure("Not initialized.");
  183. }
  184. if (ruleLoader != null) {
  185. ruleLoader.addRules(digester, pattern);
  186. }
  187. }
  188. }