View Javadoc

1   /*
2    * Copyright 2004-2009 the Seasar Foundation and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.seasar.cubby.filter;
17  
18  import static org.seasar.cubby.CubbyConstants.ATTR_FILTER_CHAIN;
19  
20  import java.io.IOException;
21  import java.util.ArrayList;
22  import java.util.List;
23  import java.util.StringTokenizer;
24  import java.util.regex.Pattern;
25  
26  import javax.servlet.Filter;
27  import javax.servlet.FilterChain;
28  import javax.servlet.FilterConfig;
29  import javax.servlet.ServletException;
30  import javax.servlet.ServletRequest;
31  import javax.servlet.ServletResponse;
32  import javax.servlet.http.HttpServletRequest;
33  import javax.servlet.http.HttpServletResponse;
34  
35  import org.seasar.cubby.internal.controller.RequestProcessor;
36  import org.seasar.cubby.internal.controller.impl.RequestProcessorImpl;
37  import org.seasar.cubby.internal.routing.Router;
38  import org.seasar.cubby.internal.routing.impl.RouterImpl;
39  import org.seasar.cubby.internal.util.StringUtils;
40  import org.seasar.cubby.routing.PathInfo;
41  
42  /**
43   * Cubby 用のフィルター。
44   * <p>
45   * 要求を解析し、対応するアクションが登録されている場合はアクションを実行します。
46   * </p>
47   * 
48   * @author agata
49   * @author baba
50   */
51  public class CubbyFilter implements Filter {
52  
53  	/** ルーティングの対象外とするパスの初期パラメータ名。 */
54  	public static final String IGNORE_PATH_PATTERN = "ignorePathPattern";
55  
56  	/** ルーティングの対象外とするパスの正規表現パターンのリスト。 */
57  	private final List<Pattern> ignorePathPatterns = new ArrayList<Pattern>();
58  
59  	/** ルーター。 */
60  	private final Router router = new RouterImpl();
61  
62  	/** 要求を処理します。 */
63  	private final RequestProcessor requestProcessor = new RequestProcessorImpl();
64  
65  	/**
66  	 * このフィルタを初期化します。
67  	 * <p>
68  	 * 使用可能な初期化パラメータ
69  	 * <table>
70  	 * <thead>
71  	 * <th>初期化パラメータ名</th>
72  	 * <th>初期化パラメータの値</th>
73  	 * <th>例</th>
74  	 * </thead> <thead>
75  	 * <tr>
76  	 * <td>{@link #IGNORE_PATH_PATTERN}</td>
77  	 * <td>ルーティングの対象外とするパスの正規表現をカンマ区切りで指定します。 HotDeploy
78  	 * 時のパフォーマンスにも影響するので、画像やスクリプトを特定のディレクトリに
79  	 * 格納していてアクションを実行するパスと明確に区別できる場合はできる限り指定するようにしてください。</td>
80  	 * <td>
81  	 * 
82  	 * <pre>
83  	 * &lt;param-name&gt;ignorePathPattern&amp;lt/param-name&gt;
84  	 * &lt;param-value&gt;/img/.*,/js/.*&lt;param-name&gt;
85  	 * </pre>
86  	 * 
87  	 * この例では /img と /js 以下のパスをルーティングの対象外にします。</td>
88  	 * </tr>
89  	 * </thead>
90  	 * </p>
91  	 * 
92  	 * @param config
93  	 *            フィルタ設定のためのオブジェクト
94  	 * @throws ServletException
95  	 *             初期化処理で例外が発生した場合
96  	 */
97  	public void init(final FilterConfig config) throws ServletException {
98  		final String ignorePathPatternString = config
99  				.getInitParameter(IGNORE_PATH_PATTERN);
100 		if (!StringUtils.isEmpty(ignorePathPatternString)) {
101 
102 			for (final StringTokenizer tokenizer = new StringTokenizer(
103 					ignorePathPatternString, ","); tokenizer.hasMoreTokens();) {
104 				final String token = tokenizer.nextToken();
105 				final Pattern pattern = Pattern.compile(token);
106 				ignorePathPatterns.add(pattern);
107 			}
108 		}
109 	}
110 
111 	/**
112 	 * {@inheritDoc}
113 	 */
114 	public void destroy() {
115 	}
116 
117 	/**
118 	 * フィルター処理を行います。
119 	 * <p>
120 	 * 要求された URI に対応する情報が {@link Router} から取得できた場合は、 {@link RequestProcessor}
121 	 * によって要求を処理します。URI に対応する情報が取得できなかった場合はフィルタチェインで次のフィルタに処理を委譲します。
122 	 * </p>
123 	 * 
124 	 * @param req
125 	 *            要求
126 	 * @param res
127 	 *            応答
128 	 * @param chain
129 	 *            フィルターチェーン
130 	 * @throws IOException
131 	 *             要求の転送や要求のチェーンがこの例外をスローする場合
132 	 * @throws ServletException
133 	 *             要求の転送や要求のチェーンがこの例外をスローする場合
134 	 * @see Router#routing(HttpServletRequest, HttpServletResponse, List)
135 	 * @see RequestProcessor#process(HttpServletRequest, HttpServletResponse,
136 	 *      PathInfo)
137 	 */
138 	public void doFilter(final ServletRequest req, final ServletResponse res,
139 			final FilterChain chain) throws IOException, ServletException {
140 		final HttpServletRequest request = (HttpServletRequest) req;
141 		final HttpServletResponse response = (HttpServletResponse) res;
142 		final PathInfo pathInfo = router.routing(request, response,
143 				ignorePathPatterns);
144 		if (pathInfo != null) {
145 			request.setAttribute(ATTR_FILTER_CHAIN, chain);
146 			try {
147 				requestProcessor.process(request, response, pathInfo);
148 			} catch (final Exception e) {
149 				if (e instanceof IOException) {
150 					throw (IOException) e;
151 				} else if (e instanceof ServletException) {
152 					throw (ServletException) e;
153 				} else {
154 					throw new ServletException(e);
155 				}
156 			}
157 		} else {
158 			chain.doFilter(request, response);
159 		}
160 	}
161 
162 }