Browse Source

Add copyToUriComponentsBuilder method

After this change UriComponentsBuilder#uriComponents method no longer
no longer copies from the given UriComponents but rather lets the
UriComponents instance copy itself to the UriComponentsBuilder.

This avoids the need for instanceof checks and also makes it possible
to distinguish between path and path segments, which otherwise is
internal knowledge of UriComponentsBuilder.

Issue: SPR-12742
pull/759/head
Rossen Stoyanchev 10 years ago
parent
commit
0e7eecfe34
  1. 37
      spring-web/src/main/java/org/springframework/web/util/HierarchicalUriComponents.java
  2. 9
      spring-web/src/main/java/org/springframework/web/util/OpaqueUriComponents.java
  3. 8
      spring-web/src/main/java/org/springframework/web/util/UriComponents.java
  4. 47
      spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java
  5. 9
      spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java
  6. 13
      spring-web/src/test/java/org/springframework/web/util/UriComponentsTests.java

37
spring-web/src/main/java/org/springframework/web/util/HierarchicalUriComponents.java

@ -417,6 +417,19 @@ final class HierarchicalUriComponents extends UriComponents { @@ -417,6 +417,19 @@ final class HierarchicalUriComponents extends UriComponents {
}
}
@Override
protected void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
builder.scheme(getScheme());
builder.userInfo(getUserInfo());
builder.host(getHost());
builder.port(getPort());
builder.replacePath("");
this.path.copyToUriComponentsBuilder(builder);
builder.replaceQueryParams(getQueryParams());
builder.fragment(getFragment());
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
@ -608,6 +621,8 @@ final class HierarchicalUriComponents extends UriComponents { @@ -608,6 +621,8 @@ final class HierarchicalUriComponents extends UriComponents {
void verify();
PathComponent expand(UriTemplateVariables uriVariables);
void copyToUriComponentsBuilder(UriComponentsBuilder builder);
}
@ -651,6 +666,11 @@ final class HierarchicalUriComponents extends UriComponents { @@ -651,6 +666,11 @@ final class HierarchicalUriComponents extends UriComponents {
return new FullPathComponent(expandedPath);
}
@Override
public void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
builder.path(getPath());
}
@Override
public boolean equals(Object obj) {
return (this == obj || (obj instanceof FullPathComponent &&
@ -672,6 +692,7 @@ final class HierarchicalUriComponents extends UriComponents { @@ -672,6 +692,7 @@ final class HierarchicalUriComponents extends UriComponents {
private final List<String> pathSegments;
public PathSegmentComponent(List<String> pathSegments) {
Assert.notNull(pathSegments);
this.pathSegments = Collections.unmodifiableList(new ArrayList<String>(pathSegments));
}
@ -723,6 +744,11 @@ final class HierarchicalUriComponents extends UriComponents { @@ -723,6 +744,11 @@ final class HierarchicalUriComponents extends UriComponents {
return new PathSegmentComponent(expandedPathSegments);
}
@Override
public void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
builder.pathSegment(getPathSegments().toArray(new String[getPathSegments().size()]));
}
@Override
public boolean equals(Object obj) {
return (this == obj || (obj instanceof PathSegmentComponent &&
@ -744,6 +770,7 @@ final class HierarchicalUriComponents extends UriComponents { @@ -744,6 +770,7 @@ final class HierarchicalUriComponents extends UriComponents {
private final List<PathComponent> pathComponents;
public PathComponentComposite(List<PathComponent> pathComponents) {
Assert.notNull(pathComponents);
this.pathComponents = pathComponents;
}
@ -789,6 +816,13 @@ final class HierarchicalUriComponents extends UriComponents { @@ -789,6 +816,13 @@ final class HierarchicalUriComponents extends UriComponents {
}
return new PathComponentComposite(expandedComponents);
}
@Override
public void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
for (PathComponent pathComponent : this.pathComponents) {
pathComponent.copyToUriComponentsBuilder(builder);
}
}
}
@ -816,6 +850,9 @@ final class HierarchicalUriComponents extends UriComponents { @@ -816,6 +850,9 @@ final class HierarchicalUriComponents extends UriComponents {
return this;
}
@Override
public void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
}
@Override
public boolean equals(Object obj) {
return (this == obj);
}

9
spring-web/src/main/java/org/springframework/web/util/OpaqueUriComponents.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@ -135,6 +135,13 @@ final class OpaqueUriComponents extends UriComponents { @@ -135,6 +135,13 @@ final class OpaqueUriComponents extends UriComponents {
}
}
@Override
protected void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
builder.scheme(getScheme());
builder.schemeSpecificPart(getSchemeSpecificPart());
builder.fragment(getFragment());
}
@Override
public boolean equals(Object obj) {

8
spring-web/src/main/java/org/springframework/web/util/UriComponents.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@ -203,6 +203,12 @@ public abstract class UriComponents implements Serializable { @@ -203,6 +203,12 @@ public abstract class UriComponents implements Serializable {
return toUriString();
}
/**
* Set all components of the given UriComponentsBuilder.
* @since 4.2
*/
protected abstract void copyToUriComponentsBuilder(UriComponentsBuilder builder);
// static expansion helpers

47
spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java

@ -447,40 +447,7 @@ public class UriComponentsBuilder implements Cloneable { @@ -447,40 +447,7 @@ public class UriComponentsBuilder implements Cloneable {
*/
public UriComponentsBuilder uriComponents(UriComponents uriComponents) {
Assert.notNull(uriComponents, "'uriComponents' must not be null");
this.scheme = uriComponents.getScheme();
if (uriComponents instanceof OpaqueUriComponents) {
this.ssp = uriComponents.getSchemeSpecificPart();
resetHierarchicalComponents();
}
else {
if (uriComponents.getUserInfo() != null) {
this.userInfo = uriComponents.getUserInfo();
}
if (uriComponents.getHost() != null) {
this.host = uriComponents.getHost();
}
if (uriComponents.getPort() != -1) {
this.port = String.valueOf(uriComponents.getPort());
}
if (StringUtils.hasLength(uriComponents.getPath())) {
List<String> segments = uriComponents.getPathSegments();
if (segments.isEmpty()) {
// Perhaps "/"
this.pathBuilder.addPath(uriComponents.getPath());
}
else {
this.pathBuilder.addPathSegments(segments.toArray(new String[segments.size()]));
}
}
if (!uriComponents.getQueryParams().isEmpty()) {
this.queryParams.clear();
this.queryParams.putAll(uriComponents.getQueryParams());
}
resetSchemeSpecificPart();
}
if (uriComponents.getFragment() != null) {
this.fragment = uriComponents.getFragment();
}
uriComponents.copyToUriComponentsBuilder(this);
return this;
}
@ -679,6 +646,18 @@ public class UriComponentsBuilder implements Cloneable { @@ -679,6 +646,18 @@ public class UriComponentsBuilder implements Cloneable {
return this;
}
/**
* Set the query parameter values overriding all existing query values.
* @param params the query parameter name
* @return this UriComponentsBuilder
*/
public UriComponentsBuilder replaceQueryParams(MultiValueMap<String, String> params) {
Assert.notNull(params, "'params' must not be null");
this.queryParams.clear();
this.queryParams.putAll(params);
return this;
}
/**
* Set the URI fragment. The given fragment may contain URI template variables,
* and may also be {@code null} to clear the fragment of this builder.

9
spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java

@ -436,6 +436,15 @@ public class UriComponentsBuilderTests { @@ -436,6 +436,15 @@ public class UriComponentsBuilderTests {
assertEquals("https://a.example.org/mvc-showcase", result.toString());
}
// SPR-12742
@Test
public void fromHttpRequestWithTrailingSlash() throws Exception {
UriComponents before = UriComponentsBuilder.fromPath("/foo/").build();
UriComponents after = UriComponentsBuilder.newInstance().uriComponents(before).build();
assertEquals("/foo/", after.getPath());
}
@Test
public void path() throws URISyntaxException {
UriComponentsBuilder builder = UriComponentsBuilder.fromPath("/foo/bar");

13
spring-web/src/test/java/org/springframework/web/util/UriComponentsTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@ -22,6 +22,7 @@ import java.io.ObjectInputStream; @@ -22,6 +22,7 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import org.junit.Test;
@ -132,6 +133,16 @@ public class UriComponentsTests { @@ -132,6 +133,16 @@ public class UriComponentsTests {
assertThat(uriComponents.toString(), equalTo(readObject.toString()));
}
@Test
public void copyToUriComponentsBuilder() {
UriComponents source = UriComponentsBuilder.fromPath("/foo/bar").pathSegment("ba/z").build();
UriComponentsBuilder targetBuilder = UriComponentsBuilder.newInstance();
source.copyToUriComponentsBuilder(targetBuilder);
UriComponents result = targetBuilder.build().encode();
assertEquals("/foo/bar/ba%2Fz", result.getPath());
assertEquals(Arrays.asList("foo", "bar", "ba%2Fz"), result.getPathSegments());
}
@Test
public void equalsHierarchicalUriComponents() throws Exception {
UriComponents uriComponents1 = UriComponentsBuilder.fromUriString("http://example.com").path("/{foo}").query("bar={baz}").build();

Loading…
Cancel
Save