View Javadoc

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 }