From 761a8362363fd99e80b149674180f79096bfe4ca Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Thu, 3 Mar 2011 15:54:29 +0000 Subject: [PATCH] SPR-2692 Add URI template support to RedirectView --- .../web/servlet/view/RedirectView.java | 54 +++++++++++-- .../view/RedirectViewUriTemplateTests.java | 76 +++++++++++++++++++ 2 files changed, 123 insertions(+), 7 deletions(-) create mode 100644 org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/RedirectViewUriTemplateTests.java diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/RedirectView.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/RedirectView.java index be918dd33a..05d3c3347d 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/RedirectView.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/RedirectView.java @@ -19,20 +19,29 @@ package org.springframework.web.servlet.view; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.lang.reflect.Array; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URLEncoder; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; +import java.util.Set; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.BeanUtils; import org.springframework.http.HttpStatus; +import org.springframework.ui.Model; import org.springframework.util.ObjectUtils; import org.springframework.web.servlet.View; +import org.springframework.web.util.UriTemplate; +import org.springframework.web.util.UriUtils; import org.springframework.web.util.WebUtils; /** @@ -214,20 +223,51 @@ public class RedirectView extends AbstractUrlBasedView { targetUrl.append(request.getContextPath()); } targetUrl.append(getUrl()); + + String enc = this.encodingScheme; + if (enc == null) { + enc = request.getCharacterEncoding(); + } + if (enc == null) { + enc = WebUtils.DEFAULT_CHARACTER_ENCODING; + } + + UriTemplate uriTemplate = createUriTemplate(targetUrl, enc); + if (uriTemplate.getVariableNames().size() > 0) { + targetUrl = new StringBuilder(uriTemplate.expand(model).toString()); + model = removeKeys(model, uriTemplate.getVariableNames()); + } if (this.exposeModelAttributes) { - String enc = this.encodingScheme; - if (enc == null) { - enc = request.getCharacterEncoding(); - } - if (enc == null) { - enc = WebUtils.DEFAULT_CHARACTER_ENCODING; - } appendQueryProperties(targetUrl, model, enc); } sendRedirect(request, response, targetUrl.toString(), this.http10Compatible); } + private UriTemplate createUriTemplate(StringBuilder targetUrl, final String encoding) { + return new UriTemplate(targetUrl.toString()) { + @Override + protected URI encodeUri(String uri) { + try { + String encoded = UriUtils.encodeUri(uri, encoding); + return new URI(encoded); + } catch (UnsupportedEncodingException ex) { + throw new IllegalStateException(ex); + } catch (URISyntaxException ex) { + throw new IllegalArgumentException("Could not create URI from [" + uri + "]: " + ex, ex); + } + } + }; + } + + private static Map removeKeys(Map map, List keysToRemove) { + Map result = new HashMap(map); + for (String key : keysToRemove) { + result.remove(key); + } + return result; + } + /** * Append query properties to the redirect URL. * Stringifies, URL-encodes and formats model attributes as query properties. diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/RedirectViewUriTemplateTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/RedirectViewUriTemplateTests.java new file mode 100644 index 0000000000..684768700c --- /dev/null +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/RedirectViewUriTemplateTests.java @@ -0,0 +1,76 @@ +/* + * Copyright 2002-2011 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.web.servlet.view; + +import static org.junit.Assert.assertEquals; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; + +public class RedirectViewUriTemplateTests { + + private MockHttpServletRequest request; + + private MockHttpServletResponse response; + + @Before + public void setUp() { + request = new MockHttpServletRequest(); + response = new MockHttpServletResponse(); + } + + @Test + public void pathVar() throws Exception { + Map model = new HashMap(); + model.put("foo", "bar"); + + String baseUrl = "http://url.somewhere.com"; + RedirectView redirectView = new RedirectView(baseUrl + "/{foo}"); + redirectView.renderMergedOutputModel(model, request, response); + + assertEquals(baseUrl + "/bar", response.getRedirectedUrl()); + } + + @Test + public void pathVarAndArrayParam() throws Exception { + Map model = new HashMap(); + model.put("foo", "bar"); + model.put("fooArr", new String[] { "baz", "bazz" }); + + RedirectView redirectView = new RedirectView("/foo/{foo}"); + redirectView.renderMergedOutputModel(model, request, response); + + assertEquals("/foo/bar?fooArr=baz&fooArr=bazz", response.getRedirectedUrl()); + } + + @Test + public void pathVarWithObjectConversion() throws Exception { + Map model = new HashMap(); + model.put("foo", new Long(611)); + + RedirectView redirectView = new RedirectView("/foo/{foo}"); + redirectView.renderMergedOutputModel(model, request, response); + + assertEquals("/foo/611", response.getRedirectedUrl()); + } + +}