001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.chain.web;
018
019
020 import java.io.IOException;
021 import javax.servlet.ServletConfig;
022 import javax.servlet.ServletContext;
023 import javax.servlet.ServletException;
024 import javax.servlet.http.HttpServlet;
025 import javax.servlet.http.HttpServletRequest;
026 import javax.servlet.http.HttpServletResponse;
027 import org.apache.commons.chain.Catalog;
028 import org.apache.commons.chain.CatalogFactory;
029 import org.apache.commons.chain.config.ConfigParser;
030 import org.apache.commons.chain.impl.CatalogBase;
031 import org.apache.commons.digester.RuleSet;
032 import org.apache.commons.logging.Log;
033 import org.apache.commons.logging.LogFactory;
034
035
036 /**
037 * <p><code>Servlet</code> that automatically scans chain configuration files
038 * in the current web application at startup time, and exposes the result in a
039 * {@link Catalog} under a specified servlet context attribute. The following
040 * <em>servlet</em> init parameters are utilized:</p>
041 * <ul>
042 * <li><strong>org.apache.commons.chain.CONFIG_CLASS_RESOURCE</strong> -
043 * comma-delimited list of chain configuration resources to be loaded
044 * via <code>ClassLoader.getResource()</code> calls. If not specified,
045 * no class loader resources will be loaded.</li>
046 * <li><strong>org.apache.commons.chain.CONFIG_WEB_RESOURCE</strong> -
047 * comma-delimited list of chain configuration webapp resources
048 * to be loaded. If not specified, no web application resources
049 * will be loaded.</li>
050 * <li><strong>org.apache.commons.chain.CONFIG_ATTR</strong> -
051 * Name of the servlet context attribute under which the
052 * resulting {@link Catalog} will be created or updated.
053 * If not specified, it is expected that parsed resources will
054 * contain <code><catalog></code> elements (which will
055 * cause registration of the created {@link Catalog}s into
056 * the {@link CatalogFactory} for this application, and no
057 * servet context attribute will be created.
058 * <strong>NOTE</strong> - This parameter is deprecated.</p>
059 * <li><strong>org.apache.commons.chain.RULE_SET</strong> -
060 * Fully qualified class name of a Digester <code>RuleSet</code>
061 * implementation to use for parsing configuration resources (this
062 * class must have a public zero-args constructor). If not defined,
063 * the standard <code>RuleSet</code> implementation will be used.</li>
064 * </ul>
065 *
066 * <p>When a web application that has configured this servlet is
067 * started, it will acquire the {@link Catalog} under the specified servlet
068 * context attribute key, creating a new one if there is none already there.
069 * This {@link Catalog} will then be populated by scanning configuration
070 * resources from the following sources (loaded in this order):</p>
071 * <ul>
072 * <li>Resources loaded from specified resource paths from the
073 * webapp's class loader (via <code>ClassLoader.getResource()</code>).</li>
074 * <li>Resources loaded from specified resource paths in the web application
075 * archive (via <code>ServetContext.getResource()</code>).</li>
076 * </ul>
077 *
078 * <p>If no attribute key is specified, on the other hand, parsed configuration
079 * resources are expected to contain <code><catalog></code> elements,
080 * and the catalogs will be registered with the {@link CatalogFactory}
081 * for this web application.</p>
082 *
083 * <p>This class runs on Servlet 2.2 or later. If you are running on a
084 * Servlet 2.3 or later system, you should also consider using
085 * {@link ChainListener} to initialize your {@link Catalog}. Note that
086 * {@link ChainListener} uses parameters of the same names, but they are
087 * <em>context</em> init parameters instead of <em>servlet</em> init
088 * parameters. Because of this, you can use both facilities in the
089 * same application, if desired.</p>
090 *
091 * @author Matthew J. Sgarlata
092 * @author Craig R. McClanahan
093 * @author Ted Husted
094 */
095
096 public class ChainServlet extends HttpServlet {
097
098
099 // ------------------------------------------------------ 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 }