KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > struts > plugins > DigestingPlugIn


1 /*
2  * $Id: DigestingPlugIn.java 164530 2005-04-25 03:11:07Z niallp $
3  *
4  * Copyright 2003-2005 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 package org.apache.struts.plugins;
20
21 import java.io.File JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.net.URL JavaDoc;
24
25 import javax.servlet.ServletException JavaDoc;
26
27 import org.apache.commons.digester.Digester;
28 import org.apache.commons.digester.RuleSet;
29 import org.apache.commons.digester.xmlrules.DigesterLoader;
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.struts.action.ActionServlet;
33 import org.apache.struts.action.PlugIn;
34 import org.apache.struts.config.ModuleConfig;
35 import org.apache.struts.util.RequestUtils;
36 import org.xml.sax.SAXException JavaDoc;
37
38 /**
39  * <p>An implementation of <code>PlugIn</code> which
40  * can be configured to instantiate a graph of objects
41  * using the Commons Digester and place the root object
42  * of that graph into the Application context.</p>
43  *
44  * @version $Rev: 164530 $
45  * @see org.apache.struts.action.PlugIn
46  * @since Struts 1.2
47  */

48 public class DigestingPlugIn implements PlugIn {
49
50     /**
51      * Commons Logging instance.
52      */

53     private static Log log = LogFactory.getLog(DigestingPlugIn.class);
54
55     protected static final String JavaDoc SOURCE_CLASSPATH = "classpath";
56
57     protected static final String JavaDoc SOURCE_FILE = "file";
58
59     protected static final String JavaDoc SOURCE_SERVLET = "servlet";
60
61     protected String JavaDoc configPath = null;
62
63     protected String JavaDoc configSource = SOURCE_SERVLET;
64
65     protected String JavaDoc digesterPath = null;
66
67     protected String JavaDoc digesterSource = SOURCE_SERVLET;
68
69     protected String JavaDoc key = null;
70
71     protected ModuleConfig moduleConfig = null;
72
73     protected String JavaDoc rulesets = null;
74
75     protected ActionServlet servlet = null;
76
77     protected boolean push = false;
78
79     /**
80      * Constructor for DigestingPlugIn.
81      */

82     public DigestingPlugIn() {
83         super();
84     }
85
86     /**
87      * Receive notification that our owning module is being shut down.
88      */

89     public void destroy() {
90         this.servlet = null;
91         this.moduleConfig = null;
92     }
93
94     /**
95      * <p>Initialize a <code>Digester</code> and use it to parse a
96      * configuration file, resulting in a root object which will be placed into
97      * the ServletContext.</p>
98      *
99      * @param servlet ActionServlet that is managing all the
100      * modules in this web application
101      * @param config ModuleConfig for the module with which
102      * this plug-in is associated
103      *
104      * @throws ServletException if this <code>PlugIn</code> cannot
105      * be successfully initialized
106      */

107     public void init(ActionServlet servlet, ModuleConfig config)
108         throws ServletException JavaDoc {
109
110         this.servlet = servlet;
111         this.moduleConfig = config;
112
113         Object JavaDoc obj = null;
114
115         Digester digester = this.initializeDigester();
116
117         if (this.push) {
118             log.debug("push == true; pushing plugin onto digester stack");
119             digester.push(this);
120         }
121
122         try {
123             log.debug("XML data file: [path: "
124                       + this.configPath
125                       + ", source: "
126                       + this.configSource + "]");
127
128             URL JavaDoc configURL = this.getConfigURL(this.configPath, this.configSource);
129             if (configURL == null) throw new ServletException JavaDoc("Unable to locate XML data file at [path: "
130                       + this.configPath
131                       + ", source: "
132                       + this.configSource + "]");
133             obj = digester.parse(configURL.openStream());
134
135         } catch (IOException JavaDoc e) {
136             // TODO Internationalize msg
137
log.error("Exception processing config", e);
138             throw new ServletException JavaDoc(e);
139
140         } catch (SAXException JavaDoc e) {
141             // TODO Internationalize msg
142
log.error("Exception processing config", e);
143             throw new ServletException JavaDoc(e);
144         }
145
146         this.storeGeneratedObject(obj);
147     }
148
149     /**
150      * Initialize the <code>Digester</code> which will be used to process the
151      * main configuration.
152      * @return a Digester, ready to use.
153      * @throws ServletException
154      */

155     protected Digester initializeDigester() throws ServletException JavaDoc {
156         Digester digester = null;
157
158         if (this.digesterPath != null && this.digesterSource != null) {
159
160             try {
161                 log.debug("Initialize digester from XML [path: "
162                           + this.digesterPath
163                           + "; source: "
164                           + this.digesterSource + "]");
165                 digester =
166                     this.digesterFromXml(this.digesterPath, this.digesterSource);
167
168             } catch (IOException JavaDoc e) {
169                 // TODO Internationalize msg
170
log.error("Exception instantiating digester from XML ", e);
171                 throw new ServletException JavaDoc(e);
172
173             }
174
175         } else {
176             log.debug("No XML rules for digester; call newDigesterInstance()");
177             digester = this.newDigesterInstance();
178         }
179
180         this.applyRuleSets(digester);
181
182         return digester;
183     }
184
185     /**
186      * <p>Instantiate a <code>Digester</code>.</p>
187      * <p>Subclasses may wish to override this to provide a subclass of Digester,
188      * or to configure the Digester using object methods.</p>
189      * @return a basic instance of <code>org.apache.commons.digester.Digester</code>
190      */

191     protected Digester newDigesterInstance() {
192         return new Digester();
193     }
194
195     /**
196      * <p>Instantiate a Digester from an XML input stream using the Commons
197      * <code>DigesterLoader</code>.</p>
198      * @param path the path to the digester rules XML to be found using <code>source</code>
199      * @param source a string indicating the lookup method to be used with <code>path</code>
200      * @return a configured Digester
201      * @throws FileNotFoundException
202      * @throws MalformedURLException
203      * @see #getConfigURL(String, String)
204      */

205     protected Digester digesterFromXml(String JavaDoc path, String JavaDoc source)
206         throws IOException JavaDoc {
207
208         URL JavaDoc configURL = this.getConfigURL(path, source);
209         if (configURL == null)
210         {
211             throw new NullPointerException JavaDoc("No resource '" + path + "' found in '" + source + "'");
212         }
213         return DigesterLoader.createDigester(configURL);
214     }
215
216     /**
217      * Instantiate any <code>RuleSet</code> classes defined in the
218      * <code>rulesets</code> property and use them to add rules to our
219      * <code>Digester</code>.
220      * @param digester the Digester instance to add RuleSet objects to.
221      * @throws ServletException
222      */

223     protected void applyRuleSets(Digester digester) throws ServletException JavaDoc {
224
225         if (this.rulesets == null || this.rulesets.trim().length() == 0) {
226             return;
227         }
228
229         rulesets = rulesets.trim();
230         String JavaDoc ruleSet = null;
231         while (rulesets.length() > 0) {
232             int comma = rulesets.indexOf(",");
233             if (comma < 0) {
234                 ruleSet = rulesets.trim();
235                 rulesets = "";
236             } else {
237                 ruleSet = rulesets.substring(0, comma).trim();
238                 rulesets = rulesets.substring(comma + 1).trim();
239             }
240
241             if (log.isDebugEnabled()) {
242                 // TODO Internationalize msg
243
log.debug("Configuring custom Digester Ruleset of type " + ruleSet);
244             }
245
246             try {
247                 RuleSet instance =
248                     (RuleSet) RequestUtils.applicationInstance(ruleSet);
249
250                 digester.addRuleSet(instance);
251
252             } catch (Exception JavaDoc e) {
253                 // TODO Internationalize msg
254
log.error("Exception configuring custom Digester RuleSet", e);
255                 throw new ServletException JavaDoc(e);
256             }
257         }
258     }
259
260     /**
261      * <p>Look up a resource path using one of a set of known path resolution mechanisms
262      * and return a URL to the resource.</p>
263      * @param path a String which is meaningful to one of the known resolution mechanisms.
264      * @param source one of the known path resolution mechanisms:
265      * <ul>
266      * <li>file - the path is a fully-qualified filesystem path.</li>
267      * <li>servlet - the path is a servlet-context relative path.</li>
268      * <li>classpath - the path is a classpath-relative path.</li>
269      * </ul>
270      * @return a URL pointing to the given path in the given mechanism.
271      * @throws FileNotFoundException
272      * @throws MalformedURLException
273      */

274     protected URL JavaDoc getConfigURL(String JavaDoc path, String JavaDoc source) throws IOException JavaDoc {
275
276         if (SOURCE_CLASSPATH.equals(source)) {
277             return this.getClassPathURL(path);
278         }
279
280         if (SOURCE_FILE.equals(source)) {
281             return this.getFileURL(path);
282         }
283
284         if (SOURCE_SERVLET.equals(source)) {
285             return this.getServletContextURL(path);
286         }
287
288         // TODO Internationalize msg
289
throw new IllegalArgumentException JavaDoc(
290             "ConfigSource " + source + " is not recognized");
291     }
292
293     /**
294      * Given a string, return a URL to a classpath resource of that name.
295      * @param path a Classpath-relative string identifying a resource.
296      * @return a URL identifying the resource on the classpath.
297      * TODO Do we need to be smarter about ClassLoaders?
298      */

299     protected URL JavaDoc getClassPathURL(String JavaDoc path) {
300         return getClass().getClassLoader().getResource(path);
301     }
302
303     /**
304      * Given a string, return a URL to a Servlet Context resource of that name.
305      * @param path a Classpath-relative string identifying a resource.
306      * @return a URL identifying the resource in the Servlet Context
307      * @throws MalformedURLException
308      */

309     protected URL JavaDoc getServletContextURL(String JavaDoc path) throws IOException JavaDoc {
310         return this.servlet.getServletContext().getResource(path);
311     }
312
313     /**
314      * Given a string, return a URL to a Filesystem resource of that name.
315      * @param path a path to a file.
316      * @return a URL identifying the resource in the in the file system.
317      * @throws MalformedURLException
318      * @throws FileNotFoundException
319      */

320     protected URL JavaDoc getFileURL(String JavaDoc path) throws IOException JavaDoc {
321         File JavaDoc file = new File JavaDoc(path);
322         return file.toURL();
323     }
324
325     /**
326      * @param configPath the path to configuration information for this PlugIn.
327      * @see #configSource
328      */

329     public void setConfigPath(String JavaDoc configPath) {
330         this.configPath = configPath;
331     }
332
333     /**
334      * @return the configPath property
335      * @see #configSource
336      */

337     public String JavaDoc getConfigPath() {
338         return configPath;
339     }
340
341     /**
342      * Set the source of the config file. Should be one of the following:
343      * <ul>
344      * <li>
345      * "classpath" - indicates that the configPath will be resolved by the
346      * ClassLoader.
347      * </li>
348      * <li>
349      * "file" - indicates that the configPath is a fully-qualified
350      * filesystem path.
351      * </li>
352      * <li>
353      * "servlet" - indicates that the configPath will be found by the
354      * ServletContext.
355      * </li>
356      * </ul>
357      * @param configSource the source (lookup method) for the config file.
358      * @see #configPath
359      */

360     public void setConfigSource(String JavaDoc configSource) {
361         this.configSource = configSource;
362     }
363
364     /**
365      * @return the string describing which access method should be used to
366      * resolve configPath.
367      * @see #configPath
368      */

369     public String JavaDoc getConfigSource() {
370         return configSource;
371     }
372
373     /**
374      * This method is called after the Digester runs to store the generated
375      * object somewhere. This implementation places the given object into the
376      * ServletContext under the attribute name as defined in <code>key</code>.
377      * @param obj The object to save.
378      */

379     protected void storeGeneratedObject(Object JavaDoc obj) {
380         log.debug("Put [" + obj + "] into application context [key:" + this.key + "]");
381         this.servlet.getServletContext().setAttribute(this.getKey(), obj);
382     }
383
384     /**
385      * @param key The ServletContext attribute name to store the generated
386      * object under.
387      */

388     public void setKey(String JavaDoc key) {
389         this.key = key;
390     }
391
392     /**
393      * @return The ServletContext attribute name the generated object is stored
394      * under.
395      */

396     public String JavaDoc getKey() {
397         return key;
398     }
399
400     /**
401      * <p>A comma-delimited list of one or more classes which implement
402      * <code>org.apache.commons.digester.RuleSet</code>. (Optional)</p>
403      */

404     public void setRulesets(String JavaDoc ruleSets) {
405         this.rulesets = ruleSets;
406     }
407
408     /**
409      * @return The configured list of <code>RuleSet</code> classes.
410      */

411     public String JavaDoc getRulesets() {
412         return this.rulesets;
413     }
414
415     /**
416      * <p>The path to a Digester XML configuration file, relative to the
417      * <code>digesterSource</code> property. (Optional)</p>
418      * @see #digesterSource
419      * @see #getConfigURL(String, String)
420      */

421     public void setDigesterPath(String JavaDoc digesterPath) {
422         this.digesterPath = digesterPath;
423     }
424
425     /**
426      * @return the configured path to a Digester XML config file, or null.
427      * @see #digesterSource
428      * @see #getConfigURL(String, String)
429      */

430     public String JavaDoc getDigesterPath() {
431         return digesterPath;
432     }
433
434     /**
435      * <p>The lookup mechanism to be used to resolve <code>digesterPath</code>
436      * (optional).
437      * </p>
438      * @param digesterSource
439      * @see #getConfigURL(String, String)
440      */

441     public void setDigesterSource(String JavaDoc digesterSource) {
442         this.digesterSource = digesterSource;
443     }
444
445     /**
446      * @return the configured lookup mechanism for resolving
447      * <code>digesterPath</code>.
448      * @see #getConfigURL(String, String)
449      */

450     public String JavaDoc getDigesterSource() {
451         return this.digesterSource;
452     }
453
454     /**
455      * <p>If set to <code>true</code>, this PlugIn will be pushed onto
456      * the Digester stack before the digester <code>parse</code> method is
457      * called.</p>
458      * <p>Defaults to <code>false</code></p>
459      * @param push
460      */

461     public void setPush(boolean push) {
462         this.push = push;
463     }
464
465     /**
466      * @return Whether or not this <code>PlugIn</code> instance will be pushed
467      * onto the <code>Digester</code> stack before <code>digester.parse()</code>
468      * is called.
469      */

470     public boolean getPush() {
471         return this.push;
472     }
473
474 }
475
Popular Tags