blob: 313baee8266dac03f8fa1d315feb1596f4cb9610 [file] [log] [blame]
//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 IBM Corporation and others.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// Contributors:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.common.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
/**
* Implements a utility class for managing URLs and URIs.
*
* @author Kelvin Low
* @since 1.0
*/
public class NetUtil {
/**
* FILE scheme.
*/
public final static String FILE_SCHEME = "file"; //$NON-NLS-1$
/**
* File URI prefix.
*/
public final static String FILE_URI_PREFIX = FILE_SCHEME + ":/"; //$NON-NLS-1$
/**
* File URI prefix size.
*/
public final static int FILE_URI_PREFIX_LENGTH = FILE_URI_PREFIX.length();
/**
* HTTP scheme.
*/
public final static String HTTP_SCHEME = "http"; //$NON-NLS-1$
/**
* HTTP URI prefix.
*/
public final static String HTTP_URI_PREFIX = HTTP_SCHEME + "://"; //$NON-NLS-1$
/**
* HTTP URI prefix size.
*/
public final static int HTTP_URI_PREFIX_LENGTH = HTTP_URI_PREFIX.length();
/**
* A table of hex values.
*/
private final static String[] HEX_VALUES = {
"%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%08", "%09", "%0A", "%0B", "%0C", "%0D", "%0E", "%0F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%18", "%19", "%1A", "%1B", "%1C", "%1D", "%1E", "%1F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%20", "%21", "%22", "%23", "%24", "%25", "%26", "%27", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%28", "%29", "%2A", "%2B", "%2C", "%2D", "%2E", "%2F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%30", "%31", "%32", "%33", "%34", "%35", "%36", "%37", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%38", "%39", "%3A", "%3B", "%3C", "%3D", "%3E", "%3F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%40", "%41", "%42", "%43", "%44", "%45", "%46", "%47", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%48", "%49", "%4A", "%4B", "%4C", "%4D", "%4E", "%4F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%50", "%51", "%52", "%53", "%54", "%55", "%56", "%57", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%58", "%59", "%5A", "%5B", "%5C", "%5D", "%5E", "%5F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%60", "%61", "%62", "%63", "%64", "%65", "%66", "%67", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%68", "%69", "%6A", "%6B", "%6C", "%6D", "%6E", "%6F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%70", "%71", "%72", "%73", "%74", "%75", "%76", "%77", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%78", "%79", "%7A", "%7B", "%7C", "%7D", "%7E", "%7F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%88", "%89", "%8A", "%8B", "%8C", "%8D", "%8E", "%8F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%98", "%99", "%9A", "%9B", "%9C", "%9D", "%9E", "%9F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%A0", "%A1", "%A2", "%A3", "%A4", "%A5", "%A6", "%A7", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%A8", "%A9", "%AA", "%AB", "%AC", "%AD", "%AE", "%AF", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%B0", "%B1", "%B2", "%B3", "%B4", "%B5", "%B6", "%B7", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%B8", "%B9", "%BA", "%BB", "%BC", "%BD", "%BE", "%BF", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%C0", "%C1", "%C2", "%C3", "%C4", "%C5", "%C6", "%C7", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%C8", "%C9", "%CA", "%CB", "%CC", "%CD", "%CE", "%CF", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%D0", "%D1", "%D2", "%D3", "%D4", "%D5", "%D6", "%D7", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%D8", "%D9", "%DA", "%DB", "%DC", "%DD", "%DE", "%DF", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%E0", "%E1", "%E2", "%E3", "%E4", "%E5", "%E6", "%E7", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%E8", "%E9", "%EA", "%EB", "%EC", "%ED", "%EE", "%EF", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%F0", "%F1", "%F2", "%F3", "%F4", "%F5", "%F6", "%F7", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"%F8", "%F9", "%FA", "%FB", "%FC", "%FD", "%FE", "%FF" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
};
/**
* Private constructor to prevent this class from being instantiated. All
* methods in this class should be static.
*/
private NetUtil() {
}
/**
* Returns the URI for the given file.
*
* @param file
* The input file.
* @return The URI for the given file.
* @throws MalformedURLException
* if an error occur while constructing the URI for the given
* file.
*/
public static String getUri(File file) throws MalformedURLException {
String url = file.toURL().toExternalForm();
StringBuffer strBuf = new StringBuffer();
int urlLength = url.length();
for (int i = 0; i < urlLength; i++) {
char ch = url.charAt(i);
switch (ch) {
case ' ':
strBuf.append("%20"); //$NON-NLS-1$
break;
default:
strBuf.append(ch);
break;
}
}
return strBuf.toString();
}
/**
* Resolves the given URI using the given the base URI.
*
* @param uri
* The URI to resolve.
* @param baseUri
* The base URI.
* @return A fully formed URI.
*/
public static String resolveUri(String uri, String baseUri) {
if (uri == null) {
return null;
}
if (uri.startsWith("../")) { //$NON-NLS-1$
if (baseUri.endsWith("/")) { //$NON-NLS-1$
baseUri = baseUri.substring(0, baseUri.length() - 1);
}
while (uri.startsWith("../")) { //$NON-NLS-1$
uri = uri.substring(3);
int index = baseUri.lastIndexOf('/');
if (index > 0) {
baseUri = baseUri.substring(0, index);
}
}
uri = "/" + uri; //$NON-NLS-1$
}
if (uri.startsWith("/")) { //$NON-NLS-1$
return baseUri.endsWith("/") //$NON-NLS-1$
? baseUri + uri.substring(1) : baseUri + uri;
}
if (uri.startsWith(FILE_URI_PREFIX) || uri.startsWith(HTTP_URI_PREFIX)) {
return uri;
}
return baseUri.endsWith("/") ? baseUri + uri : baseUri + '/' + uri; //$NON-NLS-1$
}
/**
* Returns the input stream for the given URI.
*
* @param uri
* The source URI.
* @return The input stream for the given URI.
* @throw MalformedURLException if a given XML document URI is invalid.
* @throw IOException if an I/O error occur while accessing the URI.
*/
public static InputStream getInputStream(String uri)
throws MalformedURLException, IOException {
if (uri == null) {
return null;
}
if (uri.startsWith(HTTP_URI_PREFIX)) {
URL url = new URL(uri);
return url.openStream();
} else if (uri.startsWith(FILE_URI_PREFIX)) {
uri = uri.substring(FILE_URI_PREFIX_LENGTH);
}
return new FileInputStream(NetUtil.decodeUrl(uri, null));
}
/**
* Returns the Java string represention (encoded in UTF-16) of the given URL
* (encoded in the given encoding and ASCII-escaped).
*
* @param url
* The URL to decode.
* @param encoding
* The encoding of the URL.
* @return The Java UTF-16 string respresentation.
* @throws IllegalArgumentException
* if the given URL contain improperly escaped characters.
*/
public static String decodeUrl(String url, String encoding) {
if (url == null) {
return url;
}
int len = url.length();
if (len == 0) {
return url;
}
// Unescape the url.
StringBuffer strBuf = new StringBuffer();
for (int i = 0; i < len; i++) {
char ch = url.charAt(i);
switch (ch) {
case '+':
strBuf.append(' ');
break;
case '%':
try {
strBuf.append((char) Integer.parseInt(url.substring(i + 1,
i + 3), 16));
} catch (NumberFormatException e) {
throw new IllegalArgumentException();
}
i += 2;
break;
default:
strBuf.append(ch);
break;
}
}
// Convert the un-escaped byte values to Java UTF-16 string.
String result = strBuf.toString();
if (encoding != null) {
try {
byte[] bytes = result.getBytes("8859_1"); //$NON-NLS-1$
result = new String(bytes, encoding);
} catch (UnsupportedEncodingException e) {
}
}
return result;
}
/**
* Returns the ASCII-escaped representation (encoded in the specified
* encoding) of the given URL (encoded in UTF-16).
*
* @param url
* The URL to encode.
* @param encoding
* The encoding of the URL.
* @return the ASCII-escaped respresentation.
* @throws IllegalArgumentException
* if the given URL contain improperly escaped characters.
* @throws UnsupportedEncodingException
* if the given coding is unsupport.
*/
public static String encodeUrl(String url, String encoding)
throws UnsupportedEncodingException {
if (url == null) {
return url;
}
int len = url.length();
if (len == 0) {
return url;
}
StringBuffer result = new StringBuffer();
byte[] bytes = url.getBytes(encoding);
for (int i = 0; i < bytes.length; i++) {
char ch = (char) bytes[i];
if (ch >= 'a' && ch <= 'z') {
result.append(ch);
} else if (ch >= 'A' && ch <= 'Z') {
result.append(ch);
} else if (ch >= '0' && ch <= '9') {
result.append(ch);
} else {
switch (ch) {
case '-':
case '_':
case '.':
case '!':
case '~':
case '*':
case '\'':
case '(':
case ')':
result.append(ch);
break;
default:
result.append(HEX_VALUES[ch & 0xFF]);
break;
}
}
}
return result.toString();
}
/**
* Returns the ASCII-escaped representation of the given file URL.
*
* @param fileURL
* The file URL to encode.
* @return the ASCII-escaped respresentation.
*/
public static String encodeFileURL(String fileURL) {
String url = fileURL;
StringBuffer strBuf = new StringBuffer();
int urlLength = url.length();
for (int i = 0; i < urlLength; i++) {
char ch = url.charAt(i);
switch (ch) {
case ' ':
strBuf.append("%20"); //$NON-NLS-1$
break;
default:
strBuf.append(ch);
break;
}
}
return strBuf.toString();
}
/**
* Returns the ASCII-escaped representation of the given file URL.
*
* @param fileURL
* The file URL to encode.
* @return the ASCII-escaped respresentation.
*/
public static String decodedFileUrl(String fileURL) {
String url = fileURL;
StringBuffer strBuf = new StringBuffer();
int urlLength = url.length();
for (int i = 0; i < urlLength; i++) {
char ch = url.charAt(i);
switch (ch) {
case '%':
try {
strBuf.append((char) Integer.parseInt(url.substring(i + 1,
i + 3), 16));
} catch (NumberFormatException e) {
throw new IllegalArgumentException();
}
i += 2;
break;
default:
strBuf.append(ch);
break;
}
}
return strBuf.toString();
}
public static String decodeURL (String url) throws UnsupportedEncodingException {
// url = url.replaceAll("\\+", "%2B"); //$NON-NLS-1$
url = URLDecoder.decode(url, "UTF-8"); //$NON-NLS-1$
return url;
}
}