001package org.apache.commons.digester3.plugins.strategies; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.util.Properties; 023 024import org.apache.commons.digester3.Digester; 025import org.apache.commons.digester3.plugins.PluginException; 026import org.apache.commons.digester3.plugins.RuleFinder; 027import org.apache.commons.digester3.plugins.RuleLoader; 028 029/** 030 * A rule-finding algorithm which expects the caller to specify a classname and methodname as plugin properties. 031 * 032 * @since 1.6 033 */ 034public class FinderFromClass 035 extends RuleFinder 036{ 037 private static final String DFLT_RULECLASS_ATTR = "ruleclass"; 038 039 private static final String DFLT_METHOD_ATTR = "method"; 040 041 private static final String DFLT_METHOD_NAME = "addRules"; 042 043 private final String ruleClassAttr; 044 045 private final String methodAttr; 046 047 private final String dfltMethodName; 048 049 /** 050 * See {@link #findLoader}. 051 */ 052 public FinderFromClass() 053 { 054 this( DFLT_RULECLASS_ATTR, DFLT_METHOD_ATTR, DFLT_METHOD_NAME ); 055 } 056 057 /** 058 * Create a rule-finder which invokes a user-specified method on a user-specified class whenever dynamic rules for a 059 * plugin need to be loaded. See the findRules method for more info. 060 * 061 * @param ruleClassAttr must be non-null. 062 * @param methodAttr may be null. 063 * @param dfltMethodName may be null. 064 */ 065 public FinderFromClass( String ruleClassAttr, String methodAttr, String dfltMethodName ) 066 { 067 this.ruleClassAttr = ruleClassAttr; 068 this.methodAttr = methodAttr; 069 this.dfltMethodName = dfltMethodName; 070 } 071 072 /** 073 * If there exists a property with the name matching constructor param ruleClassAttr, then load the specified class, 074 * locate the appropriate rules-adding method on that class, and return an object encapsulating that info. 075 * <p> 076 * If there is no matching property provided, then just return null. 077 * <p> 078 * The returned object (when non-null) will invoke the target method on the selected class whenever its addRules 079 * method is invoked. The target method is expected to have the following prototype: 080 * <code> public static void xxxxx(Digester d, String patternPrefix); </code> 081 * <p> 082 * The target method can be specified in several ways. If this object's constructor was passed a non-null methodAttr 083 * parameter, and the properties defines a value with that key, then that is taken as the target method name. If 084 * there is no matching property, or the constructor was passed null for methodAttr, then the dfltMethodName passed 085 * to the constructor is used as the name of the method on the target class. And if that was null, then 086 * DFLT_METHOD_NAME will be used. 087 * <p> 088 * When the user explicitly declares a plugin in the input xml, the xml attributes on the declaration tag are passed 089 * here as properties, so the user can select any class in the classpath (and any method on that class provided it 090 * has the correct prototype) as the source of dynamic rules for the plugged-in class. 091 * 092 * @param digester The digester instance where locating plugin classes 093 * @param pluginClass The plugin Java class 094 * @param p The properties object that holds any xml attributes the user may have specified on the plugin 095 * declaration in order to indicate how to locate the plugin rules. 096 * @return a source of digester rules for the specified plugin class. 097 * @throws PluginException if the algorithm finds a source of rules, but there is something invalid 098 * about that source. 099 */ 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}