package org.limewire.util;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.StringTokenizer;
import org.limewire.logging.Log;
import org.limewire.logging.LogFactory;
/**
* Utilities for <code>URIs</code>.
*/
public class URIUtils {
private static final Log LOG = LogFactory.getLog(URIUtils.class);
private static final String RESERVED = ";/?:@&=+$,";
/**
* Creates a <code>URI</code> from the input string.
* The preferred way to invoke this method is with an URL-encoded string.
* <p>
* However, if the string has not been encoded, this method will encode it.
* It is ambiguous whether a string has been encoded or not, which is why
* it is preferred to pass in the string pre-encoded.
* <p>
* This method is useful when manipulating a URI and you don't know if it is
* encoded or not.
* <p>
* @param uriString the uri to be created
* @throws URISyntaxException
*/
public static URI toURI(final String uriString) throws URISyntaxException {
URI uri;
try {
uri = new URI(uriString);
} catch (URISyntaxException e) {
// the uriString was perhaps not encoded.
// try to encode it.
String encodedURIString = encodeURI(uriString);
try {
uri = new URI(encodedURIString);
} catch (URISyntaxException e1) {
// encoding the uriString didn't help.
// this probably means there is something structurally
// wrong with it.
// NOTE: throwing the original exception.
// initing with second Exception. Not the normal
// use case for initCause(), but this will at least capture both
// stack traces
if(e.getCause() == null) {
e.initCause(e1);
}
throw e;
}
}
return uri;
}
private static String encodeURI(String url) {
StringBuilder encodedURL = new StringBuilder();
StringTokenizer st = new StringTokenizer(url, RESERVED, true);
while(st.hasMoreElements()) {
String s = st.nextToken();
if(isDelimiter(s)) {
encodedURL.append(s);
} else {
try {
encodedURL.append(URLEncoder.encode(s, Constants.ASCII_ENCODING));
} catch (UnsupportedEncodingException e1) {
// should never happen
LOG.error(e1.getMessage(), e1);
}
}
}
return encodedURL.toString();
}
private static boolean isDelimiter(String s) {
return RESERVED.contains(s);
}
/**
* Returns the port for the given URI. If no port can be found, it checks the scheme.
* If the scheme is http port 80 is returned, if https 443.
* <p>
* -1 is returned if no port can be found.
*/
public static int getPort(URI uri) {
int port = uri.getPort();
if (port == -1) {
String scheme = uri.getScheme();
if ("http".equalsIgnoreCase(scheme)) {
port = 80;
} else if ("https".equalsIgnoreCase(scheme)) {
port = 443;
}
}
return port;
}
}