1 /* 2 * Copyright 2002-2012 the original author or authors. 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, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.springframework.web.servlet.view; 18 19 import static org.easymock.EasyMock.createMock; 20 import static org.easymock.EasyMock.createNiceMock; 21 import static org.easymock.EasyMock.expect; 22 import static org.easymock.EasyMock.replay; 23 import static org.easymock.EasyMock.verify; 24 import static org.junit.Assert.assertEquals; 25 import static org.junit.Assert.assertTrue; 26 27 import java.util.ArrayList; 28 import java.util.HashMap; 29 import java.util.List; 30 import java.util.Map; 31 32 import javax.servlet.http.HttpServletRequest; 33 import javax.servlet.http.HttpServletResponse; 34 35 import junit.framework.AssertionFailedError; 36 37 import org.easymock.EasyMock; 38 import org.junit.Test; 39 import org.springframework.beans.TestBean; 40 import org.springframework.http.HttpStatus; 41 import org.springframework.mock.web.MockHttpServletRequest; 42 import org.springframework.mock.web.MockHttpServletResponse; 43 import org.springframework.mock.web.MockServletContext; 44 import org.springframework.ui.ModelMap; 45 import org.springframework.web.context.ContextLoader; 46 import org.springframework.web.context.support.StaticWebApplicationContext; 47 import org.springframework.web.servlet.DispatcherServlet; 48 import org.springframework.web.servlet.FlashMap; 49 import org.springframework.web.servlet.FlashMapManager; 50 import org.springframework.web.servlet.View; 51 import org.springframework.web.servlet.support.RequestDataValueProcessor; 52 import org.springframework.web.servlet.support.RequestDataValueProcessorWrapper; 53 import org.springframework.web.servlet.support.SessionFlashMapManager; 54 import org.springframework.web.util.WebUtils; 55 56 /** 57 * Tests for redirect view, and query string construction. 58 * Doesn't test URL encoding, although it does check that it's called. 59 * 60 * @author Rod Johnson 61 * @author Juergen Hoeller 62 * @author Sam Brannen 63 * @author Arjen Poutsma 64 * @since 27.05.2003 65 */ 66 public class RedirectViewTests { 67 68 @Test(expected = IllegalArgumentException.class) noUrlSet()69 public void noUrlSet() throws Exception { 70 RedirectView rv = new RedirectView(); 71 rv.afterPropertiesSet(); 72 } 73 74 @Test http11()75 public void http11() throws Exception { 76 RedirectView rv = new RedirectView(); 77 rv.setUrl("http://url.somewhere.com"); 78 rv.setHttp10Compatible(false); 79 MockHttpServletRequest request = createRequest(); 80 MockHttpServletResponse response = new MockHttpServletResponse(); 81 request.setAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); 82 request.setAttribute(DispatcherServlet.FLASH_MAP_MANAGER_ATTRIBUTE, new SessionFlashMapManager()); 83 rv.render(new HashMap<String, Object>(), request, response); 84 assertEquals(303, response.getStatus()); 85 assertEquals("http://url.somewhere.com", response.getHeader("Location")); 86 } 87 createRequest()88 private MockHttpServletRequest createRequest() { 89 MockHttpServletRequest request = new MockHttpServletRequest(); 90 request.setAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); 91 request.setAttribute(DispatcherServlet.FLASH_MAP_MANAGER_ATTRIBUTE, new SessionFlashMapManager()); 92 return request; 93 } 94 95 @Test explicitStatusCodeHttp11()96 public void explicitStatusCodeHttp11() throws Exception { 97 RedirectView rv = new RedirectView(); 98 rv.setUrl("http://url.somewhere.com"); 99 rv.setHttp10Compatible(false); 100 rv.setStatusCode(HttpStatus.MOVED_PERMANENTLY); 101 MockHttpServletRequest request = createRequest(); 102 MockHttpServletResponse response = new MockHttpServletResponse(); 103 rv.render(new HashMap<String, Object>(), request, response); 104 assertEquals(301, response.getStatus()); 105 assertEquals("http://url.somewhere.com", response.getHeader("Location")); 106 } 107 108 @Test explicitStatusCodeHttp10()109 public void explicitStatusCodeHttp10() throws Exception { 110 RedirectView rv = new RedirectView(); 111 rv.setUrl("http://url.somewhere.com"); 112 rv.setStatusCode(HttpStatus.MOVED_PERMANENTLY); 113 MockHttpServletRequest request = createRequest(); 114 MockHttpServletResponse response = new MockHttpServletResponse(); 115 rv.render(new HashMap<String, Object>(), request, response); 116 assertEquals(301, response.getStatus()); 117 assertEquals("http://url.somewhere.com", response.getHeader("Location")); 118 } 119 120 @Test attributeStatusCodeHttp11()121 public void attributeStatusCodeHttp11() throws Exception { 122 RedirectView rv = new RedirectView(); 123 rv.setUrl("http://url.somewhere.com"); 124 rv.setHttp10Compatible(false); 125 MockHttpServletRequest request = createRequest(); 126 request.setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, HttpStatus.CREATED); 127 MockHttpServletResponse response = new MockHttpServletResponse(); 128 rv.render(new HashMap<String, Object>(), request, response); 129 assertEquals(201, response.getStatus()); 130 assertEquals("http://url.somewhere.com", response.getHeader("Location")); 131 } 132 133 @Test flashMap()134 public void flashMap() throws Exception { 135 RedirectView rv = new RedirectView(); 136 rv.setUrl("http://url.somewhere.com/path"); 137 rv.setHttp10Compatible(false); 138 MockHttpServletRequest request = createRequest(); 139 HttpServletResponse response = new MockHttpServletResponse(); 140 FlashMap flashMap = new FlashMap(); 141 flashMap.put("successMessage", "yay!"); 142 request.setAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE, flashMap); 143 ModelMap model = new ModelMap("id", "1"); 144 rv.render(model, request, response); 145 assertEquals(303, response.getStatus()); 146 assertEquals("http://url.somewhere.com/path?id=1", response.getHeader("Location")); 147 148 assertEquals("/path", flashMap.getTargetRequestPath()); 149 assertEquals(model, flashMap.getTargetRequestParams().toSingleValueMap()); 150 } 151 152 @Test updateTargetUrl()153 public void updateTargetUrl() throws Exception { 154 StaticWebApplicationContext wac = new StaticWebApplicationContext(); 155 wac.registerSingleton("requestDataValueProcessor", RequestDataValueProcessorWrapper.class); 156 wac.setServletContext(new MockServletContext()); 157 wac.refresh(); 158 159 RequestDataValueProcessor mockProcessor = createMock(RequestDataValueProcessor.class); 160 wac.getBean(RequestDataValueProcessorWrapper.class).setRequestDataValueProcessor(mockProcessor); 161 162 RedirectView rv = new RedirectView(); 163 rv.setApplicationContext(wac); // Init RedirectView with WebAppCxt 164 rv.setUrl("/path"); 165 166 MockHttpServletRequest request = createRequest(); 167 request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac); 168 HttpServletResponse response = new MockHttpServletResponse(); 169 170 EasyMock.expect(mockProcessor.processUrl(request, "/path")).andReturn("/path?key=123"); 171 EasyMock.replay(mockProcessor); 172 173 rv.render(new ModelMap(), request, response); 174 175 EasyMock.verify(mockProcessor); 176 } 177 178 179 @Test updateTargetUrlWithContextLoader()180 public void updateTargetUrlWithContextLoader() throws Exception { 181 StaticWebApplicationContext wac = new StaticWebApplicationContext(); 182 wac.registerSingleton("requestDataValueProcessor", RequestDataValueProcessorWrapper.class); 183 184 MockServletContext servletContext = new MockServletContext(); 185 ContextLoader contextLoader = new ContextLoader(wac); 186 contextLoader.initWebApplicationContext(servletContext); 187 188 try { 189 RequestDataValueProcessor mockProcessor = createMock(RequestDataValueProcessor.class); 190 wac.getBean(RequestDataValueProcessorWrapper.class).setRequestDataValueProcessor(mockProcessor); 191 192 RedirectView rv = new RedirectView(); 193 rv.setUrl("/path"); 194 195 MockHttpServletRequest request = createRequest(); 196 HttpServletResponse response = new MockHttpServletResponse(); 197 198 EasyMock.expect(mockProcessor.processUrl(request, "/path")).andReturn("/path?key=123"); 199 EasyMock.replay(mockProcessor); 200 201 rv.render(new ModelMap(), request, response); 202 203 EasyMock.verify(mockProcessor); 204 } 205 finally { 206 contextLoader.closeWebApplicationContext(servletContext); 207 } 208 } 209 210 @Test emptyMap()211 public void emptyMap() throws Exception { 212 String url = "/myUrl"; 213 doTest(new HashMap<String, Object>(), url, false, url); 214 } 215 216 @Test emptyMapWithContextRelative()217 public void emptyMapWithContextRelative() throws Exception { 218 String url = "/myUrl"; 219 doTest(new HashMap<String, Object>(), url, true, url); 220 } 221 222 @Test singleParam()223 public void singleParam() throws Exception { 224 String url = "http://url.somewhere.com"; 225 String key = "foo"; 226 String val = "bar"; 227 Map<String, String> model = new HashMap<String, String>(); 228 model.put(key, val); 229 String expectedUrlForEncoding = url + "?" + key + "=" + val; 230 doTest(model, url, false, expectedUrlForEncoding); 231 } 232 233 @Test singleParamWithoutExposingModelAttributes()234 public void singleParamWithoutExposingModelAttributes() throws Exception { 235 String url = "http://url.somewhere.com"; 236 String key = "foo"; 237 String val = "bar"; 238 Map<String, String> model = new HashMap<String, String>(); 239 model.put(key, val); 240 String expectedUrlForEncoding = url; // + "?" + key + "=" + val; 241 doTest(model, url, false, false, expectedUrlForEncoding); 242 } 243 244 @Test paramWithAnchor()245 public void paramWithAnchor() throws Exception { 246 String url = "http://url.somewhere.com/test.htm#myAnchor"; 247 String key = "foo"; 248 String val = "bar"; 249 Map<String, String> model = new HashMap<String, String>(); 250 model.put(key, val); 251 String expectedUrlForEncoding = "http://url.somewhere.com/test.htm" + "?" + key + "=" + val + "#myAnchor"; 252 doTest(model, url, false, expectedUrlForEncoding); 253 } 254 255 @Test contextRelativeQueryParam()256 public void contextRelativeQueryParam() throws Exception { 257 String url = "/test.html?id=1"; 258 doTest(new HashMap<String, Object>(), url, true, url); 259 } 260 261 @Test twoParams()262 public void twoParams() throws Exception { 263 String url = "http://url.somewhere.com"; 264 String key = "foo"; 265 String val = "bar"; 266 String key2 = "thisIsKey2"; 267 String val2 = "andThisIsVal2"; 268 Map<String, String> model = new HashMap<String, String>(); 269 model.put(key, val); 270 model.put(key2, val2); 271 try { 272 String expectedUrlForEncoding = "http://url.somewhere.com?" + key + "=" + val + "&" + key2 + "=" + val2; 273 doTest(model, url, false, expectedUrlForEncoding); 274 } 275 catch (AssertionFailedError err) { 276 // OK, so it's the other order... probably on Sun JDK 1.6 or IBM JDK 1.5 277 String expectedUrlForEncoding = "http://url.somewhere.com?" + key2 + "=" + val2 + "&" + key + "=" + val; 278 doTest(model, url, false, expectedUrlForEncoding); 279 } 280 } 281 282 @Test arrayParam()283 public void arrayParam() throws Exception { 284 String url = "http://url.somewhere.com"; 285 String key = "foo"; 286 String[] val = new String[] {"bar", "baz"}; 287 Map<String, String[]> model = new HashMap<String, String[]>(); 288 model.put(key, val); 289 try { 290 String expectedUrlForEncoding = "http://url.somewhere.com?" + key + "=" + val[0] + "&" + key + "=" + val[1]; 291 doTest(model, url, false, expectedUrlForEncoding); 292 } 293 catch (AssertionFailedError err) { 294 // OK, so it's the other order... probably on Sun JDK 1.6 or IBM JDK 1.5 295 String expectedUrlForEncoding = "http://url.somewhere.com?" + key + "=" + val[1] + "&" + key + "=" + val[0]; 296 doTest(model, url, false, expectedUrlForEncoding); 297 } 298 } 299 300 @Test collectionParam()301 public void collectionParam() throws Exception { 302 String url = "http://url.somewhere.com"; 303 String key = "foo"; 304 List<String> val = new ArrayList<String>(); 305 val.add("bar"); 306 val.add("baz"); 307 Map<String, List<String>> model = new HashMap<String, List<String>>(); 308 model.put(key, val); 309 try { 310 String expectedUrlForEncoding = "http://url.somewhere.com?" + key + "=" + val.get(0) + "&" + key + "=" + val.get(1); 311 doTest(model, url, false, expectedUrlForEncoding); 312 } 313 catch (AssertionFailedError err) { 314 // OK, so it's the other order... probably on Sun JDK 1.6 or IBM JDK 1.5 315 String expectedUrlForEncoding = "http://url.somewhere.com?" + key + "=" + val.get(1) + "&" + key + "=" + val.get(0); 316 doTest(model, url, false, expectedUrlForEncoding); 317 } 318 } 319 320 @Test objectConversion()321 public void objectConversion() throws Exception { 322 String url = "http://url.somewhere.com"; 323 String key = "foo"; 324 String val = "bar"; 325 String key2 = "int2"; 326 Object val2 = new Long(611); 327 String key3 = "tb"; 328 Object val3 = new TestBean(); 329 Map<String, Object> model = new HashMap<String, Object>(); 330 model.put(key, val); 331 model.put(key2, val2); 332 model.put(key3, val3); 333 String expectedUrlForEncoding = "http://url.somewhere.com?" + key + "=" + val + "&" + key2 + "=" + val2; 334 doTest(model, url, false, expectedUrlForEncoding); 335 } 336 doTest(Map<String, ?> map, String url, boolean contextRelative, String expectedUrlForEncoding)337 private void doTest(Map<String, ?> map, String url, boolean contextRelative, String expectedUrlForEncoding) 338 throws Exception { 339 doTest(map, url, contextRelative, true, expectedUrlForEncoding); 340 } 341 doTest(final Map<String, ?> map, final String url, final boolean contextRelative, final boolean exposeModelAttributes, String expectedUrlForEncoding)342 private void doTest(final Map<String, ?> map, final String url, final boolean contextRelative, 343 final boolean exposeModelAttributes, String expectedUrlForEncoding) throws Exception { 344 345 class TestRedirectView extends RedirectView { 346 347 public boolean queryPropertiesCalled = false; 348 349 /** 350 * Test whether this callback method is called with correct args 351 */ 352 @Override 353 protected Map<String, Object> queryProperties(Map<String, Object> model) { 354 // They may not be the same model instance, but they're still equal 355 assertTrue("Map and model must be equal.", map.equals(model)); 356 this.queryPropertiesCalled = true; 357 return super.queryProperties(model); 358 } 359 } 360 361 TestRedirectView rv = new TestRedirectView(); 362 rv.setUrl(url); 363 rv.setContextRelative(contextRelative); 364 rv.setExposeModelAttributes(exposeModelAttributes); 365 366 HttpServletRequest request = createNiceMock("request", HttpServletRequest.class); 367 if (exposeModelAttributes) { 368 expect(request.getCharacterEncoding()).andReturn(WebUtils.DEFAULT_CHARACTER_ENCODING); 369 } 370 if (contextRelative) { 371 expectedUrlForEncoding = "/context" + expectedUrlForEncoding; 372 expect(request.getContextPath()).andReturn("/context"); 373 } 374 375 expect(request.getAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE)).andReturn(new FlashMap()); 376 377 FlashMapManager flashMapManager = new SessionFlashMapManager(); 378 expect(request.getAttribute(DispatcherServlet.FLASH_MAP_MANAGER_ATTRIBUTE)).andReturn(flashMapManager); 379 380 HttpServletResponse response = createMock("response", HttpServletResponse.class); 381 expect(response.encodeRedirectURL(expectedUrlForEncoding)).andReturn(expectedUrlForEncoding); 382 response.sendRedirect(expectedUrlForEncoding); 383 384 replay(request, response); 385 386 rv.render(map, request, response); 387 if (exposeModelAttributes) { 388 assertTrue("queryProperties() should have been called.", rv.queryPropertiesCalled); 389 } 390 391 verify(request, response); 392 } 393 394 } 395