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.servlet;
018    
019    
020    import java.io.IOException;
021    import javax.servlet.ServletException;
022    import javax.servlet.http.HttpServletRequest;
023    import javax.servlet.http.HttpServletResponse;
024    import org.apache.commons.chain.Catalog;
025    import org.apache.commons.chain.CatalogFactory;
026    import org.apache.commons.chain.Command;
027    import org.apache.commons.chain.web.ChainServlet;
028    
029    
030    /**
031     * <p>Custom subclass of {@link ChainServlet} that also dispatches incoming
032     * requests to a configurable {@link Command} loaded from the specified
033     * {@link Catalog}.</p>
034     *
035     * <p>In addition to the <em>servlet</em> init parameters supported by
036     * {@link ChainServlet}, this class supports the following additional
037     * parameters:</p>
038     * <ul>
039     * <li><strong>org.apache.commons.chain.CATALOG</strong> - Name of the
040     *     catalog from which to acquire commands to be executed.  If not
041     *     specified, the default catalog for this application will be used.</li>
042     * <li><strong>org.apache.commons.chain.COMMAND</strong> - Name of the
043     *     {@link Command} (looked up in our configured {@link Catalog} used
044     *     to process all incoming servlet requests.  If not specified,
045     *     defaults to <code>command</code>.</li>
046     * </ul>
047     *
048     * <p>Also, the <code>org.apache.commons.chain.CONFIG_ATTR</code>
049     * init parameter is also used to identify the
050     * {@link org.apache.commons.chain.Context} attribute under
051     * which our configured {@link Catalog} will be made available to
052     * {@link Command}s processing our requests, in addition to its definition
053     * of the <code>ServletContext</code> attribute key under which the
054     * {@link Catalog} is available.</p>
055     */
056    
057    public class ChainProcessor extends ChainServlet {
058    
059    
060        // ------------------------------------------------------ Manifest Constants
061    
062    
063        /**
064         * <p>The name of the servlet init parameter containing the name of the
065         * {@link Catalog} to use for processing incoming requests.</p>
066         */
067        public static final String CATALOG =
068            "org.apache.commons.chain.CATALOG";
069    
070    
071        /**
072         * <p>The default request attribute under which we expose the
073         * {@link Catalog} being used to subordinate {@link Command}s.</p>
074         */
075        public static final String CATALOG_DEFAULT =
076            "org.apache.commons.chain.CATALOG";
077    
078    
079        /**
080         * <p>The name of the servlet init parameter containing the name of the
081         * {@link Command} (loaded from our configured {@link Catalog} to use
082         * for processing each incoming request.</p>
083         */
084        public static final String COMMAND =
085            "org.apache.commons.chain.COMMAND";
086    
087    
088        /**
089         * <p>The default command name.</p>
090         */
091        private static final String COMMAND_DEFAULT = "command";
092    
093    
094        // ------------------------------------------------------ Instance Variables
095    
096    
097        /**
098         * <p>The name of the context attribute under which our {@link Catalog}
099         * is stored.  This value is also used as the name of the
100         * context attribute under which the catalog is exposed to commands.
101         * If not specified, we will look up commands in the appropriate
102         * {@link Catalog} retrieved from our {@link CatalogFactory}.</p>
103         */
104        private String attribute = null;
105    
106    
107        /**
108         * <p>The name of the {@link Catalog} to retrieve from the
109         * {@link CatalogFactory} for this application, or <code>null</code>
110         * to select the default {@link Catalog}.</p>
111         */
112        private String catalog = null;
113    
114    
115        /**
116         * <p>The name of the {@link Command} to be executed for each incoming
117         * request.</p>
118         */
119        private String command = null;
120    
121    
122        // --------------------------------------------------------- Servlet Methods
123    
124    
125        /**
126         * <p>Clean up as this application is shut down.</p>
127         */
128        public void destroy() {
129    
130            super.destroy();
131            attribute = null;
132            catalog = null;
133            command = null;
134    
135        }
136    
137    
138        /**
139         * <p>Cache the name of the command we should execute for each request.</p>
140         *
141         * @exception ServletException if an initialization error occurs
142         */
143        public void init() throws ServletException {
144    
145            super.init();
146            attribute = getServletConfig().getInitParameter(CONFIG_ATTR);
147            catalog = getServletConfig().getInitParameter(CATALOG);
148            command = getServletConfig().getInitParameter(COMMAND);
149            if (command == null) {
150                command = COMMAND_DEFAULT;
151            }
152    
153        }
154    
155    
156        /**
157         * <p>Configure a {@link ServletWebContext} for the current request, and
158         * pass it to the <code>execute()</code> method of the specified
159         * {@link Command}, loaded from our configured {@link Catalog}.</p>
160         *
161         * @param request The request we are processing
162         * @param response The response we are creating
163         *
164         * @exception IOException if an input/output error occurs
165         * @exception ServletException if a servlet exception occurs
166         */
167        public void service(HttpServletRequest request,
168                            HttpServletResponse response)
169            throws IOException, ServletException {
170    
171            ServletWebContext context =
172                new ServletWebContext(getServletContext(), request, response);
173            Catalog theCatalog = null;
174            if (attribute != null) {
175                theCatalog = (Catalog) getServletContext().getAttribute
176                    (this.attribute);
177            } else if (catalog != null) {
178                theCatalog = CatalogFactory.getInstance().getCatalog(catalog);
179            } else {
180                theCatalog = CatalogFactory.getInstance().getCatalog();
181            }
182            if (attribute == null) {
183                request.setAttribute(CATALOG_DEFAULT, theCatalog);
184            }
185            Command command = theCatalog.getCommand(this.command);
186            try {
187                command.execute(context);
188            } catch (Exception e) {
189                throw new ServletException(e);
190            }
191    
192        }
193    
194    
195    }