001: /*
002: * Copyright 2003-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.chain.web;
017:
018: import java.io.IOException;
019: import javax.servlet.ServletConfig;
020: import javax.servlet.ServletContext;
021: import javax.servlet.ServletException;
022: import javax.servlet.http.HttpServlet;
023: import javax.servlet.http.HttpServletRequest;
024: import javax.servlet.http.HttpServletResponse;
025: import org.apache.commons.chain.Catalog;
026: import org.apache.commons.chain.CatalogFactory;
027: import org.apache.commons.chain.config.ConfigParser;
028: import org.apache.commons.chain.impl.CatalogBase;
029: import org.apache.commons.digester.RuleSet;
030: import org.apache.commons.logging.Log;
031: import org.apache.commons.logging.LogFactory;
032:
033: /**
034: * <p><code>Servlet</code> that automatically scans chain configuration files
035: * in the current web application at startup time, and exposes the result in a
036: * {@link Catalog} under a specified servlet context attribute. The following
037: * <em>servlet</em> init parameters are utilized:</p>
038: * <ul>
039: * <li><strong>org.apache.commons.chain.CONFIG_CLASS_RESOURCE</strong> -
040: * comma-delimited list of chain configuration resources to be loaded
041: * via <code>ClassLoader.getResource()</code> calls. If not specified,
042: * no class loader resources will be loaded.</li>
043: * <li><strong>org.apache.commons.chain.CONFIG_WEB_RESOURCE</strong> -
044: * comma-delimited list of chain configuration webapp resources
045: * to be loaded. If not specified, no web application resources
046: * will be loaded.</li>
047: * <li><strong>org.apache.commons.chain.CONFIG_ATTR</strong> -
048: * Name of the servlet context attribute under which the
049: * resulting {@link Catalog} will be created or updated.
050: * If not specified, it is expected that parsed resources will
051: * contain <code><catalog></code> elements (which will
052: * cause registration of the created {@link Catalog}s into
053: * the {@link CatalogFactory} for this application, and no
054: * servet context attribute will be created.
055: * <strong>NOTE</strong> - This parameter is deprecated.</p>
056: * <li><strong>org.apache.commons.chain.RULE_SET</strong> -
057: * Fully qualified class name of a Digester <code>RuleSet</code>
058: * implementation to use for parsing configuration resources (this
059: * class must have a public zero-args constructor). If not defined,
060: * the standard <code>RuleSet</code> implementation will be used.</li>
061: * </ul>
062: *
063: * <p>When a web application that has configured this servlet is
064: * started, it will acquire the {@link Catalog} under the specified servlet
065: * context attribute key, creating a new one if there is none already there.
066: * This {@link Catalog} will then be populated by scanning configuration
067: * resources from the following sources (loaded in this order):</p>
068: * <ul>
069: * <li>Resources loaded from specified resource paths from the
070: * webapp's class loader (via <code>ClassLoader.getResource()</code>).</li>
071: * <li>Resources loaded from specified resource paths in the web application
072: * archive (via <code>ServetContext.getResource()</code>).</li>
073: * </ul>
074: *
075: * <p>If no attribute key is specified, on the other hand, parsed configuration
076: * resources are expected to contain <code><catalog></code> elements,
077: * and the catalogs will be registered with the {@link CatalogFactory}
078: * for this web application.</p>
079: *
080: * <p>This class runs on Servlet 2.2 or later. If you are running on a
081: * Servlet 2.3 or later system, you should also consider using
082: * {@link ChainListener} to initialize your {@link Catalog}. Note that
083: * {@link ChainListener} uses parameters of the same names, but they are
084: * <em>context</em> init parameters instead of <em>servlet</em> init
085: * parameters. Because of this, you can use both facilities in the
086: * same application, if desired.</p>
087: *
088: * @author Matthew J. Sgarlata
089: * @author Craig R. McClanahan
090: * @author Ted Husted
091: */
092:
093: public class ChainServlet extends HttpServlet {
094:
095: // ------------------------------------------------------ Manifest Constants
096:
097: /**
098: * <p>The name of the context init parameter containing the name of the
099: * servlet context attribute under which our resulting {@link Catalog}
100: * will be stored.</p>
101: */
102: public static final String CONFIG_ATTR = "org.apache.commons.chain.CONFIG_ATTR";
103:
104: /**
105: * <p>The name of the context init parameter containing a comma-delimited
106: * list of class loader resources to be scanned.</p>
107: */
108: public static final String CONFIG_CLASS_RESOURCE = "org.apache.commons.chain.CONFIG_CLASS_RESOURCE";
109:
110: /**
111: * <p>The name of the context init parameter containing a comma-delimited
112: * list of web applicaton resources to be scanned.</p>
113: */
114: public static final String CONFIG_WEB_RESOURCE = "org.apache.commons.chain.CONFIG_WEB_RESOURCE";
115:
116: /**
117: * <p>The name of the context init parameter containing the fully
118: * qualified class name of the <code>RuleSet</code> implementation
119: * for configuring our {@link ConfigParser}.</p>
120: */
121: public static final String RULE_SET = "org.apache.commons.chain.RULE_SET";
122:
123: // --------------------------------------------------------- Servlet Methods
124:
125: /**
126: * <p>Clean up after ourselves as this application shuts down.</p>
127: */
128: public void destroy() {
129:
130: ServletConfig config = getServletConfig();
131: ServletContext context = getServletContext();
132: String attr = config.getInitParameter(CONFIG_ATTR);
133: if (attr != null) {
134: context.removeAttribute(attr);
135: }
136: CatalogFactory.clear();
137:
138: }
139:
140: /**
141: * <p>Create (if necessary) and configure a {@link Catalog} from the
142: * servlet init parameters that have been specified.</p>
143: *
144: * @throws ServletException if the servlet could not be initialized
145: */
146: public void init() throws ServletException {
147:
148: Log log = LogFactory.getLog(ChainServlet.class);
149: ServletConfig config = getServletConfig();
150: ServletContext context = getServletContext();
151: if (log.isInfoEnabled()) {
152: log.info("Initializing chain servlet '"
153: + config.getServletName() + "'");
154: }
155:
156: // Retrieve servlet init parameters that we need
157: String attr = config.getInitParameter(CONFIG_ATTR);
158: String classResources = context
159: .getInitParameter(CONFIG_CLASS_RESOURCE);
160: String ruleSet = context.getInitParameter(RULE_SET);
161: String webResources = context
162: .getInitParameter(CONFIG_WEB_RESOURCE);
163:
164: // Retrieve or create the Catalog instance we may be updating
165: Catalog catalog = null;
166: if (attr != null) {
167: catalog = (Catalog) context.getAttribute(attr);
168: if (catalog == null) {
169: catalog = new CatalogBase();
170: }
171: }
172:
173: // Construct the configuration resource parser we will use
174: ConfigParser parser = new ConfigParser();
175: if (ruleSet != null) {
176: try {
177: ClassLoader loader = Thread.currentThread()
178: .getContextClassLoader();
179: if (loader == null) {
180: loader = this .getClass().getClassLoader();
181: }
182: Class clazz = loader.loadClass(ruleSet);
183: parser.setRuleSet((RuleSet) clazz.newInstance());
184: } catch (Exception e) {
185: throw new ServletException(
186: "Exception initalizing RuleSet '" + ruleSet
187: + "' instance", e);
188: }
189: }
190:
191: // Parse the resources specified in our init parameters (if any)
192: if (attr == null) {
193: ChainResources.parseClassResources(classResources, parser);
194: ChainResources.parseWebResources(context, webResources,
195: parser);
196: } else {
197: ChainResources.parseClassResources(catalog, classResources,
198: parser);
199: ChainResources.parseWebResources(catalog, context,
200: webResources, parser);
201: }
202:
203: // Expose the completed catalog (if requested)
204: if (attr != null) {
205: context.setAttribute(attr, catalog);
206: }
207:
208: }
209:
210: /**
211: * <p>Does nothing; this servlet's only purpose is to initialize a Chain
212: * and store it in the servlet context.</p>
213: *
214: * @param request the request issued by the client
215: * @param response the response to be returned to the cliengt
216: *
217: * @throws javax.servlet.ServletException (this exception is never thrown)
218: * @throws java.io.IOException (this exception is never thrown)
219: */
220: public void service(HttpServletRequest request,
221: HttpServletResponse response) throws ServletException,
222: IOException {
223:
224: // do nothing
225:
226: }
227:
228: }
|