View Javadoc

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