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.ATTR_PARAMS;
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 request.setAttribute(ATTR_FILTER_CHAIN, chain);
175 try {
176 processRequest(request, response, pathInfo);
177 } catch (final Exception e) {
178 if (e instanceof IOException) {
179 throw (IOException) e;
180 } else if (e instanceof ServletException) {
181 throw (ServletException) e;
182 } else {
183 throw new ServletException(e);
184 }
185 }
186 } else {
187 chain.doFilter(request, response);
188 }
189 }
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215 protected PathInfo findPathInfo(final HttpServletRequest request,
216 final HttpServletResponse response, final String path,
217 List<Pattern> ignorePathPatterns) {
218 final PathInfo pathInfo;
219 final Routing routing = RequestUtils
220 .getAttribute(request, ATTR_ROUTING);
221 if (routing != null) {
222 request.removeAttribute(ATTR_ROUTING);
223 pathInfo = new ForwardFromActionPathInfo(routing);
224 } else if (isIgnorePath(path, ignorePathPatterns)) {
225 pathInfo = null;
226 } else {
227 final PathResolver pathResolver = createPathResolver();
228 pathInfo = invokeRouting(request, response, path, pathResolver);
229 }
230 return pathInfo;
231 }
232
233
234
235
236
237
238
239
240
241
242
243 private static boolean isIgnorePath(final String path,
244 final List<Pattern> ignorePathPatterns) {
245 for (final Pattern pattern : ignorePathPatterns) {
246 final Matcher matcher = pattern.matcher(path);
247 if (matcher.matches()) {
248 return true;
249 }
250 }
251 return false;
252 }
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268 protected PathInfo invokeRouting(final HttpServletRequest request,
269 final HttpServletResponse response, final String path,
270 final PathResolver pathResolver) {
271 final RoutingInvocation routingInvocation = new RoutingInvocationImpl(
272 path, pathResolver, request, response);
273 try {
274 return routingInvocation.proceed();
275 } catch (final Exception e) {
276 logger.warn("routing failed.", e);
277 return null;
278 }
279 }
280
281
282
283
284
285
286 static class RoutingInvocationImpl implements RoutingInvocation {
287
288
289 private final String path;
290
291
292 private final PathResolver pathResolver;
293
294
295 private final HttpServletRequest request;
296
297
298 private final HttpServletResponse response;
299
300
301 private final Iterator<Plugin> pluginsIterator;
302
303
304
305
306
307
308
309
310
311
312
313
314
315 public RoutingInvocationImpl(final String path,
316 final PathResolver pathResolver,
317 final HttpServletRequest request,
318 final HttpServletResponse response) {
319 this.path = path;
320 this.pathResolver = pathResolver;
321 this.request = request;
322 this.response = response;
323
324 final PluginRegistry pluginRegistry = PluginRegistry.getInstance();
325 this.pluginsIterator = pluginRegistry.getPlugins().iterator();
326 }
327
328
329
330
331 public PathInfo proceed() throws Exception {
332 if (pluginsIterator.hasNext()) {
333 final Plugin plugin = pluginsIterator.next();
334 return plugin.invokeRouting(this);
335 } else {
336 final PathInfo pathInfo = pathResolver.getPathInfo(path,
337 request.getMethod(), request.getCharacterEncoding());
338 return pathInfo;
339 }
340 }
341
342
343
344
345 public String getPath() {
346 return path;
347 }
348
349
350
351
352 public PathResolver getPathResolver() {
353 return pathResolver;
354 }
355
356
357
358
359 public HttpServletRequest getRequest() {
360 return request;
361 }
362
363
364
365
366 public HttpServletResponse getResponse() {
367 return response;
368 }
369
370 }
371
372
373
374
375
376
377
378
379
380
381
382
383
384 protected void processRequest(final HttpServletRequest request,
385 final HttpServletResponse response, final PathInfo pathInfo)
386 throws Exception {
387 final HttpServletRequest wrappedRequest = new CubbyHttpServletRequestWrapper(
388 this, request, pathInfo.getURIParameters());
389 final RequestProcessingInvocation invocation = new RequestProcessingInvocationImpl(
390 this, wrappedRequest, response, pathInfo);
391 invocation.proceed();
392 }
393
394
395
396
397
398
399
400
401 protected Map<String, Object[]> parseRequest(
402 final HttpServletRequest request) {
403 final RequestParserProvider requestParserProvider = ProviderFactory
404 .get(RequestParserProvider.class);
405 final Map<String, Object[]> parameterMap = requestParserProvider
406 .getParameterMap(request);
407 return parameterMap;
408 }
409
410
411
412
413
414
415 static class RequestProcessingInvocationImpl implements
416 RequestProcessingInvocation {
417
418
419 private CubbyFilter cubbyFilter;
420
421
422 private final HttpServletRequest request;
423
424
425 private final HttpServletResponse response;
426
427
428 private final PathInfo pathInfo;
429
430
431 private final Iterator<Plugin> pluginsIterator;
432
433
434
435
436
437
438
439
440
441
442
443
444
445 public RequestProcessingInvocationImpl(final CubbyFilter cubbyFilter,
446 final HttpServletRequest request,
447 final HttpServletResponse response, final PathInfo pathInfo) {
448 this.cubbyFilter = cubbyFilter;
449 this.request = request;
450 this.response = response;
451 this.pathInfo = pathInfo;
452
453 final PluginRegistry pluginRegistry = PluginRegistry.getInstance();
454 this.pluginsIterator = pluginRegistry.getPlugins().iterator();
455 }
456
457
458
459
460 public Void proceed() throws Exception {
461 if (pluginsIterator.hasNext()) {
462 final Plugin plugin = pluginsIterator.next();
463 plugin.invokeRequestProcessing(this);
464 } else {
465 final HttpServletRequest request = getRequest();
466 final Map<String, Object[]> parameterMap = cubbyFilter
467 .parseRequest(request);
468 request.setAttribute(ATTR_PARAMS, parameterMap);
469 final Routing routing = pathInfo.dispatch(parameterMap);
470 ThreadContext.enter(request, response);
471 try {
472 final ActionProcessor actionProcessor = cubbyFilter
473 .createActionProcessor();
474 final ActionResultWrapper actionResultWrapper = actionProcessor
475 .process(request, response, routing);
476 actionResultWrapper.execute(request, response);
477 } finally {
478 ThreadContext.exit();
479 }
480 }
481 return null;
482 }
483
484
485
486
487 public HttpServletRequest getRequest() {
488 return request;
489 }
490
491
492
493
494 public HttpServletResponse getResponse() {
495 return response;
496 }
497
498
499
500
501 public PathInfo getPathInfo() {
502 return pathInfo;
503 }
504
505 }
506
507
508
509
510
511
512 protected PathResolver createPathResolver() {
513 final PathResolverProvider pathResolverProvider = ProviderFactory
514 .get(PathResolverProvider.class);
515 final PathResolver pathResolver = pathResolverProvider
516 .getPathResolver();
517 return pathResolver;
518 }
519
520
521
522
523
524
525 protected ActionProcessor createActionProcessor() {
526 final ActionProcessor actionProcessor = new ActionProcessorImpl();
527 return actionProcessor;
528 }
529
530
531
532
533
534
535 protected MessagesBehaviour createMessagesBehaviour() {
536 final Container container = ProviderFactory
537 .get(ContainerProvider.class).getContainer();
538 final MessagesBehaviour messagesBehaviour = container
539 .lookup(MessagesBehaviour.class);
540 return messagesBehaviour;
541 }
542
543
544
545
546
547
548 static class ForwardFromActionPathInfo implements PathInfo {
549
550 private final Routing routing;
551
552 private final Map<String, String[]> uriParameters = Collections
553 .emptyMap();
554
555 public ForwardFromActionPathInfo(final Routing routing) {
556 this.routing = routing;
557 }
558
559
560
561
562 public Map<String, String[]> getURIParameters() {
563 return uriParameters;
564 }
565
566
567
568
569 public Routing dispatch(final Map<String, Object[]> parameterMap) {
570 return routing;
571 }
572
573 }
574
575 }