/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.chain2.web;

import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.chain2.Catalog;
import org.apache.commons.chain2.config.xml.XmlConfigParser;
import org.apache.commons.chain2.impl.CatalogBase;
import org.apache.commons.chain2.impl.CatalogFactoryBase;
import org.apache.commons.chain2.web.servlet.ServletWebContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * <p><code>Servlet</code> that automatically scans chain configuration files
 * in the current web application at startup time, and exposes the result in a
 * {@link Catalog} under a specified servlet context attribute.  The following
 * <em>servlet</em> init parameters are utilized:</p>
 * <ul>
 * <li><strong>org.apache.commons.chain2.CONFIG_CLASS_RESOURCE</strong> -
 *     comma-delimited list of chain configuration resources to be loaded
 *     via <code>ClassLoader.getResource()</code> calls.  If not specified,
 *     no class loader resources will be loaded.</li>
 * <li><strong>org.apache.commons.chain2.CONFIG_WEB_RESOURCE</strong> -
 *     comma-delimited list of chain configuration webapp resources
 *     to be loaded.  If not specified, no web application resources
 *     will be loaded.</li>
 * <li><strong>org.apache.commons.chain2.CONFIG_ATTR</strong> -
 *     Name of the servlet context attribute under which the
 *     resulting {@link Catalog} will be created or updated.
 *     If not specified, it is expected that parsed resources will
 *     contain <code>&lt;catalog&gt;</code> elements (which will
 *     cause registration of the created {@link Catalog}s into
 *     the {@link CatalogFactoryBase} for this application, and no
 *     servet context attribute will be created.
 *     <strong>NOTE</strong> - This parameter is deprecated.</p>
 * <li><strong>org.apache.commons.chain2.RULE_SET</strong> -
 *     Fully qualified class name of a Digester <code>RuleSet</code>
 *     implementation to use for parsing configuration resources (this
 *     class must have a public zero-args constructor).  If not defined,
 *     the standard <code>RuleSet</code> implementation will be used.</li>
 * </ul>
 *
 * <p>When a web application that has configured this servlet is
 * started, it will acquire the {@link Catalog} under the specified servlet
 * context attribute key, creating a new one if there is none already there.
 * This {@link Catalog} will then be populated by scanning configuration
 * resources from the following sources (loaded in this order):</p>
 * <ul>
 * <li>Resources loaded from specified resource paths from the
 *     webapp's class loader (via <code>ClassLoader.getResource()</code>).</li>
 * <li>Resources loaded from specified resource paths in the web application
 *     archive (via <code>ServetContext.getResource()</code>).</li>
 * </ul>
 *
 * <p>If no attribute key is specified, on the other hand, parsed configuration
 * resources are expected to contain <code>&lt;catalog&gt;</code> elements,
 * and the catalogs will be registered with the {@link CatalogFactoryBase}
 * for this web application.</p>
 *
 * <p>This class runs on Servlet 2.2 or later.  If you are running on a
 * Servlet 2.3 or later system, you should also consider using
 * {@link ChainListener} to initialize your {@link Catalog}.  Note that
 * {@link ChainListener} uses parameters of the same names, but they are
 * <em>context</em> init parameters instead of <em>servlet</em> init
 * parameters. Because of this, you can use both facilities in the
 * same application, if desired.</p>
 *
 * @version $Id$
 */
public class ChainServlet extends HttpServlet {
    {
        CatalogFactoryBase.checkForValidConfigurationModule();
    }

    // ------------------------------------------------------ Manifest Constants

    /**
     *
     */
    private static final long serialVersionUID = 20120724L;

    /**
     * <p>The name of the context init parameter containing the name of the
     * servlet context attribute under which our resulting {@link Catalog}
     * will be stored.</p>
     */
    public static final String CONFIG_ATTR =
        "org.apache.commons.chain2.CONFIG_ATTR";

    /**
     * <p>The name of the context init parameter containing a comma-delimited
     * list of class loader resources to be scanned.</p>
     */
    public static final String CONFIG_CLASS_RESOURCE =
        "org.apache.commons.chain2.CONFIG_CLASS_RESOURCE";

    /**
     * <p>The name of the context init parameter containing a comma-delimited
     * list of web application resources to be scanned.</p>
     */
    public static final String CONFIG_WEB_RESOURCE =
        "org.apache.commons.chain2.CONFIG_WEB_RESOURCE";

    /**
     * <p>The name of the context init parameter containing the fully
     * qualified class name of the <code>RuleSet</code> implementation
     * for configuring our {@link XmlConfigParser}.</p>
     */
    public static final String RULE_SET =
        "org.apache.commons.chain2.RULE_SET";

    // --------------------------------------------------------- Servlet Methods

    /**
     * <p>Clean up after ourselves as this application shuts down.</p>
     */
    @Override
    public void destroy() {
        ServletConfig config = getServletConfig();
        ServletContext context = getServletContext();
        String attr = config.getInitParameter(CONFIG_ATTR);
        if (attr != null) {
            context.removeAttribute(attr);
        }
        CatalogFactoryBase.clear();
    }

    /**
     * <p>Create (if necessary) and configure a {@link Catalog} from the
     * servlet init parameters that have been specified.</p>
     *
     * @throws ServletException if the servlet could not be initialized
     */
    @Override
    public void init() throws ServletException {
        Log log = LogFactory.getLog(ChainServlet.class);
        ServletConfig config = getServletConfig();
        ServletContext context = getServletContext();
        if (log.isInfoEnabled()) {
            log.info("Initializing chain servlet '"
                     + config.getServletName() + "'");
        }

        // Retrieve servlet init parameters that we need
        String attr = config.getInitParameter(CONFIG_ATTR);
        String classResources =
            context.getInitParameter(CONFIG_CLASS_RESOURCE);
        String ruleSet = context.getInitParameter(RULE_SET);
        String webResources = context.getInitParameter(CONFIG_WEB_RESOURCE);

        // Retrieve or create the Catalog instance we may be updating
        Catalog<String, Object, ServletWebContext<String, Object>> catalog = null;
        if (attr != null) {
            Object catalogRef = context.getAttribute(attr);

            if (catalogRef == null || !(catalogRef instanceof Catalog)) {
                catalog = new CatalogBase<String, Object, ServletWebContext<String, Object>>();
            } else {
                catalog = (Catalog<String, Object, ServletWebContext<String, Object>>)catalogRef;
            }
        }

        // Construct the configuration resource parser we will use
        ClassLoader cl = Thread.currentThread().getContextClassLoader() == null ?
                this.getClass().getClassLoader() :
                Thread.currentThread().getContextClassLoader();

        XmlConfigParser parser = ruleSet == null ?
                new XmlConfigParser() : new XmlConfigParser(ruleSet, cl);

        // Parse the resources specified in our init parameters (if any)
        if (attr == null) {
            ChainResources.parseClassResources
                (classResources, parser);
            ChainResources.parseWebResources
                (context, webResources, parser);
        } else {
            ChainResources.parseClassResources
                (classResources, parser);
            ChainResources.parseWebResources
                (context, webResources, parser);
        }

        // Expose the completed catalog (if requested)
        if (attr != null) {
            context.setAttribute(attr, catalog);
        }
    }

    /**
     * <p>Does nothing; this servlet's only purpose is to initialize a Chain
     * and store it in the servlet context.</p>
     *
     * @param request the request issued by the client
     * @param response the response to be returned to the cliengt
     *
     * @throws javax.servlet.ServletException (this exception is never thrown)
     * @throws java.io.IOException (this exception is never thrown)
     */
    @Override
    public void service(HttpServletRequest request,
                        HttpServletResponse response)
        throws ServletException, IOException {
          // do nothing
    }

}
