diff options
Diffstat (limited to 'libjava/java/net/URL.java')
-rw-r--r-- | libjava/java/net/URL.java | 416 |
1 files changed, 312 insertions, 104 deletions
diff --git a/libjava/java/net/URL.java b/libjava/java/net/URL.java index 00dad2c..98e7d5f 100644 --- a/libjava/java/net/URL.java +++ b/libjava/java/net/URL.java @@ -1,56 +1,180 @@ -// URL.java - A Uniform Resource Locator. +/* URL.java -- Uniform Resource Locator Class + Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ -/* Copyright (C) 1999, 2000, 2002 Free Software Foundation - - This file is part of libgcj. - -This software is copyrighted work licensed under the terms of the -Libgcj License. Please consult the file "LIBGCJ_LICENSE" for -details. */ package java.net; -import java.io.*; +import java.io.InputStream; +import java.io.IOException; +import java.io.Serializable; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.util.Hashtable; import java.util.StringTokenizer; -/** - * @author Warren Levy <warrenl@cygnus.com> - * @date March 4, 1999. - */ -/** +/* * Written using on-line Java Platform 1.2 API Specification, as well * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). * Status: Believed complete and correct. */ +/** + * This final class represents an Internet Uniform Resource Locator (URL). + * For details on the syntax of URL's and what they can be used for, + * refer to RFC 1738, available from <a + * href="http://ds.internic.net/rfcs/rfc1738.txt">http://ds.internic.net/rfcs/rfc1738.txt</a> + * <p> + * There are a great many protocols supported by URL's such as "http", + * "ftp", and "file". This object can handle any arbitrary URL for which + * a URLStreamHandler object can be written. Default protocol handlers + * are provided for the "http" and "ftp" protocols. Additional protocols + * handler implementations may be provided in the future. In any case, + * an application or applet can install its own protocol handlers that + * can be "chained" with other protocol hanlders in the system to extend + * the base functionality provided with this class. (Note, however, that + * unsigned applets cannot access properties by default or install their + * own protocol handlers). + * <p> + * This chaining is done via the system property java.protocol.handler.pkgs + * If this property is set, it is assumed to be a "|" separated list of + * package names in which to attempt locating protocol handlers. The + * protocol handler is searched for by appending the string + * ".<protocol>.Handler" to each packed in the list until a hander is found. + * If a protocol handler is not found in this list of packages, or if the + * property does not exist, then the default protocol handler of + * "gnu.java.net.<protocol>.Handler" is tried. If this is + * unsuccessful, a MalformedURLException is thrown. + * <p> + * All of the constructor methods of URL attempt to load a protocol + * handler and so any needed protocol handlers must be installed when + * the URL is constructed. + * <p> + * Here is an example of how URL searches for protocol handlers. Assume + * the value of java.protocol.handler.pkgs is "com.foo|com.bar" and the + * URL is "news://comp.lang.java.programmer". URL would looking the + * following places for protocol handlers: + * <p><pre> + * com.foo.news.Handler + * com.bar.news.Handler + * gnu.java.net.news.Handler + * </pre><p> + * If the protocol handler is not found in any of those locations, a + * MalformedURLException would be thrown. + * <p> + * Please note that a protocol handler must be a subclass of + * URLStreamHandler. + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Warren Levy <warrenl@cygnus.com> + * + * @see URLStreamHandler + */ public final class URL implements Serializable { + /** + * The name of the protocol for this URL. + * The protocol is always stored in lower case. + */ private String protocol; + + /** + * The "authority" portion of the URL. + */ private String authority; - private String userInfo; + + /** + * The hostname or IP address of this protocol. + * This includes a possible user. For example <code>joe@some.host.net</code>. + */ private String host; + + /** + * The port number of this protocol or -1 if the port number used is + * the default for this protocol. + */ private int port = -1; // Initialize for constructor using context. + + /** + * The "file" portion of the URL. It is defined as <code>path[?query]</code>. + */ private String file; - private String query; + + /** + * The anchor portion of the URL. + */ private String ref; + + /** + * This is the hashCode for this URL + */ private int hashCode = 0; + + /** + * The protocol handler in use for this URL + */ transient private URLStreamHandler handler; + + /** + * This a table where we cache protocol handlers to avoid the overhead + * of looking them up each time. + */ private static Hashtable handlers = new Hashtable(); + + /** + * If an application installs its own protocol handler factory, this is + * where we keep track of it. + */ private static URLStreamHandlerFactory factory; private static final long serialVersionUID = -7627629688361524110L; /** - * Creates an URL object from the given arguments - * - * @param protocol The protocol of the URL - * @param host The host of the URL - * @param port The port of the URL - * @param file The file of the URL + * Constructs a URL and loads a protocol handler for the values passed as + * arguments. + * + * @param protocol The protocol for this URL ("http", "ftp", etc) + * @param host The hostname or IP address to connect to + * @param port The port number to use, or -1 to use the protocol's + * default port + * @param file The "file" portion of the URL. * - * @exception MalformedURLException If an error occurs + * @exception MalformedURLException If a protocol handler cannot be loaded or + * a parse error occurs. */ public URL(String protocol, String host, int port, String file) throws MalformedURLException @@ -59,13 +183,15 @@ public final class URL implements Serializable } /** - * Creates an URL object from the given arguments + * Constructs a URL and loads a protocol handler for the values passed in + * as arugments. Uses the default port for the protocol. * - * @param protocol The protocol of the URL - * @param host The host of the URL - * @param file The file of the URL + * @param protocol The protocol for this URL ("http", "ftp", etc) + * @param host The hostname or IP address for this URL + * @param file The "file" portion of this URL. * - * @exception MalformedURLException If an error occurs + * @exception MalformedURLException If a protocol handler cannot be loaded or + * a parse error occurs. */ public URL(String protocol, String host, String file) throws MalformedURLException @@ -73,19 +199,26 @@ public final class URL implements Serializable this(protocol, host, -1, file, null); } + /** - * Creates an URL object from the given arguments + * This method initializes a new instance of <code>URL</code> with the + * specified protocol, host, port, and file. Additionally, this method + * allows the caller to specify a protocol handler to use instead of + * the default. If this handler is specified, the caller must have + * the "specifyStreamHandler" permission (see <code>NetPermission</code>) + * or a <code>SecurityException</code> will be thrown. * - * @param protocol The protocol of the URL - * @param host The host of the URL - * @param port The port of the URL - * @param file The file of the URL - * @param handler The stream handler for the URL + * @param protocol The protocol for this URL ("http", "ftp", etc) + * @param host The hostname or IP address to connect to + * @param port The port number to use, or -1 to use the protocol's default + * port + * @param file The "file" portion of the URL. + * @param handler The protocol handler to use with this URL. * - * @exception MalformedURLException If an error occurs - * @exception SecurityException If a security manager exists and its - * checkPermission method doesn't allow specifying a stream handler - * explicitly + * @exception MalformedURLException If no protocol handler can be loaded + * for the specified protocol. + * @exception SecurityException If the <code>SecurityManager</code> exists + * and does not allow the caller to specify its own protocol handler. * * @since 1.2 */ @@ -94,18 +227,18 @@ public final class URL implements Serializable { if (protocol == null) throw new MalformedURLException("null protocol"); - this.protocol = protocol; + this.protocol = protocol.toLowerCase(); if (handler != null) { - SecurityManager s = System.getSecurityManager (); + SecurityManager s = System.getSecurityManager(); if (s != null) s.checkPermission (new NetPermission ("specifyStreamHandler")); this.handler = handler; } else - this.handler = setURLStreamHandler(protocol); + this.handler = getURLStreamHandler(protocol); if (this.handler == null) throw new MalformedURLException ( @@ -113,9 +246,7 @@ public final class URL implements Serializable this.host = host; this.port = port; - this.userInfo = null; this.authority = null; - this.query = null; int hashAt = file.indexOf('#'); if (hashAt < 0) @@ -132,24 +263,37 @@ public final class URL implements Serializable } /** - * Creates an URL object from the given arguments - * - * @param spec The string to parse an URL + * Initializes a URL from a complete string specification such as + * "http://www.urbanophile.com/arenn/". First the protocol name is parsed + * out of the string. Then a handler is located for that protocol and + * the parseURL() method of that protocol handler is used to parse the + * remaining fields. * - * @exception MalformedURLException If an error occurs + * @param spec The complete String representation of a URL + * + * @exception MalformedURLException If a protocol handler cannot be found + * or the URL cannot be parsed */ public URL(String spec) throws MalformedURLException { this((URL) null, spec, (URLStreamHandler) null); } - /** - * Creates an URL object from the given arguments - * + /* + * This method parses a String representation of a URL within the + * context of an existing URL. Principally this means that any + * fields not present the URL are inheritied from the context URL. + * This allows relative URL's to be easily constructed. If the + * context argument is null, then a complete URL must be specified + * in the URL string. If the protocol parsed out of the URL is + * different from the context URL's protocol, then then URL String + * is also expected to be a complete URL. + * * @param context The context on which to parse the specification * @param spec The string to parse an URL * - * @exception MalformedURLException If an error occurs + * @exception MalformedURLException If a protocol handler cannot be found + * for the URL cannot be parsed */ public URL(URL context, String spec) throws MalformedURLException { @@ -158,16 +302,30 @@ public final class URL implements Serializable /** * Creates an URL from given arguments + * This method parses a String representation of a URL within the + * context of an existing URL. Principally this means that any fields + * not present the URL are inheritied from the context URL. This allows + * relative URL's to be easily constructed. If the context argument is + * null, then a complete URL must be specified in the URL string. + * If the protocol parsed out of the URL is different + * from the context URL's protocol, then then URL String is also + * expected to be a complete URL. + * <p> + * Additionally, this method allows the caller to specify a protocol handler + * to use instead of the default. If this handler is specified, the caller + * must have the "specifyStreamHandler" permission + * (see <code>NetPermission</code>) or a <code>SecurityException</code> + * will be thrown. * * @param context The context in which to parse the specification * @param spec The string to parse as an URL * @param handler The stream handler for the URL * - * @exception MalformedURLException If an error occurs - * @exception SecurityException If a security manager exists and its - * checkPermission method doesn't allow specifying a stream handler - * explicitly - * + * @exception MalformedURLException If a protocol handler cannot be found + * or the URL cannot be parsed + * @exception SecurityException If the <code>SecurityManager</code> exists + * and does not allow the caller to specify its own protocol handler. + * * @since 1.2 */ public URL(URL context, String spec, URLStreamHandler handler) @@ -198,16 +356,14 @@ public final class URL implements Serializable (colon < (slash = spec.indexOf('/')) || slash < 0)) { // Protocol specified in spec string. - protocol = spec.substring(0, colon); + protocol = spec.substring(0, colon).toLowerCase(); if (context != null && context.protocol.equals(protocol)) { // The 1.2 doc specifically says these are copied to the new URL. host = context.host; port = context.port; file = context.file; - userInfo = context.userInfo; authority = context.authority; - query = context.query; } } else if (context != null) @@ -219,9 +375,7 @@ public final class URL implements Serializable host = context.host; port = context.port; file = context.file; - userInfo = context.userInfo; authority = context.authority; - query = context.query; } else // Protocol NOT specified in spec. and no context available. throw new @@ -236,7 +390,7 @@ public final class URL implements Serializable this.handler = handler; } else - this.handler = setURLStreamHandler(protocol); + this.handler = getURLStreamHandler(protocol); if (this.handler == null) throw new MalformedURLException("Protocol handler not found: " @@ -255,7 +409,14 @@ public final class URL implements Serializable } /** - * Checks if two URLs are equal + * Test another URL for equality with this one. This will be true only if + * the argument is non-null and all of the fields in the URL's match + * exactly (ie, protocol, host, port, file, and ref). Overrides + * Object.equals(), implemented by calling the equals method of the handler. + * + * @param url The URL to compare with + * + * @return true if the URL is equal, false otherwise */ public boolean equals(Object obj) { @@ -268,9 +429,12 @@ public final class URL implements Serializable } /** - * Gets the contents of this URL + * Returns the contents of this URL as an object by first opening a + * connection, then calling the getContent() method against the connection * - * @exception IOException If an error occurs + * @return A content object for this URL + * @exception IOException If opening the connection or getting the + * content fails. * * @since 1.3 */ @@ -291,15 +455,18 @@ public final class URL implements Serializable } /** - * Returns the file of the URL + * Returns the file portion of the URL. + * Defined as <code>path[?query]</code>. + * Returns the empty string if there is no file portion. */ public String getFile() { - return file; + return file == null ? "" : file; } /** - * Returns the path of the URL + * Returns the path of the URL. This is the part of the file before any '?' + * character. * * @since 1.3 */ @@ -324,11 +491,17 @@ public final class URL implements Serializable */ public String getHost() { - return host; + int at = (host == null) ? -1 : host.indexOf('@'); + return at < 0 ? host : host.substring(at + 1, host.length()); } /** - * Returns of port of the URL + * Returns the port number of this URL or -1 if the default port number is + * being used. + * + * @return The port number + * + * @see #getDefaultPort() */ public int getPort() { @@ -336,11 +509,12 @@ public final class URL implements Serializable } /** - * Returns the default port of the URL + * Returns the default port of the URL. If the StreamHandler for the URL + * protocol does not define a default port it returns -1. */ public int getDefaultPort() { - return 0; + return handler.getDefaultPort(); } /** @@ -351,13 +525,22 @@ public final class URL implements Serializable return protocol; } + /** + * Returns the ref (sometimes called the "# reference" or "anchor") portion + * of the URL. + * + * @return The ref + */ public String getRef() { return ref; } /** - * Returns the user information of the URL + * Returns the user information of the URL. This is the part of the host + * name before the '@'. + * + * @return the user at a particular host or null when no user defined. */ public String getUserInfo () { @@ -366,11 +549,15 @@ public final class URL implements Serializable } /** - * Returns the query of the URL + * Returns the query of the URL. This is the part of the file before the + * '?'. + * + * @ return the query part of the file, or null when there is no query part. */ public String getQuery () { - return query; + int quest = file.indexOf('?'); + return quest < 0 ? null : file.substring(quest + 1, file.length()); } /** @@ -378,20 +565,6 @@ public final class URL implements Serializable */ public int hashCode() { - // JCL book says this is computed using (only) the hashcodes of the - // protocol, host and file fields. Empirical evidence indicates this - // is probably XOR in JDK 1.1. In JDK 1.2 it seems to be a sum including - // the port. - // - // JDK 1.2 online doc infers that host could be null because it - // explicitly states that file cannot be null but is silent on host. - // A simple example with protocol "http" (hashcode 3213448), host null, - // file "/" (hashcode 47) produced a hashcode (3213494) which appeared - // to be the sum of the two hashcodes plus the port. Another example - // using "/index.html" for file bore this out; as well as "#" for file - // (which was reduced to "" with a hashcode of zero). A "" host also - // causes the port number and the two hashcodes to be summed. - if (hashCode != 0) return hashCode; // Use cached value if available. else @@ -400,8 +573,10 @@ public final class URL implements Serializable /** * Returns a URLConnection object that represents a connection to the remote - * object referred to by the URL + * object referred to by the URL. The URLConnection is created by calling the + * openConnection() method of the protocol handler * + * @return A URLConnection for this URL * @exception IOException If an error occurs */ public URLConnection openConnection() throws IOException @@ -420,6 +595,16 @@ public final class URL implements Serializable return openConnection().getInputStream(); } + /** + * Tests whether or not another URL refers to the same "file" as this one. + * This will be true if and only if the passed object is not null, is a + * URL, and matches all fields but the ref (ie, protocol, host, port, + * and file); + * + * @param url The URL object to test with + * + * @return true if URL matches this URL's file, false otherwise + */ public boolean sameFile(URL other) { return handler.sameFile(this, other); @@ -427,8 +612,15 @@ public final class URL implements Serializable /** * Sets the specified fields of the URL. This is not a public method so - * that only URLStreamHandlers can modify URL fields. URLs are otherwise - * constant + * that only URLStreamHandlers can modify URL fields. This might be called + * by the <code>parseURL()</code> method in that class. URLs are otherwise + * constant. + * + * @param protocol The protocol name for this URL + * @param host The hostname or IP address for this URL + * @param port The port number of this URL + * @param file The "file" portion of this URL. + * @param ref The anchor portion of this URL. */ protected void set(String protocol, String host, int port, String file, String ref) @@ -437,14 +629,12 @@ public final class URL implements Serializable // invalid protocol. It will cause the handler to be set to null // thus overriding a valid handler. Callers of this method should // be aware of this. - this.handler = setURLStreamHandler(protocol); - this.protocol = protocol; + this.handler = getURLStreamHandler(protocol); + this.protocol = protocol.toLowerCase(); this.authority = null; - this.userInfo = null; this.port = port; this.host = host; this.file = file; - this.query = null; this.ref = ref; hashCode = hashCode(); // Used for serialization. } @@ -452,7 +642,7 @@ public final class URL implements Serializable /** * Sets the specified fields of the URL. This is not a public method so * that only URLStreamHandlers can modify URL fields. URLs are otherwise - * constant + * constant. * * @since 1.3 */ @@ -464,8 +654,8 @@ public final class URL implements Serializable // invalid protocol. It will cause the handler to be set to null // thus overriding a valid handler. Callers of this method should // be aware of this. - this.handler = setURLStreamHandler(protocol); - this.protocol = protocol; + this.handler = getURLStreamHandler(protocol); + this.protocol = protocol.toLowerCase(); if (userInfo == null) this.host = host; else @@ -480,9 +670,13 @@ public final class URL implements Serializable } /** - * Sets an application's URLStreamHandlerFactory + * Sets the URLStreamHandlerFactory for this class. This factory is + * responsible for returning the appropriate protocol handler for + * a given URL. + * + * @param fac The URLStreamHandlerFactory class to use * - * @exception Error If the application has already set a factory + * @exception Error If the factory is alread set. * @exception SecurityException If a security manager exists and its * checkSetFactory method doesn't allow the operation */ @@ -500,19 +694,33 @@ public final class URL implements Serializable factory = fac; } + /** + * Returns a String representing this URL. The String returned is + * created by calling the protocol handler's toExternalForm() method. + * + * @return A string for this URL + */ public String toExternalForm() { // Identical to toString(). return handler.toExternalForm(this); } + /** + * Returns a String representing this URL. Identical to toExternalForm(). + * The value returned is created by the protocol handler's + * toExternalForm method. Overrides Object.toString() + * + * @return A string for this URL + */ public String toString() { // Identical to toExternalForm(). return handler.toExternalForm(this); } - private URLStreamHandler setURLStreamHandler(String protocol) + private static synchronized URLStreamHandler + getURLStreamHandler(String protocol) { URLStreamHandler handler; @@ -532,7 +740,7 @@ public final class URL implements Serializable // This is an interesting case. It's tempting to think that we // could call Class.forName ("gnu.gcj.protocol.file.Handler") to // get the appropriate class. Unfortunately, if we do that the - // program will never terminate, because setURLStreamHandler is + // program will never terminate, because getURLStreamHandler is // eventually called by Class.forName. // // Treating "file" as a special case is the minimum that will @@ -587,7 +795,7 @@ public final class URL implements Serializable throws IOException, ClassNotFoundException { ois.defaultReadObject(); - this.handler = setURLStreamHandler(protocol); + this.handler = getURLStreamHandler(protocol); if (this.handler == null) throw new IOException("Handler for protocol " + protocol + " not found"); } |