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