Minor changes along with 3.1.3 backport
Issue: SPR-9798 Issue: SPR-9804
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user