home *** CD-ROM | disk | FTP | other *** search
/ Java Programmer's Toolkit / Java Programmer's Toolkit.iso / solaris2 / jdk / src / java / net / url_java < prev    next >
Encoding:
Text File  |  1995-10-30  |  10.7 KB  |  396 lines

  1. /*
  2.  * @(#)URL.java    1.22 95/10/24
  3.  * 
  4.  * Copyright (c) 1994-1995 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for NON-COMMERCIAL purposes and without fee is hereby
  8.  * granted provided that this copyright notice appears in all copies. Please
  9.  * refer to the file "copyright.html" for further important copyright and
  10.  * licensing information.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
  15.  * OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
  16.  * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
  17.  * ITS DERIVATIVES.
  18.  */
  19.  
  20. package java.net;
  21.  
  22. import java.io.IOException;
  23. import java.io.InputStream;
  24. import java.io.OutputStream;
  25. import java.util.Hashtable;
  26.  
  27. /**
  28.  * Class URL represents a Uniform Reference Locator -- a reference
  29.  * to an object on the World Wide Web. This is a constant object,
  30.  * once it is created its fields cannot be changed.
  31.  *
  32.  * @version     1.22, 10/24/95
  33.  * @author     James Gosling
  34.  */
  35.  
  36. public final class URL {
  37.     /** 
  38.      * The protocol to use (ftp, http, nntp, ... etc.) . 
  39.      */
  40.     private String protocol;
  41.  
  42.     /** 
  43.      * The host name in which to connect to. 
  44.      */
  45.     private String host;
  46.  
  47.     /** 
  48.      * The protocol port to connect to. 
  49.      */
  50.     private int port = -1;
  51.  
  52.     /** 
  53.      * The specified file name on that host. 
  54.      */
  55.     private String file;
  56.  
  57.     /** 
  58.      * # reference. 
  59.      */
  60.     private String ref;
  61.  
  62.     /**
  63.      * The URLStreamHandler for this URL.
  64.      */
  65.     URLStreamHandler handler;
  66.  
  67.     /** 
  68.      * Creates an absolute URL from the specified protocol,
  69.      * host, port and file.
  70.      * @param protocol the protocol to use
  71.      * @param host the host to connect to
  72.      * @param port the port at that host to connect to
  73.      * @param file the file on that host
  74.      * @exception MalformedURLException If an unknown protocol is 
  75.      * found. 
  76.      */
  77.     public URL(String protocol, String host, int port, String file)
  78.     throws MalformedURLException {
  79.     this.protocol = protocol;
  80.     this.host = host;
  81.     this.file = file;
  82.     this.port = port;
  83.     if ((handler = getURLStreamHandler(protocol)) == null) {
  84.         throw new MalformedURLException("unknown protocol: " + protocol);
  85.     }
  86.     }
  87.  
  88.     /** 
  89.      * Creates an absolute URL from the specified protocol,
  90.      * host, and file.  The port number used will be the default for the
  91.      * protocol.
  92.      * @param protocol the protocol to use
  93.      * @param host the host to connect to
  94.      * @param file the file on that host
  95.      * @exception MalformedURLException If an unknown protocol is 
  96.      * found. 
  97.      */
  98.     public URL(String protocol, String host, String file) throws MalformedURLException {
  99.     this(protocol, host, -1, file);
  100.     }
  101.  
  102.     /**
  103.      * Creates a URL from the unparsed absolute URL.
  104.      * @param spec the URL String to parse
  105.      */
  106.     public URL(String spec) throws MalformedURLException {
  107.     this(null, spec);
  108.     }
  109.  
  110.     /** 
  111.      * Creates a URL from the unparsed URL in the context of
  112.      * the specified context.  If spec is an absolute URL,
  113.      * cool, otherwise, parse it in terms of the context.
  114.      * Context may be null (indicating no context).
  115.      * @param context the context to parse the URL to.
  116.      * @param spec the URL String to parse
  117.      * @exception MalformedURLException If the protocol is equal to null. 
  118.      */
  119.     public URL(URL context, String spec) throws MalformedURLException {
  120.     String original = spec;
  121.     int i, limit, c;
  122.     int start = 0;
  123.     String newProtocol = null;
  124.  
  125.     try {
  126.         limit = spec.length();
  127.         while ((limit > 0) && (spec.charAt(limit - 1) <= ' ')) {
  128.         limit--;    //eliminate trailing whitespace
  129.         }
  130.         while ((start < limit) && (spec.charAt(start) <= ' ')) {
  131.         start++;    // eliminate leading whitespace
  132.         }
  133.  
  134.         if (spec.regionMatches(true, start, "url:", 0, 4)) {
  135.         start += 4;
  136.         }
  137.         for (i = start ; (i < limit) && ((c = spec.charAt(i)) != '/') ; i++) {
  138.         if (c == ':') {
  139.             newProtocol = spec.substring(start, i).toLowerCase();
  140.             start = i + 1;
  141.             break;
  142.         }
  143.         }
  144.         // Only use our context if the protocols match.
  145.         if ((context != null) && ((newProtocol == null) ||
  146.                     newProtocol.equals(context.protocol))) {
  147.         protocol = context.protocol;
  148.         host = context.host;
  149.         port = context.port;
  150.         file = context.file;
  151.         } else {
  152.         protocol = newProtocol;
  153.         }
  154.  
  155.         if (protocol == null) {
  156.         // turns into MalformedURLException below
  157.         throw new Exception();
  158.         }
  159.  
  160.         if ((handler = getURLStreamHandler(protocol)) == null) {
  161.         // turns into MalformedURLException below
  162.         throw new Exception();
  163.         }
  164.  
  165.         i = spec.indexOf('#', start);
  166.         if (i >= 0) {
  167.         ref = spec.substring(i + 1, limit);
  168.         limit = i;
  169.         }
  170.         handler.parseURL(this, spec, start, limit);
  171.  
  172.     } catch(Exception e) {
  173.         throw new MalformedURLException(original + ": " + e);
  174.     }
  175.     }
  176.  
  177.     /**
  178.      * Sets the fields of the URL. This is not a public method so that 
  179.      * only URLStreamHandlers can modify URL fields. URLs are 
  180.      * otherwise constant.
  181.      *
  182.      * REMIND: this method will be moved to URLStreamHandler
  183.      *
  184.      * @param protocol the protocol to use
  185.      * @param host the host name to connecto to
  186.      * @param port the protocol port to connect to
  187.      * @param file the specified file name on that host
  188.      * @param ref the reference
  189.      */
  190.     protected void set(String protocol, String host, int port, String file, String ref) {
  191.     this.protocol = protocol;
  192.     this.host = host;
  193.     this.port = port;
  194.     this.file = file;
  195.     this.ref = ref;
  196.     }
  197.  
  198.     /**
  199.      * Gets the port number. Returns -1 if the port is not set.
  200.      */
  201.     public int getPort() {
  202.     return port;
  203.     }
  204.  
  205.     /**
  206.      * Gets the protocol name.
  207.      */
  208.     public String getProtocol() {
  209.     return protocol;
  210.     }
  211.  
  212.     /**
  213.      * Gets the host name.
  214.      */
  215.     public String getHost() {
  216.     return host;
  217.     }
  218.  
  219.     /**
  220.      * Gets the file name.
  221.      */
  222.     public String getFile() {
  223.     return file;
  224.     }
  225.  
  226.     /**
  227.      * Gets the ref.
  228.      */
  229.     public String getRef() {
  230.     return ref;
  231.     }
  232.  
  233.     /**
  234.      * Compares two URLs.
  235.      * @param    obj the URL to compare against.
  236.      * @return    true if and only if they are equal, false otherwise.
  237.      */
  238.     public boolean equals(Object obj) {
  239.     return (obj instanceof URL) && sameFile((URL)obj);
  240.     }
  241.  
  242.     /** 
  243.      * Creates an integer suitable for hash table indexing. 
  244.      */
  245.     public int hashCode() {
  246.     int inhash = 0;
  247.     try {
  248.         inhash = InetAddress.getByName(host).hashCode();
  249.     } catch(UnknownHostException e) {
  250.     }
  251.     return protocol.hashCode() ^ inhash ^ file.hashCode();
  252.     }
  253.  
  254.     /**
  255.      * Compares the host components of two URLs.
  256.      * @param h1 the URL of the first host to compare 
  257.      * @param h2 the URL of the second host to compare 
  258.      * @return    true if and only if they are equal, false otherwise.
  259.      * @exception UnknownHostException If an unknown host is found.
  260.      */
  261.     boolean hostsEqual(String h1, String h2) {
  262.     if (h1.equals(h2)) {
  263.         return true;
  264.     }
  265.     // Have to resolve addresses before comparing, otherwise
  266.     // names like tachyon and tachyon.eng would compare different
  267.     try {
  268.         InetAddress a1 = InetAddress.getByName(h1);
  269.         InetAddress a2 = InetAddress.getByName(h2);
  270.         return a1.equals(a2);
  271.     } catch(UnknownHostException e) {
  272.     } catch(SecurityException e) {
  273.     }
  274.     return false;
  275.     }
  276.  
  277.     /**
  278.      * Compares two URLs, excluding the "ref" fields: sameFile is true
  279.      * if the true references the same remote object, but not necessarily
  280.      * the same subpiece of that object.
  281.      * @param    other    the URL to compare against.
  282.      * @return    true if and only if they are equal, false otherwise.
  283.      */
  284.     public boolean sameFile(URL other) {
  285.     // AVH: should we not user getPort to compare ports?
  286.     return protocol.equals(other.protocol) &&
  287.            hostsEqual(host, other.host) &&
  288.            (port == other.port) &&
  289.            file.equals(other.file);
  290.     }
  291.  
  292.     /**
  293.      * Converts to a human-readable form.
  294.      * @return    the textual representation.
  295.      */
  296.     public String toString() {
  297.     return toExternalForm();
  298.     }
  299.  
  300.     /**
  301.      * Reverses the parsing of the URL.
  302.      * @return    the textual representation of the fully qualified URL (ie.
  303.      *        after the context and canonicalization have been applied).
  304.      */
  305.     public String toExternalForm() {
  306.     return handler.toExternalForm(this);
  307.     }
  308.  
  309.     /** 
  310.      * Creates (if not already in existance) a URLConnection object that
  311.      * contains a connection to the remote object referred to by
  312.      * the URL.  Invokes the appropriate protocol handler.  Failure is
  313.      * indicated by throwing an exception.
  314.      * @exception IOException If an I/O exception has occurred.
  315.      * @see URLConnection
  316.      */
  317.     public URLConnection openConnection()
  318.     throws java.io.IOException
  319.     {
  320.     return handler.openConnection(this);
  321.     }
  322.  
  323.     /**
  324.      * Opens an input stream.
  325.      * @exception IOException If an I/O exception has occurred.
  326.      */
  327.     public final InputStream openStream()             // REMIND: drop final
  328.     throws java.io.IOException
  329.     {
  330.     return openConnection().getInputStream();
  331.     }
  332.  
  333.     /**
  334.      * Gets the contents from this opened connection.
  335.      * @exception IOException If an I/O exception has occurred.
  336.      */
  337.     public final Object getContent()                 // REMIND: drop final
  338.     throws java.io.IOException
  339.     {
  340.     return openConnection().getContent();
  341.     }
  342.  
  343.     /**
  344.      * The URLStreamHandler factory.
  345.      */
  346.     static URLStreamHandlerFactory factory;
  347.  
  348.     /**
  349.      * Sets the URLStreamHandler factory.
  350.      * @param fac the desired factory
  351.      * @exception Exception If the factory has already been defined.
  352.      */
  353.     public static synchronized void setURLStreamHandlerFactory(URLStreamHandlerFactory fac) {
  354.     if (factory != null) {
  355.         throw new Error("factory already defined");
  356.     }
  357.     SecurityManager security = System.getSecurityManager();
  358.     if (security != null) {
  359.         security.checkSetFactory();
  360.     }
  361.     factory = fac;
  362.     }
  363.  
  364.     /**
  365.      * A table of protocol handlers.
  366.      */
  367.     static Hashtable handlers = new Hashtable();
  368.  
  369.     /**
  370.      * Gets the Stream Handler.
  371.      * @param protocol the protocol to use
  372.      */
  373.     static synchronized URLStreamHandler getURLStreamHandler(String protocol) {
  374.     URLStreamHandler handler = (URLStreamHandler)handlers.get(protocol);
  375.     if (handler == null) {
  376.         // Use the factory (if any)
  377.         if (factory != null) {
  378.         handler = factory.createURLStreamHandler(protocol);
  379.         }
  380.  
  381.         // Try java protocol handler
  382.         if (handler == null) {
  383.         try {
  384.             String clname = "sun.net.www.protocol." + protocol + ".Handler";
  385.             handler = (URLStreamHandler)Class.forName(clname).newInstance();
  386.         } catch (Exception e) {
  387.         }
  388.         }
  389.         if (handler != null) {
  390.         handlers.put(protocol, handler);
  391.         }
  392.     }
  393.     return handler;
  394.     }
  395. }
  396.