Browse Source

Polish HierarchicalUriComponents

pull/1271/head
Rossen Stoyanchev 11 years ago
parent
commit
a274ede3ef
  1. 97
      spring-web/src/main/java/org/springframework/web/util/HierarchicalUriComponents.java

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

@ -39,6 +39,7 @@ import org.springframework.util.StringUtils;
* Extension of {@link UriComponents} for hierarchical URIs. * Extension of {@link UriComponents} for hierarchical URIs.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Rossen Stoyanchev
* @author Phillip Webb * @author Phillip Webb
* @since 3.1.3 * @since 3.1.3
* @see <a href="http://tools.ietf.org/html/rfc3986#section-1.2.3">Hierarchical URIs</a> * @see <a href="http://tools.ietf.org/html/rfc3986#section-1.2.3">Hierarchical URIs</a>
@ -73,8 +74,9 @@ final class HierarchicalUriComponents extends UriComponents {
* @param encoded whether the components are already encoded * @param encoded whether the components are already encoded
* @param verify whether the components need to be checked for illegal characters * @param verify whether the components need to be checked for illegal characters
*/ */
HierarchicalUriComponents(String scheme, String userInfo, String host, String port, PathComponent path, HierarchicalUriComponents(String scheme, String userInfo, String host, String port,
MultiValueMap<String, String> queryParams, String fragment, boolean encoded, boolean verify) { PathComponent path, MultiValueMap<String, String> queryParams,
String fragment, boolean encoded, boolean verify) {
super(scheme, fragment); super(scheme, fragment);
this.userInfo = userInfo; this.userInfo = userInfo;
@ -175,41 +177,44 @@ final class HierarchicalUriComponents extends UriComponents {
// encoding // encoding
/** /**
* Encodes all URI components using their specific encoding rules, and returns the result as a new * Encode all URI components using their specific encoding rules and return
* {@code UriComponents} instance. * the result as a new {@code UriComponents} instance.
* @param encoding the encoding of the values contained in this map * @param encoding the encoding of the values contained in this map
* @return the encoded uri components * @return the encoded uri components
* @throws UnsupportedEncodingException if the given encoding is not supported * @throws UnsupportedEncodingException if the given encoding is not supported
*/ */
@Override @Override
public HierarchicalUriComponents encode(String encoding) throws UnsupportedEncodingException { public HierarchicalUriComponents encode(String encoding) throws UnsupportedEncodingException {
Assert.hasLength(encoding, "Encoding must not be empty");
if (this.encoded) { if (this.encoded) {
return this; return this;
} }
String encodedScheme = encodeUriComponent(getScheme(), encoding, Type.SCHEME); Assert.hasLength(encoding, "Encoding must not be empty");
String encodedUserInfo = encodeUriComponent(this.userInfo, encoding, Type.USER_INFO); String schemeTo = encodeUriComponent(getScheme(), encoding, Type.SCHEME);
String encodedHost = encodeUriComponent(this.host, encoding, getHostType()); String userInfoTo = encodeUriComponent(this.userInfo, encoding, Type.USER_INFO);
String hostTo = encodeUriComponent(this.host, encoding, getHostType());
PathComponent pathTo = this.path.encode(encoding);
MultiValueMap<String, String> paramsTo = encodeQueryParams(encoding);
String fragmentTo = encodeUriComponent(this.getFragment(), encoding, Type.FRAGMENT);
return new HierarchicalUriComponents(schemeTo, userInfoTo, hostTo, this.port,
pathTo, paramsTo, fragmentTo, true, false);
}
PathComponent encodedPath = this.path.encode(encoding); private MultiValueMap<String, String> encodeQueryParams(String encoding) throws UnsupportedEncodingException {
MultiValueMap<String, String> encodedQueryParams = int size = this.queryParams.size();
new LinkedMultiValueMap<String, String>(this.queryParams.size()); MultiValueMap<String, String> result = new LinkedMultiValueMap<String, String>(size);
for (Map.Entry<String, List<String>> entry : this.queryParams.entrySet()) { for (Map.Entry<String, List<String>> entry : this.queryParams.entrySet()) {
String encodedName = encodeUriComponent(entry.getKey(), encoding, Type.QUERY_PARAM); String name = encodeUriComponent(entry.getKey(), encoding, Type.QUERY_PARAM);
List<String> encodedValues = new ArrayList<String>(entry.getValue().size()); List<String> values = new ArrayList<String>(entry.getValue().size());
for (String value : entry.getValue()) { for (String value : entry.getValue()) {
String encodedValue = encodeUriComponent(value, encoding, Type.QUERY_PARAM); values.add(encodeUriComponent(value, encoding, Type.QUERY_PARAM));
encodedValues.add(encodedValue);
} }
encodedQueryParams.put(encodedName, encodedValues); result.put(name, values);
} }
String encodedFragment = encodeUriComponent(this.getFragment(), encoding, Type.FRAGMENT); return result;
return new HierarchicalUriComponents(encodedScheme, encodedUserInfo, encodedHost, this.port, encodedPath,
encodedQueryParams, encodedFragment, true, false);
} }
/** /**
* Encodes the given source into an encoded String using the rules specified * Encode the given source into an encoded String using the rules specified
* by the given component and with the given options. * by the given component and with the given options.
* @param source the source string * @param source the source string
* @param encoding the encoding of the source string * @param encoding the encoding of the source string
@ -217,7 +222,9 @@ final class HierarchicalUriComponents extends UriComponents {
* @return the encoded URI * @return the encoded URI
* @throws IllegalArgumentException when the given uri parameter is not a valid URI * @throws IllegalArgumentException when the given uri parameter is not a valid URI
*/ */
static String encodeUriComponent(String source, String encoding, Type type) throws UnsupportedEncodingException { static String encodeUriComponent(String source, String encoding, Type type)
throws UnsupportedEncodingException {
if (source == null) { if (source == null) {
return null; return null;
} }
@ -291,17 +298,19 @@ final class HierarchicalUriComponents extends UriComponents {
int u = Character.digit(hex1, 16); int u = Character.digit(hex1, 16);
int l = Character.digit(hex2, 16); int l = Character.digit(hex2, 16);
if (u == -1 || l == -1) { if (u == -1 || l == -1) {
throw new IllegalArgumentException("Invalid encoded sequence \"" + source.substring(i) + "\""); throw new IllegalArgumentException("Invalid encoded sequence \"" +
source.substring(i) + "\"");
} }
i += 2; i += 2;
} }
else { else {
throw new IllegalArgumentException("Invalid encoded sequence \"" + source.substring(i) + "\""); throw new IllegalArgumentException("Invalid encoded sequence \"" +
source.substring(i) + "\"");
} }
} }
else if (!type.isAllowed(ch)) { else if (!type.isAllowed(ch)) {
throw new IllegalArgumentException( throw new IllegalArgumentException("Invalid character '" + ch + "' for " +
"Invalid character '" + ch + "' for " + type.name() + " in \"" + source + "\""); type.name() + " in \"" + source + "\"");
} }
} }
} }
@ -312,25 +321,31 @@ final class HierarchicalUriComponents extends UriComponents {
@Override @Override
protected HierarchicalUriComponents expandInternal(UriTemplateVariables uriVariables) { protected HierarchicalUriComponents expandInternal(UriTemplateVariables uriVariables) {
Assert.state(!this.encoded, "Cannot expand an already encoded UriComponents object"); Assert.state(!this.encoded, "Cannot expand an already encoded UriComponents object");
String expandedScheme = expandUriComponent(getScheme(), uriVariables);
String expandedUserInfo = expandUriComponent(this.userInfo, uriVariables); String schemeTo = expandUriComponent(getScheme(), uriVariables);
String expandedHost = expandUriComponent(this.host, uriVariables); String userInfoTo = expandUriComponent(this.userInfo, uriVariables);
String expandedPort = expandUriComponent(this.port, uriVariables); String hostTo = expandUriComponent(this.host, uriVariables);
PathComponent expandedPath = this.path.expand(uriVariables); String portTo = expandUriComponent(this.port, uriVariables);
MultiValueMap<String, String> expandedQueryParams = PathComponent pathTo = this.path.expand(uriVariables);
new LinkedMultiValueMap<String, String>(this.queryParams.size()); MultiValueMap<String, String> paramsTo = expandQueryParams(uriVariables);
String fragmentTo = expandUriComponent(this.getFragment(), uriVariables);
return new HierarchicalUriComponents(schemeTo, userInfoTo, hostTo, portTo,
pathTo, paramsTo, fragmentTo, false, false);
}
private MultiValueMap<String, String> expandQueryParams(UriTemplateVariables variables) {
int size = this.queryParams.size();
MultiValueMap<String, String> result = new LinkedMultiValueMap<String, String>(size);
for (Map.Entry<String, List<String>> entry : this.queryParams.entrySet()) { for (Map.Entry<String, List<String>> entry : this.queryParams.entrySet()) {
String expandedName = expandUriComponent(entry.getKey(), uriVariables); String name = expandUriComponent(entry.getKey(), variables);
List<String> expandedValues = new ArrayList<String>(entry.getValue().size()); List<String> values = new ArrayList<String>(entry.getValue().size());
for (String value : entry.getValue()) { for (String value : entry.getValue()) {
String expandedValue = expandUriComponent(value, uriVariables); values.add(expandUriComponent(value, variables));
expandedValues.add(expandedValue);
} }
expandedQueryParams.put(expandedName, expandedValues); result.put(name, values);
} }
String expandedFragment = expandUriComponent(this.getFragment(), uriVariables); return result;
return new HierarchicalUriComponents(expandedScheme, expandedUserInfo, expandedHost, expandedPort, expandedPath,
expandedQueryParams, expandedFragment, false, false);
} }
/** /**
@ -468,7 +483,7 @@ final class HierarchicalUriComponents extends UriComponents {
* <p>Contains methods to indicate whether a given character is valid in a specific URI component. * <p>Contains methods to indicate whether a given character is valid in a specific URI component.
* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a> * @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>
*/ */
static enum Type { enum Type {
SCHEME { SCHEME {
@Override @Override

Loading…
Cancel
Save