package org.springframework.cloud.util;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
/**
* Utility class that allows expressing URIs in alternative forms: individual fields or a URI string
*
* @author Ramnivas Laddad
* @author Scott Frederick
*/
public class UriInfo {
private String scheme;
private String host;
private int port;
private String userName;
private String password;
private String path;
private String query;
private String schemeSpecificPart;
private String uriString;
public UriInfo(String scheme, String host, int port, String username, String password) {
this(scheme, host, port, username, password, null, null);
}
public UriInfo(String scheme, String host, int port, String username, String password, String path) {
this(scheme, host, port, username, password, path, null);
}
public UriInfo(String scheme, String host, int port, String username, String password, String path, String query) {
this.scheme = scheme;
this.host = host;
this.port = port;
this.userName = username;
this.password = password;
this.path = path;
this.query = query;
this.uriString = buildUri().toString();
}
public UriInfo(String uriString) {
this.uriString = uriString;
URI uri = getUri();
this.scheme = uri.getScheme();
this.host = uri.getHost();
this.port = uri.getPort();
this.path = parsePath(uri);
this.query = uri.getQuery();
this.schemeSpecificPart = uri.getSchemeSpecificPart();
String[] userinfo = parseUserinfo(uri);
this.userName = uriDecode(userinfo[0]);
this.password = uriDecode(userinfo[1]);
}
public String getScheme() {
return scheme;
}
public String getHost() {
return host;
}
public int getPort() {
return port;
}
public String getUserName() {
return userName;
}
public String getPassword() {
return password;
}
public String getPath() {
return path;
}
public String getQuery() {
return query;
}
public String getSchemeSpecificPart() {
return schemeSpecificPart;
}
public URI getUri() {
try {
return new URI(uriString);
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Invalid URI " + uriString, e);
}
}
public String getUriString() {
return uriString;
}
private URI buildUri() {
String userInfo = null;
if (userName != null && password != null) {
userInfo = userName + ":" + password;
}
String cleanedPath = path == null || path.startsWith("/") ? path : "/" + path;
try {
return new URI(scheme, userInfo, host, port, cleanedPath, query, null);
}
catch (URISyntaxException e) {
String details = String.format("Error creating URI with components: " +
"scheme=%s, userInfo=%s, host=%s, port=%d, path=%s, query=%s",
scheme, userInfo, host, port, cleanedPath, query);
throw new IllegalArgumentException(details, e);
}
}
private String[] parseUserinfo(URI uri) {
String userInfo = uri.getRawUserInfo();
if (userInfo != null) {
String[] userPass = userInfo.split(":");
if (userPass.length != 2) {
throw new IllegalArgumentException("Bad userinfo in URI: " + uri);
}
return userPass;
}
return new String[]{null, null};
}
private String parsePath(URI uri) {
String rawPath = uri.getRawPath();
if (rawPath != null && rawPath.length() > 1) {
return rawPath.substring(1);
}
return null;
}
private static String uriDecode(String s) {
if (s == null) {
return null;
}
try {
// URLDecode decodes '+' to a space, as for
// form encoding. So protect plus signs.
return URLDecoder.decode(s.replace("+", "%2B"), "US-ASCII");
} catch (java.io.UnsupportedEncodingException e) {
// US-ASCII is always supported
throw new RuntimeException(e);
}
}
@Override
public String toString() {
return uriString;
}
}