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 }