1 package org.apache.commons.digester3.plugins.strategies; 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.digester3.Digester; 25 import org.apache.commons.digester3.plugins.PluginException; 26 import org.apache.commons.digester3.plugins.RuleFinder; 27 import org.apache.commons.digester3.plugins.RuleLoader; 28 29 /** 30 * A rule-finding algorithm which expects the caller to specify a classname and methodname as plugin properties. 31 * 32 * @since 1.6 33 */ 34 public class FinderFromClass 35 extends RuleFinder 36 { 37 private static final String DFLT_RULECLASS_ATTR = "ruleclass"; 38 39 private static final String DFLT_METHOD_ATTR = "method"; 40 41 private static final String DFLT_METHOD_NAME = "addRules"; 42 43 private final String ruleClassAttr; 44 45 private final String methodAttr; 46 47 private final String dfltMethodName; 48 49 /** 50 * See {@link #findLoader}. 51 */ 52 public FinderFromClass() 53 { 54 this( DFLT_RULECLASS_ATTR, DFLT_METHOD_ATTR, DFLT_METHOD_NAME ); 55 } 56 57 /** 58 * Create a rule-finder which invokes a user-specified method on a user-specified class whenever dynamic rules for a 59 * plugin need to be loaded. See the findRules method for more info. 60 * 61 * @param ruleClassAttr must be non-null. 62 * @param methodAttr may be null. 63 * @param dfltMethodName may be null. 64 */ 65 public FinderFromClass( String ruleClassAttr, String methodAttr, String dfltMethodName ) 66 { 67 this.ruleClassAttr = ruleClassAttr; 68 this.methodAttr = methodAttr; 69 this.dfltMethodName = dfltMethodName; 70 } 71 72 /** 73 * If there exists a property with the name matching constructor param ruleClassAttr, then load the specified class, 74 * locate the appropriate rules-adding method on that class, and return an object encapsulating that info. 75 * <p> 76 * If there is no matching property provided, then just return null. 77 * <p> 78 * The returned object (when non-null) will invoke the target method on the selected class whenever its addRules 79 * method is invoked. The target method is expected to have the following prototype: 80 * <code> public static void xxxxx(Digester d, String patternPrefix); </code> 81 * <p> 82 * The target method can be specified in several ways. If this object's constructor was passed a non-null methodAttr 83 * parameter, and the properties defines a value with that key, then that is taken as the target method name. If 84 * there is no matching property, or the constructor was passed null for methodAttr, then the dfltMethodName passed 85 * to the constructor is used as the name of the method on the target class. And if that was null, then 86 * DFLT_METHOD_NAME will be used. 87 * <p> 88 * When the user explicitly declares a plugin in the input xml, the xml attributes on the declaration tag are passed 89 * here as properties, so the user can select any class in the classpath (and any method on that class provided it 90 * has the correct prototype) as the source of dynamic rules for the plugged-in class. 91 * 92 * @param digester The digester instance where locating plugin classes 93 * @param pluginClass The plugin Java class 94 * @param p The properties object that holds any xml attributes the user may have specified on the plugin 95 * declaration in order to indicate how to locate the plugin rules. 96 * @return a source of digester rules for the specified plugin class. 97 * @throws PluginException if the algorithm finds a source of rules, but there is something invalid 98 * about that source. 99 */ 100 @Override 101 public RuleLoader findLoader( Digester digester, Class<?> pluginClass, Properties p ) 102 throws PluginException 103 { 104 String ruleClassName = p.getProperty( ruleClassAttr ); 105 if ( ruleClassName == null ) 106 { 107 // nope, user hasn't requested dynamic rules to be loaded 108 // from a specific class. 109 return null; 110 } 111 112 // ok, we are in business 113 String methodName = null; 114 if ( methodAttr != null ) 115 { 116 methodName = p.getProperty( methodAttr ); 117 } 118 if ( methodName == null ) 119 { 120 methodName = dfltMethodName; 121 } 122 if ( methodName == null ) 123 { 124 methodName = DFLT_METHOD_NAME; 125 } 126 127 Class<?> ruleClass; 128 try 129 { 130 // load the plugin class object 131 ruleClass = digester.getClassLoader().loadClass( ruleClassName ); 132 } 133 catch ( ClassNotFoundException cnfe ) 134 { 135 throw new PluginException( "Unable to load class " + ruleClassName, cnfe ); 136 } 137 138 return new LoaderFromClass( ruleClass, methodName ); 139 } 140 141 }