diff --git a/org.springframework.web/src/main/java/org/springframework/web/util/UriBuilder.java b/org.springframework.web/src/main/java/org/springframework/web/util/UriBuilder.java index f2e0b7364d..b27db5b16a 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/util/UriBuilder.java +++ b/org.springframework.web/src/main/java/org/springframework/web/util/UriBuilder.java @@ -220,8 +220,8 @@ public class UriBuilder { UriTemplate template; if (scheme != null) { - template = new UriTemplate(scheme, UriComponent.SCHEME); - uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariables)); + template = new UriComponentTemplate(scheme, UriComponent.SCHEME, encodeUriVariableValues); + uriBuilder.append(template.expandAsString(uriVariables)); uriBuilder.append(':'); } @@ -229,14 +229,14 @@ public class UriBuilder { uriBuilder.append("//"); if (StringUtils.hasLength(userInfo)) { - template = new UriTemplate(userInfo, UriComponent.USER_INFO); - uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariables)); + template = new UriComponentTemplate(userInfo, UriComponent.USER_INFO, encodeUriVariableValues); + uriBuilder.append(template.expandAsString(uriVariables)); uriBuilder.append('@'); } if (host != null) { - template = new UriTemplate(host, UriComponent.HOST); - uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariables)); + template = new UriComponentTemplate(host, UriComponent.HOST, encodeUriVariableValues); + uriBuilder.append(template.expandAsString(uriVariables)); } if (port != -1) { @@ -256,20 +256,20 @@ public class UriBuilder { else if (endsWithSlash && startsWithSlash) { pathSegment = pathSegment.substring(1); } - template = new UriTemplate(pathSegment, UriComponent.PATH_SEGMENT); - uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariables)); + template = new UriComponentTemplate(pathSegment, UriComponent.PATH_SEGMENT, encodeUriVariableValues); + uriBuilder.append(template.expandAsString(uriVariables)); } } if (queryBuilder.length() > 0) { uriBuilder.append('?'); - template = new UriTemplate(queryBuilder.toString(), UriComponent.QUERY); - uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariables)); + template = new UriComponentTemplate(queryBuilder.toString(), UriComponent.QUERY, encodeUriVariableValues); + uriBuilder.append(template.expandAsString(uriVariables)); } if (StringUtils.hasLength(fragment)) { uriBuilder.append('#'); - template = new UriTemplate(fragment, UriComponent.FRAGMENT); - uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariables)); + template = new UriComponentTemplate(fragment, UriComponent.FRAGMENT, encodeUriVariableValues); + uriBuilder.append(template.expandAsString(uriVariables)); } return URI.create(uriBuilder.toString()); @@ -308,8 +308,8 @@ public class UriBuilder { UriTemplate template; if (scheme != null) { - template = new UriTemplate(scheme, UriComponent.SCHEME); - uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariableValues)); + template = new UriComponentTemplate(scheme, UriComponent.SCHEME, encodeUriVariableValues); + uriBuilder.append(template.expandAsString(uriVariableValues)); uriBuilder.append(':'); } @@ -317,14 +317,14 @@ public class UriBuilder { uriBuilder.append("//"); if (StringUtils.hasLength(userInfo)) { - template = new UriTemplate(userInfo, UriComponent.USER_INFO); - uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariableValues)); + template = new UriComponentTemplate(userInfo, UriComponent.USER_INFO, encodeUriVariableValues); + uriBuilder.append(template.expandAsString(uriVariableValues)); uriBuilder.append('@'); } if (host != null) { - template = new UriTemplate(host, UriComponent.HOST); - uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariableValues)); + template = new UriComponentTemplate(host, UriComponent.HOST, encodeUriVariableValues); + uriBuilder.append(template.expandAsString(uriVariableValues)); } if (port != -1) { @@ -344,21 +344,21 @@ public class UriBuilder { else if (endsWithSlash && startsWithSlash) { pathSegment = pathSegment.substring(1); } - template = new UriTemplate(pathSegment, UriComponent.PATH_SEGMENT); - uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariableValues)); + template = new UriComponentTemplate(pathSegment, UriComponent.PATH_SEGMENT, encodeUriVariableValues); + uriBuilder.append(template.expandAsString(uriVariableValues)); } } if (queryBuilder.length() > 0) { uriBuilder.append('?'); - template = new UriTemplate(queryBuilder.toString(), UriComponent.QUERY); - uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariableValues)); + template = new UriComponentTemplate(queryBuilder.toString(), UriComponent.QUERY, encodeUriVariableValues); + uriBuilder.append(template.expandAsString(uriVariableValues)); } if (StringUtils.hasLength(fragment)) { uriBuilder.append('#'); - template = new UriTemplate(fragment, UriComponent.FRAGMENT); - uriBuilder.append(template.expandAsString(encodeUriVariableValues, uriVariableValues)); + template = new UriComponentTemplate(fragment, UriComponent.FRAGMENT, encodeUriVariableValues); + uriBuilder.append(template.expandAsString(uriVariableValues)); } return URI.create(uriBuilder.toString()); diff --git a/org.springframework.web/src/main/java/org/springframework/web/util/UriComponentTemplate.java b/org.springframework.web/src/main/java/org/springframework/web/util/UriComponentTemplate.java new file mode 100644 index 0000000000..d354ca2dcc --- /dev/null +++ b/org.springframework.web/src/main/java/org/springframework/web/util/UriComponentTemplate.java @@ -0,0 +1,46 @@ +/* + * 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.util; + +import org.springframework.util.Assert; + +/** + * Subclass of {@link UriTemplate} that operates on URI components, rather than full URIs. + * + * @author Arjen Poutsma + * @since 3.1 + */ +class UriComponentTemplate extends UriTemplate { + + private final UriComponent uriComponent; + + private boolean encodeUriVariableValues; + + UriComponentTemplate(String uriTemplate, UriComponent uriComponent, boolean encodeUriVariableValues) { + super(uriTemplate); + Assert.notNull(uriComponent, "'uriComponent' must not be null"); + this.uriComponent = uriComponent; + this.encodeUriVariableValues = encodeUriVariableValues; + } + + @Override + protected String getVariableValueAsString(Object variableValue) { + String variableValueString = super.getVariableValueAsString(variableValue); + return encodeUriVariableValues ? UriUtils.encode(variableValueString, uriComponent, false) : + variableValueString; + } +} diff --git a/org.springframework.web/src/main/java/org/springframework/web/util/UriTemplate.java b/org.springframework.web/src/main/java/org/springframework/web/util/UriTemplate.java index 51ebb22460..6026020b97 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/util/UriTemplate.java +++ b/org.springframework.web/src/main/java/org/springframework/web/util/UriTemplate.java @@ -56,8 +56,6 @@ public class UriTemplate implements Serializable { private final String uriTemplate; - private final UriComponent uriComponent; - /** * Construct a new {@link UriTemplate} with the given URI String. @@ -68,19 +66,6 @@ public class UriTemplate implements Serializable { this.uriTemplate = uriTemplate; this.variableNames = parser.getVariableNames(); this.matchPattern = parser.getMatchPattern(); - this.uriComponent = null; - } - - /** - * Construct a new {@link UriTemplate} with the given URI String. - * @param uriTemplate the URI template string - */ - public UriTemplate(String uriTemplate, UriComponent uriComponent) { - Parser parser = new Parser(uriTemplate); - this.uriTemplate = uriTemplate; - this.variableNames = parser.getVariableNames(); - this.matchPattern = parser.getMatchPattern(); - this.uriComponent = uriComponent; } /** @@ -110,7 +95,7 @@ public class UriTemplate implements Serializable { * or if it does not contain values for all the variable names */ public URI expand(Map uriVariables) { - return encodeUri(expandAsString(false, uriVariables)); + return encodeUri(expandAsString(uriVariables)); } /** @@ -125,13 +110,13 @@ public class UriTemplate implements Serializable { * System.out.println(template.expand(uriVariables)); * * will print:
http://example.com/hotels/1/bookings/42
- * @param encodeUriVariableValues indicates whether uri template variables should be encoded or not + * * @param uriVariables the map of URI variables * @return the expanded URI * @throws IllegalArgumentException if uriVariables is null; * or if it does not contain values for all the variable names */ - public String expandAsString(boolean encodeUriVariableValues, Map uriVariables) { + public String expandAsString(Map uriVariables) { Assert.notNull(uriVariables, "'uriVariables' must not be null"); Object[] values = new Object[this.variableNames.size()]; for (int i = 0; i < this.variableNames.size(); i++) { @@ -141,7 +126,7 @@ public class UriTemplate implements Serializable { } values[i] = uriVariables.get(name); } - return expandAsString(encodeUriVariableValues, values); + return expandAsString(values); } /** @@ -159,7 +144,7 @@ public class UriTemplate implements Serializable { * or if it does not contain sufficient variables */ public URI expand(Object... uriVariableValues) { - return encodeUri(expandAsString(false, uriVariableValues)); + return encodeUri(expandAsString(uriVariableValues)); } /** @@ -171,13 +156,13 @@ public class UriTemplate implements Serializable { * System.out.println(template.expand("1", "42)); * * will print:
http://example.com/hotels/1/bookings/42
- * @param encodeVariableValues indicates whether uri template variables should be encoded or not + * * @param uriVariableValues the array of URI variables * @return the expanded URI * @throws IllegalArgumentException if uriVariables is null * or if it does not contain sufficient variables */ - public String expandAsString(boolean encodeVariableValues, Object... uriVariableValues) { + public String expandAsString(Object... uriVariableValues) { Assert.notNull(uriVariableValues, "'uriVariableValues' must not be null"); if (uriVariableValues.length < this.variableNames.size()) { throw new IllegalArgumentException( @@ -188,18 +173,27 @@ public class UriTemplate implements Serializable { StringBuffer uriBuffer = new StringBuffer(); int i = 0; while (matcher.find()) { - Object uriVariable = uriVariableValues[i++]; - String uriVariableString = uriVariable != null ? uriVariable.toString() : ""; - if (encodeVariableValues && uriComponent != null) { - uriVariableString = UriUtils.encode(uriVariableString, uriComponent, false); - } - String replacement = Matcher.quoteReplacement(uriVariableString); + Object uriVariableValue = uriVariableValues[i++]; + String uriVariableValueString = getVariableValueAsString(uriVariableValue); + String replacement = Matcher.quoteReplacement(uriVariableValueString); matcher.appendReplacement(uriBuffer, replacement); } matcher.appendTail(uriBuffer); return uriBuffer.toString(); } + /** + * Template method that returns the string representation of the given URI template value. + * + *

Defaults implementation simply calls {@link Object#toString()}, or returns an empty string for {@code null}. + * + * @param variableValue the URI template variable value + * @return the variable value as string + */ + protected String getVariableValueAsString(Object variableValue) { + return variableValue != null ? variableValue.toString() : ""; + } + /** * Indicate whether the given URI matches this template. * @param uri the URI to match to