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