diff options
Diffstat (limited to 'libjava')
-rw-r--r-- | libjava/ChangeLog | 5 | ||||
-rw-r--r-- | libjava/java/net/URL.java | 416 | ||||
-rw-r--r-- | libjava/java/net/URLStreamHandler.java | 218 |
3 files changed, 474 insertions, 165 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog index be3ade9..e86ab93 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,8 @@ +2002-11-21 Mark Wielaard <mark@klomp.org> + + * java/net/URL.java: Merge with Classpath (partly). + * java/net/URLStreamHandler: Merge with Classpath. + 2002-11-22 Michael Koch <konqueror@gmx.de> * include/posix.h: 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"); } diff --git a/libjava/java/net/URLStreamHandler.java b/libjava/java/net/URLStreamHandler.java index a30f157..128a0d2 100644 --- a/libjava/java/net/URLStreamHandler.java +++ b/libjava/java/net/URLStreamHandler.java @@ -1,28 +1,78 @@ -// URLStreamHandler.java - Superclass of all stream protocol handlers. +/* URLStreamHandler.java -- Abstract superclass for all protocol handlers + Copyright (C) 1998, 1999, 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, 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.IOException; -/** - * @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 class is the superclass of all URL protocol handlers. The URL + * class loads the appropriate protocol handler to establish a connection + * to a (possibly) remote service (eg, "http", "ftp") and to do protocol + * specific parsing of URL's. Refer to the URL class documentation for + * details on how that class locates and loads protocol handlers. + * <p> + * A protocol handler implementation should override the openConnection() + * method, and optionally override the parseURL() and toExternalForm() + * methods if necessary. (The default implementations will parse/write all + * URL's in the same form as http URL's). A protocol specific subclass + * of URLConnection will most likely need to be created as well. + * <p> + * Note that the instance methods in this class are called as if they + * were static methods. That is, a URL object to act on is passed with + * every call rather than the caller assuming the URL is stored in an + * instance variable of the "this" object. + * <p> + * The methods in this class are protected and accessible only to subclasses. + * URLStreamConnection objects are intended for use by the URL class only, + * not by other classes (unless those classes are implementing protocols). + * + * @author Aaron M. Renn (arenn@urbanophile.com) + * @author Warren Levy (warrenl@cygnus.com) + * + * @see URL + */ public abstract class URLStreamHandler { /** @@ -33,8 +83,15 @@ public abstract class URLStreamHandler } /** - * Opens a connection to the object referenced by the URL argument. - * This method should be overridden by a subclass. + * Returns a URLConnection for the passed in URL. Note that this should + * not actually create the connection to the (possibly) remote host, but + * rather simply return a URLConnection object. The connect() method of + * URL connection is used to establish the actual connection, possibly + * after the caller sets up various connection options. + * + * @param url The URL to get a connection object for + * + * @return A URLConnection object for the given URL * * @exception IOException If an error occurs */ @@ -42,28 +99,33 @@ public abstract class URLStreamHandler throws IOException; /** - * Pasrses the given URL + * This method parses the string passed in as a URL and set's the + * instance data fields in the URL object passed in to the various values + * parsed out of the string. The start parameter is the position to start + * scanning the string. This is usually the position after the ":" which + * terminates the protocol name. The end parameter is the position to + * stop scanning. This will be either the end of the String, or the + * position of the "#" character, which separates the "file" portion of + * the URL from the "anchor" portion. + * <p> + * This method assumes URL's are formatted like http protocol URL's, so + * subclasses that implement protocols with URL's the follow a different + * syntax should override this method. The lone exception is that if + * the protocol name set in the URL is "file", this method will accept + * a an empty hostname (i.e., "file:///"), which is legal for that protocol * - * @param u The URL to parse - * @param spec The specification to use - * @param start The character index at which to begin parsing. This is just - * past the ':' (if there is one) that specifies the determination of the - * protocol name - * @param limit The character position to stop parsing at. This is the end - * of the string or the position of the "#" character, if present. All - * information after the sharp sign indicates an anchor + * @param url The URL object in which to store the results + * @param spec The String-ized URL to parse + * @param start The position in the string to start scanning from + * @param end The position in the string to stop scanning */ - protected void parseURL(URL u, String spec, int start, int limit) + protected void parseURL(URL url, String spec, int start, int end) { - String host = u.getHost(); - int port = u.getPort(); - String file = u.getFile(); + String host = url.getHost(); + int port = url.getPort(); + String file = url.getFile(); + String ref = url.getRef(); - /* TBD: The JDK 1.2 doc specifically says that limit is the position - * to stop parsing at and that it will be either the end of the string - * or the position of '#'; thus the doc infers that this method does - * not set the ref. - */ if (spec.regionMatches (start, "//", 0, 2)) { int hostEnd; @@ -74,7 +136,7 @@ public abstract class URLStreamHandler if (slash >= 0) hostEnd = slash; else - hostEnd = limit; + hostEnd = end; host = spec.substring (start, hostEnd); @@ -103,28 +165,46 @@ public abstract class URLStreamHandler else if (host == null) host = ""; - if (start < limit && spec.charAt(start) == '/') - { - // This is an absolute path name; ignore any file context. - file = spec.substring(start, limit); - } - else if (file == null || file.length() <= 0) + if (file == null || file.length() == 0 + || (start < end && spec.charAt(start) == '/')) { // No file context available; just spec for file. - file = spec.substring(start, limit); - } - else if (start < limit) + // Or this is an absolute path name; ignore any file context. + file = spec.substring(start, end); + ref = null; + } + else if (start < end) { // Context is available, but only override it if there is a new file. file = file.substring(0, file.lastIndexOf('/')) - + '/' + spec.substring(start, limit); + + '/' + spec.substring(start, end); + ref = null; } - u.set(u.getProtocol(), host, port, file, u.getRef()); + if (ref == null) + { + // Normally there should be no '#' in the file part, + // but we are nice. + int hash = file.indexOf('#'); + if (hash != -1) + { + ref = file.substring(hash + 1, file.length()); + file = file.substring(0, hash); + } + } + + // XXX - Classpath used to call PlatformHelper.toCanonicalForm() on + // the file part. It seems like overhead, but supposedly there is some + // benefit in windows based systems (it also lowercased the string). + + setURL(url, url.getProtocol(), host, port, file, ref); } private static String canonicalizeFilename(String file) { + // XXX - GNU Classpath has an implementation that might be more appropriate + // for Windows based systems (gnu.java.io.PlatformHelper.toCanonicalForm) + int index; // Replace "/./" with "/". This probably isn't very efficient in @@ -179,7 +259,8 @@ public abstract class URLStreamHandler } /** - * Sets the fields of the URL argument to the indicated values + * This methods sets the instance variables representing the various fields + * of the URL to the values passed in. * * @param u The URL to modify * @param protocol The protocol to set @@ -317,38 +398,53 @@ public abstract class URLStreamHandler } /** - * Converts an URL of a specific protocol to a string + * This method converts a URL object into a String. This method creates + * Strings in the mold of http URL's, so protocol handlers which use URL's + * that have a different syntax should override this method * - * @param u The URL to convert + * @param url The URL object to convert */ protected String toExternalForm(URL u) { - String resStr, host, file, ref; + String protocol, host, file, ref; int port; - resStr = u.getProtocol() + ":"; + protocol = u.getProtocol(); + + // 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. host = u.getHost(); + if (host == null) + host = ""; + port = u.getPort(); file = u.getFile(); ref = u.getRef(); - // 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. - // + // Guess a reasonable size for the string buffer so we have to resize + // at most once. + int size = protocol.length() + host.length() + file.length() + 24; + StringBuffer sb = new StringBuffer(size); + + sb.append(protocol); + sb.append(':'); + + if (host.length() != 0) + sb.append("//").append(host); + // Note that this produces different results from JDK 1.2 as JDK 1.2 // ignores a non-default port if host is null or "". That is inconsistent // with the spec since the result of this method is spec'ed so it can be // used to construct a new URL that is equivalent to the original. - if (host == null) - host = ""; - if (port >= 0 || ! (host.length() == 0)) - resStr = resStr + "//" + host + (port < 0 ? "" : ":" + port); + boolean port_needed = port >= 0 && port != getDefaultPort(); + if (port_needed) + sb.append(':').append(port); - resStr = resStr + file; + sb.append(file); if (ref != null) - resStr = resStr + "#" + ref; + sb.append('#').append(ref); - return resStr; + return sb.toString(); } } |