SPR-5973: Made UriComponent enum inner type of UriComponents

This commit is contained in:
Arjen Poutsma 2011-09-09 10:57:13 +00:00
parent 6c58da0e55
commit 65baafa032
6 changed files with 298 additions and 315 deletions

View File

@ -176,10 +176,10 @@ public class UriBuilder {
if (CollectionUtils.isEmpty(uriVariables)) {
return build();
}
String scheme = expand(this.scheme, UriComponent.SCHEME, uriVariables, encodeUriVariableValues);
String userInfo = expand(this.userInfo, UriComponent.USER_INFO, uriVariables, encodeUriVariableValues);
String host = expand(this.host, UriComponent.HOST, uriVariables, encodeUriVariableValues);
String port = expand(this.portAsString(), UriComponent.PORT, uriVariables, encodeUriVariableValues);
String scheme = expand(this.scheme, UriComponents.Type.SCHEME, uriVariables, encodeUriVariableValues);
String userInfo = expand(this.userInfo, UriComponents.Type.USER_INFO, uriVariables, encodeUriVariableValues);
String host = expand(this.host, UriComponents.Type.HOST, uriVariables, encodeUriVariableValues);
String port = expand(this.portAsString(), UriComponents.Type.PORT, uriVariables, encodeUriVariableValues);
String path = null;
if (!this.pathSegments.isEmpty()) {
StringBuilder pathBuilder = new StringBuilder();
@ -193,20 +193,20 @@ public class UriBuilder {
else if (endsWithSlash && startsWithSlash) {
pathSegment = pathSegment.substring(1);
}
pathSegment = expand(pathSegment, UriComponent.PATH_SEGMENT, uriVariables, encodeUriVariableValues);
pathSegment = expand(pathSegment, UriComponents.Type.PATH_SEGMENT, uriVariables, encodeUriVariableValues);
pathBuilder.append(pathSegment);
}
path = pathBuilder.toString();
}
String query = expand(this.queryAsString(), UriComponent.QUERY, uriVariables, encodeUriVariableValues);
String fragment = expand(this.fragment, UriComponent.FRAGMENT, uriVariables, encodeUriVariableValues);
String query = expand(this.queryAsString(), UriComponents.Type.QUERY, uriVariables, encodeUriVariableValues);
String fragment = expand(this.fragment, UriComponents.Type.FRAGMENT, uriVariables, encodeUriVariableValues);
String uri = UriUtils.buildUri(scheme, null, userInfo, host, port, path, query, fragment);
return URI.create(uri);
}
private String expand(String source,
UriComponent uriComponent,
UriComponents.Type uriComponent,
Map<String, ?> uriVariables,
boolean encodeUriVariableValues) {
if (source == null) {
@ -252,7 +252,7 @@ public class UriBuilder {
UriTemplate template;
if (scheme != null) {
template = new UriComponentTemplate(scheme, UriComponent.SCHEME, encodeUriVariableValues);
template = new UriComponentTemplate(scheme, UriComponents.Type.SCHEME, encodeUriVariableValues);
uriBuilder.append(template.expandAsString(uriVariableValues));
uriBuilder.append(':');
}
@ -261,13 +261,13 @@ public class UriBuilder {
uriBuilder.append("//");
if (StringUtils.hasLength(userInfo)) {
template = new UriComponentTemplate(userInfo, UriComponent.USER_INFO, encodeUriVariableValues);
template = new UriComponentTemplate(userInfo, UriComponents.Type.USER_INFO, encodeUriVariableValues);
uriBuilder.append(template.expandAsString(uriVariableValues));
uriBuilder.append('@');
}
if (host != null) {
template = new UriComponentTemplate(host, UriComponent.HOST, encodeUriVariableValues);
template = new UriComponentTemplate(host, UriComponents.Type.HOST, encodeUriVariableValues);
uriBuilder.append(template.expandAsString(uriVariableValues));
}
@ -288,20 +288,20 @@ public class UriBuilder {
else if (endsWithSlash && startsWithSlash) {
pathSegment = pathSegment.substring(1);
}
template = new UriComponentTemplate(pathSegment, UriComponent.PATH_SEGMENT, encodeUriVariableValues);
template = new UriComponentTemplate(pathSegment, UriComponents.Type.PATH_SEGMENT, encodeUriVariableValues);
uriBuilder.append(template.expandAsString(uriVariableValues));
}
}
if (queryBuilder.length() > 0) {
uriBuilder.append('?');
template = new UriComponentTemplate(queryBuilder.toString(), UriComponent.QUERY, encodeUriVariableValues);
template = new UriComponentTemplate(queryBuilder.toString(), UriComponents.Type.QUERY, encodeUriVariableValues);
uriBuilder.append(template.expandAsString(uriVariableValues));
}
if (StringUtils.hasLength(fragment)) {
uriBuilder.append('#');
template = new UriComponentTemplate(fragment, UriComponent.FRAGMENT, encodeUriVariableValues);
template = new UriComponentTemplate(fragment, UriComponents.Type.FRAGMENT, encodeUriVariableValues);
uriBuilder.append(template.expandAsString(uriVariableValues));
}
@ -357,7 +357,7 @@ public class UriBuilder {
public UriBuilder scheme(String scheme) {
if (scheme != null) {
Assert.hasLength(scheme, "'scheme' must not be empty");
this.scheme = encodeUriComponent(scheme, UriComponent.SCHEME);
this.scheme = encodeUriComponent(scheme, UriComponents.Type.SCHEME);
}
else {
this.scheme = null;
@ -375,7 +375,7 @@ public class UriBuilder {
public UriBuilder userInfo(String userInfo) {
if (userInfo != null) {
Assert.hasLength(userInfo, "'userInfo' must not be empty");
this.userInfo = encodeUriComponent(userInfo, UriComponent.USER_INFO);
this.userInfo = encodeUriComponent(userInfo, UriComponents.Type.USER_INFO);
}
else {
this.userInfo = null;
@ -393,7 +393,7 @@ public class UriBuilder {
public UriBuilder host(String host) {
if (host != null) {
Assert.hasLength(host, "'host' must not be empty");
this.host = encodeUriComponent(host, UriComponent.HOST);
this.host = encodeUriComponent(host, UriComponents.Type.HOST);
}
else {
this.host = null;
@ -440,7 +440,7 @@ public class UriBuilder {
public UriBuilder pathSegment(String... segments) throws IllegalArgumentException {
Assert.notNull(segments, "'segments' must not be null");
for (String segment : segments) {
this.pathSegments.add(encodeUriComponent(segment, UriComponent.PATH_SEGMENT));
this.pathSegments.add(encodeUriComponent(segment, UriComponents.Type.PATH_SEGMENT));
}
return this;
@ -458,7 +458,7 @@ public class UriBuilder {
public UriBuilder queryParam(String name, Object... values) {
Assert.notNull(name, "'name' must not be null");
String encodedName = encodeUriComponent(name, UriComponent.QUERY_PARAM);
String encodedName = encodeUriComponent(name, UriComponents.Type.QUERY_PARAM);
if (ObjectUtils.isEmpty(values)) {
if (queryBuilder.length() != 0) {
@ -476,7 +476,7 @@ public class UriBuilder {
String valueAsString = value != null ? value.toString() : "";
if (valueAsString.length() != 0) {
queryBuilder.append('=');
queryBuilder.append(encodeUriComponent(valueAsString, UriComponent.QUERY_PARAM));
queryBuilder.append(encodeUriComponent(valueAsString, UriComponents.Type.QUERY_PARAM));
}
}
@ -498,7 +498,7 @@ public class UriBuilder {
public UriBuilder fragment(String fragment) {
if (fragment != null) {
Assert.hasLength(fragment, "'fragment' must not be empty");
this.fragment = encodeUriComponent(fragment, UriComponent.FRAGMENT);
this.fragment = encodeUriComponent(fragment, UriComponents.Type.FRAGMENT);
}
else {
this.fragment = null;
@ -507,7 +507,7 @@ public class UriBuilder {
}
private String encodeUriComponent(String source, UriComponent uriComponent) {
private String encodeUriComponent(String source, UriComponents.Type uriComponent) {
return UriUtils.encodeUriComponent(source, uriComponent, EnumSet.of(UriUtils.EncodingOption.ALLOW_TEMPLATE_VARS));
}

View File

@ -1,168 +0,0 @@
/*
* 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;
/**
* Enumeration used to identify the parts of a URI.
*
* <p>Contains methods to indicate whether a given character is valid in a specific URI component.
*
* @author Arjen Poutsma
* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>
* @since 3.1
*/
public enum UriComponent {
SCHEME {
@Override
public boolean isAllowed(int c) {
return isAlpha(c) || isDigit(c) || '+' == c || '-' == c || '.' == c;
}
},
AUTHORITY {
@Override
public boolean isAllowed(int c) {
return isUnreserved(c) || isSubDelimiter(c) || ':' == c || '@' == c;
}
},
USER_INFO {
@Override
public boolean isAllowed(int c) {
return isUnreserved(c) || isSubDelimiter(c) || ':' == c;
}
},
HOST {
@Override
public boolean isAllowed(int c) {
return isUnreserved(c) || isSubDelimiter(c);
}
},
PORT {
@Override
public boolean isAllowed(int c) {
return isDigit(c);
}
},
PATH {
@Override
public boolean isAllowed(int c) {
return isPchar(c) || '/' == c;
}
},
PATH_SEGMENT {
@Override
public boolean isAllowed(int c) {
return isPchar(c);
}
},
QUERY {
@Override
public boolean isAllowed(int c) {
return isPchar(c) || '/' == c || '?' == c;
}
},
QUERY_PARAM {
@Override
public boolean isAllowed(int c) {
if ('=' == c || '+' == c || '&' == c) {
return false;
}
else {
return isPchar(c) || '/' == c || '?' == c;
}
}
},
FRAGMENT {
@Override
public boolean isAllowed(int c) {
return isPchar(c) || '/' == c || '?' == c;
}
};
/**
* Indicates whether the given character is allowed in this URI component.
*
* @param c the character
* @return {@code true} if the character is allowed; {@code false} otherwise
*/
public abstract boolean isAllowed(int c);
/**
* Indicates whether the given character is in the {@code ALPHA} set.
*
* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
*/
protected boolean isAlpha(int c) {
return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
}
/**
* Indicates whether the given character is in the {@code DIGIT} set.
*
* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
*/
protected boolean isDigit(int c) {
return c >= '0' && c <= '9';
}
/**
* Indicates whether the given character is in the {@code gen-delims} set.
*
* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
*/
protected boolean isGenericDelimiter(int c) {
return ':' == c || '/' == c || '?' == c || '#' == c || '[' == c || ']' == c || '@' == c;
}
/**
* Indicates whether the given character is in the {@code sub-delims} set.
*
* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
*/
protected boolean isSubDelimiter(int c) {
return '!' == c || '$' == c || '&' == c || '\'' == c || '(' == c || ')' == c || '*' == c || '+' == c ||
',' == c || ';' == c || '=' == c;
}
/**
* Indicates whether the given character is in the {@code reserved} set.
*
* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
*/
protected boolean isReserved(char c) {
return isGenericDelimiter(c) || isReserved(c);
}
/**
* Indicates whether the given character is in the {@code unreserved} set.
*
* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
*/
protected boolean isUnreserved(int c) {
return isAlpha(c) || isDigit(c) || '-' == c || '.' == c || '_' == c || '~' == c;
}
/**
* Indicates whether the given character is in the {@code pchar} set.
*
* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
*/
protected boolean isPchar(int c) {
return isUnreserved(c) || isSubDelimiter(c) || ':' == c || '@' == c;
}
}

View File

@ -26,11 +26,11 @@ import org.springframework.util.Assert;
*/
class UriComponentTemplate extends UriTemplate {
private final UriComponent uriComponent;
private final UriComponents.Type uriComponent;
private boolean encodeUriVariableValues;
UriComponentTemplate(String uriTemplate, UriComponent uriComponent, boolean encodeUriVariableValues) {
UriComponentTemplate(String uriTemplate, UriComponents.Type uriComponent, boolean encodeUriVariableValues) {
super(uriTemplate);
Assert.notNull(uriComponent, "'uriComponent' must not be null");
this.uriComponent = uriComponent;

View File

@ -37,24 +37,24 @@ import org.springframework.util.StringUtils;
* Represents the components that make up a URI, mapping component type to string values. Contains convenience getters
* and setters for all components, as well as the regular {@link Map} implementation.
*
* <p>This mapping does not contain mappings for {@link UriComponent#PATH_SEGMENT} or nor {@link
* UriComponent#QUERY_PARAM}, since those components can occur multiple times in the URI. Instead, one can use {@link
* <p>This mapping does not contain mappings for {@link org.springframework.web.util.UriComponents.Type#PATH_SEGMENT} or nor {@link
* org.springframework.web.util.UriComponents.Type#QUERY_PARAM}, since those components can occur multiple times in the URI. Instead, one can use {@link
* #getPathSegments()} or {@link #getQueryParams()} respectively.
*
* @author Arjen Poutsma
* @since 3.1
*/
public class UriComponents implements Map<UriComponent, String> {
public class UriComponents implements Map<UriComponents.Type, String> {
private static final String PATH_DELIMITER = "/";
private static final Pattern QUERY_PARAM_PATTERN = Pattern.compile("([^&=]+)=?([^&=]+)?");
private final Map<UriComponent, String> uriComponents;
private final Map<Type, String> uriComponents;
/** Constructs a new, empty instance of the {@code UriComponents} object. */
public UriComponents() {
this.uriComponents = new EnumMap<UriComponent, String>(UriComponent.class);
this.uriComponents = new EnumMap<Type, String>(Type.class);
}
/**
@ -62,9 +62,9 @@ public class UriComponents implements Map<UriComponent, String> {
*
* @param uriComponents the component to initialize with
*/
public UriComponents(Map<UriComponent, String> uriComponents) {
public UriComponents(Map<Type, String> uriComponents) {
Assert.notNull(uriComponents, "'uriComponents' must not be null");
this.uriComponents = new EnumMap<UriComponent, String>(uriComponents);
this.uriComponents = new EnumMap<Type, String>(uriComponents);
}
// convenience properties
@ -75,7 +75,7 @@ public class UriComponents implements Map<UriComponent, String> {
* @return the scheme. Can be {@code null}.
*/
public String getScheme() {
return get(UriComponent.SCHEME);
return get(Type.SCHEME);
}
/**
@ -84,7 +84,7 @@ public class UriComponents implements Map<UriComponent, String> {
* @param scheme the scheme. Can be {@code null}.
*/
public void setScheme(String scheme) {
put(UriComponent.SCHEME, scheme);
put(Type.SCHEME, scheme);
}
/**
@ -93,7 +93,7 @@ public class UriComponents implements Map<UriComponent, String> {
* @return the authority. Can be {@code null}.
*/
public String getAuthority() {
return get(UriComponent.AUTHORITY);
return get(Type.AUTHORITY);
}
/**
@ -102,7 +102,7 @@ public class UriComponents implements Map<UriComponent, String> {
* @param authority the authority. Can be {@code null}.
*/
public void setAuthority(String authority) {
put(UriComponent.AUTHORITY, authority);
put(Type.AUTHORITY, authority);
}
/**
@ -111,7 +111,7 @@ public class UriComponents implements Map<UriComponent, String> {
* @return the user info. Can be {@code null}.
*/
public String getUserInfo() {
return get(UriComponent.USER_INFO);
return get(Type.USER_INFO);
}
/**
@ -120,7 +120,7 @@ public class UriComponents implements Map<UriComponent, String> {
* @param userInfo the user info. Can be {@code null}
*/
public void setUserInfo(String userInfo) {
put(UriComponent.USER_INFO, userInfo);
put(Type.USER_INFO, userInfo);
}
/**
@ -129,7 +129,7 @@ public class UriComponents implements Map<UriComponent, String> {
* @return the host. Can be {@code null}.
*/
public String getHost() {
return get(UriComponent.HOST);
return get(Type.HOST);
}
/**
@ -138,7 +138,7 @@ public class UriComponents implements Map<UriComponent, String> {
* @param host the host. Can be {@code null}.
*/
public void setHost(String host) {
put(UriComponent.HOST, host);
put(Type.HOST, host);
}
/**
@ -147,7 +147,7 @@ public class UriComponents implements Map<UriComponent, String> {
* @return the port as string. Can be {@code null}.
*/
public String getPort() {
return get(UriComponent.PORT);
return get(Type.PORT);
}
/**
@ -156,7 +156,7 @@ public class UriComponents implements Map<UriComponent, String> {
* @param port the port as string. Can be {@code null}.
*/
public void setPort(String port) {
put(UriComponent.PORT, port);
put(Type.PORT, port);
}
/**
@ -176,7 +176,7 @@ public class UriComponents implements Map<UriComponent, String> {
*/
public void setPortAsInteger(int port) {
String portString = port > -1 ? Integer.toString(port) : null;
put(UriComponent.PORT, portString);
put(Type.PORT, portString);
}
/**
@ -185,7 +185,7 @@ public class UriComponents implements Map<UriComponent, String> {
* @return the path. Can be {@code null}.
*/
public String getPath() {
return get(UriComponent.PATH);
return get(Type.PATH);
}
/**
@ -194,7 +194,7 @@ public class UriComponents implements Map<UriComponent, String> {
* @param path the path. Can be {@code null}.
*/
public void setPath(String path) {
put(UriComponent.PATH, path);
put(Type.PATH, path);
}
/**
@ -240,7 +240,7 @@ public class UriComponents implements Map<UriComponent, String> {
* @return the query. Can be {@code null}.
*/
public String getQuery() {
return get(UriComponent.QUERY);
return get(Type.QUERY);
}
/**
@ -249,7 +249,7 @@ public class UriComponents implements Map<UriComponent, String> {
* @param query the query. Can be {@code null}.
*/
public void setQuery(String query) {
put(UriComponent.QUERY, query);
put(Type.QUERY, query);
}
/**
@ -315,7 +315,7 @@ public class UriComponents implements Map<UriComponent, String> {
* @return the fragment. Can be {@code null}.
*/
public String getFragment() {
return get(UriComponent.FRAGMENT);
return get(Type.FRAGMENT);
}
/**
@ -324,7 +324,7 @@ public class UriComponents implements Map<UriComponent, String> {
* @param fragment the fragment. Can be {@code null}.
*/
public void setFragment(String fragment) {
put(UriComponent.FRAGMENT, fragment);
put(Type.FRAGMENT, fragment);
}
// Map implementation
@ -349,7 +349,7 @@ public class UriComponents implements Map<UriComponent, String> {
return this.uriComponents.get(key);
}
public String put(UriComponent key, String value) {
public String put(Type key, String value) {
return this.uriComponents.put(key, value);
}
@ -357,7 +357,7 @@ public class UriComponents implements Map<UriComponent, String> {
return this.uriComponents.remove(key);
}
public void putAll(Map<? extends UriComponent, ? extends String> m) {
public void putAll(Map<? extends Type, ? extends String> m) {
this.uriComponents.putAll(m);
}
@ -365,7 +365,7 @@ public class UriComponents implements Map<UriComponent, String> {
this.uriComponents.clear();
}
public Set<UriComponent> keySet() {
public Set<Type> keySet() {
return this.uriComponents.keySet();
}
@ -373,7 +373,7 @@ public class UriComponents implements Map<UriComponent, String> {
return this.uriComponents.values();
}
public Set<Entry<UriComponent, String>> entrySet() {
public Set<Entry<Type, String>> entrySet() {
return this.uriComponents.entrySet();
}
@ -399,5 +399,155 @@ public class UriComponents implements Map<UriComponent, String> {
return this.uriComponents.toString();
}
// inner types
/**
* Enumeration used to identify the parts of a URI.
*
* <p>Contains methods to indicate whether a given character is valid in a specific URI component.
*
* @author Arjen Poutsma
* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>
*/
public static enum Type {
SCHEME {
@Override
public boolean isAllowed(int c) {
return isAlpha(c) || isDigit(c) || '+' == c || '-' == c || '.' == c;
}
},
AUTHORITY {
@Override
public boolean isAllowed(int c) {
return isUnreserved(c) || isSubDelimiter(c) || ':' == c || '@' == c;
}
},
USER_INFO {
@Override
public boolean isAllowed(int c) {
return isUnreserved(c) || isSubDelimiter(c) || ':' == c;
}
},
HOST {
@Override
public boolean isAllowed(int c) {
return isUnreserved(c) || isSubDelimiter(c);
}
},
PORT {
@Override
public boolean isAllowed(int c) {
return isDigit(c);
}
},
PATH {
@Override
public boolean isAllowed(int c) {
return isPchar(c) || '/' == c;
}
},
PATH_SEGMENT {
@Override
public boolean isAllowed(int c) {
return isPchar(c);
}
},
QUERY {
@Override
public boolean isAllowed(int c) {
return isPchar(c) || '/' == c || '?' == c;
}
},
QUERY_PARAM {
@Override
public boolean isAllowed(int c) {
if ('=' == c || '+' == c || '&' == c) {
return false;
}
else {
return isPchar(c) || '/' == c || '?' == c;
}
}
},
FRAGMENT {
@Override
public boolean isAllowed(int c) {
return isPchar(c) || '/' == c || '?' == c;
}
};
/**
* Indicates whether the given character is allowed in this URI component.
*
* @param c the character
* @return {@code true} if the character is allowed; {@code false} otherwise
*/
public abstract boolean isAllowed(int c);
/**
* Indicates whether the given character is in the {@code ALPHA} set.
*
* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
*/
protected boolean isAlpha(int c) {
return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
}
/**
* Indicates whether the given character is in the {@code DIGIT} set.
*
* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
*/
protected boolean isDigit(int c) {
return c >= '0' && c <= '9';
}
/**
* Indicates whether the given character is in the {@code gen-delims} set.
*
* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
*/
protected boolean isGenericDelimiter(int c) {
return ':' == c || '/' == c || '?' == c || '#' == c || '[' == c || ']' == c || '@' == c;
}
/**
* Indicates whether the given character is in the {@code sub-delims} set.
*
* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
*/
protected boolean isSubDelimiter(int c) {
return '!' == c || '$' == c || '&' == c || '\'' == c || '(' == c || ')' == c || '*' == c || '+' == c ||
',' == c || ';' == c || '=' == c;
}
/**
* Indicates whether the given character is in the {@code reserved} set.
*
* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
*/
protected boolean isReserved(char c) {
return isGenericDelimiter(c) || isReserved(c);
}
/**
* Indicates whether the given character is in the {@code unreserved} set.
*
* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
*/
protected boolean isUnreserved(int c) {
return isAlpha(c) || isDigit(c) || '-' == c || '.' == c || '_' == c || '~' == c;
}
/**
* Indicates whether the given character is in the {@code pchar} set.
*
* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
*/
protected boolean isPchar(int c) {
return isUnreserved(c) || isSubDelimiter(c) || ':' == c || '@' == c;
}
}
}

View File

@ -79,37 +79,37 @@ public abstract class UriUtils {
*
* <p>The returned map will contain keys for
* <ul>
* <li>{@link UriComponent#SCHEME}</li>
* <li>{@link UriComponent#AUTHORITY}</li>
* <li>{@link UriComponent#USER_INFO}</li>
* <li>{@link UriComponent#HOST}</li>
* <li>{@link UriComponent#PORT}</li>
* <li>{@link UriComponent#PATH}</li>
* <li>{@link UriComponent#QUERY}</li>
* <li>{@link UriComponent#FRAGMENT}</li>
* <li>{@link org.springframework.web.util.UriComponents.Type#SCHEME}</li>
* <li>{@link org.springframework.web.util.UriComponents.Type#AUTHORITY}</li>
* <li>{@link org.springframework.web.util.UriComponents.Type#USER_INFO}</li>
* <li>{@link org.springframework.web.util.UriComponents.Type#HOST}</li>
* <li>{@link org.springframework.web.util.UriComponents.Type#PORT}</li>
* <li>{@link org.springframework.web.util.UriComponents.Type#PATH}</li>
* <li>{@link org.springframework.web.util.UriComponents.Type#QUERY}</li>
* <li>{@link org.springframework.web.util.UriComponents.Type#FRAGMENT}</li>
* </ul>
* though the values assigned to these keys is {@code null} if they do not occur in the given source URI.
*
* <p><strong>Note</strong> that the returned map will never contain mappings for {@link UriComponent#PATH_SEGMENT},
* nor {@link UriComponent#QUERY_PARAM}, since those components can occur multiple times in the URI.
* <p><strong>Note</strong> that the returned map will never contain mappings for {@link org.springframework.web.util.UriComponents.Type#PATH_SEGMENT},
* nor {@link org.springframework.web.util.UriComponents.Type#QUERY_PARAM}, since those components can occur multiple times in the URI.
*
* @param uri the source URI
* @return the URI components of the URI
*/
public static Map<UriComponent, String> parseUriComponents(String uri) {
public static Map<UriComponents.Type, String> parseUriComponents(String uri) {
Assert.notNull(uri, "'uri' must not be null");
Matcher m = URI_PATTERN.matcher(uri);
if (m.matches()) {
Map<UriComponent, String> result = new EnumMap<UriComponent, String>(UriComponent.class);
Map<UriComponents.Type, String> result = new EnumMap<UriComponents.Type, String>(UriComponents.Type.class);
result.put(UriComponent.SCHEME, m.group(2));
result.put(UriComponent.AUTHORITY, m.group(3));
result.put(UriComponent.USER_INFO, m.group(5));
result.put(UriComponent.HOST, m.group(6));
result.put(UriComponent.PORT, m.group(8));
result.put(UriComponent.PATH, m.group(9));
result.put(UriComponent.QUERY, m.group(11));
result.put(UriComponent.FRAGMENT, m.group(13));
result.put(UriComponents.Type.SCHEME, m.group(2));
result.put(UriComponents.Type.AUTHORITY, m.group(3));
result.put(UriComponents.Type.USER_INFO, m.group(5));
result.put(UriComponents.Type.HOST, m.group(6));
result.put(UriComponents.Type.PORT, m.group(8));
result.put(UriComponents.Type.PATH, m.group(9));
result.put(UriComponents.Type.QUERY, m.group(11));
result.put(UriComponents.Type.FRAGMENT, m.group(13));
return result;
}
@ -124,37 +124,37 @@ public abstract class UriUtils {
*
* <p>The returned map will contain keys for
* <ul>
* <li>{@link UriComponent#SCHEME}</li>
* <li>{@link UriComponent#AUTHORITY}</li>
* <li>{@link UriComponent#USER_INFO}</li>
* <li>{@link UriComponent#HOST}</li>
* <li>{@link UriComponent#PORT}</li>
* <li>{@link UriComponent#PATH}</li>
* <li>{@link UriComponent#QUERY}</li>
* <li>{@link org.springframework.web.util.UriComponents.Type#SCHEME}</li>
* <li>{@link org.springframework.web.util.UriComponents.Type#AUTHORITY}</li>
* <li>{@link org.springframework.web.util.UriComponents.Type#USER_INFO}</li>
* <li>{@link org.springframework.web.util.UriComponents.Type#HOST}</li>
* <li>{@link org.springframework.web.util.UriComponents.Type#PORT}</li>
* <li>{@link org.springframework.web.util.UriComponents.Type#PATH}</li>
* <li>{@link org.springframework.web.util.UriComponents.Type#QUERY}</li>
* </ul>
* though the values assigned to these keys is {@code null} if they do not occur in the given source URI.
*
* <p><strong>Note</strong> that the returned map will never contain mappings for {@link UriComponent#PATH_SEGMENT},
* nor {@link UriComponent#QUERY_PARAM}, since those components can occur multiple times in the URI. Nor does it
* contain a mapping for {@link UriComponent#FRAGMENT}, as fragments are not supposed to be sent to the server, but
* <p><strong>Note</strong> that the returned map will never contain mappings for {@link org.springframework.web.util.UriComponents.Type#PATH_SEGMENT},
* nor {@link org.springframework.web.util.UriComponents.Type#QUERY_PARAM}, since those components can occur multiple times in the URI. Nor does it
* contain a mapping for {@link org.springframework.web.util.UriComponents.Type#FRAGMENT}, as fragments are not supposed to be sent to the server, but
* retained by the client.
*
* @param httpUrl the source URI
* @return the URI components of the URI
*/
public static Map<UriComponent, String> parseHttpUrlComponents(String httpUrl) {
public static Map<UriComponents.Type, String> parseHttpUrlComponents(String httpUrl) {
Assert.notNull(httpUrl, "'httpUrl' must not be null");
Matcher m = HTTP_URL_PATTERN.matcher(httpUrl);
if (m.matches()) {
Map<UriComponent, String> result = new EnumMap<UriComponent, String>(UriComponent.class);
Map<UriComponents.Type, String> result = new EnumMap<UriComponents.Type, String>(UriComponents.Type.class);
result.put(UriComponent.SCHEME, m.group(1));
result.put(UriComponent.AUTHORITY, m.group(2));
result.put(UriComponent.USER_INFO, m.group(4));
result.put(UriComponent.HOST, m.group(5));
result.put(UriComponent.PORT, m.group(7));
result.put(UriComponent.PATH, m.group(8));
result.put(UriComponent.QUERY, m.group(10));
result.put(UriComponents.Type.SCHEME, m.group(1));
result.put(UriComponents.Type.AUTHORITY, m.group(2));
result.put(UriComponents.Type.USER_INFO, m.group(4));
result.put(UriComponents.Type.HOST, m.group(5));
result.put(UriComponents.Type.PORT, m.group(7));
result.put(UriComponents.Type.PATH, m.group(8));
result.put(UriComponents.Type.QUERY, m.group(10));
return result;
}
@ -168,20 +168,21 @@ public abstract class UriUtils {
/**
* Builds a URI from the given URI components. The given map should contain at least one entry.
*
* <p><strong>Note</strong> that {@link UriComponent#PATH_SEGMENT} and {@link UriComponent#QUERY_PARAM} keys (if any)
* will not be used to build the URI, in favor of {@link UriComponent#PATH} and {@link UriComponent#QUERY}
* <p><strong>Note</strong> that {@link org.springframework.web.util.UriComponents.Type#PATH_SEGMENT} and {@link org.springframework.web.util.UriComponents.Type#QUERY_PARAM} keys (if any)
* will not be used to build the URI, in favor of {@link org.springframework.web.util.UriComponents.Type#PATH} and {@link org.springframework.web.util.UriComponents.Type#QUERY}
* respectively.
*
* @param uriComponents the components to build the URI out of
* @return the URI created from the given components
*/
public static String buildUri(Map<UriComponent, String> uriComponents) {
public static String buildUri(Map<UriComponents.Type, String> uriComponents) {
Assert.notEmpty(uriComponents, "'uriComponents' must not be empty");
return buildUri(uriComponents.get(UriComponent.SCHEME), uriComponents.get(UriComponent.AUTHORITY),
uriComponents.get(UriComponent.USER_INFO), uriComponents.get(UriComponent.HOST),
uriComponents.get(UriComponent.PORT), uriComponents.get(UriComponent.PATH),
uriComponents.get(UriComponent.QUERY), uriComponents.get(UriComponent.FRAGMENT));
return buildUri(uriComponents.get(UriComponents.Type.SCHEME), uriComponents.get(
UriComponents.Type.AUTHORITY),
uriComponents.get(UriComponents.Type.USER_INFO), uriComponents.get(UriComponents.Type.HOST),
uriComponents.get(UriComponents.Type.PORT), uriComponents.get(UriComponents.Type.PATH),
uriComponents.get(UriComponents.Type.QUERY), uriComponents.get(UriComponents.Type.FRAGMENT));
}
/**
@ -261,7 +262,7 @@ public abstract class UriUtils {
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
*/
public static String encodeUri(String uri, String encoding) throws UnsupportedEncodingException {
Map<UriComponent, String> uriComponents = parseUriComponents(uri);
Map<UriComponents.Type, String> uriComponents = parseUriComponents(uri);
return encodeUriComponents(uriComponents, encoding);
}
@ -277,7 +278,7 @@ public abstract class UriUtils {
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
*/
public static String encodeHttpUrl(String httpUrl, String encoding) throws UnsupportedEncodingException {
Map<UriComponent, String> uriComponents = parseHttpUrlComponents(httpUrl);
Map<UriComponents.Type, String> uriComponents = parseHttpUrlComponents(httpUrl);
return encodeUriComponents(uriComponents, encoding);
}
@ -291,13 +292,13 @@ public abstract class UriUtils {
* @throws IllegalArgumentException when the given uri parameter is not a valid URI
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
*/
public static String encodeUriComponents(Map<UriComponent, String> uriComponents,
public static String encodeUriComponents(Map<UriComponents.Type, String> uriComponents,
String encoding) throws UnsupportedEncodingException {
Assert.notEmpty(uriComponents, "'uriComponents' must not be empty");
Assert.hasLength(encoding, "'encoding' must not be empty");
Map<UriComponent, String> encodedUriComponents = new EnumMap<UriComponent, String>(UriComponent.class);
for (Map.Entry<UriComponent, String> entry : uriComponents.entrySet()) {
Map<UriComponents.Type, String> encodedUriComponents = new EnumMap<UriComponents.Type, String>(UriComponents.Type.class);
for (Map.Entry<UriComponents.Type, String> entry : uriComponents.entrySet()) {
if (entry.getValue() != null) {
String encodedValue = encodeUriComponent(entry.getValue(), encoding, entry.getKey(), null);
encodedUriComponents.put(entry.getKey(), encodedValue);
@ -369,7 +370,7 @@ public abstract class UriUtils {
* @return the encoded URI
* @throws IllegalArgumentException when the given uri parameter is not a valid URI
*/
public static String encodeUriComponent(String source, UriComponent uriComponent) {
public static String encodeUriComponent(String source, UriComponents.Type uriComponent) {
return encodeUriComponent(source, uriComponent, null);
}
@ -386,7 +387,7 @@ public abstract class UriUtils {
* @see EncodingOption
*/
public static String encodeUriComponent(String source,
UriComponent uriComponent,
UriComponents.Type uriComponent,
Set<EncodingOption> encodingOptions) {
try {
return encodeUriComponent(source, DEFAULT_ENCODING, uriComponent, encodingOptions);
@ -408,7 +409,7 @@ public abstract class UriUtils {
*/
public static String encodeUriComponent(String source,
String encoding,
UriComponent uriComponent) throws UnsupportedEncodingException {
UriComponents.Type uriComponent) throws UnsupportedEncodingException {
return encodeUriComponent(source, encoding, uriComponent, null);
}
@ -426,7 +427,7 @@ public abstract class UriUtils {
*/
public static String encodeUriComponent(String source,
String encoding,
UriComponent uriComponent,
UriComponents.Type uriComponent,
Set<EncodingOption> encodingOptions) throws UnsupportedEncodingException {
Assert.hasLength(encoding, "'encoding' must not be empty");
@ -435,7 +436,7 @@ public abstract class UriUtils {
}
private static byte[] encodeInternal(byte[] source,
UriComponent uriComponent,
UriComponents.Type uriComponent,
Set<EncodingOption> encodingOptions) {
Assert.notNull(source, "'source' must not be null");
Assert.notNull(uriComponent, "'uriComponent' must not be null");
@ -480,7 +481,7 @@ public abstract class UriUtils {
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
*/
public static String encodeScheme(String scheme, String encoding) throws UnsupportedEncodingException {
return encodeUriComponent(scheme, encoding, UriComponent.SCHEME, null);
return encodeUriComponent(scheme, encoding, UriComponents.Type.SCHEME, null);
}
/**
@ -492,7 +493,7 @@ public abstract class UriUtils {
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
*/
public static String encodeAuthority(String authority, String encoding) throws UnsupportedEncodingException {
return encodeUriComponent(authority, encoding, UriComponent.AUTHORITY, null);
return encodeUriComponent(authority, encoding, UriComponents.Type.AUTHORITY, null);
}
/**
@ -504,7 +505,7 @@ public abstract class UriUtils {
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
*/
public static String encodeUserInfo(String userInfo, String encoding) throws UnsupportedEncodingException {
return encodeUriComponent(userInfo, encoding, UriComponent.USER_INFO, null);
return encodeUriComponent(userInfo, encoding, UriComponents.Type.USER_INFO, null);
}
/**
@ -516,7 +517,7 @@ public abstract class UriUtils {
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
*/
public static String encodeHost(String host, String encoding) throws UnsupportedEncodingException {
return encodeUriComponent(host, encoding, UriComponent.HOST, null);
return encodeUriComponent(host, encoding, UriComponents.Type.HOST, null);
}
/**
@ -528,7 +529,7 @@ public abstract class UriUtils {
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
*/
public static String encodePort(String port, String encoding) throws UnsupportedEncodingException {
return encodeUriComponent(port, encoding, UriComponent.PORT, null);
return encodeUriComponent(port, encoding, UriComponents.Type.PORT, null);
}
/**
@ -540,7 +541,7 @@ public abstract class UriUtils {
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
*/
public static String encodePath(String path, String encoding) throws UnsupportedEncodingException {
return encodeUriComponent(path, encoding, UriComponent.PATH, null);
return encodeUriComponent(path, encoding, UriComponents.Type.PATH, null);
}
/**
@ -552,7 +553,7 @@ public abstract class UriUtils {
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
*/
public static String encodePathSegment(String segment, String encoding) throws UnsupportedEncodingException {
return encodeUriComponent(segment, encoding, UriComponent.PATH_SEGMENT, null);
return encodeUriComponent(segment, encoding, UriComponents.Type.PATH_SEGMENT, null);
}
/**
@ -564,7 +565,7 @@ public abstract class UriUtils {
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
*/
public static String encodeQuery(String query, String encoding) throws UnsupportedEncodingException {
return encodeUriComponent(query, encoding, UriComponent.QUERY, null);
return encodeUriComponent(query, encoding, UriComponents.Type.QUERY, null);
}
/**
@ -576,7 +577,7 @@ public abstract class UriUtils {
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
*/
public static String encodeQueryParam(String queryParam, String encoding) throws UnsupportedEncodingException {
return encodeUriComponent(queryParam, encoding, UriComponent.QUERY_PARAM, null);
return encodeUriComponent(queryParam, encoding, UriComponents.Type.QUERY_PARAM, null);
}
/**
@ -588,7 +589,7 @@ public abstract class UriUtils {
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
*/
public static String encodeFragment(String fragment, String encoding) throws UnsupportedEncodingException {
return encodeUriComponent(fragment, encoding, UriComponent.FRAGMENT, null);
return encodeUriComponent(fragment, encoding, UriComponents.Type.FRAGMENT, null);
}

View File

@ -33,42 +33,42 @@ public class UriUtilsTests {
@Test
public void parseUriComponents() {
Map<UriComponent, String> result = UriUtils.parseUriComponents("http://www.ietf.org/rfc/rfc3986.txt");
assertEquals("http", result.get(UriComponent.SCHEME));
assertNull(result.get(UriComponent.USER_INFO));
assertEquals("www.ietf.org", result.get(UriComponent.HOST));
assertNull(result.get(UriComponent.PORT));
assertEquals("/rfc/rfc3986.txt", result.get(UriComponent.PATH));
assertNull(result.get(UriComponent.QUERY));
assertNull(result.get(UriComponent.FRAGMENT));
Map<UriComponents.Type, String> result = UriUtils.parseUriComponents("http://www.ietf.org/rfc/rfc3986.txt");
assertEquals("http", result.get(UriComponents.Type.SCHEME));
assertNull(result.get(UriComponents.Type.USER_INFO));
assertEquals("www.ietf.org", result.get(UriComponents.Type.HOST));
assertNull(result.get(UriComponents.Type.PORT));
assertEquals("/rfc/rfc3986.txt", result.get(UriComponents.Type.PATH));
assertNull(result.get(UriComponents.Type.QUERY));
assertNull(result.get(UriComponents.Type.FRAGMENT));
result = UriUtils.parseUriComponents(
"http://arjen:foobar@java.sun.com:80/javase/6/docs/api/java/util/BitSet.html?foo=bar#and(java.util.BitSet)");
assertEquals("http", result.get(UriComponent.SCHEME));
assertEquals("arjen:foobar", result.get(UriComponent.USER_INFO));
assertEquals("java.sun.com", result.get(UriComponent.HOST));
assertEquals("80", result.get(UriComponent.PORT));
assertEquals("/javase/6/docs/api/java/util/BitSet.html", result.get(UriComponent.PATH));
assertEquals("foo=bar", result.get(UriComponent.QUERY));
assertEquals("and(java.util.BitSet)", result.get(UriComponent.FRAGMENT));
assertEquals("http", result.get(UriComponents.Type.SCHEME));
assertEquals("arjen:foobar", result.get(UriComponents.Type.USER_INFO));
assertEquals("java.sun.com", result.get(UriComponents.Type.HOST));
assertEquals("80", result.get(UriComponents.Type.PORT));
assertEquals("/javase/6/docs/api/java/util/BitSet.html", result.get(UriComponents.Type.PATH));
assertEquals("foo=bar", result.get(UriComponents.Type.QUERY));
assertEquals("and(java.util.BitSet)", result.get(UriComponents.Type.FRAGMENT));
result = UriUtils.parseUriComponents("mailto:java-net@java.sun.com");
assertEquals("mailto", result.get(UriComponent.SCHEME));
assertNull(result.get(UriComponent.USER_INFO));
assertNull(result.get(UriComponent.HOST));
assertNull(result.get(UriComponent.PORT));
assertEquals("java-net@java.sun.com", result.get(UriComponent.PATH));
assertNull(result.get(UriComponent.QUERY));
assertNull(result.get(UriComponent.FRAGMENT));
assertEquals("mailto", result.get(UriComponents.Type.SCHEME));
assertNull(result.get(UriComponents.Type.USER_INFO));
assertNull(result.get(UriComponents.Type.HOST));
assertNull(result.get(UriComponents.Type.PORT));
assertEquals("java-net@java.sun.com", result.get(UriComponents.Type.PATH));
assertNull(result.get(UriComponents.Type.QUERY));
assertNull(result.get(UriComponents.Type.FRAGMENT));
result = UriUtils.parseUriComponents("docs/guide/collections/designfaq.html#28");
assertNull(result.get(UriComponent.SCHEME));
assertNull(result.get(UriComponent.USER_INFO));
assertNull(result.get(UriComponent.HOST));
assertNull(result.get(UriComponent.PORT));
assertEquals("docs/guide/collections/designfaq.html", result.get(UriComponent.PATH));
assertNull(result.get(UriComponent.QUERY));
assertEquals("28", result.get(UriComponent.FRAGMENT));
assertNull(result.get(UriComponents.Type.SCHEME));
assertNull(result.get(UriComponents.Type.USER_INFO));
assertNull(result.get(UriComponents.Type.HOST));
assertNull(result.get(UriComponents.Type.PORT));
assertEquals("docs/guide/collections/designfaq.html", result.get(UriComponents.Type.PATH));
assertNull(result.get(UriComponents.Type.QUERY));
assertEquals("28", result.get(UriComponents.Type.FRAGMENT));
}
@Test