View Javadoc

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 }