home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1998 February / VPR9802A.ISO / APP_DEMO / VC / MAIN.BIN / URLConnection.java < prev    next >
Text File  |  1997-10-27  |  39KB  |  1,079 lines

  1. /*
  2.  * @(#)URLConnection.java    1.28 97/03/10
  3.  * 
  4.  * Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  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
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  * CopyrightVersion 1.1_beta
  20.  * 
  21.  */
  22.  
  23. package java.net;
  24.  
  25. import java.io.IOException;
  26. import java.io.InputStream;
  27. import java.io.OutputStream;
  28. import java.util.Hashtable;
  29. import java.util.Date;
  30. import java.util.StringTokenizer;
  31.  
  32. /**
  33.  * The abstract class <code>URLConnection</code> is the superclass 
  34.  * of all classes that represent a communications link between the 
  35.  * application and a URL. Instances of this class can be used both to 
  36.  * read from and to write to the resource referenced by the URL. In 
  37.  * general, creating a connection to a URL is a multistep process: 
  38.  * <p>
  39.  * <center><table border>
  40.  * <tr><th><code>openConnection()</code></th>
  41.  *     <th><code>connect()</code></th></tr>
  42.  * <tr><td>Manipulate parameters that affect the connection to the remote 
  43.  *         resource.</td>
  44.  *     <td>Interact with the resource; query header fields and
  45.  *         contents.</td></tr>
  46.  * </table>
  47.  * ---------------------------->
  48.  * <br>time</center>
  49.  *
  50.  * <ol>
  51.  * <li>The connection object is created by invoking the
  52.  *     <code>openConnection</code> method on a URL.
  53.  * <li>The setup parameters and general request properties are manipulated.
  54.  * <li>The actual connection to the remote object is made, using the
  55.  *    <code>connect</code> method.
  56.  * <li>The remote object becomes available. The header fields and the contents
  57.  *     of the remote object can be accessed.
  58.  * </ol>
  59.  * <p>
  60.  * The setup parameters are modified using the following methods: 
  61.  * <ul><code>
  62.  *   <li>setAllowUserInteraction
  63.  *   <li>setDoInput
  64.  *   <li>setDoOutput
  65.  *   <li>setIfModifiedSince
  66.  *   <li>setUseCaches
  67.  * </code></ul>
  68.  * <p>
  69.  * and the general request properties are modified using the method:
  70.  * <ul><code>
  71.  *   <li>setRequestProperty
  72.  * </code></ul>
  73.  * <p>
  74.  * Default values for the <code>AllowUserInteraction</code> and 
  75.  * <code>UseCaches</code> parameters can be set using the methods 
  76.  * <code>setDefaultAllowUserInteraction</code> and 
  77.  * <code>setDefaultUseCaches</code>. Default values for general 
  78.  * request properties can be set using the 
  79.  * <code>setDefaultRequestProperty</code> method. 
  80.  * <p>
  81.  * Each of the above <code>set</code> methods has a corresponding 
  82.  * <code>get</code> method to retrieve the value of the parameter or 
  83.  * general request property. The specific parameters and general 
  84.  * request properties that are applicable are protocol specific. 
  85.  * <p>
  86.  * The following methods are used to access the header fields and 
  87.  * the contents after the connection is made to the remote object:
  88.  * <ul><code>
  89.  *   <li>getContent
  90.  *   <li>getHeaderField
  91.  *   <li>getInputStream
  92.  *   <li>getOutputStream
  93.  * </code></ul>
  94.  * <p>
  95.  * Certain header fields are accessed frequently. The methods:
  96.  * <ul><code>
  97.  *   <li>getContentEncoding
  98.  *   <li>getContentLength
  99.  *   <li>getContentType
  100.  *   <li>getDate
  101.  *   <li>getExpiration
  102.  *   <li>getLastModifed
  103.  * </code></ul>
  104.  * <p>
  105.  * provide convenient access to these fields. The 
  106.  * <code>getContentType</code> method is used by the 
  107.  * <code>getContent</code> method to determine the type of the remote 
  108.  * object; subclasses may find it convenient to override the 
  109.  * <code>getContentType</code> method. 
  110.  * <p>
  111.  * In the common case, all of the pre-connection parameters and 
  112.  * general request properties can be ignored: the pre-connection 
  113.  * parameters and request properties default to sensible values. For 
  114.  * most clients of this interface, there are only two interesting 
  115.  * methods: <code>getInputStream</code> and <code>getObject</code>, 
  116.  * which are mirrored in the <code>URL</code> class by convenience methods.
  117.  * <p>
  118.  * More information on the request properties and header fields of 
  119.  * an <code>http</code> connection can be found at:
  120.  * <ul><code>
  121.  *   http://www.w3.org/hypertext/WWW/Protocols/HTTP1.0/draft-ietf-http-spec.html
  122.  * </code></ul>
  123.  *
  124.  * @author  James Gosling
  125.  * @version 1.28, 03/10/97
  126.  * @see     java.net.URL#openConnection()
  127.  * @see     java.net.URLConnection#connect()
  128.  * @see     java.net.URLConnection#getContent()
  129.  * @see     java.net.URLConnection#getContentEncoding()
  130.  * @see     java.net.URLConnection#getContentLength()
  131.  * @see     java.net.URLConnection#getContentType()
  132.  * @see     java.net.URLConnection#getDate()
  133.  * @see     java.net.URLConnection#getExpiration()
  134.  * @see     java.net.URLConnection#getHeaderField(int)
  135.  * @see     java.net.URLConnection#getHeaderField(java.lang.String)
  136.  * @see     java.net.URLConnection#getInputStream()
  137.  * @see     java.net.URLConnection#getLastModified()
  138.  * @see     java.net.URLConnection#getOutputStream()
  139.  * @see     java.net.URLConnection#setAllowUserInteraction(boolean)
  140.  * @see     java.net.URLConnection#setDefaultRequestProperty(java.lang.String, java.lang.String)
  141.  * @see     java.net.URLConnection#setDefaultUseCaches(boolean)
  142.  * @see     java.net.URLConnection#setDoInput(boolean)
  143.  * @see     java.net.URLConnection#setDoOutput(boolean)
  144.  * @see     java.net.URLConnection#setIfModifiedSince(long)
  145.  * @see     java.net.URLConnection#setRequestProperty(java.lang.String, java.lang.String)
  146.  * @see     java.net.URLConnection#setUseCaches(boolean)
  147.  * @since   JDK1.0
  148.  */
  149. abstract public class URLConnection {
  150.    /**
  151.      * The URL represents the remote object on the World Wide Web to 
  152.      * which this connection is opened. 
  153.      * <p>
  154.      * The value of this field can be accessed by the 
  155.      * <code>getURL</code> method. 
  156.      * <p>
  157.      * The default value of this variable is the value of the URL 
  158.      * argument in the <code>URLConnection</code> constructor. 
  159.      *
  160.      * @see     java.net.URLConnection#getURL()
  161.      * @see     java.net.URLConnection#url
  162.      * @since   JDK1.0
  163.      */
  164.     protected URL url;
  165.  
  166.    /**
  167.      * This variable is set by the <code>setDoInput</code> method. Its 
  168.      * value is returned by the <code>getDoInput</code> method. 
  169.      * <p>
  170.      * A URL connection can be used for input and/or output. Setting the 
  171.      * <code>doInput</code> flag to <code>true</code> indicates that 
  172.      * the application intends to read data from the URL connection. 
  173.      * <p>
  174.      * The default value of this field is <code>true</code>. 
  175.      *
  176.      * @see     java.net.URLConnection#getDoInput()
  177.      * @see     java.net.URLConnection#setDoInput(boolean)
  178.      * @since   JDK1.0
  179.      */
  180.     protected boolean doInput = true;
  181.  
  182.    /**
  183.      * This variable is set by the <code>setDoOutput</code> method. Its 
  184.      * value is returned by the <code>getDoInput</code> method. 
  185.      * <p>
  186.      * A URL connection can be used for input and/or output. Setting the 
  187.      * <code>doOutput</code> flag to <code>true</code> indicates 
  188.      * that the application intends to write data to the URL connection. 
  189.      * <p>
  190.      * The default value of this field is <code>false</code>. 
  191.      *
  192.      * @see     java.net.URLConnection#getDoOutput()
  193.      * @see     java.net.URLConnection#setDoOutput(boolean)
  194.      * @since   JDK1.0
  195.      */
  196.     protected boolean doOutput = false;
  197.  
  198.     private static boolean defaultAllowUserInteraction = false;
  199.  
  200.    /**
  201.      * If <code>true</code>, this <code>URL</code> is being examined in 
  202.      * a context in which it makes sense to allow user interactions such 
  203.      * as popping up an authentication dialog. If <code>false</code>, 
  204.      * then no user interaction is allowed. 
  205.      * <p>
  206.      * The value of this field can be set by the 
  207.      * <code>setAllowUserInteraction</code> method.
  208.      * Its value is returned by the 
  209.      * <code>getAllowUserInteraction</code> method.
  210.      * Its default value is the value of the argument in the last invocation 
  211.      * of the <code>setDefaultAllowUserInteraction</code> method. 
  212.      *
  213.      * @see     java.net.URLConnection#getAllowUserInteraction()
  214.      * @see     java.net.URLConnection#setAllowUserInteraction(boolean)
  215.      * @see     java.net.URLConnection#setDefaultAllowUserInteraction(boolean)
  216.      * @since   JDK1.0
  217.      */
  218.     protected boolean allowUserInteraction = defaultAllowUserInteraction;
  219.  
  220.     private static boolean defaultUseCaches = true;
  221.  
  222.    /**
  223.      * If <code>true</code>, the protocol is allowed to use caching 
  224.      * whenever it can. If <code>false</code>, the protocol must always 
  225.      * try to get a fresh copy of the object. 
  226.      * <p>
  227.      * This field is set by the <code>setUseCaches</code> method. Its 
  228.      * value is returned by the <code>getUseCaches</code> method.
  229.      * <p>
  230.      * Its default value is the value given in the last invocation of the 
  231.      * <code>setDefaultUseCaches</code> method. 
  232.      *
  233.      * @see     java.net.URLConnection#setUseCaches(boolean)
  234.      * @see     java.net.URLConnection#getUseCaches()
  235.      * @see     java.net.URLConnection#setDefaultUseCaches(boolean)
  236.      * @since   JDK1.0
  237.      */
  238.     protected boolean useCaches = defaultUseCaches;
  239.  
  240.    /**
  241.      * Some protocols support skipping the fetching of the object unless 
  242.      * the object has been modified more recently than a certain time. 
  243.      * <p>
  244.      * A nonzero value gives a time as the number of seconds since 
  245.      * January 1, 1970, GMT. The object is fetched only if it has been 
  246.      * modified more recently than that time. 
  247.      * <p>
  248.      * This variable is set by the <code>setIfModifiedSince</code> 
  249.      * method. Its value is returned by the 
  250.      * <code>getIfModifiedSince</code> method.
  251.      * <p>
  252.      * The default value of this field is <code>0</code>, indicating 
  253.      * that the fetching must always occur. 
  254.      *
  255.      * @see     java.net.URLConnection#getIfModifiedSince()
  256.      * @see     java.net.URLConnection#setIfModifiedSince(long)
  257.      * @since   JDK1.0
  258.      */
  259.     protected long ifModifiedSince = 0;
  260.  
  261.    /**
  262.     * @since   JDK1.1
  263.      */
  264.     // REMIND: should there be an accessor/mutator function for this?
  265.     public static FileNameMap fileNameMap;
  266.  
  267.    /**
  268.      * If <code>false</code>, this connection object has not created a 
  269.      * communications link to the specified URL. If <code>true</code>, 
  270.      * the communications link has been established. 
  271.      *
  272.      * @since   JDK1.0
  273.      */
  274.     protected boolean connected = false;
  275.  
  276.     /**
  277.      * Opens a communications link to the resource referenced by this 
  278.      * URL, if such a connection has not already been established. 
  279.      * <p>
  280.      * If the <code>connect</code> method is called when the connection 
  281.      * has already been opened (indicated by the <code>connected</code> 
  282.      * field having the value <code>true</code>), the call is ignored. 
  283.      * <p>
  284.      * URLConnection objects go through two phases: first they are
  285.      * created, then they are connected.  After being created, and
  286.      * before being connected, various options can be specified
  287.      * (e.g., doInput and UseCaches).  After connecting, it is an
  288.      * error to try to set them.  Operations that depend on being
  289.      * connected, like getContentLength, will implicitly perform the
  290.      * connection, if necessary.
  291.      *
  292.      * @exception  IOException  if an I/O error occurs while opening the
  293.      *               connection.
  294.      * @see        java.net.URLConnection#connected
  295.      * @since      JDK1.0
  296.      */
  297.     abstract public void connect() throws IOException;
  298.  
  299.     /**
  300.      * Constructs a URL connection to the specified URL. A connection to 
  301.      * the object referenced by the URL is not created. 
  302.      *
  303.      * @param   url   the specified URL.
  304.      * @since   JDK1.0
  305.      */
  306.     protected URLConnection(URL url) {
  307.     this.url = url;
  308.     }
  309.  
  310.     /**
  311.      * Returns the value of this <code>URLConnection</code>'s <code>URL</code>
  312.      * field.
  313.      *
  314.      * @return  the value of this <code>URLConnection</code>'s <code>URL</code>
  315.      *          field.
  316.      * @see     java.net.URLConnection#url
  317.      * @since   JDK1.0
  318.      */
  319.     public URL getURL() {
  320.     return url;
  321.     }
  322.  
  323.     /**
  324.      * Returns the value of the <code>content-length</code> header field.
  325.      *
  326.      * @return  the content length of the resource that this connection's URL
  327.      *          references, or <code>-1</code> if the content length is
  328.      *          not known.
  329.      * @since   JDK1.0
  330.      */
  331.     public int getContentLength() {
  332.     return getHeaderFieldInt("content-length", -1);
  333.     }
  334.  
  335.     /**
  336.      * Returns the value of the <code>content-type</code> header field.
  337.      *
  338.      * @return  the content type of the resource that the URL references,
  339.      *          or <code>null</code> if not known.
  340.      * @see     java.net.URLConnection#getHeaderField(java.lang.String)
  341.      * @since   JDK1.0
  342.      */
  343.     public String getContentType() {
  344.     return getHeaderField("content-type");
  345.     }
  346.  
  347.     /**
  348.      * Returns the value of the <code>content-encoding</code> header field.
  349.      *
  350.      * @return  the content encoding of the resource that the URL references,
  351.      *          or <code>null</code> if not known.
  352.      * @see     java.net.URLConnection#getHeaderField(java.lang.String)
  353.      * @since   JDK1.0
  354.      */
  355.     public String getContentEncoding() {
  356.     return getHeaderField("content-encoding");
  357.     }
  358.  
  359.     /**
  360.      * Returns the value of the <code>expires</code> header field. 
  361.      *
  362.      * @return  the expiration date of the resource that this URL references,
  363.      *          or 0 if not known. The value is the number of seconds since
  364.      *          January 1, 1970 GMT.
  365.      * @see     java.net.URLConnection#getHeaderField(java.lang.String)
  366.      * @since   JDK1.0
  367.      */
  368.     public long getExpiration() {
  369.     return getHeaderFieldDate("expires", 0);
  370.     }
  371.  
  372.     /**
  373.      * Returns the value of the <code>date</code> header field. 
  374.      *
  375.      * @return  the sending date of the resource that the URL references,
  376.      *          or <code>0</code> if not known. The value returned is the
  377.      *          number of seconds since January 1, 1970 GMT.
  378.      * @see     java.net.URLConnection#getHeaderField(java.lang.String)
  379.      * @since   JDK1.0
  380.      */
  381.     public long getDate() {
  382.     return getHeaderFieldDate("date", 0);
  383.     }
  384.  
  385.     /**
  386.      * Returns the value of the <code>last-modified</code> header field. 
  387.      * The result is the number of seconds since January 1, 1970 GMT.
  388.      *
  389.      * @return  the date the resource referenced by this
  390.      *          <code>URLConnection</code> was last modified, or 0 if not known.
  391.      * @see     java.net.URLConnection#getHeaderField(java.lang.String)
  392.      * @since   JDK1.0
  393.      */
  394.     public long getLastModified() {
  395.     return getHeaderFieldDate("last-modified", 0);
  396.     }
  397.  
  398.     /**
  399.      * Returns the name of the specified header field.
  400.      *
  401.      * @param   name   the name of a header field.
  402.      * @return  the value of the named header field, or <code>null</code>
  403.      *          if there is no such field in the header.
  404.      * @since   JDK1.0
  405.      */
  406.     public String getHeaderField(String name) {
  407.     return null;
  408.     }
  409.  
  410.     /**
  411.      * Returns the value of the named field parsed as a number.
  412.      * <p>
  413.      * This form of <code>getHeaderField</code> exists because some 
  414.      * connection types (e.g., <code>http-ng</code>) have pre-parsed 
  415.      * headers. Classes for that connection type can override this method 
  416.      * and short-circuit the parsing. 
  417.      *
  418.      * @param   name      the name of the header field.
  419.      * @param   Default   the default value.
  420.      * @return  the value of the named field, parsed as an integer. The
  421.      *          <code>Default</code> value is returned if the field is
  422.      *          missing or malformed.
  423.      * @since   JDK1.0
  424.      */
  425.     public int getHeaderFieldInt(String name, int Default) {
  426.     try {
  427.         return Integer.parseInt(getHeaderField(name));
  428.     } catch(Throwable t) {}
  429.     return Default;
  430.     }
  431.  
  432.     /**
  433.      * Returns the value of the named field parsed as date.
  434.      * The result is the number of seconds since January 1, 1970 GMT
  435.      * represented by the named field. 
  436.      * <p>
  437.      * This form of <code>getHeaderField</code> exists because some 
  438.      * connection types (e.g., <code>http-ng</code>) have pre-parsed 
  439.      * headers. Classes for that connection type can override this method 
  440.      * and short-circuit the parsing. 
  441.      *
  442.      * @param   name     the name of the header field.
  443.      * @param   Default   a default value.
  444.      * @return  the value of the field, parsed as a date. The value of the
  445.      *          <code>Default</code> argument is returned if the field is
  446.      *          missing or malformed.
  447.      * @since   JDK1.0
  448.      */
  449.     public long getHeaderFieldDate(String name, long Default) {
  450.     try {
  451.         return Date.parse(getHeaderField(name));
  452.     } catch(Throwable t) {}
  453.     return Default;
  454.     }
  455.  
  456.     /**
  457.      * Returns the key for the <code>n</code><sup>th</sup> header field.
  458.      *
  459.      * @param   n   an index.
  460.      * @return  the key for the <code>n</code><sup>th</sup> header field,
  461.      *          or <code>null</code> if there are fewer than <code>n</code>
  462.      *          fields.
  463.      * @since   JDK1.0
  464.      */
  465.     public String getHeaderFieldKey(int n) {
  466.     return null;
  467.     }
  468.  
  469.     /**
  470.      * Returns the value for the <code>n</code><sup>th</sup> header field. 
  471.      * It returns <code>null</code> if there are fewer than 
  472.      * <code>n</code> fields. 
  473.      * <p>
  474.      * This method can be used in conjunction with the 
  475.      * <code>getHeaderFieldKey</code> method to iterate through all 
  476.      * the headers in the message. 
  477.      *
  478.      * @param   n   an index.
  479.      * @return  the value of the <code>n</code><sup>th</sup> header field.
  480.      * @see     java.net.URLConnection#getHeaderFieldKey(int)
  481.      * @since   JDK1.0
  482.      */
  483.     public String getHeaderField(int n) {
  484.     return null;
  485.     }
  486.  
  487.     /**
  488.      * Retrieves the contents of this URL connection. 
  489.      * <p>
  490.      * This method first determines the content type of the object by 
  491.      * calling the <code>getContentType</code> method. If this is 
  492.      * the first time that the application has seen that specific content 
  493.      * type, a content handler for that content type is created: 
  494.      * <ol>
  495.      * <li>If the application has set up a content handler factory instance
  496.      *     using the <code>setContentHandlerFactory</code> method, the
  497.      *     <code>createContentHandler</code> method of that instance is called
  498.      *     with the content type as an argument; the result is a content
  499.      *     handler for that content type.
  500.      * <li>If no content handler factory has yet been set up, or if the
  501.      *     factory's <code>createContentHandler</code> method returns
  502.      *     <code>null</code>, then the application loads the class named:
  503.      *     <ul><code>
  504.      *         sun.net.www.content.<<i>contentType</i>>
  505.      *     </code></ul>
  506.      *     where <<i>contentType</i>> is formed by taking the
  507.      *     content-type string, replacing all slash characters with a
  508.      *     <code>period</code> ('.'), and all other non-alphanumeric characters
  509.      *     with the underscore character '<code>_</code>'. The alphanumeric
  510.      *     characters are specifically the 26 uppercase ASCII letters
  511.      *     '<code>A</code>' through '<code>Z</code>', the 26 lowercase ASCII
  512.      *     letters '<code>a</code>' through '<code>z</code>', and the 10 ASCII
  513.      *     digits '<code>0</code>' through '<code>9</code>'. If the specified
  514.      *     class does not exist, or is not a subclass of
  515.      *     <code>ContentHandler</code>, then an
  516.      *     <code>UnknownServiceException</code> is thrown.
  517.      * </ol>
  518.      *
  519.      * @return     the object fetched. The <code>instanceOf</code> operation
  520.      *               should be used to determine the specific kind of object
  521.      *               returned.
  522.      * @exception  IOException              if an I/O error occurs while
  523.      *               getting the content.
  524.      * @exception  UnknownServiceException  if the protocol does not support
  525.      *               the content type.
  526.      * @see        java.net.ContentHandlerFactory#createContentHandler(java.lang.String)
  527.      * @see        java.net.URLConnection#getContentType()
  528.      * @see        java.net.URLConnection#setContentHandlerFactory(java.net.ContentHandlerFactory)
  529.      * @since      JDK1.0
  530.      */
  531.     public Object getContent() throws IOException {
  532.     return getContentHandler().getContent(this);
  533.     }
  534.  
  535.     /**
  536.      * Returns an input stream that reads from this open connection.
  537.      *
  538.      * @return     an input stream that reads from this open connection.
  539.      * @exception  IOException              if an I/O error occurs while
  540.      *               creating the input stream.
  541.      * @exception  UnknownServiceException  if the protocol does not support
  542.      *               input.
  543.      * @since   JDK1.0
  544.      */
  545.     public InputStream getInputStream() throws IOException {
  546.     throw new UnknownServiceException("protocol doesn't support input");
  547.     }
  548.  
  549.     /**
  550.      * Returns an output stream that writes to this connection.
  551.      *
  552.      * @return     an output stream that writes to this connection.
  553.      * @exception  IOException              if an I/O error occurs while
  554.      *               creating the output stream.
  555.      * @exception  UnknownServiceException  if the protocol does not support
  556.      *               output.
  557.      * @since   JDK1.0
  558.      */
  559.     public OutputStream getOutputStream() throws IOException {
  560.     throw new UnknownServiceException("protocol doesn't support output");
  561.     }
  562.  
  563.     /**
  564.      * Returns a <code>String</code> representation of this URL connection.
  565.      *
  566.      * @return  a string representation of this <code>URLConnection</code>.
  567.      * @since   JDK1.0
  568.      */
  569.     public String toString() {
  570.     return this.getClass().getName() + ":" + url;
  571.     }
  572.  
  573.     /**
  574.      * Sets the value of the <code>doInput</code> field for this 
  575.      * <code>URLConnection</code> to the specified value. 
  576.      * <p>
  577.      * A URL connection can be used for input and/or output.  Set the DoInput
  578.      * flag to true if you intend to use the URL connection for input,
  579.      * false if not.  The default is true unless DoOutput is explicitly
  580.      * set to true, in which case DoInput defaults to false.
  581.      *
  582.      * @param   value   the new value.
  583.      * @see     java.net.URLConnection#doInput
  584.      * @since   JDK1.0
  585.      */
  586.     public void setDoInput(boolean doinput) {
  587.     if (connected)
  588.         throw new IllegalAccessError("Already connected");
  589.     doInput = doinput;
  590.     }
  591.  
  592.     /**
  593.      * Returns the value of this <code>URLConnection</code>'s
  594.      * <code>doInput</code> flag.
  595.      *
  596.      * @return  the value of this <code>URLConnection</code>'s
  597.      *          <code>doInput</code> flag.
  598.      * @see     java.net.URLConnection#doInput
  599.      * @since   JDK1.0
  600.      */
  601.     public boolean getDoInput() {
  602.     return doInput;
  603.     }
  604.  
  605.     /**
  606.      * Sets the value of the <code>doOutput</code> field for this 
  607.      * <code>URLConnection</code> to the specified value. 
  608.      * <p>
  609.      * A URL connection can be used for input and/or output.  Set the DoOutput
  610.      * flag to true if you intend to use the URL connection for output,
  611.      * false if not.  The default is false.
  612.      *
  613.      * @param   value   the new value.
  614.      * @see     java.net.URLConnection#doOutput
  615.      * @since   JDK1.0
  616.      */
  617.     public void setDoOutput(boolean dooutput) {
  618.     if (connected)
  619.         throw new IllegalAccessError("Already connected");
  620.     doOutput = dooutput;
  621.     }
  622.  
  623.     /**
  624.      * Returns the value of this <code>URLConnection</code>'s
  625.      * <code>doOutput</code> flag.
  626.      *
  627.      * @return  the value of this <code>URLConnection</code>'s
  628.      *          <code>doOutput</code> flag.
  629.      * @see     java.net.URLConnection#doOutput
  630.      * @since   JDK1.0
  631.      */
  632.     public boolean getDoOutput() {
  633.     return doOutput;
  634.     }
  635.  
  636.     /**
  637.      * Set the value of the <code>allowUserInteraction</code> field of 
  638.      * this <code>URLConnection</code>. 
  639.      *
  640.      * @param   allowuserinteraction   the new value.
  641.      * @see     java.net.URLConnection#allowUserInteraction
  642.      * @since   JDK1.0
  643.      */
  644.     public void setAllowUserInteraction(boolean allowuserinteraction) {
  645.     if (connected)
  646.         throw new IllegalAccessError("Already connected");
  647.     allowUserInteraction = allowuserinteraction;
  648.     }
  649.  
  650.     /**
  651.      * Returns the value of the <code>allowUserInteraction</code> field for
  652.      * this object.
  653.      *
  654.      * @return  the value of the <code>allowUserInteraction</code> field for
  655.      *          this object.
  656.      * @see     java.net.URLConnection#allowUserInteraction
  657.      * @since   JDK1.0
  658.      */
  659.     public boolean getAllowUserInteraction() {
  660.     return allowUserInteraction;
  661.     }
  662.  
  663.     /**
  664.      * Sets the default value of the 
  665.      * <code>allowUserInteraction</code> field for all future 
  666.      * <code>URLConnection</code> objects to the specified value. 
  667.      *
  668.      * @param   defaultallowuserinteraction   the new value.
  669.      * @see     java.net.URLConnection#allowUserInteraction
  670.      * @since   JDK1.0
  671.      */
  672.     public static void setDefaultAllowUserInteraction(boolean defaultallowuserinteraction) {
  673.     defaultAllowUserInteraction = defaultallowuserinteraction;
  674.     }
  675.  
  676.     /**
  677.      * Returns the default value of the <code>allowUserInteraction</code>
  678.      * field.
  679.      * <p>
  680.      * Ths default is "sticky", being a part of the static state of all
  681.      * URLConnections.  This flag applies to the next, and all following
  682.      * URLConnections that are created.
  683.      *
  684.      * @return  the default value of the <code>allowUserInteraction</code>
  685.      *          field.
  686.      * @see     java.net.URLConnection#allowUserInteraction
  687.      * @since   JDK1.0
  688.      */
  689.     public static boolean getDefaultAllowUserInteraction() {
  690.     return defaultAllowUserInteraction;
  691.     }
  692.  
  693.     /**
  694.      * Sets the value of the <code>useCaches</code> field of this 
  695.      * <code>URLConnection</code> to the specified value. 
  696.      * <p>
  697.      * Some protocols do caching of documents.  Occasionally, it is important
  698.      * to be able to "tunnel through" and ignore the caches (e.g., the
  699.      * "reload" button in a browser).  If the UseCaches flag on a connection
  700.      * is true, the connection is allowed to use whatever caches it can.
  701.      *  If false, caches are to be ignored.
  702.      *  The default value comes from DefaultUseCaches, which defaults to
  703.      * true.
  704.      *
  705.      * @see     java.net.URLConnection#useCaches
  706.      * @since   JDK1.0
  707.      */
  708.     public void setUseCaches(boolean usecaches) {
  709.     if (connected)
  710.         throw new IllegalAccessError("Already connected");
  711.     useCaches = usecaches;
  712.     }
  713.  
  714.     /**
  715.      * Returns the value of this <code>URLConnection</code>'s
  716.      * <code>useCaches</code> field.
  717.      *
  718.      * @return  the value of this <code>URLConnection</code>'s
  719.      *          <code>useCaches</code> field.
  720.      * @see     java.net.URLConnection#useCaches
  721.      * @since   JDK1.0
  722.      */
  723.     public boolean getUseCaches() {
  724.     return useCaches;
  725.     }
  726.  
  727.     /**
  728.      * Sets the value of the <code>ifModifiedSince</code> field of 
  729.      * this <code>URLConnection</code> to the specified value.
  730.      *
  731.      * @param   value   the new value.
  732.      * @see     java.net.URLConnection#ifModifiedSince
  733.      * @since   JDK1.0
  734.      */
  735.     public void setIfModifiedSince(long ifmodifiedsince) {
  736.     if (connected)
  737.         throw new IllegalAccessError("Already connected");
  738.     ifModifiedSince = ifmodifiedsince;
  739.     }
  740.  
  741.     /**
  742.      * Returns the value of this object's <code>ifModifiedSince</code> field.
  743.      *
  744.      * @return  the value of this object's <code>ifModifiedSince</code> field.
  745.      * @see     java.net.URLConnection#ifModifiedSince
  746.      * @since   JDK1.0
  747.      */
  748.     public long getIfModifiedSince() {
  749.     return ifModifiedSince;
  750.     }
  751.  
  752.    /**
  753.      * Returns the default value of a <code>URLConnection</code>'s
  754.      * <code>useCaches</code> flag.
  755.      * <p>
  756.      * Ths default is "sticky", being a part of the static state of all
  757.      * URLConnections.  This flag applies to the next, and all following
  758.      * URLConnections that are created.
  759.      *
  760.      * @return  the default value of a <code>URLConnection</code>'s
  761.      *          <code>useCaches</code> flag.
  762.      * @see     java.net.URLConnection#useCaches
  763.      * @since   JDK1.0
  764.      */
  765.     public boolean getDefaultUseCaches() {
  766.     return defaultUseCaches;
  767.     }
  768.  
  769.    /**
  770.      * Sets the default value of the <code>useCaches</code> field to the 
  771.      * specified value. 
  772.      *
  773.      * @param   defaultusecaches   the new value.
  774.      * @see     java.net.URLConnection#useCaches
  775.      * @since   JDK1.0
  776.      */
  777.     public void setDefaultUseCaches(boolean defaultusecaches) {
  778.     defaultUseCaches = defaultusecaches;
  779.     }
  780.  
  781.     /**
  782.      * Sets the general request property. 
  783.      *
  784.      * @param   key     the keyword by which the request is known
  785.      *                  (e.g., "<code>accept</code>").
  786.      * @param   value   the value associated with it.
  787.      * @since   JDK1.0
  788.      */
  789.     public void setRequestProperty(String key, String value) {
  790.     if (connected)
  791.         throw new IllegalAccessError("Already connected");
  792.     }
  793.  
  794.     /**
  795.      * Returns the value of the named general request property for this
  796.      * connection.
  797.      *
  798.      * @return  the value of the named general request property for this
  799.      *           connection.
  800.      * @since   JDK1.0
  801.      */
  802.     public String getRequestProperty(String key) {
  803.     if (connected)
  804.         throw new IllegalAccessError("Already connected");
  805.     return null;
  806.     }
  807.  
  808.     /**
  809.      * Sets the default value of a general request property. When a 
  810.      * <code>URLConnection</code> is created, it is initialized with 
  811.      * these properties. 
  812.      *
  813.      * @param   key     the keyword by which the request is known
  814.      *                  (e.g., "<code>accept</code>").
  815.      * @param   value   the value associated with the key.
  816.      * @since   JDK1.0
  817.      */
  818.     public static void setDefaultRequestProperty(String key, String value) {
  819.     }
  820.  
  821.     /**
  822.      * Returns the value of the default request property. Default request 
  823.      * properties are set for every connection. 
  824.      *
  825.      * @return  the value of the default request property for the specified key.
  826.      * @see     java.net.URLConnection#setDefaultRequestProperty(java.lang.String, java.lang.String)
  827.      * @since   JDK1.0
  828.      */
  829.     public static String getDefaultRequestProperty(String key) {
  830.     return null;
  831.     }
  832.  
  833.     /**
  834.      * The ContentHandler factory.
  835.      */
  836.     static ContentHandlerFactory factory;
  837.  
  838.     /**
  839.      * Sets the <code>ContentHandlerFactory</code> of an 
  840.      * application. It can be called at most once by an application. 
  841.      * <p>
  842.      * The <code>ContentHandlerFactory</code> instance is used to 
  843.      * construct a content handler from a content type 
  844.      *
  845.      * @param      fac   the desired factory.
  846.      * @exception  Error  if the factory has already been defined.
  847.      * @see        java.net.ContentHandlerFactory
  848.      * @see        java.net.URLConnection#getContent()
  849.      * @since      JDK1.0
  850.      */
  851.     public static synchronized void setContentHandlerFactory(ContentHandlerFactory fac) {
  852.     if (factory != null) {
  853.         throw new Error("factory already defined");
  854.     }
  855.     SecurityManager security = System.getSecurityManager();
  856.     if (security != null) {
  857.         security.checkSetFactory();
  858.     }
  859.     factory = fac;
  860.     }
  861.  
  862.     private static Hashtable handlers = new Hashtable();
  863.     private static ContentHandler UnknownContentHandlerP = new UnknownContentHandler();
  864.  
  865.     /**
  866.      * Gets the Content Handler appropriate for this connection.
  867.      * @param connection the connection to use.
  868.      */
  869.     synchronized ContentHandler getContentHandler()
  870.     throws UnknownServiceException
  871.     {
  872.     String contentType = getContentType();
  873.     ContentHandler handler = null;
  874.     if (contentType == null)
  875.         throw new UnknownServiceException("no content-type");
  876.     try {
  877.         handler = (ContentHandler) handlers.get(contentType);
  878.         if (handler != null)
  879.         return handler;
  880.     } catch(Exception e) {
  881.     }
  882.     if (factory != null)
  883.         handler = factory.createContentHandler(contentType);
  884.     if (handler == null) {
  885.         try {
  886.         handler = lookupContentHandlerClassFor(contentType);
  887.         } catch(Exception e) {
  888.         e.printStackTrace();
  889.         handler = UnknownContentHandlerP;
  890.         }
  891.         handlers.put(contentType, handler);
  892.     }
  893.     return handler;
  894.     }
  895.  
  896.     private static final String contentClassPrefix = "sun.net.www.content";
  897.     private static final String contentPathProp = "java.content.handler.pkgs";
  898.  
  899.     /**
  900.      * Looks for a content handler in a user-defineable set of places.
  901.      * By default it looks in sun.net.www.content, but users can define a 
  902.      * vertical-bar delimited set of class prefixes to search through in 
  903.      * addition by defining the java.content.handler.pkgs property.
  904.      * The class name must be of the form:
  905.      * <pre>
  906.      *     {package-prefix}.{major}.{minor}
  907.      * e.g.
  908.      *     YoyoDyne.experimental.text.plain
  909.      * </pre>
  910.      */
  911.     private ContentHandler lookupContentHandlerClassFor(String contentType)
  912.     throws InstantiationException, IllegalAccessException, ClassNotFoundException {
  913.     String contentHandlerClassName = typeToPackageName(contentType);
  914.  
  915.     String contentHandlerPkgPrefixes = getContentHandlerPkgPrefixes();
  916.  
  917.     StringTokenizer packagePrefixIter =
  918.         new StringTokenizer(contentHandlerPkgPrefixes, "|");
  919.     
  920.     while (packagePrefixIter.hasMoreTokens()) {
  921.         String packagePrefix = packagePrefixIter.nextToken().trim();
  922.  
  923.         try {
  924.         String name = packagePrefix + "." + contentHandlerClassName;
  925.         ContentHandler handler =
  926.             (ContentHandler) Class.forName(name).newInstance();
  927.         return handler;
  928.         } catch(Exception e) {
  929.         }
  930.     }
  931.     
  932.     return UnknownContentHandlerP;
  933.     }
  934.  
  935.     /**
  936.      * Utility function to map a MIME content type into an equivalent
  937.      * pair of class name components.  For example: "text/html" would
  938.      * be returned as "text.html"
  939.      */
  940.     private String typeToPackageName(String contentType) {
  941.     int len = contentType.length();
  942.     char nm[] = new char[len];
  943.     contentType.getChars(0, len, nm, 0);
  944.     for (int i = 0; i < len; i++) {
  945.         char c = nm[i];
  946.         if (c == '/') {
  947.         nm[i] = '.';
  948.         } else if (!('A' <= c && c <= 'Z' ||
  949.                'a' <= c && c <= 'z' ||
  950.                '0' <= c && c <= '9')) {
  951.         nm[i] = '_';
  952.         }
  953.     }
  954.     return new String(nm);
  955.     }
  956.  
  957.  
  958.     /**
  959.      * Returns a vertical bar separated list of package prefixes for potential
  960.      * content handlers.  Tries to get the java.content.handler.pkgs property
  961.      * to use as a set of package prefixes to search.  Whether or not
  962.      * that property has been defined, the sun.net.www.content is always
  963.      * the last one on the returned package list.
  964.      */
  965.     private String getContentHandlerPkgPrefixes() {
  966.     String packagePrefixList = System.getProperty(contentPathProp, "");
  967.     if (packagePrefixList != "") {
  968.         packagePrefixList += "|";
  969.     }
  970.     
  971.     return packagePrefixList + contentClassPrefix;
  972.     }
  973.  
  974.     /**
  975.      * Tries to determine the content type of an object, based 
  976.      * on the specified "file" component of a URL.
  977.      * This is a convenience method that can be used by 
  978.      * subclasses that override the <code>getContentType</code> method. 
  979.      *
  980.      * @param   fname   a filename.
  981.      * @return  a guess as to what the content type of the object is,
  982.      *          based upon its file name.
  983.      * @see     java.net.URLConnection#getContentType()
  984.      * @since   JDK1.0
  985.      */
  986.     protected static String guessContentTypeFromName(String fname) {
  987.     String contentType = null;
  988.     if (fileNameMap != null) {
  989.         contentType = fileNameMap.getContentTypeFor(fname);
  990.     }
  991.  
  992.     return contentType;
  993.     }
  994.  
  995.     /**
  996.      * Tries to determine the type of an input stream based on the 
  997.      * characters at the beginning of the input stream. This method can 
  998.      * be used by subclasses that override the 
  999.      * <code>getContentType</code> method. 
  1000.      * <p>
  1001.      * Ideally, this routine would not be needed. But many 
  1002.      * <code>http</code> servers return the incorrect content type; in 
  1003.      * addition, there are many nonstandard extensions. Direct inspection 
  1004.      * of the bytes to determine the content type is often more accurate 
  1005.      * than believing the content type claimed by the <code>http</code> server.
  1006.      *
  1007.      * @param      is   an input stream that supports marks.
  1008.      * @return     a guess at the content type, or <code>null</code> if none
  1009.      *             can be determined.
  1010.      * @exception  IOException  if an I/O error occurs while reading the
  1011.      *               input stream.
  1012.      * @see        java.io.InputStream#mark(int)
  1013.      * @see        java.io.InputStream#markSupported()
  1014.      * @see        java.net.URLConnection#getContentType()
  1015.      * @since      JDK1.0
  1016.      */
  1017.     static public String guessContentTypeFromStream(InputStream is) throws IOException
  1018.     {
  1019.     is.mark(10);
  1020.     int c1 = is.read();
  1021.     int c2 = is.read();
  1022.     int c3 = is.read();
  1023.     int c4 = is.read();
  1024.     int c5 = is.read();
  1025.     int c6 = is.read();
  1026.     is.reset();
  1027.     if (c1 == 0xCA && c2 == 0xFE && c3 == 0xBA && c4 == 0xBE)
  1028.         return "application/java-vm";
  1029.     if (c1 == 0xAC && c2 == 0xED)
  1030.         // next two bytes are version number, currently 0x00 0x05
  1031.         return "application/x-java-serialized-object";
  1032.     if (c1 == 'G' && c2 == 'I' && c3 == 'F' && c4 == '8')
  1033.         return "image/gif";
  1034.     if (c1 == '#' && c2 == 'd' && c3 == 'e' && c4 == 'f')
  1035.         return "image/x-bitmap";
  1036.     if (c1 == '!' && c2 == ' ' && c3 == 'X' && c4 == 'P' && c5 == 'M' && c6 == '2')
  1037.         return "image/x-pixmap";
  1038.     if (c1 == '<')
  1039.         if (c2 == '!'
  1040.             || (c6 == '>'
  1041.             && (c2 == 'h' && (c3 == 't' && c4 == 'm' && c5 == 'l' ||
  1042.                       c3 == 'e' && c4 == 'a' && c5 == 'd')
  1043.               || c2 == 'b' && c3 == 'o' && c4 == 'd' && c5 == 'y')))
  1044.         return "text/html";
  1045.  
  1046.     if (c1 == 0x2E && c2 == 0x73 && c3 == 0x6E && c4 == 0x64)
  1047.         return "audio/basic";  // .au format, big endian
  1048.     if (c1 == 0x64 && c2 == 0x6E && c3 == 0x73 && c4 == 0x2E)
  1049.         return "audio/basic";  // .au format, little endian
  1050.     if (c1 == '<')
  1051.         if (c2 == '!'
  1052.         || ((c2 == 'h' && (c3 == 't' && c4 == 'm' && c5 == 'l' ||
  1053.                    c3 == 'e' && c4 == 'a' && c5 == 'd')
  1054.              || c2 == 'b' && c3 == 'o' && c4 == 'd' && c5 == 'y'))
  1055.         || ((c2 == 'H' && (c3 == 'T' && c4 == 'M' && c5 == 'L' ||
  1056.                    c3 == 'E' && c4 == 'A' && c5 == 'D')
  1057.              || c2 == 'B' && c3 == 'O' && c4 == 'D' && c5 == 'Y')))
  1058.         return "text/html";
  1059.  
  1060.     if (c1 == 0xFF && c2 == 0xD8 && c3 == 0xFF && c4 == 0xE0)
  1061.         return "image/jpeg";
  1062.     if (c1 == 0xFF && c2 == 0xD8 && c3 == 0xFF && c4 == 0xEE)
  1063.         return "image/jpg";
  1064.  
  1065.     if (c1 == 'R' && c2 == 'I' && c3 == 'F' && c4 == 'F')
  1066.         /* I don't know if this is official but evidence
  1067.          * suggests that .wav files start with "RIFF" - brown
  1068.          */
  1069.         return "audio/x-wav";  
  1070.     return null;
  1071.     }
  1072. }
  1073.  
  1074. class UnknownContentHandler extends ContentHandler {
  1075.     public Object getContent(URLConnection uc) throws IOException {
  1076.     return uc.getInputStream();
  1077.     }
  1078. }
  1079.