home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1997 May
/
Pcwk0597.iso
/
sybase
/
starbuck
/
java.z
/
URL.java
< prev
next >
Wrap
Text File
|
1996-05-03
|
12KB
|
431 lines
/*
* @(#)URL.java 1.29 96/02/29
*
* Copyright (c) 1994-1996 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for NON-COMMERCIAL purposes and without fee is hereby
* granted provided that this copyright notice appears in all copies. Please
* refer to the file "copyright.html" for further important copyright and
* licensing information.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
* OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
* LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
* ITS DERIVATIVES.
*/
package java.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Hashtable;
import java.util.StringTokenizer;
/**
* Class URL represents a Uniform Reference Locator -- a reference
* to an object on the World Wide Web. This is a constant object,
* once it is created, its fields cannot be changed.
*
* @version 1.29, 29 Feb 1996
* @author James Gosling
*/
public final class URL {
/**
* The property which specifies the package prefix list to be scanned
* for protocol handlers. The value of this property (if any) should
* be a vertical bar delimited list of package names to search through
* for a protocol handler to load. The policy of this class is that
* all protocol handlers will be in a class called <protocolname>.Handler,
* and each package in the list is examined in turn for a matching
* handler. If none are found (or the property is not specified), the
* default package prefix, sun.net.www.protocol, is used. The search
* proceeds from the first package in the last to the last and stops
* when a match is found.
*/
private static final String protocolPathProp = "java.protocol.handler.pkgs";
/**
* The protocol to use (ftp, http, nntp, ... etc.) .
*/
private String protocol;
/**
* The host name in which to connect to.
*/
private String host;
/**
* The protocol port to connect to.
*/
private int port = -1;
/**
* The specified file name on that host.
*/
private String file;
/**
* # reference.
*/
private String ref;
/**
* The URLStreamHandler for this URL.
*/
URLStreamHandler handler;
/**
* Creates an absolute URL from the specified protocol,
* host, port and file.
* @param protocol the protocol to use
* @param host the host to connect to
* @param port the port at that host to connect to
* @param file the file on that host
* @exception MalformedURLException If an unknown protocol is
* found.
*/
public URL(String protocol, String host, int port, String file)
throws MalformedURLException {
this.protocol = protocol;
this.host = host;
this.file = file;
this.port = port;
if ((handler = getURLStreamHandler(protocol)) == null) {
throw new MalformedURLException("unknown protocol: " + protocol);
}
}
/**
* Creates an absolute URL from the specified protocol,
* host, and file. The port number used will be the default for the
* protocol.
* @param protocol the protocol to use
* @param host the host to connect to
* @param file the file on that host
* @exception MalformedURLException If an unknown protocol is
* found.
*/
public URL(String protocol, String host, String file) throws MalformedURLException {
this(protocol, host, -1, file);
}
/**
* Creates a URL from the unparsed absolute URL.
* @param spec the URL String to parse
*/
public URL(String spec) throws MalformedURLException {
this(null, spec);
}
/**
* Creates a URL from the unparsed URL in the specified context.If
* spec is an absolute URL it is used as is. Otherwise it isparsed
* in terms of the context. Context may be null (indicating no
* context).
* @param context the context to parse the URL to
* @param spec the URL String to parse
* @exception MalformedURLException If the protocol is equal to null.
*/
public URL(URL context, String spec) throws MalformedURLException {
String original = spec;
int i, limit, c;
int start = 0;
String newProtocol = null;
try {
limit = spec.length();
while ((limit > 0) && (spec.charAt(limit - 1) <= ' ')) {
limit--; //eliminate trailing whitespace
}
while ((start < limit) && (spec.charAt(start) <= ' ')) {
start++; // eliminate leading whitespace
}
if (spec.regionMatches(true, start, "url:", 0, 4)) {
start += 4;
}
for (i = start ; (i < limit) && ((c = spec.charAt(i)) != '/') ; i++) {
if (c == ':') {
newProtocol = spec.substring(start, i).toLowerCase();
start = i + 1;
break;
}
}
// Only use our context if the protocols match.
if ((context != null) && ((newProtocol == null) ||
newProtocol.equals(context.protocol))) {
protocol = context.protocol;
host = context.host;
port = context.port;
file = context.file;
} else {
protocol = newProtocol;
}
if (protocol == null) {
throw new MalformedURLException("no protocol: "+original);
}
if ((handler = getURLStreamHandler(protocol)) == null) {
throw new MalformedURLException("unknown protocol: "+protocol);
}
i = spec.indexOf('#', start);
if (i >= 0) {
ref = spec.substring(i + 1, limit);
limit = i;
}
handler.parseURL(this, spec, start, limit);
} catch(MalformedURLException e) {
throw e;
} catch(Exception e) {
throw new MalformedURLException(original + ": " + e);
}
}
/**
* Sets the fields of the URL. This is not a public method so that
* only URLStreamHandlers can modify URL fields. URLs are
* otherwise constant.
*
* REMIND: this method will be moved to URLStreamHandler
*
* @param protocol the protocol to use
* @param host the host name to connecto to
* @param port the protocol port to connect to
* @param file the specified file name on that host
* @param ref the reference
*/
protected void set(String protocol, String host, int port, String file, String ref) {
this.protocol = protocol;
this.host = host;
this.port = port;
this.file = file;
this.ref = ref;
}
/**
* Gets the port number. Returns -1 if the port is not set.
*/
public int getPort() {
return port;
}
/**
* Gets the protocol name.
*/
public String getProtocol() {
return protocol;
}
/**
* Gets the host name.
*/
public String getHost() {
return host;
}
/**
* Gets the file name.
*/
public String getFile() {
return file;
}
/**
* Gets the ref.
*/
public String getRef() {
return ref;
}
/**
* Compares two URLs.
* @param obj the URL to compare against.
* @return true if and only if they are equal, false otherwise.
*/
public boolean equals(Object obj) {
return (obj instanceof URL) && sameFile((URL)obj);
}
/**
* Creates an integer suitable for hash table indexing.
*/
public int hashCode() {
int inhash = 0;
if (!host.equals("")) {
try {
inhash = InetAddress.getByName(host).hashCode();
} catch(UnknownHostException e) {
}
}
return protocol.hashCode() ^ inhash ^ file.hashCode();
}
/**
* Compares the host components of two URLs.
* @param h1 the URL of the first host to compare
* @param h2 the URL of the second host to compare
* @return true if and only if they are equal, false otherwise.
* @exception UnknownHostException If an unknown host is found.
*/
boolean hostsEqual(String h1, String h2) {
if (h1.equals(h2)) {
return true;
}
// Have to resolve addresses before comparing, otherwise
// names like tachyon and tachyon.eng would compare different
try {
InetAddress a1 = InetAddress.getByName(h1);
InetAddress a2 = InetAddress.getByName(h2);
return a1.equals(a2);
} catch(UnknownHostException e) {
} catch(SecurityException e) {
}
return false;
}
/**
* Compares two URLs, excluding the "ref" fields: sameFile is true
* if the true references the same remote object, but not necessarily
* the same subpiece of that object.
* @param other the URL to compare against.
* @return true if and only if they are equal, false otherwise.
*/
public boolean sameFile(URL other) {
// AVH: should we not user getPort to compare ports?
return protocol.equals(other.protocol) &&
hostsEqual(host, other.host) &&
(port == other.port) &&
file.equals(other.file);
}
/**
* Converts to a human-readable form.
* @return the textual representation.
*/
public String toString() {
return toExternalForm();
}
/**
* Reverses the parsing of the URL.
* @return the textual representation of the fully qualified URL (i.e.
* after the context and canonicalization have been applied).
*/
public String toExternalForm() {
return handler.toExternalForm(this);
}
/**
* Creates (if not already in existance) a URLConnection object that
* contains a connection to the remote object referred to by
* the URL. Invokes the appropriate protocol handler. Failure is
* indicated by throwing an exception.
* @exception IOException If an I/O exception has occurred.
* @see URLConnection
*/
public URLConnection openConnection()
throws java.io.IOException
{
return handler.openConnection(this);
}
/**
* Opens an input stream.
* @exception IOException If an I/O exception has occurred.
*/
public final InputStream openStream() // REMIND: drop final
throws java.io.IOException
{
return openConnection().getInputStream();
}
/**
* Gets the contents from this opened connection.
* @exception IOException If an I/O exception has occurred.
*/
public final Object getContent() // REMIND: drop final
throws java.io.IOException
{
return openConnection().getContent();
}
/**
* The URLStreamHandler factory.
*/
static URLStreamHandlerFactory factory;
/**
* Sets the URLStreamHandler factory.
* @param fac the desired factory
* @exception Error If the factory has already been defined.
*/
public static synchronized void setURLStreamHandlerFactory(URLStreamHandlerFactory fac) {
if (factory != null) {
throw new Error("factory already defined");
}
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkSetFactory();
}
factory = fac;
}
/**
* A table of protocol handlers.
*/
static Hashtable handlers = new Hashtable();
/**
* Gets the Stream Handler.
* @param protocol the protocol to use
*/
static synchronized URLStreamHandler getURLStreamHandler(String protocol) {
URLStreamHandler handler = (URLStreamHandler)handlers.get(protocol);
if (handler == null) {
// Use the factory (if any)
if (factory != null) {
handler = factory.createURLStreamHandler(protocol);
}
// Try java protocol handler
if (handler == null) {
String packagePrefixList =
System.getProperty(protocolPathProp, "");
if (packagePrefixList != "") {
packagePrefixList += "|";
}
// REMIND: decide whether to allow the "null" class prefix
// or not.
packagePrefixList += "sun.net.www.protocol";
StringTokenizer packagePrefixIter =
new StringTokenizer(packagePrefixList, "|");
while (handler == null && packagePrefixIter.hasMoreTokens()) {
String packagePrefix = packagePrefixIter.nextToken().trim();
try {
String clname = packagePrefix + "." + protocol
+ ".Handler";
handler = (URLStreamHandler)Class.forName(clname).newInstance();
} catch (Exception e) {
}
}
}
if (handler != null) {
handlers.put(protocol, handler);
}
}
return handler;
}
}