View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.chain.web.javax.servlet;
18  
19  import java.io.IOException;
20  
21  import javax.servlet.ServletException;
22  import javax.servlet.http.HttpServletRequest;
23  import javax.servlet.http.HttpServletResponse;
24  
25  import org.apache.commons.chain.Catalog;
26  import org.apache.commons.chain.CatalogFactory;
27  import org.apache.commons.chain.Command;
28  import org.apache.commons.chain.web.javax.ChainServlet;
29  
30  /**
31   * Custom subclass of {@link ChainServlet} that also dispatches incoming
32   * requests to a configurable {@link Command} loaded from the specified
33   * {@link Catalog}.
34   *
35   * <p>In addition to the <em>servlet</em> init parameters supported by
36   * {@link ChainServlet}, this class supports the following additional
37   * parameters:</p>
38   * <ul>
39   * <li><strong>org.apache.commons.chain.CATALOG</strong> - Name of the
40   *     catalog from which to acquire commands to be executed. If not
41   *     specified, the default catalog for this application will be used.</li>
42   * <li><strong>org.apache.commons.chain.COMMAND</strong> - Name of the
43   *     {@link Command} (looked up in our configured {@link Catalog} used
44   *     to process all incoming servlet requests. If not specified,
45   *     defaults to {@code command}.</li>
46   * </ul>
47   *
48   * <p>Also, the {@code org.apache.commons.chain.CONFIG_ATTR}
49   * init parameter is also used to identify the
50   * {@link org.apache.commons.chain.Context} attribute under
51   * which our configured {@link Catalog} will be made available to
52   * {@link Command}s processing our requests, in addition to its definition
53   * of the {@code ServletContext} attribute key under which the
54   * {@link Catalog} is available.</p>
55   */
56  
57  public class ChainProcessor extends ChainServlet {
58      private static final long serialVersionUID = -6817532768031279260L;
59  
60      // ------------------------------------------------------ Manifest Constants
61  
62      /**
63       * The name of the servlet init parameter containing the name of the
64       * {@link Catalog} to use for processing incoming requests.
65       */
66      public static final String CATALOG =
67          "org.apache.commons.chain.CATALOG";
68  
69      /**
70       * The default request attribute under which we expose the
71       * {@link Catalog} being used to subordinate {@link Command}s.
72       */
73      public static final String CATALOG_DEFAULT =
74          "org.apache.commons.chain.CATALOG";
75  
76      /**
77       * The name of the servlet init parameter containing the name of the
78       * {@link Command} (loaded from our configured {@link Catalog} to use
79       * for processing each incoming request.
80       */
81      public static final String COMMAND =
82          "org.apache.commons.chain.COMMAND";
83  
84      /**
85       * The default command name.
86       */
87      private static final String COMMAND_DEFAULT = "command";
88  
89      // ------------------------------------------------------ Instance Variables
90  
91      /**
92       * The name of the context attribute under which our {@link Catalog}
93       * is stored. This value is also used as the name of the context
94       * attribute under which the catalog is exposed to commands. If not
95       * specified, we will look up commands in the appropriate
96       * {@link Catalog} retrieved from our {@link CatalogFactory}
97       */
98      private String attribute = null;
99  
100     /**
101      * The name of the {@link Catalog} to retrieve from the
102      * {@link CatalogFactory} for this application, or {@code null}
103      * to select the default {@link Catalog}.
104      */
105     private String catalog = null;
106 
107     /**
108      * The name of the {@link Command} to be executed for each incoming
109      * request.
110      */
111     private String command = null;
112 
113     // ------------------------------------------------------------ Constructors
114 
115     /**
116      * The Default-Constructor for this class.
117      */
118     public ChainProcessor() {
119     }
120 
121     // --------------------------------------------------------- Servlet Methods
122 
123     /**
124      * Clean up as this application is shut down.
125      */
126     @Override
127     public void destroy() {
128         super.destroy();
129         attribute = null;
130         catalog = null;
131         command = null;
132     }
133 
134     /**
135      * Cache the name of the command we should execute for each request.
136      *
137      * @throws ServletException if an initialization error occurs
138      */
139     @Override
140     public void init() throws ServletException {
141         super.init();
142         attribute = getServletConfig().getInitParameter(CONFIG_ATTR);
143         catalog = getServletConfig().getInitParameter(CATALOG);
144         command = getServletConfig().getInitParameter(COMMAND);
145         if (command == null) {
146             command = COMMAND_DEFAULT;
147         }
148     }
149 
150     /**
151      * Configure a {@link ServletWebContext} for the current request, and
152      * pass it to the {@code execute()} method of the specified
153      * {@link Command}, loaded from our configured {@link Catalog}.
154      *
155      * @param request The request we are processing
156      * @param response The response we are creating
157      *
158      * @throws IOException if an input/output error occurs
159      * @throws ServletException if a servlet exception occurs
160      */
161     @Override
162     public void service(HttpServletRequest request,
163                         HttpServletResponse response)
164         throws IOException, ServletException {
165 
166         ServletWebContext context =
167             new ServletWebContext(getServletContext(), request, response);
168         Catalog<ServletWebContext> theCatalog = null;
169         if (attribute != null) {
170             @SuppressWarnings("unchecked")
171             Catalog<ServletWebContext> catalog = (Catalog<ServletWebContext>)
172                     getServletContext().getAttribute(this.attribute);
173             theCatalog = catalog;
174         } else if (catalog != null) {
175             theCatalog = CatalogFactory.<ServletWebContext>getInstance().getCatalog(catalog);
176         } else {
177             theCatalog = CatalogFactory.<ServletWebContext>getInstance().getCatalog();
178         }
179         if (attribute == null) {
180             request.setAttribute(CATALOG_DEFAULT, theCatalog);
181         }
182         Command<ServletWebContext> command = theCatalog.getCommand(this.command);
183         try {
184             command.execute(context);
185         } catch (Exception e) {
186             throw new ServletException(e);
187         }
188     }
189 }