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 }