home *** CD-ROM | disk | FTP | other *** search
/ Java Programmer's Toolkit / Java Programmer's Toolkit.iso / src / java / net / url~1.jav < prev    next >
Encoding:
Text File  |  1996-01-12  |  10.8 KB  |  399 lines

  1. /*
  2.  * @(#)URL.java    1.27 95/12/18
  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.27, 12/18/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 specified context.If
  112.      * spec is an absolute URL it is used as is. Otherwise it isparsed
  113.      * in terms of the context.  Context may be null (indicating no
  114.      * context).
  115.  
  116.      * @param context the context to parse the URL to
  117.      * @param spec the URL String to parse
  118.      * @exception MalformedURLException If the protocol is equal to null. 
  119.      */
  120.     public URL(URL context, String spec) throws MalformedURLException {
  121.     String original = spec;
  122.     int i, limit, c;
  123.     int start = 0;
  124.     String newProtocol = null;
  125.  
  126.     try {
  127.         limit = spec.length();
  128.         while ((limit > 0) && (spec.charAt(limit - 1) <= ' ')) {
  129.         limit--;    //eliminate trailing whitespace
  130.         }
  131.         while ((start < limit) && (spec.charAt(start) <= ' ')) {
  132.         start++;    // eliminate leading whitespace
  133.         }
  134.  
  135.         if (spec.regionMatches(true, start, "url:", 0, 4)) {
  136.         start += 4;
  137.         }
  138.         for (i = start ; (i < limit) && ((c = spec.charAt(i)) != '/') ; i++) {
  139.         if (c == ':') {
  140.             newProtocol = spec.substring(start, i).toLowerCase();
  141.             start = i + 1;
  142.             break;
  143.         }
  144.         }
  145.         // Only use our context if the protocols match.
  146.         if ((context != null) && ((newProtocol == null) ||
  147.                     newProtocol.equals(context.protocol))) {
  148.         protocol = context.protocol;
  149.         host = context.host;
  150.         port = context.port;
  151.         file = context.file;
  152.         } else {
  153.         protocol = newProtocol;
  154.         }
  155.  
  156.         if (protocol == null) {
  157.         throw new MalformedURLException("no protocol: "+original);
  158.         }
  159.  
  160.         if ((handler = getURLStreamHandler(protocol)) == null) {
  161.         throw new MalformedURLException("unknown protocol: "+protocol);
  162.         }
  163.  
  164.         i = spec.indexOf('#', start);
  165.         if (i >= 0) {
  166.         ref = spec.substring(i + 1, limit);
  167.         limit = i;
  168.         }
  169.         handler.parseURL(this, spec, start, limit);
  170.  
  171.     } catch(MalformedURLException e) {
  172.         throw e;
  173.     } catch(Exception e) {
  174.         throw new MalformedURLException(original + ": " + e);
  175.     }
  176.     }
  177.  
  178.     /**
  179.      * Sets the fields of the URL. This is not a public method so that 
  180.      * only URLStreamHandlers can modify URL fields. URLs are 
  181.      * otherwise constant.
  182.      *
  183.      * REMIND: this method will be moved to URLStreamHandler
  184.      *
  185.      * @param protocol the protocol to use
  186.      * @param host the host name to connecto to
  187.      * @param port the protocol port to connect to
  188.      * @param file the specified file name on that host
  189.      * @param ref the reference
  190.      */
  191.     protected void set(String protocol, String host, int port, String file, String ref) {
  192.     this.protocol = protocol;
  193.     this.host = host;
  194.     this.port = port;
  195.     this.file = file;
  196.     this.ref = ref;
  197.     }
  198.  
  199.     /**
  200.      * Gets the port number. Returns -1 if the port is not set.
  201.      */
  202.     public int getPort() {
  203.     return port;
  204.     }
  205.  
  206.     /**
  207.      * Gets the protocol name.
  208.      */
  209.     public String getProtocol() {
  210.     return protocol;
  211.     }
  212.  
  213.     /**
  214.      * Gets the host name.
  215.      */
  216.     public String getHost() {
  217.     return host;
  218.     }
  219.  
  220.     /**
  221.      * Gets the file name.
  222.      */
  223.     public String getFile() {
  224.     return file;
  225.     }
  226.  
  227.     /**
  228.      * Gets the ref.
  229.      */
  230.     public String getRef() {
  231.     return ref;
  232.     }
  233.  
  234.     /**
  235.      * Compares two URLs.
  236.      * @param    obj the URL to compare against.
  237.      * @return    true if and only if they are equal, false otherwise.
  238.      */
  239.     public boolean equals(Object obj) {
  240.     return (obj instanceof URL) && sameFile((URL)obj);
  241.     }
  242.  
  243.     /** 
  244.      * Creates an integer suitable for hash table indexing. 
  245.      */
  246.     public int hashCode() {
  247.     int inhash = 0;
  248.     if (!host.equals("")) {
  249.         try {
  250.         inhash = InetAddress.getByName(host).hashCode();
  251.         } catch(UnknownHostException e) {
  252.         }
  253.     }
  254.     return protocol.hashCode() ^ inhash ^ file.hashCode();
  255.     }
  256.  
  257.     /**
  258.      * Compares the host components of two URLs.
  259.      * @param h1 the URL of the first host to compare 
  260.      * @param h2 the URL of the second host to compare 
  261.      * @return    true if and only if they are equal, false otherwise.
  262.      * @exception UnknownHostException If an unknown host is found.
  263.      */
  264.     boolean hostsEqual(String h1, String h2) {
  265.     if (h1.equals(h2)) {
  266.         return true;
  267.     }
  268.     // Have to resolve addresses before comparing, otherwise
  269.     // names like tachyon and tachyon.eng would compare different
  270.     try {
  271.         InetAddress a1 = InetAddress.getByName(h1);
  272.         InetAddress a2 = InetAddress.getByName(h2);
  273.         return a1.equals(a2);
  274.     } catch(UnknownHostException e) {
  275.     } catch(SecurityException e) {
  276.     }
  277.     return false;
  278.     }
  279.  
  280.     /**
  281.      * Compares two URLs, excluding the "ref" fields: sameFile is true
  282.      * if the true references the same remote object, but not necessarily
  283.      * the same subpiece of that object.
  284.      * @param    other    the URL to compare against.
  285.      * @return    true if and only if they are equal, false otherwise.
  286.      */
  287.     public boolean sameFile(URL other) {
  288.     // AVH: should we not user getPort to compare ports?
  289.     return protocol.equals(other.protocol) &&
  290.            hostsEqual(host, other.host) &&
  291.            (port == other.port) &&
  292.            file.equals(other.file);
  293.     }
  294.  
  295.     /**
  296.      * Converts to a human-readable form.
  297.      * @return    the textual representation.
  298.      */
  299.     public String toString() {
  300.     return toExternalForm();
  301.     }
  302.  
  303.     /**
  304.      * Reverses the parsing of the URL.
  305.      * @return    the textual representation of the fully qualified URL (i.e.
  306.      *        after the context and canonicalization have been applied).
  307.      */
  308.     public String toExternalForm() {
  309.     return handler.toExternalForm(this);
  310.     }
  311.  
  312.     /** 
  313.      * Creates (if not already in existance) a URLConnection object that
  314.      * contains a connection to the remote object referred to by
  315.      * the URL.  Invokes the appropriate protocol handler.  Failure is
  316.      * indicated by throwing an exception.
  317.      * @exception IOException If an I/O exception has occurred.
  318.      * @see URLConnection
  319.      */
  320.     public URLConnection openConnection()
  321.     throws java.io.IOException
  322.     {
  323.     return handler.openConnection(this);
  324.     }
  325.  
  326.     /**
  327.      * Opens an input stream.
  328.      * @exception IOException If an I/O exception has occurred.
  329.      */
  330.     public final InputStream openStream()             // REMIND: drop final
  331.     throws java.io.IOException
  332.     {
  333.     return openConnection().getInputStream();
  334.     }
  335.  
  336.     /**
  337.      * Gets the contents from this opened connection.
  338.      * @exception IOException If an I/O exception has occurred.
  339.      */
  340.     public final Object getContent()                 // REMIND: drop final
  341.     throws java.io.IOException
  342.     {
  343.     return openConnection().getContent();
  344.     }
  345.  
  346.     /**
  347.      * The URLStreamHandler factory.
  348.      */
  349.     static URLStreamHandlerFactory factory;
  350.  
  351.     /**
  352.      * Sets the URLStreamHandler factory.
  353.      * @param fac the desired factory
  354.      * @exception Error If the factory has already been defined.
  355.      */
  356.     public static synchronized void setURLStreamHandlerFactory(URLStreamHandlerFactory fac) {
  357.     if (factory != null) {
  358.         throw new Error("factory already defined");
  359.     }
  360.     SecurityManager security = System.getSecurityManager();
  361.     if (security != null) {
  362.         security.checkSetFactory();
  363.     }
  364.     factory = fac;
  365.     }
  366.  
  367.     /**
  368.      * A table of protocol handlers.
  369.      */
  370.     static Hashtable handlers = new Hashtable();
  371.  
  372.     /**
  373.      * Gets the Stream Handler.
  374.      * @param protocol the protocol to use
  375.      */
  376.     static synchronized URLStreamHandler getURLStreamHandler(String protocol) {
  377.     URLStreamHandler handler = (URLStreamHandler)handlers.get(protocol);
  378.     if (handler == null) {
  379.         // Use the factory (if any)
  380.         if (factory != null) {
  381.         handler = factory.createURLStreamHandler(protocol);
  382.         }
  383.  
  384.         // Try java protocol handler
  385.         if (handler == null) {
  386.         try {
  387.             String clname = "sun.net.www.protocol." + protocol + ".Handler";
  388.             handler = (URLStreamHandler)Class.forName(clname).newInstance();
  389.         } catch (Exception e) {
  390.         }
  391.         }
  392.         if (handler != null) {
  393.         handlers.put(protocol, handler);
  394.         }
  395.     }
  396.     return handler;
  397.     }
  398. }
  399.