View Javadoc

1   /*
2    * Copyright 2003-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.IOException;
20  import javax.servlet.ServletConfig;
21  import javax.servlet.ServletContext;
22  import javax.servlet.ServletException;
23  import javax.servlet.http.HttpServlet;
24  import javax.servlet.http.HttpServletRequest;
25  import javax.servlet.http.HttpServletResponse;
26  import org.apache.commons.chain.Catalog;
27  import org.apache.commons.chain.CatalogFactory;
28  import org.apache.commons.chain.config.ConfigParser;
29  import org.apache.commons.chain.impl.CatalogBase;
30  import org.apache.commons.digester.RuleSet;
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  
34  
35  /***
36   * <p><code>Servlet</code> that automatically scans chain configuration files
37   * in the current web application at startup time, and exposes the result in a
38   * {@link Catalog} under a specified servlet context attribute.  The following
39   * <em>servlet</em> init parameters are utilized:</p>
40   * <ul>
41   * <li><strong>org.apache.commons.chain.CONFIG_CLASS_RESOURCE</strong> -
42   *     comma-delimited list of chain configuration resources to be loaded
43   *     via <code>ClassLoader.getResource()</code> calls.  If not specified,
44   *     no class loader resources will be loaded.</li>
45   * <li><strong>org.apache.commons.chain.CONFIG_WEB_RESOURCE</strong> -
46   *     comma-delimited list of chain configuration webapp resources
47   *     to be loaded.  If not specified, no web application resources
48   *     will be loaded.</li>
49   * <li><strong>org.apache.commons.chain.CONFIG_ATTR</strong> -
50   *     Name of the servlet context attribute under which the
51   *     resulting {@link Catalog} will be created or updated.
52   *     If not specified, it is expected that parsed resources will
53   *     contain <code>&lt;catalog&gt;</code> elements (which will
54   *     cause registration of the created {@link Catalog}s into
55   *     the {@link CatalogFactory} for this application, and no
56   *     servet context attribute will be created.
57   *     <strong>NOTE</strong> - This parameter is deprecated.</p>
58   * <li><strong>org.apache.commons.chain.RULE_SET</strong> -
59   *     Fully qualified class name of a Digester <code>RuleSet</code>
60   *     implementation to use for parsing configuration resources (this
61   *     class must have a public zero-args constructor).  If not defined,
62   *     the standard <code>RuleSet</code> implementation will be used.</li>
63   * </ul>
64   *
65   * <p>When a web application that has configured this servlet is
66   * started, it will acquire the {@link Catalog} under the specified servlet
67   * context attribute key, creating a new one if there is none already there.
68   * This {@link Catalog} will then be populated by scanning configuration
69   * resources from the following sources (loaded in this order):</p>
70   * <ul>
71   * <li>Resources loaded from specified resource paths from the
72   *     webapp's class loader (via <code>ClassLoader.getResource()</code>).</li>
73   * <li>Resources loaded from specified resource paths in the web application
74   *     archive (via <code>ServetContext.getResource()</code>).</li>
75   * </ul>
76   *
77   * <p>If no attribute key is specified, on the other hand, parsed configuration
78   * resources are expected to contain <code>&lt;catalog&gt;</code> elements,
79   * and the catalogs will be registered with the {@link CatalogFactory}
80   * for this web application.</p>
81   *
82   * <p>This class runs on Servlet 2.2 or later.  If you are running on a
83   * Servlet 2.3 or later system, you should also consider using
84   * {@link ChainListener} to initialize your {@link Catalog}.  Note that
85   * {@link ChainListener} uses parameters of the same names, but they are
86   * <em>context</em> init parameters instead of <em>servlet</em> init
87   * parameters. Because of this, you can use both facilities in the
88   * same application, if desired.</p>
89   *
90   * @author Matthew J. Sgarlata
91   * @author Craig R. McClanahan
92   * @author Ted Husted
93   */
94  
95  public class ChainServlet extends HttpServlet {
96  
97  
98      // ------------------------------------------------------ Manifest Constants
99  
100 
101     /***
102      * <p>The name of the context init parameter containing the name of the
103      * servlet context attribute under which our resulting {@link Catalog}
104      * will be stored.</p>
105      */
106     public static final String CONFIG_ATTR =
107         "org.apache.commons.chain.CONFIG_ATTR";
108 
109 
110     /***
111      * <p>The name of the context init parameter containing a comma-delimited
112      * list of class loader resources to be scanned.</p>
113      */
114     public static final String CONFIG_CLASS_RESOURCE =
115         "org.apache.commons.chain.CONFIG_CLASS_RESOURCE";
116 
117 
118     /***
119      * <p>The name of the context init parameter containing a comma-delimited
120      * list of web applicaton resources to be scanned.</p>
121      */
122     public static final String CONFIG_WEB_RESOURCE =
123         "org.apache.commons.chain.CONFIG_WEB_RESOURCE";
124 
125 
126     /***
127      * <p>The name of the context init parameter containing the fully
128      * qualified class name of the <code>RuleSet</code> implementation
129      * for configuring our {@link ConfigParser}.</p>
130      */
131     public static final String RULE_SET =
132         "org.apache.commons.chain.RULE_SET";
133 
134 
135     // -------------------------------------------------------- Static Variables
136 
137 
138     /***
139      * <p>The <code>Log</code> instance to use with this class.</p>
140      */
141     protected static final Log log = LogFactory.getLog(ChainServlet.class);
142 
143 
144     // --------------------------------------------------------- Servlet Methods
145 
146 
147     /***
148      * <p>Clean up after ourselves as this application shuts down.</p>
149      */
150     public void destroy() {
151 
152         ServletConfig config = getServletConfig();
153         ServletContext context = getServletContext();
154         String attr = config.getInitParameter(CONFIG_ATTR);
155         if (attr != null) {
156             context.removeAttribute(attr);
157         }
158         CatalogFactory.clear();
159 
160     }
161 
162 
163     /***
164      * <p>Create (if necessary) and configure a {@link Catalog} from the
165      * servlet init parameters that have been specified.</p>
166      *
167      * @throws ServletException if the servlet could not be initialized
168      */
169     public void init() throws ServletException {
170 
171         ServletConfig config = getServletConfig();
172         ServletContext context = getServletContext();
173         if (log.isInfoEnabled()) {
174             log.info("Initializing chain servlet '"
175                      + config.getServletName() + "'");
176         }
177 
178         // Retrieve servlet init parameters that we need
179         String attr = config.getInitParameter(CONFIG_ATTR);
180         String classResources =
181             context.getInitParameter(CONFIG_CLASS_RESOURCE);
182         String ruleSet = context.getInitParameter(RULE_SET);
183         String webResources = context.getInitParameter(CONFIG_WEB_RESOURCE);
184 
185         // Retrieve or create the Catalog instance we may be updating
186         Catalog catalog = null;
187         if (attr != null) {
188             catalog = (Catalog) context.getAttribute(attr);
189             if (catalog == null) {
190                 catalog = new CatalogBase();
191             }
192         }
193 
194         // Construct the configuration resource parser we will use
195         ConfigParser parser = new ConfigParser();
196         if (ruleSet != null) {
197             try {
198                 ClassLoader loader =
199                     Thread.currentThread().getContextClassLoader();
200                 if (loader == null) {
201                     loader = this.getClass().getClassLoader();
202                 }
203                 Class clazz = loader.loadClass(ruleSet);
204                 parser.setRuleSet((RuleSet) clazz.newInstance());
205             } catch (Exception e) {
206                 throw new ServletException("Exception initalizing RuleSet '"
207                                            + ruleSet + "' instance", e);
208             }
209         }
210 
211         // Parse the resources specified in our init parameters (if any)
212         if (attr == null) {
213             ChainResources.parseClassResources
214                 (classResources, parser);
215             ChainResources.parseWebResources
216                 (context, webResources, parser);
217         } else {
218             ChainResources.parseClassResources
219                 (catalog, classResources, parser);
220             ChainResources.parseWebResources
221                 (catalog, context, webResources, parser);
222         }
223 
224         // Expose the completed catalog (if requested)
225         if (attr != null) {
226             context.setAttribute(attr, catalog);
227         }
228 
229     }
230 
231 
232     /***
233      * <p>Does nothing; this servlet's only purpose is to initialize a Chain
234      * and store it in the servlet context.</p>
235      *
236      * @param request the request issued by the client
237      * @param response the response to be returned to the cliengt
238      *
239      * @throws javax.servlet.ServletException (this exception is never thrown)
240      * @throws java.io.IOException (this exception is never thrown)
241      */
242     public void service(HttpServletRequest request,
243                         HttpServletResponse response)
244         throws ServletException, IOException {
245 
246         ; // do nothing
247 
248     }
249 
250 
251 }