View Javadoc

1   /*
2    * Copyright 2004-2010 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  
17  package org.seasar.cubby.unit;
18  
19  import java.io.IOException;
20  import java.util.Arrays;
21  import java.util.Iterator;
22  
23  import javax.servlet.Filter;
24  import javax.servlet.FilterChain;
25  import javax.servlet.FilterConfig;
26  import javax.servlet.ServletContext;
27  import javax.servlet.ServletException;
28  import javax.servlet.ServletRequest;
29  import javax.servlet.ServletResponse;
30  import javax.servlet.http.HttpServletRequest;
31  import javax.servlet.http.HttpServletRequestWrapper;
32  import javax.servlet.http.HttpServletResponse;
33  
34  import org.seasar.cubby.CubbyConstants;
35  import org.seasar.cubby.action.ActionContext;
36  import org.seasar.cubby.action.ActionResult;
37  import org.seasar.cubby.filter.CubbyFilter;
38  import org.seasar.cubby.internal.plugin.PluginManager;
39  import org.seasar.cubby.plugin.AbstractPlugin;
40  import org.seasar.cubby.plugin.ActionResultInvocation;
41  import org.seasar.cubby.plugin.PluginRegistry;
42  
43  /**
44   * アクションを実行するためのクラスです。
45   * 
46   * @author someda
47   * @author baba
48   */
49  public class CubbyRunner {
50  
51  	/** プラグインマネージャ。 */
52  	private static PluginManager pluginManager = new PluginManager(
53  			PluginRegistry.getInstance());
54  
55  	/**
56  	 * リクエストに応じたアクションを実行します。
57  	 * <p>
58  	 * <code>filters</code> が指定された場合はアクションを実行する前後に
59  	 * {@link Filter#doFilter(ServletRequest, ServletResponse, FilterChain)}
60  	 * を実行します。
61  	 * </p>
62  	 * 
63  	 * @param request
64  	 *            テスト用の要求
65  	 * @param response
66  	 *            テスト用の応答
67  	 * @param filters
68  	 *            実行するサーブレットフィルタ
69  	 * @return アクションメソッドの実行結果。アクションメソッドが見つからなかったり結果がない場合は <code>null</code>
70  	 * @throws Exception
71  	 *             アクションメソッドの実行時に例外が発生した場合
72  	 */
73  	public static ActionResult processAction(final HttpServletRequest request,
74  			final HttpServletResponse response, final Filter... filters)
75  			throws Exception {
76  		final ServletContext servletContext = new MockServletContext();
77  		return processAction(servletContext, request, response, filters);
78  	}
79  
80  	/**
81  	 * リクエストに応じたアクションを実行します。
82  	 * <p>
83  	 * <code>filters</code> が指定された場合はアクションを実行する前後に
84  	 * {@link Filter#doFilter(ServletRequest, ServletResponse, FilterChain)}
85  	 * を実行します。
86  	 * </p>
87  	 * 
88  	 * @param servletContext
89  	 *            サーブレットコンテキスト
90  	 * @param request
91  	 *            テスト用の要求
92  	 * @param response
93  	 *            テスト用の応答
94  	 * @param filters
95  	 *            実行するサーブレットフィルタ
96  	 * @return アクションメソッドの実行結果。アクションメソッドが見つからなかったり結果がない場合は <code>null</code>
97  	 * @throws Exception
98  	 *             アクションメソッドの実行時に例外が発生した場合
99  	 */
100 	public static ActionResult processAction(
101 			final ServletContext servletContext,
102 			final HttpServletRequest request,
103 			final HttpServletResponse response, final Filter... filters)
104 			throws Exception {
105 		return doProcess(false, servletContext, request, response, filters);
106 	}
107 
108 	/**
109 	 * リクエストに応じたアクションを実行し、その結果の {@link ActionResult} も実行します。
110 	 * <p>
111 	 * <code>filters</code> が指定された場合はアクションを実行する前後に
112 	 * {@link Filter#doFilter(ServletRequest, ServletResponse, FilterChain)}
113 	 * を実行します。
114 	 * </p>
115 	 * 
116 	 * @param request
117 	 *            テスト用の要求
118 	 * @param response
119 	 *            テスト用の応答
120 	 * @param filters
121 	 *            実行するサーブレットフィルタ
122 	 * @return アクションメソッドの実行結果。アクションメソッドが見つからなかったり結果がない場合は <code>null</code>
123 	 * @throws Exception
124 	 *             アクションメソッドの実行時に例外が発生した場合
125 	 * @since 2.0.2
126 	 */
127 	public static ActionResult processActionAndExecuteActionResult(
128 			final HttpServletRequest request,
129 			final HttpServletResponse response, final Filter... filters)
130 			throws Exception {
131 		final ServletContext servletContext = new MockServletContext();
132 		return processActionAndExecuteActionResult(servletContext, request,
133 				response, filters);
134 	}
135 
136 	/**
137 	 * リクエストに応じたアクションを実行し、その結果の {@link ActionResult} も実行します。
138 	 * <p>
139 	 * <code>filters</code> が指定された場合はアクションを実行する前後に
140 	 * {@link Filter#doFilter(ServletRequest, ServletResponse, FilterChain)}
141 	 * を実行します。
142 	 * </p>
143 	 * 
144 	 * @param servletContext
145 	 *            サーブレットコンテキスト
146 	 * @param request
147 	 *            テスト用の要求
148 	 * @param response
149 	 *            テスト用の応答
150 	 * @param filters
151 	 *            実行するサーブレットフィルタ
152 	 * @return アクションメソッドの実行結果。アクションメソッドが見つからなかったり結果がない場合は <code>null</code>
153 	 * @throws Exception
154 	 *             アクションメソッドの実行時に例外が発生した場合
155 	 * @since 2.0.2
156 	 */
157 	public static ActionResult processActionAndExecuteActionResult(
158 			final ServletContext servletContext,
159 			final HttpServletRequest request,
160 			final HttpServletResponse response, final Filter... filters)
161 			throws Exception {
162 		return doProcess(true, servletContext, request, response, filters);
163 	}
164 
165 	/**
166 	 * リクエストに応じたアクションを実行します。
167 	 * 
168 	 * @param executeActionResult
169 	 *            {@link ActionResult} を実行する場合は <code>true</code>、そうでない場合は
170 	 *            <code>false</code>
171 	 * @param servletContext
172 	 *            サーブレットコンテキスト
173 	 * @param request
174 	 *            テスト用の要求
175 	 * @param response
176 	 *            テスト用の応答
177 	 * @param filters
178 	 *            実行するサーブレットフィルタ
179 	 * @return アクションメソッドの実行結果。アクションメソッドが見つからなかったり結果がない場合は <code>null</code>
180 	 * @throws Exception
181 	 *             アクションメソッドの実行時に例外が発生した場合
182 	 */
183 	private static ActionResult doProcess(final boolean executeActionResult,
184 			final ServletContext servletContext,
185 			final HttpServletRequest request,
186 			final HttpServletResponse response, final Filter... filters)
187 			throws Exception {
188 		final FilterConfig filterConfig = new MockFilterConfig(servletContext);
189 		for (final Filter filter : filters) {
190 			filter.init(filterConfig);
191 		}
192 
193 		try {
194 			final CubbyRunnerPlugin cubbyRunnerPlugin = new CubbyRunnerPlugin();
195 			final PluginRegistry pluginRegistry = PluginRegistry.getInstance();
196 			pluginRegistry.register(cubbyRunnerPlugin);
197 
198 			pluginManager.init(servletContext);
199 			CubbyRunnerHttpServletRequestWrapper requestWrapper = new CubbyRunnerHttpServletRequestWrapper(
200 					request);
201 			final ActionInvokeFilterChain chain = new ActionInvokeFilterChain(
202 					filters);
203 			chain.doFilter(requestWrapper, response);
204 
205 			final ActionResult actionResult = cubbyRunnerPlugin
206 					.getActionResult();
207 			if (executeActionResult) {
208 				final ActionContext actionContext = requestWrapper
209 						.getActionContext();
210 				actionResult.execute(actionContext, requestWrapper, response);
211 			}
212 			return actionResult;
213 		} finally {
214 			pluginManager.destroy();
215 			for (final Filter filter : filters) {
216 				filter.destroy();
217 			}
218 		}
219 	}
220 
221 	static class ActionInvokeFilterChain implements FilterChain {
222 
223 		private final Iterator<Filter> iterator;
224 
225 		public ActionInvokeFilterChain(final Filter... filters) {
226 			this.iterator = Arrays.asList(filters).iterator();
227 		}
228 
229 		public void doFilter(final ServletRequest request,
230 				final ServletResponse response) throws IOException,
231 				ServletException {
232 			if (iterator.hasNext()) {
233 				final Filter filter = iterator.next();
234 				filter.doFilter(request, response, this);
235 			} else {
236 				try {
237 					invoke((HttpServletRequest) request,
238 							(HttpServletResponse) response);
239 				} catch (final Exception e) {
240 					throw new ServletException(e);
241 				}
242 			}
243 		}
244 
245 		private void invoke(final HttpServletRequest request,
246 				final HttpServletResponse response) throws Exception {
247 			final CubbyFilter cubbyFilter = new CubbyFilter();
248 			cubbyFilter.doFilter(request, response, this);
249 		}
250 
251 	}
252 
253 	static class CubbyRunnerPlugin extends AbstractPlugin {
254 
255 		private ActionResult actionResult;
256 
257 		@Override
258 		public void invokeActionResult(ActionResultInvocation invocation)
259 				throws Exception {
260 			this.actionResult = invocation.getActionResult();
261 		}
262 
263 		public ActionResult getActionResult() {
264 			return actionResult;
265 		}
266 
267 	}
268 
269 	static class CubbyRunnerHttpServletRequestWrapper extends
270 			HttpServletRequestWrapper {
271 
272 		private ActionContext actionContext;
273 
274 		public CubbyRunnerHttpServletRequestWrapper(HttpServletRequest request) {
275 			super(request);
276 		}
277 
278 		@Override
279 		public void setAttribute(String name, Object o) {
280 			if (CubbyConstants.ATTR_ACTION_CONTEXT.equals(name)) {
281 				this.actionContext = (ActionContext) o;
282 			}
283 			super.setAttribute(name, o);
284 		}
285 
286 		public ActionContext getActionContext() {
287 			return actionContext;
288 		}
289 
290 	}
291 
292 }