1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.struts.chain;
22
23 import org.apache.commons.beanutils.ConstructorUtils;
24 import org.apache.commons.chain.Catalog;
25 import org.apache.commons.chain.CatalogFactory;
26 import org.apache.commons.chain.Command;
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.struts.action.ActionServlet;
30 import org.apache.struts.action.RequestProcessor;
31 import org.apache.struts.chain.contexts.ActionContext;
32 import org.apache.struts.chain.contexts.ServletActionContext;
33 import org.apache.struts.config.ControllerConfig;
34 import org.apache.struts.config.ModuleConfig;
35 import org.apache.struts.upload.MultipartRequestWrapper;
36 import org.apache.struts.util.RequestUtils;
37
38 import javax.servlet.ServletContext;
39 import javax.servlet.ServletException;
40 import javax.servlet.UnavailableException;
41 import javax.servlet.http.HttpServletRequest;
42 import javax.servlet.http.HttpServletResponse;
43
44 import java.io.IOException;
45
46 import java.lang.reflect.Constructor;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 public class ComposableRequestProcessor extends RequestProcessor {
71
72
73
74
75
76
77 private static final Class[] SERVLET_ACTION_CONTEXT_CTOR_SIGNATURE =
78 new Class[] {
79 ServletContext.class, HttpServletRequest.class,
80 HttpServletResponse.class
81 };
82
83
84
85
86
87 public static final String ACTION_CONTEXT_CLASS = "ACTION_CONTEXT_CLASS";
88
89
90
91
92 protected static final Log LOG =
93 LogFactory.getLog(ComposableRequestProcessor.class);
94
95
96
97
98
99 protected CatalogFactory catalogFactory = null;
100
101
102
103
104
105 protected Catalog catalog = null;
106
107
108
109
110 protected Command command = null;
111
112
113
114
115
116 private Class actionContextClass;
117
118
119
120
121
122 private Constructor servletActionContextConstructor = null;
123
124
125
126
127
128
129 public void destroy() {
130 super.destroy();
131 catalogFactory = null;
132 catalog = null;
133 command = null;
134 actionContextClass = null;
135 servletActionContextConstructor = null;
136 }
137
138
139
140
141
142
143
144
145 public void init(ActionServlet servlet, ModuleConfig moduleConfig)
146 throws ServletException {
147 LOG.info(
148 "Initializing composable request processor for module prefix '"
149 + moduleConfig.getPrefix() + "'");
150 super.init(servlet, moduleConfig);
151
152 initCatalogFactory(servlet, moduleConfig);
153
154 ControllerConfig controllerConfig = moduleConfig.getControllerConfig();
155
156 String catalogName = controllerConfig.getCatalog();
157
158 catalog = this.catalogFactory.getCatalog(catalogName);
159
160 if (catalog == null) {
161 throw new ServletException("Cannot find catalog '" + catalogName
162 + "'");
163 }
164
165 String commandName = controllerConfig.getCommand();
166
167 command = catalog.getCommand(commandName);
168
169 if (command == null) {
170 throw new ServletException("Cannot find command '" + commandName
171 + "'");
172 }
173
174 this.setActionContextClassName(controllerConfig.getProperty(
175 ACTION_CONTEXT_CLASS));
176 }
177
178
179
180
181
182
183
184
185
186 private void setActionContextClass(Class actionContextClass) {
187 this.actionContextClass = actionContextClass;
188
189 if (actionContextClass != null) {
190 this.servletActionContextConstructor =
191 ConstructorUtils.getAccessibleConstructor(actionContextClass,
192 SERVLET_ACTION_CONTEXT_CTOR_SIGNATURE);
193 } else {
194 this.servletActionContextConstructor = null;
195 }
196 }
197
198
199
200
201
202
203
204
205
206
207
208 private void setActionContextClassName(String className)
209 throws ServletException {
210 if ((className != null) && (className.trim().length() > 0)) {
211 if (LOG.isDebugEnabled()) {
212 LOG.debug(
213 "setActionContextClassName: requested context class: "
214 + className);
215 }
216
217 try {
218 Class actionContextClass =
219 RequestUtils.applicationClass(className);
220
221 if (!ActionContext.class.isAssignableFrom(actionContextClass)) {
222 throw new UnavailableException("ActionContextClass " + "["
223 + className + "]"
224 + " must implement ActionContext interface.");
225 }
226
227 this.setActionContextClass(actionContextClass);
228 } catch (ClassNotFoundException e) {
229 throw new UnavailableException("ActionContextClass "
230 + className + " not found.");
231 }
232 } else {
233 if (LOG.isDebugEnabled()) {
234 LOG.debug("setActionContextClassName: no className specified");
235 }
236
237 this.setActionContextClass(null);
238 }
239 }
240
241
242
243
244
245
246
247
248
249
250
251 protected void initCatalogFactory(ActionServlet servlet,
252 ModuleConfig moduleConfig) {
253 if (this.catalogFactory != null) {
254 return;
255 }
256
257 this.catalogFactory = CatalogFactory.getInstance();
258 }
259
260
261
262
263
264
265
266
267
268
269 public void process(HttpServletRequest request, HttpServletResponse response)
270 throws IOException, ServletException {
271
272 request = processMultipart(request);
273
274
275 ActionContext context = contextInstance(request, response);
276
277
278 try {
279 if (LOG.isDebugEnabled()) {
280 LOG.debug("Using processing chain for this request");
281 }
282
283 command.execute(context);
284 } catch (Exception e) {
285
286 throw new ServletException(e);
287 }
288
289
290 context.release();
291 }
292
293
294
295
296
297
298
299
300
301
302
303
304 protected ActionContext contextInstance(HttpServletRequest request,
305 HttpServletResponse response)
306 throws ServletException {
307 ActionContext context =
308 createActionContextInstance(getServletContext(), request, response);
309
310 initializeActionContext(context);
311
312 return context;
313 }
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334 protected ActionContext createActionContextInstance(
335 ServletContext servletContext, HttpServletRequest request,
336 HttpServletResponse response)
337 throws ServletException {
338 if (this.actionContextClass == null) {
339 return new ServletActionContext(servletContext, request, response);
340 }
341
342 try {
343 if (this.servletActionContextConstructor == null) {
344 return (ActionContext) this.actionContextClass.newInstance();
345 }
346
347 return (ActionContext) this.servletActionContextConstructor
348 .newInstance(new Object[] { servletContext, request, response });
349 } catch (Exception e) {
350 throw new ServletException(
351 "Error creating ActionContext instance of type "
352 + this.actionContextClass, e);
353 }
354 }
355
356
357
358
359
360
361
362
363
364
365
366 protected void initializeActionContext(ActionContext context) {
367 if (context instanceof ServletActionContext) {
368 ((ServletActionContext) context).setActionServlet(this.servlet);
369 }
370
371 context.setModuleConfig(this.moduleConfig);
372 }
373
374
375
376
377
378
379
380
381 protected HttpServletRequest processMultipart(HttpServletRequest request) {
382 if (!"POST".equalsIgnoreCase(request.getMethod())) {
383 return (request);
384 }
385
386 String contentType = request.getContentType();
387
388 if ((contentType != null)
389 && contentType.startsWith("multipart/form-data")) {
390 return (new MultipartRequestWrapper(request));
391 } else {
392 return (request);
393 }
394 }
395
396
397
398
399
400
401
402
403
404 public void setCatalogFactory(CatalogFactory catalogFactory) {
405 this.catalogFactory = catalogFactory;
406 }
407 }