]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
URL.java: Merge with Classpath (partly).
authorMark Wielaard <mark@klomp.org>
Fri, 22 Nov 2002 16:48:52 +0000 (16:48 +0000)
committerMark Wielaard <mark@gcc.gnu.org>
Fri, 22 Nov 2002 16:48:52 +0000 (16:48 +0000)
* java/net/URL.java: Merge with Classpath (partly).
* java/net/URLStreamHandler: Merge with Classpath.

From-SVN: r59378

libjava/ChangeLog
libjava/java/net/URL.java
libjava/java/net/URLStreamHandler.java

index be3ade93bf57d30d89e37cef60910932a3841a3f..e86ab93c93dd7919e7fd6c8f52e3f9f048b5bf64 100644 (file)
@@ -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:
index 00dad2c78717a12ea9cc4df37e169585b3ee94b3..98e7d5f7c3148c3442ecb3c72cc196eaf2b489f6 100644 (file)
-// 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");
   }
index a30f1570f89e053eb36a9f9216dee7f489be63af..128a0d2d3da0bc1b1d8df60ba2e813d4aeb03b5c 100644 (file)
@@ -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();
   }
 }