    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.action;
    17
    18  import static org.easymock.EasyMock.createMock;
    19  import static org.easymock.EasyMock.eq;
    20  import static org.easymock.EasyMock.expect;
    21  import static org.easymock.EasyMock.expectLastCall;
    22  import static org.easymock.EasyMock.getCurrentArguments;
    23  import static org.easymock.EasyMock.isA;
    24  import static org.easymock.EasyMock.replay;
    25  import static org.easymock.EasyMock.verify;
    26  import static org.junit.Assert.assertEquals;
    27  import static org.junit.Assert.assertNotNull;
    28  import static org.junit.Assert.assertTrue;
    29
    30  import java.lang.reflect.Method;
    31  import java.util.ArrayList;
    32  import java.util.List;
    33
    34  import javax.servlet.RequestDispatcher;
    35  import javax.servlet.http.HttpServletRequest;
    36  import javax.servlet.http.HttpServletRequestWrapper;
    37  import javax.servlet.http.HttpServletResponse;
    38
    39  import org.easymock.IAnswer;
    40  import org.junit.After;
    41  import org.junit.Before;
    42  import org.junit.Test;
    43  import org.seasar.cubby.CubbyConstants;
    44  import org.seasar.cubby.mock.MockActionContext;
    45  import org.seasar.cubby.mock.MockPathResolverProvider;
    46  import org.seasar.cubby.plugin.PluginRegistry;
    47  import org.seasar.cubby.plugins.BinderPlugin;
    48  import org.seasar.cubby.routing.PathResolver;
    49  import org.seasar.cubby.routing.Routing;
    50  import org.seasar.cubby.routing.impl.PathResolverImpl;
    51  import org.seasar.cubby.routing.impl.PathTemplateParserImpl;
    52  import org.seasar.cubby.spi.PathResolverProvider;
    53
    54  public class ForwardTest {
    55
    56  	private final PluginRegistry pluginRegistry = PluginRegistry.getInstance();
    57
    58  	private final MockAction action = new MockAction();
    59
    60  	private HttpServletRequest request;
    61
    62  	private RequestDispatcher requestDispatcher;
    63
    64  	private HttpServletResponse response;
    65
    66  	@Before
    67  	public void setupProvider() {
    68  		final List<Class<?>> actionClasses = new ArrayList<Class<?>>();
    69  		actionClasses.add(MockAction.class);
    70  		final PathResolver pathResolver = new PathResolverImpl(
    71  				new PathTemplateParserImpl());
    72  		pathResolver.addAll(actionClasses);
    73  		final BinderPlugin binderPlugin = new BinderPlugin();
    74  		binderPlugin.bind(PathResolverProvider.class).toInstance(
    75  				new MockPathResolverProvider(pathResolver));
    76  		pluginRegistry.register(binderPlugin);
    77  	}
    78
    79  	@After
    80  	public void tearDownProvider() {
    81  		pluginRegistry.clear();
    82  	}
    83
    84  	@Before
    85  	public void setupRequest() {
    86  		request = createMock(HttpServletRequest.class);
    87  		expect(request.getCharacterEncoding()).andReturn("UTF-8").anyTimes();
    88  		requestDispatcher = createMock(RequestDispatcher.class);
    89  		response = createMock(HttpServletResponse.class);
    90  	}
    91
    92  	@Test
    93  	public void basicSequence() throws Exception {
    94  		final Method method = action.getClass().getMethod("dummy1");
    95  		final MockActionContext actionContext = new MockActionContext(action,
    96  				MockAction.class, method);
    97
    98  		expect(request.getRequestDispatcher("/mock/path.jsp")).andStubAnswer(
    99  				new IAnswer<RequestDispatcher>() {
    100
    101 					public RequestDispatcher answer() throws Throwable {
    102 						assertTrue(actionContext.isPrerendered());
    103 						return requestDispatcher;
    104 					}
    105
    106 				});
    107 		requestDispatcher.forward(request, response);
    108 		expectLastCall();
    109 		replay(request, requestDispatcher, response);
    110
    111 		final Forward forward = new Forward("path.jsp");
    112 		forward.execute(actionContext, request, response);
    113 		assertTrue(actionContext.isPostrendered());
    114 		verify(request, requestDispatcher, response);
    115 	}
    116
    117 	@Test
    118 	public void relativePath() throws Exception {
    119 		final Method method = action.getClass().getMethod("dummy1");
    120 		final MockActionContext actionContext = new MockActionContext(action,
    121 				MockAction.class, method);
    122
    123 		expect(request.getRequestDispatcher("/mock/page.jsp")).andReturn(
    124 				requestDispatcher);
    125 		requestDispatcher.forward(request, response);
    126 		expectLastCall();
    127 		replay(request, requestDispatcher, response);
    128
    129 		final Forward forward = new Forward("page.jsp");
    130 		forward.execute(actionContext, request, response);
    131 		verify(request, requestDispatcher, response);
    132 	}
    133
    134 	@Test
    135 	public void absolutePath() throws Exception {
    136 		final Method method = action.getClass().getMethod("dummy1");
    137 		final ActionContext actionContext = new MockActionContext(action,
    138 				MockAction.class, method);
    139
    140 		expect(request.getRequestDispatcher("/absolute/path.jsp")).andReturn(
    141 				requestDispatcher);
    142 		requestDispatcher.forward(request, response);
    143 		expectLastCall();
    144 		replay(request, requestDispatcher, response);
    145
    146 		final Forward forward = new Forward("/absolute/path.jsp");
    147 		forward.execute(actionContext, request, response);
    148 		verify(request, requestDispatcher, response);
    149 	}
    150
    151 	@Test
    152 	public void getPath() throws Exception {
    153 		final Forward forward = new Forward("/absolute/path.jsp");
    154 		assertEquals("/absolute/path.jsp", forward.getPath("UTF-8"));
    155 	}
    156
    157 	@Test
    158 	public void param() throws Exception {
    159 		final Forward forward = new Forward("/absolute/path.jsp").param(
    160 				"value1", "123").param("value2", "456");
    161 		assertEquals("/absolute/path.jsp?value1=123&value2=456", forward
    162 				.getPath("UTF-8"));
    163 	}
    164
    165 	@Test
    166 	public void forwardByClassAndMethodName() throws Exception {
    167 		final Method method = action.getClass().getMethod("dummy1");
    168 		final ActionContext actionContext = new MockActionContext(action,
    169 				MockAction.class, method);
    170
    171 		request.setAttribute(eq(CubbyConstants.ATTR_ROUTING),
    172 				isA(Routing.class));
    173 		expectLastCall().andAnswer(new IAnswer<Object>() {
    174
    175 			public Object answer() throws Throwable {
    176 				final Routing routing = Routing.class
    177 						.cast(getCurrentArguments()[1]);
    178 				assertNotNull(routing);
    179 				assertEquals(MockAction.class, routing.getActionClass());
    180 				final Method forwardMethod = action.getClass().getMethod(
    181 						"dummy2");
    182 				assertEquals(forwardMethod, routing.getActionMethod());
    183 				return null;
    184 			}
    185
    186 		});
    187 		expect(request.getRequestDispatcher("/mock/dummy2/5/abc")).andReturn(
    188 				requestDispatcher);
    189 		requestDispatcher.forward(request, response);
    190 		expectLastCall();
    191 		replay(request, requestDispatcher, response);
    192
    193 		final Forward forward = new Forward(MockAction.class, "dummy2").param(
    194 				"value1", "5").param("value2", "abc");
    195 		forward.execute(actionContext, request, response);
    196 	}
    197
    198 	@Test
    199 	public void forwardByClassAndIndex() throws Exception {
    200 		final Method method = action.getClass().getMethod("dummy1");
    201 		final ActionContext actionContext = new MockActionContext(action,
    202 				MockAction.class, method);
    203
    204 		request.setAttribute(eq(CubbyConstants.ATTR_ROUTING),
    205 				isA(Routing.class));
    206 		expectLastCall().andAnswer(new IAnswer<Object>() {
    207
    208 			public Object answer() throws Throwable {
    209 				final Routing routing = Routing.class
    210 						.cast(getCurrentArguments()[1]);
    211 				assertNotNull(routing);
    212 				assertEquals(MockAction.class, routing.getActionClass());
    213 				final Method forwardMethod = action.getClass().getMethod(
    214 						"index");
    215 				assertEquals(forwardMethod, routing.getActionMethod());
    216 				return null;
    217 			}
    218
    219 		});
    220 		expect(request.getRequestDispatcher("/mock/")).andReturn(
    221 				requestDispatcher);
    222 		requestDispatcher.forward(request, response);
    223 		expectLastCall();
    224 		replay(request, requestDispatcher, response);
    225
    226 		final Forward forward = new Forward(MockAction.class);
    227 		PluginRegistry.getInstance().clear();
    228
    229 		assertEquals("/mock/", forward.getPath("UTF-8"));
    230 		forward.execute(actionContext, request, response);
    231 	}
    232
    233 	@Test
    234 	public void forwardByClassAndMethodNameWithParam() throws Exception {
    235 		final Method method = action.getClass().getMethod("dummy1");
    236 		final ActionContext actionContext = new MockActionContext(action,
    237 				MockAction.class, method);
    238
    239 		request.setAttribute(eq(CubbyConstants.ATTR_ROUTING),
    240 				isA(Routing.class));
    241 		expectLastCall().andAnswer(new IAnswer<Object>() {
    242
    243 			public Object answer() throws Throwable {
    244 				final Routing routing = Routing.class
    245 						.cast(getCurrentArguments()[1]);
    246 				assertNotNull(routing);
    247 				assertEquals(MockAction.class, routing.getActionClass());
    248 				final Method forwardMethod = action.getClass().getMethod(
    249 						"dummy2");
    250 				assertEquals(forwardMethod, routing.getActionMethod());
    251 				return null;
    252 			}
    253
    254 		});
    255 		expect(request.getRequestDispatcher("/mock/dummy2/123/456")).andReturn(
    256 				requestDispatcher);
    257 		requestDispatcher.forward(request, response);
    258 		expectLastCall();
    259 		replay(request, requestDispatcher, response);
    260
    261 		final Forward forward = new Forward(MockAction.class, "dummy2").param(
    262 				"value1", "123").param("value2", "456");
    263 		PluginRegistry.getInstance().clear();
    264
    265 		assertEquals("/mock/dummy2/123/456", forward.getPath("UTF-8"));
    266 		forward.execute(actionContext, request, response);
    267 	}
    268
    269 	interface Asserter {
    270 		void assertDispatchPath(String path);
    271 	}
    272
    273 	static class RequestDispatcherAssertionWrapper extends
    274 			HttpServletRequestWrapper {
    275
    276 		private final Asserter asserter;
    277
    278 		public RequestDispatcherAssertionWrapper(
    279 				final HttpServletRequest request, final Asserter asserter) {
    280 			super(request);
    281 			this.asserter = asserter;
    282 		}
    283
    284 		@Override
    285 		public RequestDispatcher getRequestDispatcher(final String path) {
    286 			asserter.assertDispatchPath(path);
    287 			return super.getRequestDispatcher(path);
    288 		}
    289
    290 	}
    291
    292 }