diff --git a/build-spring-framework/resources/changelog.txt b/build-spring-framework/resources/changelog.txt index 0597b8d235..ae57f45e77 100644 --- a/build-spring-framework/resources/changelog.txt +++ b/build-spring-framework/resources/changelog.txt @@ -31,6 +31,9 @@ Changes in version 3.1.1 (2012-02-06) * fix request mapping bug involving direct vs pattern path matches with HTTP methods * revise the FlashMapManager contract and implemenation to address a flaw in its design * Remove check for HTTP "POST" when resolving multipart request controller method arguments +* add normalize() method to UriComponents +* remove empty path segments from input to UriComponentsBuilder +* add fromRequestUri(request) and fromCurrentRequestUri() methods to ServletUriCommonentsBuilder Changes in version 3.1 GA (2011-12-12) -------------------------------------- diff --git a/org.springframework.web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java b/org.springframework.web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java index f4ed1f252e..c95d620256 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java +++ b/org.springframework.web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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. @@ -18,7 +18,7 @@ package org.springframework.web.util; import java.net.URI; import java.util.ArrayList; -import java.util.Collections; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.regex.Matcher; @@ -80,7 +80,7 @@ public class UriComponentsBuilder { "^" + HTTP_PATTERN + "(//(" + USERINFO_PATTERN + "@)?" + HOST_PATTERN + "(:" + PORT_PATTERN + ")?" + ")?" + PATH_PATTERN + "(\\?" + LAST_PATTERN + ")?"); - + private String scheme; private String userInfo; @@ -223,10 +223,10 @@ public class UriComponentsBuilder { } /** - * Builds a {@code UriComponents} instance and replaces URI template variables - * with the values from a map. This is a shortcut method, which combines - * calls to {@link #build()} and then {@link UriComponents#expand(Map)}. - * + * Builds a {@code UriComponents} instance and replaces URI template variables + * with the values from a map. This is a shortcut method, which combines + * calls to {@link #build()} and then {@link UriComponents#expand(Map)}. + * * @param uriVariables the map of URI variables * @return the URI components with expanded values */ @@ -235,17 +235,17 @@ public class UriComponentsBuilder { } /** - * Builds a {@code UriComponents} instance and replaces URI template variables - * with the values from an array. This is a shortcut method, which combines - * calls to {@link #build()} and then {@link UriComponents#expand(Object...)}. - * + * Builds a {@code UriComponents} instance and replaces URI template variables + * with the values from an array. This is a shortcut method, which combines + * calls to {@link #build()} and then {@link UriComponents#expand(Object...)}. + * * @param uriVariableValues URI variable values * @return the URI components with expanded values */ public UriComponents buildAndExpand(Object... uriVariableValues) { return build(false).expand(uriVariableValues); } - + // URI components methods /** @@ -347,8 +347,8 @@ public class UriComponentsBuilder { } /** - * Sets the path of this builder overriding all existing path and path segment values. - * + * Sets the path of this builder overriding all existing path and path segment values. + * * @param path the URI path; a {@code null} value results in an empty path. * @return this UriComponentsBuilder */ @@ -394,7 +394,7 @@ public class UriComponentsBuilder { /** * Sets the query of this builder overriding all existing query parameters. - * + * * @param query the query string; a {@code null} value removes all query parameters. * @return this UriComponentsBuilder */ @@ -430,7 +430,7 @@ public class UriComponentsBuilder { /** * Sets the query parameter values overriding all existing query values for the same parameter. * If no values are given, the query parameter is removed. - * + * * @param name the query parameter name * @param values the query parameter values * @return this UriComponentsBuilder @@ -443,7 +443,7 @@ public class UriComponentsBuilder { } return this; } - + /** * Sets the URI fragment. The given fragment may contain URI template variables, and may also be {@code null} to clear * the fragment of this builder. @@ -509,7 +509,17 @@ public class UriComponentsBuilder { private final List pathSegments = new ArrayList(); private PathSegmentComponentBuilder(String... pathSegments) { - Collections.addAll(this.pathSegments, pathSegments); + this.pathSegments.addAll(removeEmptyPathSegments(pathSegments)); + } + + private Collection removeEmptyPathSegments(String... pathSegments) { + List result = new ArrayList(); + for (String segment : pathSegments) { + if (StringUtils.hasText(segment)) { + result.add(segment); + } + } + return result; } public UriComponents.PathComponent build() { @@ -523,7 +533,7 @@ public class UriComponentsBuilder { } public PathComponentBuilder appendPathSegments(String... pathSegments) { - Collections.addAll(this.pathSegments, pathSegments); + this.pathSegments.addAll(removeEmptyPathSegments(pathSegments)); return this; } } diff --git a/org.springframework.web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java b/org.springframework.web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java index 303bcd2d15..2d9323ca8d 100644 --- a/org.springframework.web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java +++ b/org.springframework.web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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. @@ -45,7 +45,7 @@ public class UriComponentsBuilderTests { URI expected = new URI("http://example.com/foo?bar#baz"); assertEquals("Invalid result URI", expected, result.toUri()); } - + @Test public void fromPath() throws URISyntaxException { UriComponents result = UriComponentsBuilder.fromPath("foo").queryParam("bar").fragment("baz").build(); @@ -176,6 +176,15 @@ public class UriComponentsBuilderTests { assertEquals(Arrays.asList("foo"), result.getPathSegments()); } + @Test + public void pathSegmentsSomeEmpty() { + UriComponentsBuilder builder = UriComponentsBuilder.newInstance().pathSegment("", "foo", "", "bar"); + UriComponents result = builder.build(); + + assertEquals("/foo/bar", result.getPath()); + assertEquals(Arrays.asList("foo", "bar"), result.getPathSegments()); + } + @Test public void replacePath() { UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://www.ietf.org/rfc/rfc2396.txt"); @@ -183,26 +192,26 @@ public class UriComponentsBuilderTests { UriComponents result = builder.build(); assertEquals("http://www.ietf.org/rfc/rfc3986.txt", result.toUriString()); - + builder = UriComponentsBuilder.fromUriString("http://www.ietf.org/rfc/rfc2396.txt"); builder.replacePath(null); result = builder.build(); assertEquals("http://www.ietf.org", result.toUriString()); } - + @Test public void replaceQuery() { UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://example.com/foo?foo=bar&baz=qux"); builder.replaceQuery("baz=42"); UriComponents result = builder.build(); - + assertEquals("http://example.com/foo?baz=42", result.toUriString()); builder = UriComponentsBuilder.fromUriString("http://example.com/foo?foo=bar&baz=qux"); builder.replaceQuery(null); result = builder.build(); - + assertEquals("http://example.com/foo", result.toUriString()); } @@ -234,13 +243,13 @@ public class UriComponentsBuilderTests { UriComponentsBuilder builder = UriComponentsBuilder.newInstance().queryParam("baz", "qux", 42); builder.replaceQueryParam("baz", "xuq", 24); UriComponents result = builder.build(); - + assertEquals("baz=xuq&baz=24", result.getQuery()); builder = UriComponentsBuilder.newInstance().queryParam("baz", "qux", 42); builder.replaceQueryParam("baz"); result = builder.build(); - + assertNull("Query param should have been deleted", result.getQuery()); }