KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > chain > web > ChainListener


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

16 package org.apache.commons.chain.web;
17
18
19 import java.io.InputStream JavaDoc;
20 import java.net.URL JavaDoc;
21 import java.util.HashSet JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.Set JavaDoc;
24 import javax.servlet.ServletContext JavaDoc;
25 import javax.servlet.ServletContextEvent JavaDoc;
26 import javax.servlet.ServletContextListener JavaDoc;
27 import org.apache.commons.chain.Catalog;
28 import org.apache.commons.chain.CatalogFactory;
29 import org.apache.commons.chain.config.ConfigParser;
30 import org.apache.commons.chain.impl.CatalogBase;
31 import org.apache.commons.digester.RuleSet;
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34
35
36 /**
37  * <p><code>ServletContextListener</code> that automatically
38  * scans chain configuration files in the current web application at
39  * startup time, and exposes the result in a {@link Catalog} under a
40  * specified servlet context attribute. The following <em>context</em> init
41  * parameters are utilized:</p>
42  * <ul>
43  * <li><strong>org.apache.commons.chain.CONFIG_CLASS_RESOURCE</strong> -
44  * comma-delimited list of chain configuration resources to be loaded
45  * via <code>ClassLoader.getResource()</code> calls. If not specified,
46  * no class loader resources will be loaded.</li>
47  * <li><strong>org.apache.commons.chain.CONFIG_WEB_RESOURCE</strong> -
48  * comma-delimited list of chain configuration webapp resources
49  * to be loaded. If not specified, no web application resources
50  * will be loaded.</li>
51  * <li><strong>org.apache.commons.chain.CONFIG_ATTR</strong> -
52  * Name of the servlet context attribute under which the
53  * resulting {@link Catalog} will be created or updated.
54  * If not specified, it is expected that parsed resources will
55  * contain <code>&lt;catalog&gt;</code> elements (which will
56  * cause registration of the created {@link Catalog}s into
57  * the {@link CatalogFactory} for this application, and no
58  * servet context attribute will be created.
59  * <strong>NOTE</strong> - This parameter is deprecated.</p>
60  * <li><strong>org.apache.commons.chain.RULE_SET</strong> -
61  * Fully qualified class name of a Digester <code>RuleSet</code>
62  * implementation to use for parsing configuration resources (this
63  * class must have a public zero-args constructor). If not defined,
64  * the standard <code>RuleSet</code> implementation will be used.</li>
65  * </ul>
66  *
67  * <p>When a web application that has configured this listener is
68  * started, it will acquire the {@link Catalog} under the specified servlet
69  * context attribute key, creating a new one if there is none already there.
70  * This {@link Catalog} will then be populated by scanning configuration
71  * resources from the following sources (loaded in this order):</p>
72  * <ul>
73  * <li>Resources loaded from any <code>META-INF/chain-config.xml</code>
74  * resource found in a JAR file in <code>/WEB-INF/lib</code>.</li>
75  * <li>Resources loaded from specified resource paths from the
76  * webapp's class loader (via <code>ClassLoader.getResource()</code>).</li>
77  * <li>Resources loaded from specified resource paths in the web application
78  * archive (via <code>ServetContext.getResource()</code>).</li>
79  * </ul>
80  *
81  * <p>If no attribute key is specified, on the other hand, parsed configuration
82  * resources are expected to contain <code>&lt;catalog&gt;</code> elements,
83  * and the catalogs will be registered with the {@link CatalogFactory}
84  * for this web application.</p>
85  *
86  * <p>This class requires Servlet 2.3 or later. If you are running on
87  * Servlet 2.2 system, consider using {@link ChainServlet} instead.
88  * Note that {@link ChainServlet} uses parameters of the
89  * same names, but they are <em>servlet</em> init parameters instead
90  * of <em>context</em> init parameters. Because of this, you can use
91  * both facilities in the same application, if desired.</p>
92  *
93  * @author Craig R. McClanahan
94  * @author Ted Husted
95  * @version $Revision: 1.7 $ $Date: 2004/11/30 05:52:23 $
96  */

97
98 public class ChainListener implements ServletContextListener JavaDoc {
99
100
101     // ------------------------------------------------------ Manifest Constants
102

103
104     /**
105      * <p>The name of the context init parameter containing the name of the
106      * servlet context attribute under which our resulting {@link Catalog}
107      * will be stored.</p>
108      */

109     public static final String JavaDoc CONFIG_ATTR =
110         "org.apache.commons.chain.CONFIG_ATTR";
111
112
113     /**
114      * <p>The name of the context init parameter containing a comma-delimited
115      * list of class loader resources to be scanned.</p>
116      */

117     public static final String JavaDoc CONFIG_CLASS_RESOURCE =
118         "org.apache.commons.chain.CONFIG_CLASS_RESOURCE";
119
120
121     /**
122      * <p>The name of the context init parameter containing a comma-delimited
123      * list of web applicaton resources to be scanned.</p>
124      */

125     public static final String JavaDoc CONFIG_WEB_RESOURCE =
126         "org.apache.commons.chain.CONFIG_WEB_RESOURCE";
127
128
129     /**
130      * <p>The name of the context init parameter containing the fully
131      * qualified class name of the <code>RuleSet</code> implementation
132      * for configuring our {@link ConfigParser}.</p>
133      */

134     public static final String JavaDoc RULE_SET =
135         "org.apache.commons.chain.RULE_SET";
136
137
138     // -------------------------------------------------------- Static Variables
139

140
141     /**
142      * <p>The <code>Log</code> instance for this class.</p>
143      */

144     private static final Log log = LogFactory.getLog(ChainListener.class);
145
146
147     // ------------------------------------------ ServletContextListener Methods
148

149
150     /**
151      * <p>Remove the configured {@link Catalog} from the servlet context
152      * attributes for this web application.</p>
153      *
154      * @param event <code>ServletContextEvent</code> to be processed
155      */

156     public void contextDestroyed(ServletContextEvent JavaDoc event) {
157
158         ServletContext JavaDoc context = event.getServletContext();
159         String JavaDoc attr = context.getInitParameter(CONFIG_ATTR);
160         if (attr != null) {
161             context.removeAttribute(attr);
162         }
163         CatalogFactory.clear();
164
165     }
166
167
168     /**
169      * <p>Scan the required chain configuration resources, assemble the
170      * configured chains into a {@link Catalog}, and expose it as a
171      * servlet context attribute under the specified key.</p>
172      *
173      * @param event <code>ServletContextEvent</code> to be processed
174      */

175     public void contextInitialized(ServletContextEvent JavaDoc event) {
176
177         if (log.isInfoEnabled()) {
178             log.info("Initializing chain listener");
179         }
180         ServletContext JavaDoc context = event.getServletContext();
181
182         // Retrieve context init parameters that we need
183
String JavaDoc attr = context.getInitParameter(CONFIG_ATTR);
184         String JavaDoc classResources =
185             context.getInitParameter(CONFIG_CLASS_RESOURCE);
186         String JavaDoc ruleSet = context.getInitParameter(RULE_SET);
187         String JavaDoc webResources = context.getInitParameter(CONFIG_WEB_RESOURCE);
188
189         // Retrieve or create the Catalog instance we may be updating
190
Catalog catalog = null;
191         if (attr != null) {
192             catalog = (Catalog) context.getAttribute(attr);
193             if (catalog == null) {
194                 catalog = new CatalogBase();
195             }
196         }
197
198         // Construct the configuration resource parser we will use
199
ConfigParser parser = new ConfigParser();
200         if (ruleSet != null) {
201             try {
202                 ClassLoader JavaDoc loader =
203                     Thread.currentThread().getContextClassLoader();
204                 if (loader == null) {
205                     loader = this.getClass().getClassLoader();
206                 }
207                 Class JavaDoc clazz = loader.loadClass(ruleSet);
208                 parser.setRuleSet((RuleSet) clazz.newInstance());
209             } catch (Exception JavaDoc e) {
210                 throw new RuntimeException JavaDoc("Exception initalizing RuleSet '"
211                                            + ruleSet + "' instance: "
212                                            + e.getMessage());
213             }
214         }
215
216         // Parse the resources specified in our init parameters (if any)
217
if (attr == null) {
218             parseJarResources(context, parser);
219             ChainResources.parseClassResources
220                 (classResources, parser);
221             ChainResources.parseWebResources
222                 (context, webResources, parser);
223         } else {
224             parseJarResources(catalog, context, parser);
225             ChainResources.parseClassResources
226                 (catalog, classResources, parser);
227             ChainResources.parseWebResources
228                 (catalog, context, webResources, parser);
229         }
230
231         // Expose the completed catalog (if requested)
232
if (attr != null) {
233             context.setAttribute(attr, catalog);
234         }
235
236     }
237
238
239     // --------------------------------------------------------- Private Methods
240

241
242     /**
243      * <p>Parse resources found in JAR files in the <code>/WEB-INF/lib</code>
244      * subdirectory (if any).</p>
245      *
246      * @param context <code>ServletContext</code> for this web application
247      * @param parser {@link ConfigParser} to use for parsing
248      */

249     private void parseJarResources(ServletContext JavaDoc context,
250                                    ConfigParser parser) {
251
252         Set JavaDoc jars = context.getResourcePaths("/WEB-INF/lib");
253         if (jars == null) {
254             jars = new HashSet JavaDoc();
255         }
256         String JavaDoc path = null;
257         Iterator JavaDoc paths = jars.iterator();
258         while (paths.hasNext()) {
259
260             path = (String JavaDoc) paths.next();
261             if (!path.endsWith(".jar")) {
262                 continue;
263             }
264             URL JavaDoc resourceURL = null;
265             try {
266                 URL JavaDoc jarURL = context.getResource(path);
267                 resourceURL = new URL JavaDoc("jar:"
268                                       + translate(jarURL.toExternalForm())
269                                       + "!/META-INF/chain-config.xml");
270                 if (resourceURL == null) {
271                     continue;
272                 }
273                 InputStream JavaDoc is = null;
274                 try {
275                     is = resourceURL.openStream();
276                 } catch (Exception JavaDoc e) {
277                     ; // means there is no such resource
278
}
279                 if (is == null) {
280                     continue;
281                 } else {
282                     is.close();
283                 }
284                 parser.parse(resourceURL);
285             } catch (Exception JavaDoc e) {
286                 throw new RuntimeException JavaDoc
287                     ("Exception parsing chain config resource '"
288                      + resourceURL.toExternalForm() + "': "
289                      + e.getMessage());
290             }
291         }
292
293     }
294
295
296     /**
297      * <p>Parse resources found in JAR files in the <code>/WEB-INF/lib</code>
298      * subdirectory (if any).</p>
299      *
300      * @param catalog {@link Catalog} we are populating
301      * @param context <code>ServletContext</code> for this web application
302      * @param parser {@link ConfigParser} to use for parsing
303      *
304      * @deprecated Use the variant that does not take a catalog, on a
305      * configuration resource containing "catalog" element(s)
306      */

307     private void parseJarResources(Catalog catalog, ServletContext JavaDoc context,
308                                    ConfigParser parser) {
309
310         Set JavaDoc jars = context.getResourcePaths("/WEB-INF/lib");
311         if (jars == null) {
312             jars = new HashSet JavaDoc();
313         }
314         String JavaDoc path = null;
315         Iterator JavaDoc paths = jars.iterator();
316         while (paths.hasNext()) {
317
318             path = (String JavaDoc) paths.next();
319             if (!path.endsWith(".jar")) {
320                 continue;
321             }
322             URL JavaDoc resourceURL = null;
323             try {
324                 URL JavaDoc jarURL = context.getResource(path);
325                 resourceURL = new URL JavaDoc("jar:"
326                                       + translate(jarURL.toExternalForm())
327                                       + "!/META-INF/chain-config.xml");
328                 if (resourceURL == null) {
329                     continue;
330                 }
331                 InputStream JavaDoc is = null;
332                 try {
333                     is = resourceURL.openStream();
334                 } catch (Exception JavaDoc e) {
335                     ; // means there is no such resource
336
}
337                 if (is == null) {
338                     continue;
339                 } else {
340                     is.close();
341                 }
342                 parser.parse(catalog, resourceURL);
343             } catch (Exception JavaDoc e) {
344                 throw new RuntimeException JavaDoc
345                     ("Exception parsing chain config resource '"
346                      + resourceURL.toExternalForm() + "': "
347                      + e.getMessage());
348             }
349         }
350
351     }
352
353
354     /**
355      * <p>Translate space character into <code>&pct;20</code> to avoid problems
356      * with paths that contain spaces on some JVMs.</p>
357      *
358      * @param value Value to translate
359      */

360     private String JavaDoc translate(String JavaDoc value) {
361
362         while (true) {
363             int index = value.indexOf(' ');
364             if (index < 0) {
365                 break;
366             }
367             value = value.substring(0, index) + value.substring(index + 1);
368         }
369         return (value);
370
371     }
372
373
374 }
375
Popular Tags