1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.seasar.cubby.filter;
18
19 import static org.seasar.cubby.CubbyConstants.ATTR_FILTER_CHAIN;
20 import static org.seasar.cubby.CubbyConstants.*;
21 import static org.seasar.cubby.CubbyConstants.ATTR_ROUTING;
22 import static org.seasar.cubby.internal.util.LogMessages.format;
23
24 import java.io.IOException;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.StringTokenizer;
31 import java.util.regex.Matcher;
32 import java.util.regex.Pattern;
33
34 import javax.servlet.Filter;
35 import javax.servlet.FilterChain;
36 import javax.servlet.FilterConfig;
37 import javax.servlet.ServletException;
38 import javax.servlet.ServletRequest;
39 import javax.servlet.ServletResponse;
40 import javax.servlet.http.HttpServletRequest;
41 import javax.servlet.http.HttpServletResponse;
42
43 import org.seasar.cubby.CubbyConstants;
44 import org.seasar.cubby.controller.MessagesBehaviour;
45 import org.seasar.cubby.internal.controller.ActionProcessor;
46 import org.seasar.cubby.internal.controller.ActionResultWrapper;
47 import org.seasar.cubby.internal.controller.ThreadContext;
48 import org.seasar.cubby.internal.controller.impl.ActionProcessorImpl;
49 import org.seasar.cubby.internal.util.RequestUtils;
50 import org.seasar.cubby.internal.util.StringUtils;
51 import org.seasar.cubby.plugin.Plugin;
52 import org.seasar.cubby.plugin.PluginRegistry;
53 import org.seasar.cubby.plugin.RequestProcessingInvocation;
54 import org.seasar.cubby.plugin.RoutingInvocation;
55 import org.seasar.cubby.routing.PathInfo;
56 import org.seasar.cubby.routing.PathResolver;
57 import org.seasar.cubby.routing.Routing;
58 import org.seasar.cubby.spi.ContainerProvider;
59 import org.seasar.cubby.spi.PathResolverProvider;
60 import org.seasar.cubby.spi.ProviderFactory;
61 import org.seasar.cubby.spi.RequestParserProvider;
62 import org.seasar.cubby.spi.container.Container;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
65
66
67
68
69
70
71
72
73
74
75 public class CubbyFilter implements Filter {
76
77
78 private static final Logger logger = LoggerFactory
79 .getLogger(CubbyFilter.class);
80
81
82 public static final String IGNORE_PATH_PATTERN = "ignorePathPattern";
83
84
85 private final List<Pattern> ignorePathPatterns = new ArrayList<Pattern>();
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119 public void init(final FilterConfig config) throws ServletException {
120 final String ignorePathPatternString = config
121 .getInitParameter(IGNORE_PATH_PATTERN);
122 if (!StringUtils.isEmpty(ignorePathPatternString)) {
123
124 for (final StringTokenizer tokenizer = new StringTokenizer(
125 ignorePathPatternString, ","); tokenizer.hasMoreTokens();) {
126 final String token = tokenizer.nextToken();
127 final Pattern pattern = Pattern.compile(token);
128 ignorePathPatterns.add(pattern);
129 }
130 }
131 }
132
133
134
135
136 public void destroy() {
137 }
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160 public void doFilter(final ServletRequest req, final ServletResponse res,
161 final FilterChain chain) throws IOException, ServletException {
162 final HttpServletRequest request = (HttpServletRequest) req;
163 final HttpServletResponse response = (HttpServletResponse) res;
164
165 final String path = RequestUtils.getPath(request);
166 if (logger.isDebugEnabled()) {
167 logger.debug(format("DCUB0006", path));
168 }
169
170 final PathInfo pathInfo = findPathInfo(request, response, path,
171 ignorePathPatterns);
172
173 if (pathInfo != null) {
174 setupWrapeeRequest(request);
175 request.setAttribute(ATTR_FILTER_CHAIN, chain);
176 try {
177 processRequest(request, response, pathInfo);
178 } catch (final Exception e) {
179 if (e instanceof IOException) {
180 throw (IOException) e;
181 } else if (e instanceof ServletException) {
182 throw (ServletException) e;
183 } else {
184 throw new ServletException(e);
185 }
186 }
187 } else {
188 chain.doFilter(request, response);
189 }
190 }
191
192 private void setupWrapeeRequest(final HttpServletRequest request) {
193 final HttpServletRequest wrapeeRequest = (HttpServletRequest) request
194 .getAttribute(ATTR_WRAPEE_REQUEST);
195 if (wrapeeRequest == null) {
196 request.setAttribute(ATTR_WRAPEE_REQUEST, request);
197 }
198 }
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224 protected PathInfo findPathInfo(final HttpServletRequest request,
225 final HttpServletResponse response, final String path,
226 List<Pattern> ignorePathPatterns) {
227 final PathInfo pathInfo;
228 final Routing routing = RequestUtils
229 .getAttribute(request, ATTR_ROUTING);
230 if (routing != null) {
231 request.removeAttribute(ATTR_ROUTING);
232 pathInfo = new ForwardFromActionPathInfo(routing);
233 } else if (isIgnorePath(path, ignorePathPatterns)) {
234 pathInfo = null;
235 } else {
236 final PathResolver pathResolver = createPathResolver();
237 pathInfo = invokeRouting(request, response, path, pathResolver);
238 }
239 return pathInfo;
240 }
241
242
243
244
245
246
247
248
249
250
251
252 private static boolean isIgnorePath(final String path,
253 final List<Pattern> ignorePathPatterns) {
254 for (final Pattern pattern : ignorePathPatterns) {
255 final Matcher matcher = pattern.matcher(path);
256 if (matcher.matches()) {
257 return true;
258 }
259 }
260 return false;
261 }
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277 protected PathInfo invokeRouting(final HttpServletRequest request,
278 final HttpServletResponse response, final String path,
279 final PathResolver pathResolver) {
280 final RoutingInvocation routingInvocation = new RoutingInvocationImpl(
281 path, pathResolver, request, response);
282 try {
283 return routingInvocation.proceed();
284 } catch (final Exception e) {
285 logger.warn("routing failed.", e);
286 return null;
287 }
288 }
289
290
291
292
293
294
295 static class RoutingInvocationImpl implements RoutingInvocation {
296
297
298 private final String path;
299
300
301 private final PathResolver pathResolver;
302
303
304 private final HttpServletRequest request;
305
306
307 private final HttpServletResponse response;
308
309
310 private final Iterator<Plugin> pluginsIterator;
311
312
313
314
315
316
317
318
319
320
321
322
323
324 public RoutingInvocationImpl(final String path,
325 final PathResolver pathResolver,
326 final HttpServletRequest request,
327 final HttpServletResponse response) {
328 this.path = path;
329 this.pathResolver = pathResolver;
330 this.request = request;
331 this.response = response;
332
333 final PluginRegistry pluginRegistry = PluginRegistry.getInstance();
334 this.pluginsIterator = pluginRegistry.getPlugins().iterator();
335 }
336
337
338
339
340 public PathInfo proceed() throws Exception {
341 if (pluginsIterator.hasNext()) {
342 final Plugin plugin = pluginsIterator.next();
343 return plugin.invokeRouting(this);
344 } else {
345 final PathInfo pathInfo = pathResolver.getPathInfo(path,
346 request.getMethod(), request.getCharacterEncoding());
347 return pathInfo;
348 }
349 }
350
351
352
353
354 public String getPath() {
355 return path;
356 }
357
358
359
360
361 public PathResolver getPathResolver() {
362 return pathResolver;
363 }
364
365
366
367
368 public HttpServletRequest getRequest() {
369 return request;
370 }
371
372
373
374
375 public HttpServletResponse getResponse() {
376 return response;
377 }
378
379 }
380
381
382
383
384
385
386
387
388
389
390
391
392
393 protected void processRequest(final HttpServletRequest request,
394 final HttpServletResponse response, final PathInfo pathInfo)
395 throws Exception {
396 final HttpServletRequest wrappedRequest = new CubbyHttpServletRequestWrapper(
397 this, request, pathInfo.getURIParameters());
398 final RequestProcessingInvocation invocation = new RequestProcessingInvocationImpl(
399 this, wrappedRequest, response, pathInfo);
400 invocation.proceed();
401 }
402
403
404
405
406
407
408
409
410 protected Map<String, Object[]> parseRequest(
411 final HttpServletRequest request) {
412 final RequestParserProvider requestParserProvider = ProviderFactory
413 .get(RequestParserProvider.class);
414 final Map<String, Object[]> parameterMap = requestParserProvider
415 .getParameterMap(request);
416 return parameterMap;
417 }
418
419
420
421
422
423
424 static class RequestProcessingInvocationImpl implements
425 RequestProcessingInvocation {
426
427
428 private CubbyFilter cubbyFilter;
429
430
431 private final HttpServletRequest request;
432
433
434 private final HttpServletResponse response;
435
436
437 private final PathInfo pathInfo;
438
439
440 private final Iterator<Plugin> pluginsIterator;
441
442
443
444
445
446
447
448
449
450
451
452
453
454 public RequestProcessingInvocationImpl(final CubbyFilter cubbyFilter,
455 final HttpServletRequest request,
456 final HttpServletResponse response, final PathInfo pathInfo) {
457 this.cubbyFilter = cubbyFilter;
458 this.request = request;
459 this.response = response;
460 this.pathInfo = pathInfo;
461
462 final PluginRegistry pluginRegistry = PluginRegistry.getInstance();
463 this.pluginsIterator = pluginRegistry.getPlugins().iterator();
464 }
465
466
467
468
469 public Void proceed() throws Exception {
470 if (pluginsIterator.hasNext()) {
471 final Plugin plugin = pluginsIterator.next();
472 plugin.invokeRequestProcessing(this);
473 } else {
474 final HttpServletRequest request = getRequest();
475 final Map<String, Object[]> parameterMap = cubbyFilter
476 .parseRequest(request);
477 request.setAttribute(ATTR_PARAMS, parameterMap);
478 final Routing routing = pathInfo.dispatch(parameterMap);
479 ThreadContext.enter(request, response);
480 try {
481 final ActionProcessor actionProcessor = cubbyFilter
482 .createActionProcessor();
483 final ActionResultWrapper actionResultWrapper = actionProcessor
484 .process(request, response, routing);
485 actionResultWrapper.execute(request, response);
486 } finally {
487 ThreadContext.exit();
488 }
489 }
490 return null;
491 }
492
493
494
495
496 public HttpServletRequest getRequest() {
497 return request;
498 }
499
500
501
502
503 public HttpServletResponse getResponse() {
504 return response;
505 }
506
507
508
509
510 public PathInfo getPathInfo() {
511 return pathInfo;
512 }
513
514 }
515
516
517
518
519
520
521 protected PathResolver createPathResolver() {
522 final PathResolverProvider pathResolverProvider = ProviderFactory
523 .get(PathResolverProvider.class);
524 final PathResolver pathResolver = pathResolverProvider
525 .getPathResolver();
526 return pathResolver;
527 }
528
529
530
531
532
533
534 protected ActionProcessor createActionProcessor() {
535 final ActionProcessor actionProcessor = new ActionProcessorImpl();
536 return actionProcessor;
537 }
538
539
540
541
542
543
544 protected MessagesBehaviour createMessagesBehaviour() {
545 final Container container = ProviderFactory
546 .get(ContainerProvider.class).getContainer();
547 final MessagesBehaviour messagesBehaviour = container
548 .lookup(MessagesBehaviour.class);
549 return messagesBehaviour;
550 }
551
552
553
554
555
556
557 static class ForwardFromActionPathInfo implements PathInfo {
558
559 private final Routing routing;
560
561 private final Map<String, String[]> uriParameters = Collections
562 .emptyMap();
563
564 public ForwardFromActionPathInfo(final Routing routing) {
565 this.routing = routing;
566 }
567
568
569
570
571 public Map<String, String[]> getURIParameters() {
572 return uriParameters;
573 }
574
575
576
577
578 public Routing dispatch(final Map<String, Object[]> parameterMap) {
579 return routing;
580 }
581
582 }
583
584 }