Minor changes along with 3.1.3 backport

Issue: SPR-9798
Issue: SPR-9804
This commit is contained in:
Juergen Hoeller
2012-10-10 17:04:11 +02:00
committed by unknown
parent e5cfe8a2c5
commit 9eeb6f15e5
6 changed files with 335 additions and 380 deletions

View File

@@ -43,7 +43,7 @@ import org.springframework.util.StringUtils;
*/
final class HierarchicalUriComponents extends UriComponents {
private static final char PATH_DELIMITER = '/';
private static final char PATH_DELIMITER = '/';
private final String userInfo;
@@ -57,9 +57,9 @@ final class HierarchicalUriComponents extends UriComponents {
private final boolean encoded;
/**
* Package-private constructor. All arguments are optional, and can be {@code null}.
*
* @param scheme the scheme
* @param userInfo the user info
* @param host the host
@@ -70,9 +70,8 @@ final class HierarchicalUriComponents extends UriComponents {
* @param encoded whether the components are already encoded
* @param verify whether the components need to be checked for illegal characters
*/
HierarchicalUriComponents(String scheme, String userInfo, String host, int port,
PathComponent path, MultiValueMap<String, String> queryParams,
String fragment, boolean encoded, boolean verify) {
HierarchicalUriComponents(String scheme, String userInfo, String host, int port, PathComponent path,
MultiValueMap<String, String> queryParams, String fragment, boolean encoded, boolean verify) {
super(scheme, fragment);
this.userInfo = userInfo;
@@ -87,6 +86,7 @@ final class HierarchicalUriComponents extends UriComponents {
}
}
// component getters
@Override
@@ -95,19 +95,19 @@ final class HierarchicalUriComponents extends UriComponents {
}
@Override
public String getUserInfo() {
public String getUserInfo() {
return this.userInfo;
}
}
@Override
public String getHost() {
@Override
public String getHost() {
return this.host;
}
}
@Override
public int getPort() {
@Override
public int getPort() {
return this.port;
}
}
@Override
public String getPath() {
@@ -154,32 +154,30 @@ final class HierarchicalUriComponents extends UriComponents {
}
/**
* Returns the map of query parameters.
*
* @return the query parameters. Empty if no query has been set.
*/
@Override
public MultiValueMap<String, String> getQueryParams() {
* Returns the map of query parameters. Empty if no query has been set.
*/
@Override
public MultiValueMap<String, String> getQueryParams() {
return this.queryParams;
}
}
// encoding
/**
* Encodes all URI components using their specific encoding rules, and returns the result as a new
* {@code UriComponents} instance.
*
* @param encoding the encoding of the values contained in this map
* @return the encoded uri components
* @throws UnsupportedEncodingException if the given encoding is not supported
*/
@Override
public HierarchicalUriComponents encode(String encoding) throws UnsupportedEncodingException {
Assert.hasLength(encoding, "'encoding' must not be empty");
* Encodes all URI components using their specific encoding rules, and returns the result as a new
* {@code UriComponents} instance.
* @param encoding the encoding of the values contained in this map
* @return the encoded uri components
* @throws UnsupportedEncodingException if the given encoding is not supported
*/
@Override
public HierarchicalUriComponents encode(String encoding) throws UnsupportedEncodingException {
Assert.hasLength(encoding, "'encoding' must not be empty");
if (this.encoded) {
return this;
}
if (this.encoded) {
return this;
}
String encodedScheme = encodeUriComponent(this.getScheme(), encoding, Type.SCHEME);
String encodedUserInfo = encodeUriComponent(this.userInfo, encoding, Type.USER_INFO);
@@ -200,18 +198,16 @@ final class HierarchicalUriComponents extends UriComponents {
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
* by the given component and with the given options.
*
* @param source the source string
* @param encoding the encoding of the source string
* @param type the URI component for the source
* @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 {
@@ -228,36 +224,33 @@ final class HierarchicalUriComponents extends UriComponents {
private static byte[] encodeBytes(byte[] source, Type type) {
Assert.notNull(source, "'source' must not be null");
Assert.notNull(type, "'type' must not be null");
Assert.notNull(type, "'type' must not be null");
ByteArrayOutputStream bos = new ByteArrayOutputStream(source.length);
for (int i = 0; i < source.length; i++) {
int b = source[i];
if (b < 0) {
b += 256;
}
if (type.isAllowed(b)) {
bos.write(b);
}
else {
bos.write('%');
char hex1 = Character.toUpperCase(Character.forDigit((b >> 4) & 0xF, 16));
char hex2 = Character.toUpperCase(Character.forDigit(b & 0xF, 16));
bos.write(hex1);
bos.write(hex2);
}
}
return bos.toByteArray();
}
ByteArrayOutputStream bos = new ByteArrayOutputStream(source.length);
for (int i = 0; i < source.length; i++) {
int b = source[i];
if (b < 0) {
b += 256;
}
if (type.isAllowed(b)) {
bos.write(b);
}
else {
bos.write('%');
char hex1 = Character.toUpperCase(Character.forDigit((b >> 4) & 0xF, 16));
char hex2 = Character.toUpperCase(Character.forDigit(b & 0xF, 16));
bos.write(hex1);
bos.write(hex2);
}
}
return bos.toByteArray();
}
// verifying
/**
* Verifies all URI components to determine whether they contain any illegal
* characters, throwing an {@code IllegalArgumentException} if so.
*
* @throws IllegalArgumentException if any component has illegal characters
*/
private void verify() {
@@ -277,7 +270,6 @@ final class HierarchicalUriComponents extends UriComponents {
verifyUriComponent(getFragment(), Type.FRAGMENT);
}
private static void verifyUriComponent(String source, Type type) {
if (source == null) {
return;
@@ -309,6 +301,7 @@ final class HierarchicalUriComponents extends UriComponents {
}
}
// expanding
@Override
@@ -337,47 +330,46 @@ final class HierarchicalUriComponents extends UriComponents {
}
/**
* Normalize the path removing sequences like "path/..".
* @see StringUtils#cleanPath(String)
*/
@Override
public UriComponents normalize() {
* Normalize the path removing sequences like "path/..".
* @see StringUtils#cleanPath(String)
*/
@Override
public UriComponents normalize() {
String normalizedPath = StringUtils.cleanPath(getPath());
return new HierarchicalUriComponents(getScheme(), this.userInfo, this.host,
this.port, new FullPathComponent(normalizedPath), this.queryParams,
getFragment(), this.encoded, false);
}
}
// other functionality
/**
* Returns a URI string from this {@code UriComponents} instance.
*
* @return the URI string
*/
@Override
public String toUriString() {
StringBuilder uriBuilder = new StringBuilder();
/**
* Returns a URI string from this {@code UriComponents} instance.
*/
@Override
public String toUriString() {
StringBuilder uriBuilder = new StringBuilder();
if (getScheme() != null) {
uriBuilder.append(getScheme());
uriBuilder.append(':');
}
if (getScheme() != null) {
uriBuilder.append(getScheme());
uriBuilder.append(':');
}
if (this.userInfo != null || this.host != null) {
uriBuilder.append("//");
if (this.userInfo != null) {
if (this.userInfo != null || this.host != null) {
uriBuilder.append("//");
if (this.userInfo != null) {
uriBuilder.append(this.userInfo);
uriBuilder.append('@');
}
if (this.host != null) {
uriBuilder.append('@');
}
if (this.host != null) {
uriBuilder.append(host);
}
if (this.port != -1) {
uriBuilder.append(':');
}
if (this.port != -1) {
uriBuilder.append(':');
uriBuilder.append(port);
}
}
}
}
String path = getPath();
if (StringUtils.hasLength(path)) {
@@ -389,53 +381,51 @@ final class HierarchicalUriComponents extends UriComponents {
String query = getQuery();
if (query != null) {
uriBuilder.append('?');
uriBuilder.append(query);
}
uriBuilder.append('?');
uriBuilder.append(query);
}
if (getFragment() != null) {
uriBuilder.append('#');
if (getFragment() != null) {
uriBuilder.append('#');
uriBuilder.append(getFragment());
}
}
return uriBuilder.toString();
}
return uriBuilder.toString();
}
/**
* Returns a {@code URI} from this {@code UriComponents} instance.
*
* @return the URI
*/
@Override
public URI toUri() {
try {
if (this.encoded) {
return new URI(toString());
}
else {
/**
* Returns a {@code URI} from this {@code UriComponents} instance.
*/
@Override
public URI toUri() {
try {
if (this.encoded) {
return new URI(toString());
}
else {
String path = getPath();
if (StringUtils.hasLength(path) && path.charAt(0) != PATH_DELIMITER) {
path = PATH_DELIMITER + path;
}
return new URI(getScheme(), getUserInfo(), getHost(), getPort(), path, getQuery(),
getFragment());
}
}
catch (URISyntaxException ex) {
throw new IllegalStateException("Could not create URI object: " + ex.getMessage(), ex);
}
}
}
}
catch (URISyntaxException ex) {
throw new IllegalStateException("Could not create URI object: " + ex.getMessage(), ex);
}
}
@Override
public boolean equals(Object o) {
if (this == o) {
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(o instanceof OpaqueUriComponents)) {
if (!(obj instanceof OpaqueUriComponents)) {
return false;
}
HierarchicalUriComponents other = (HierarchicalUriComponents) o;
HierarchicalUriComponents other = (HierarchicalUriComponents) obj;
if (ObjectUtils.nullSafeEquals(getScheme(), other.getScheme())) {
return false;
@@ -474,157 +464,155 @@ final class HierarchicalUriComponents extends UriComponents {
return result;
}
// 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>
*/
static enum Type {
/**
* 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.
* @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>
*/
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;
}
};
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 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 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 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 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 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 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 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;
}
/**
* 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;
}
}
}
/**
* Defines the contract for path (segments).
@@ -640,9 +628,9 @@ final class HierarchicalUriComponents extends UriComponents {
void verify();
PathComponent expand(UriTemplateVariables uriVariables);
}
/**
* Represents a path backed by a string.
*/
@@ -679,14 +667,9 @@ final class HierarchicalUriComponents extends UriComponents {
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o instanceof FullPathComponent) {
FullPathComponent other = (FullPathComponent) o;
return this.getPath().equals(other.getPath());
}
return false;
public boolean equals(Object obj) {
return (this == obj || (obj instanceof FullPathComponent &&
getPath().equals(((FullPathComponent) obj).getPath())));
}
@Override
@@ -750,14 +733,9 @@ final class HierarchicalUriComponents extends UriComponents {
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o instanceof PathSegmentComponent) {
PathSegmentComponent other = (PathSegmentComponent) o;
return this.getPathSegments().equals(other.getPathSegments());
}
return false;
public boolean equals(Object obj) {
return (this == obj || (obj instanceof PathSegmentComponent &&
getPathSegments().equals(((PathSegmentComponent) obj).getPathSegments())));
}
@Override
@@ -844,8 +822,8 @@ final class HierarchicalUriComponents extends UriComponents {
}
@Override
public boolean equals(Object o) {
return this == o;
public boolean equals(Object obj) {
return (this == obj);
}
@Override

View File

@@ -45,6 +45,7 @@ final class OpaqueUriComponents extends UriComponents {
this.ssp = schemeSpecificPart;
}
@Override
public String getSchemeSpecificPart() {
return this.ssp;
@@ -134,15 +135,15 @@ final class OpaqueUriComponents extends UriComponents {
}
@Override
public boolean equals(Object o) {
if (this == o) {
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(o instanceof OpaqueUriComponents)) {
if (!(obj instanceof OpaqueUriComponents)) {
return false;
}
OpaqueUriComponents other = (OpaqueUriComponents) o;
OpaqueUriComponents other = (OpaqueUriComponents) obj;
if (ObjectUtils.nullSafeEquals(getScheme(), other.getScheme())) {
return false;

View File

@@ -35,8 +35,8 @@ import org.springframework.util.MultiValueMap;
* variables.
*
* @author Arjen Poutsma
* @see UriComponentsBuilder
* @since 3.1
* @see UriComponentsBuilder
*/
public abstract class UriComponents {
@@ -45,97 +45,80 @@ public abstract class UriComponents {
/** Captures URI template variable names. */
private static final Pattern NAMES_PATTERN = Pattern.compile("\\{([^/]+?)\\}");
private final String scheme;
private final String fragment;
protected UriComponents(String scheme, String fragment) {
this.scheme = scheme;
this.fragment = fragment;
}
// component getters
/**
* Returns the scheme.
*
* @return the scheme. Can be {@code null}.
* Returns the scheme. Can be {@code null}.
*/
public final String getScheme() {
return scheme;
}
/**
* Returns the scheme specific part.
*
* @retur the scheme specific part. Can be {@code null}.
* Returns the scheme specific part. Can be {@code null}.
*/
public abstract String getSchemeSpecificPart();
/**
* Returns the user info.
*
* @return the user info. Can be {@code null}.
* Returns the user info. Can be {@code null}.
*/
public abstract String getUserInfo();
/**
* Returns the host.
*
* @return the host. Can be {@code null}.
* Returns the host. Can be {@code null}.
*/
public abstract String getHost();
/**
* Returns the port. Returns {@code -1} if no port has been set.
*
* @return the port
*/
public abstract int getPort();
/**
* Returns the path.
*
* @return the path. Can be {@code null}.
* Returns the path. Can be {@code null}.
*/
public abstract String getPath();
/**
* Returns the list of path segments.
*
* @return the path segments. Empty if no path has been set.
* Returns the list of path segments. Empty if no path has been set.
*/
public abstract List<String> getPathSegments();
/**
* Returns the query.
*
* @return the query. Can be {@code null}.
* Returns the query. Can be {@code null}.
*/
public abstract String getQuery();
/**
* Returns the map of query parameters.
*
* @return the query parameters. Empty if no query has been set.
* Returns the map of query parameters. Empty if no query has been set.
*/
public abstract MultiValueMap<String, String> getQueryParams();
/**
* Returns the fragment.
*
* @return the fragment. Can be {@code null}.
* Returns the fragment. Can be {@code null}.
*/
public final String getFragment() {
return fragment;
return this.fragment;
}
// encoding
/**
* Encodes all URI components using their specific encoding rules, and returns the result
* Encode all URI components using their specific encoding rules, and returns the result
* as a new {@code UriComponents} instance. This method uses UTF-8 to encode.
*
* @return the encoded uri components
*/
public final UriComponents encode() {
@@ -148,48 +131,43 @@ public abstract class UriComponents {
}
/**
* Encodes all URI components using their specific encoding rules, and
* Encode all URI components using their specific encoding rules, and
* returns the result as a new {@code UriComponents} instance.
*
* @param encoding the encoding of the values contained in this map
* @return the encoded uri components
* @throws UnsupportedEncodingException if the given encoding is not supported
*/
public abstract UriComponents encode(String encoding) throws UnsupportedEncodingException;
// expanding
/**
* Replaces all URI template variables with the values from a given map. The map keys
* represent variable names; the values variable values. The order of variables is not
* significant.
*
* @param uriVariables the map of URI variables
* @return the expanded uri components
*/
public final UriComponents expand(Map<String, ?> uriVariables) {
Assert.notNull(uriVariables, "'uriVariables' must not be null");
return expandInternal(new MapTemplateVariables(uriVariables));
}
/**
* Replaces all URI template variables with the values from a given array. The array
* represent variable values. The order of variables is significant.
*
* @param uriVariableValues URI variable values
* @return the expanded uri components
*/
public final UriComponents expand(Object... uriVariableValues) {
Assert.notNull(uriVariableValues, "'uriVariableValues' must not be null");
return expandInternal(new VarArgsTemplateVariables(uriVariableValues));
}
/**
* Replaces all URI template variables with the values from the given {@link
* UriTemplateVariables}
*
* @param uriVariables URI template values
* @return the expanded uri components
*/
@@ -227,15 +205,11 @@ public abstract class UriComponents {
/**
* Returns a URI string from this {@code UriComponents} instance.
*
* @return the URI string
*/
public abstract String toUriString();
/**
* Returns a {@code URI} from this {@code UriComponents} instance.
*
* @return the URI
*/
public abstract URI toUri();
@@ -246,14 +220,13 @@ public abstract class UriComponents {
/**
* Normalize the path removing sequences like "path/..".
*
* @see org.springframework.util.StringUtils#cleanPath(String)
*/
public abstract UriComponents normalize();
/**
* Defines the contract for URI Template variables
*
* @see HierarchicalUriComponents#expand
*/
interface UriTemplateVariables {
@@ -281,6 +254,7 @@ public abstract class UriComponents {
}
}
/**
* URI template variables backed by a variable argument array.
*/
@@ -301,5 +275,4 @@ public abstract class UriComponents {
}
}
}

View File

@@ -32,8 +32,8 @@ import org.springframework.util.StringUtils;
/**
* Builder for {@link UriComponents}.
* <p/>
* Typical usage involves:
*
* <p></p>Typical usage involves:
* <ol>
* <li>Create a {@code UriComponentsBuilder} with one of the static factory methods (such as
* {@link #fromPath(String)} or {@link #fromUri(URI)})</li>
@@ -46,10 +46,10 @@ import org.springframework.util.StringUtils;
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @since 3.1
* @see #newInstance()
* @see #fromPath(String)
* @see #fromUri(URI)
* @since 3.1
*/
public class UriComponentsBuilder {

View File

@@ -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.
@@ -29,9 +29,9 @@ import org.springframework.util.Assert;
*
* <p>All {@code encode*(String, String} methods in this class operate in a similar way:
* <ul>
* <li>Valid characters for the specific URI component as defined in RFC 3986 stay the same.</li>
* <li>All other characters are converted into one or more bytes in the given encoding scheme. Each of the
* resulting bytes is written as a hexadecimal string in the "<code>%<i>xy</i></code>" format.</li>
* <li>Valid characters for the specific URI component as defined in RFC 3986 stay the same.</li>
* <li>All other characters are converted into one or more bytes in the given encoding scheme. Each of the
* resulting bytes is written as a hexadecimal string in the "<code>%<i>xy</i></code>" format.</li>
* </ul>
*
* @author Arjen Poutsma
@@ -64,6 +64,7 @@ public abstract class UriUtils {
private static final Pattern HTTP_URL_PATTERN = Pattern.compile(
"^" + HTTP_PATTERN + "(//(" + USERINFO_PATTERN + "@)?" + HOST_PATTERN + "(:" + PORT_PATTERN + ")?" + ")?" +
PATH_PATTERN + "(\\?" + LAST_PATTERN + ")?");
// encoding
/**
@@ -73,8 +74,8 @@ public abstract class UriUtils {
* characters in query parameter names and query parameter values because they cannot
* be parsed in a reliable way. Instead use:
* <pre>
* UriComponents uriComponents = UriComponentsBuilder.fromUri("/path?name={value}").buildAndExpand("a=b");
* String encodedUri = uriComponents.encode().toUriString();
* UriComponents uriComponents = UriComponentsBuilder.fromUri("/path?name={value}").buildAndExpand("a=b");
* String encodedUri = uriComponents.encode().toUriString();
* </pre>
* @param uri the URI to be encoded
* @param encoding the character encoding to encode to
@@ -114,8 +115,8 @@ public abstract class UriUtils {
* characters in query parameter names and query parameter values because they cannot
* be parsed in a reliable way. Instead use:
* <pre>
* UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl("/path?name={value}").buildAndExpand("a=b");
* String encodedUri = uriComponents.encode().toUriString();
* UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl("/path?name={value}").buildAndExpand("a=b");
* String encodedUri = uriComponents.encode().toUriString();
* </pre>
* @param httpUrl the HTTP URL to be encoded
* @param encoding the character encoding to encode to
@@ -167,42 +168,42 @@ public abstract class UriUtils {
String host, String port, String path, String query, String fragment, String encoding)
throws UnsupportedEncodingException {
Assert.hasLength(encoding, "'encoding' must not be empty");
StringBuilder sb = new StringBuilder();
Assert.hasLength(encoding, "'encoding' must not be empty");
StringBuilder sb = new StringBuilder();
if (scheme != null) {
sb.append(encodeScheme(scheme, encoding));
sb.append(':');
}
if (scheme != null) {
sb.append(encodeScheme(scheme, encoding));
sb.append(':');
}
if (authority != null) {
sb.append("//");
if (userInfo != null) {
sb.append(encodeUserInfo(userInfo, encoding));
sb.append('@');
}
if (host != null) {
sb.append(encodeHost(host, encoding));
}
if (port != null) {
sb.append(':');
sb.append(encodePort(port, encoding));
}
}
if (authority != null) {
sb.append("//");
if (userInfo != null) {
sb.append(encodeUserInfo(userInfo, encoding));
sb.append('@');
}
if (host != null) {
sb.append(encodeHost(host, encoding));
}
if (port != null) {
sb.append(':');
sb.append(encodePort(port, encoding));
}
}
sb.append(encodePath(path, encoding));
sb.append(encodePath(path, encoding));
if (query != null) {
sb.append('?');
sb.append(encodeQuery(query, encoding));
}
if (query != null) {
sb.append('?');
sb.append(encodeQuery(query, encoding));
}
if (fragment != null) {
sb.append('#');
sb.append(encodeFragment(fragment, encoding));
}
if (fragment != null) {
sb.append('#');
sb.append(encodeFragment(fragment, encoding));
}
return sb.toString();
return sb.toString();
}
@@ -334,11 +335,11 @@ public abstract class UriUtils {
/**
* Decodes the given encoded source String into an URI. Based on the following rules:
* <ul>
* <li>Alphanumeric characters {@code "a"} through {@code "z"}, {@code "A"} through {@code "Z"}, and
* {@code "0"} through {@code "9"} stay the same.</li>
* <li>Special characters {@code "-"}, {@code "_"}, {@code "."}, and {@code "*"} stay the same.</li>
* <li>A sequence "<code>%<i>xy</i></code>" is interpreted as a hexadecimal representation of the character.</li>
* </ul>
* <li>Alphanumeric characters {@code "a"} through {@code "z"}, {@code "A"} through {@code "Z"}, and
* {@code "0"} through {@code "9"} stay the same.</li>
* <li>Special characters {@code "-"}, {@code "_"}, {@code "."}, and {@code "*"} stay the same.</li>
* <li>A sequence "<code>%<i>xy</i></code>" is interpreted as a hexadecimal representation of the character.</li>
* </ul>
* @param source the source string
* @param encoding the encoding
* @return the decoded URI