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 */
017package org.apache.commons.chain.web.javax;
018
019import java.io.IOException;
020
021import javax.servlet.ServletConfig;
022import javax.servlet.ServletContext;
023import javax.servlet.ServletException;
024import javax.servlet.http.HttpServlet;
025import javax.servlet.http.HttpServletRequest;
026import javax.servlet.http.HttpServletResponse;
027
028import org.apache.commons.chain.Catalog;
029import org.apache.commons.chain.CatalogFactory;
030import org.apache.commons.chain.config.ConfigParser;
031import org.slf4j.Logger;
032import org.slf4j.LoggerFactory;
033
034/**
035 * {@code Servlet} that automatically scans chain configuration files
036 * in the current web application at startup time, and exposes the result in a
037 * {@link Catalog} under a specified servlet context attribute. The following
038 * <em>servlet</em> init parameters are utilized:
039 * <ul>
040 * <li><strong>org.apache.commons.chain.CONFIG_CLASS_RESOURCE</strong> -
041 *     comma-delimited list of chain configuration resources to be loaded
042 *     via {@code ClassLoader.getResource()} calls. If not specified,
043 *     no class loader resources will be loaded.</li>
044 * <li><strong>org.apache.commons.chain.CONFIG_WEB_RESOURCE</strong> -
045 *     comma-delimited list of chain configuration webapp resources
046 *     to be loaded. If not specified, no web application resources
047 *     will be loaded.</li>
048 * <li><strong>org.apache.commons.chain.CONFIG_ATTR</strong> -
049 *     Name of the servlet context attribute under which the
050 *     resulting {@link Catalog} will be created or updated.
051 *     If not specified, it is expected that parsed resources will
052 *     contain {@code &lt;catalog&gt;} elements (which will
053 *     cause registration of the created {@link Catalog}s into
054 *     the {@link CatalogFactory} for this application, and no
055 *     servet context attribute will be created.
056 *     <strong>NOTE</strong> - This parameter is deprecated.</li>
057 * <li><strong>org.apache.commons.chain.RULE_SET</strong> -
058 *     Fully qualified class name of a Digester {@code RuleSet}
059 *     implementation to use for parsing configuration resources (this
060 *     class must have a public zero-args constructor). If not defined,
061 *     the standard {@code RuleSet} implementation will be used.</li>
062 * </ul>
063 *
064 * <p>When a web application that has configured this servlet is
065 * started, it will acquire the {@link Catalog} under the specified servlet
066 * context attribute key, creating a new one if there is none already there.
067 * This {@link Catalog} will then be populated by scanning configuration
068 * resources from the following sources (loaded in this order):</p>
069 * <ul>
070 * <li>Resources loaded from specified resource paths from the
071 *     webapp's class loader (via {@code ClassLoader.getResource()}).</li>
072 * <li>Resources loaded from specified resource paths in the web application
073 *     archive (via {@code ServetContext.getResource()}).</li>
074 * </ul>
075 *
076 * <p>If no attribute key is specified, on the other hand, parsed configuration
077 * resources are expected to contain {@code &lt;catalog&gt;} elements,
078 * and the catalogs will be registered with the {@link CatalogFactory}
079 * for this web application.</p>
080 *
081 * <p>This class runs on Servlet 2.2 or later. If you are running on a
082 * Servlet 2.3 or later system, you should also consider using
083 * {@link ChainListener} to initialize your {@link Catalog}. Note that
084 * {@link ChainListener} uses parameters of the same names, but they are
085 * <em>context</em> init parameters instead of <em>servlet</em> init
086 * parameters. Because of this, you can use both facilities in the
087 * same application, if desired.</p>
088 *
089 * @author Matthew J. Sgarlata
090 * @author Craig R. McClanahan
091 * @author Ted Husted
092 */
093public class ChainServlet extends HttpServlet {
094    private static final long serialVersionUID = 4833344945293509188L;
095
096    // ------------------------------------------------------ Manifest Constants
097
098    /**
099     * The name of the context init parameter containing the name of the
100     * servlet context attribute under which our resulting {@link Catalog}
101     * will be stored.
102     */
103    public static final String CONFIG_ATTR = ChainInit.CONFIG_ATTR;
104
105    /**
106     * The name of the context init parameter containing a comma-delimited
107     * list of class loader resources to be scanned.
108     */
109    public static final String CONFIG_CLASS_RESOURCE =
110        ChainInit.CONFIG_CLASS_RESOURCE;
111
112    /**
113     * The name of the context init parameter containing a comma-delimited
114     * list of web application resources to be scanned.
115     */
116    public static final String CONFIG_WEB_RESOURCE =
117        ChainInit.CONFIG_WEB_RESOURCE;
118
119    /**
120     * The name of the context init parameter containing the fully
121     * qualified class name of the {@code RuleSet} implementation
122     * for configuring our {@link ConfigParser}.
123     */
124    public static final String RULE_SET = ChainInit.RULE_SET;
125
126    // ------------------------------------------------------------ Constructors
127
128    /**
129     * The Default-Constructor for this class.
130     */
131    public ChainServlet() {
132    }
133
134    // --------------------------------------------------------- Servlet Methods
135
136    /**
137     * Clean up after ourselves as this application shuts down.
138     */
139    @Override
140    public void destroy() {
141        final ServletConfig config = getServletConfig();
142        final ServletContext context = getServletContext();
143        ChainInit.destroy(context, config.getInitParameter(CONFIG_ATTR));
144    }
145
146    /**
147     * Create (if necessary) and configure a {@link Catalog} from the
148     * servlet init parameters that have been specified.
149     *
150     * @throws ServletException if the servlet could not be initialized
151     */
152    @Override
153    public void init() throws ServletException {
154        final Logger logger = LoggerFactory.getLogger(ChainServlet.class);
155        final ServletConfig config = getServletConfig();
156        final ServletContext context = getServletContext();
157        logger.info("Initializing chain servlet '{}'", config.getServletName());
158
159        ChainInit.initialize(context, config.getInitParameter(CONFIG_ATTR), logger, false);
160    }
161
162    /**
163     * Does nothing; this servlet's only purpose is to initialize a Chain
164     * and store it in the servlet context.
165     *
166     * @param request the request issued by the client
167     * @param response the response to be returned to the cliengt
168     *
169     * @throws ServletException this exception is never thrown
170     * @throws IOException this exception is never thrown
171     */
172    @Override
173    public void service(HttpServletRequest request,
174                        HttpServletResponse response)
175        throws ServletException, IOException {
176
177          // do nothing
178    }
179}