home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / main.bin / URLConnection.java < prev    next >
Text File  |  1998-01-23  |  41KB  |  1,082 lines

  1. /*
  2.  * @(#)URLConnection.java    1.30 97/08/21
  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>getLastModified
  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.30, 08/21/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 value of the specified header field. Names of  
  400.      * header fields to pass to this method can be obtained from 
  401.      * getHeaderFieldKey.
  402.      *
  403.      * @param   name   the name of a header field. 
  404.      * @return  the value of the named header field, or <code>null</code>
  405.      *          if there is no such field in the header.
  406.      * @see     java.net.URLConnection#getHeaderFieldKey(int)
  407.      * @since   JDK1.0
  408.      */
  409.     public String getHeaderField(String name) {
  410.     return null;
  411.     }
  412.  
  413.     /**
  414.      * Returns the value of the named field parsed as a number.
  415.      * <p>
  416.      * This form of <code>getHeaderField</code> exists because some 
  417.      * connection types (e.g., <code>http-ng</code>) have pre-parsed 
  418.      * headers. Classes for that connection type can override this method 
  419.      * and short-circuit the parsing. 
  420.      *
  421.      * @param   name      the name of the header field.
  422.      * @param   Default   the default value.
  423.      * @return  the value of the named field, parsed as an integer. The
  424.      *          <code>Default</code> value is returned if the field is
  425.      *          missing or malformed.
  426.      * @since   JDK1.0
  427.      */
  428.     public int getHeaderFieldInt(String name, int Default) {
  429.     try {
  430.         return Integer.parseInt(getHeaderField(name));
  431.     } catch(Throwable t) {}
  432.     return Default;
  433.     }
  434.  
  435.     /**
  436.      * Returns the value of the named field parsed as date.
  437.      * The result is the number of seconds since January 1, 1970 GMT
  438.      * represented by the named field. 
  439.      * <p>
  440.      * This form of <code>getHeaderField</code> exists because some 
  441.      * connection types (e.g., <code>http-ng</code>) have pre-parsed 
  442.      * headers. Classes for that connection type can override this method 
  443.      * and short-circuit the parsing. 
  444.      *
  445.      * @param   name     the name of the header field.
  446.      * @param   Default   a default value.
  447.      * @return  the value of the field, parsed as a date. The value of the
  448.      *          <code>Default</code> argument is returned if the field is
  449.      *          missing or malformed.
  450.      * @since   JDK1.0
  451.      */
  452.     public long getHeaderFieldDate(String name, long Default) {
  453.     try {
  454.         return Date.parse(getHeaderField(name));
  455.     } catch(Throwable t) {}
  456.     return Default;
  457.     }
  458.  
  459.     /**
  460.      * Returns the key for the <code>n</code><sup>th</sup> header field.
  461.      *
  462.      * @param   n   an index.
  463.      * @return  the key for the <code>n</code><sup>th</sup> header field,
  464.      *          or <code>null</code> if there are fewer than <code>n</code>
  465.      *          fields.
  466.      * @since   JDK1.0
  467.      */
  468.     public String getHeaderFieldKey(int n) {
  469.     return null;
  470.     }
  471.  
  472.     /**
  473.      * Returns the value for the <code>n</code><sup>th</sup> header field. 
  474.      * It returns <code>null</code> if there are fewer than 
  475.      * <code>n</code> fields. 
  476.      * <p>
  477.      * This method can be used in conjunction with the 
  478.      * <code>getHeaderFieldKey</code> method to iterate through all 
  479.      * the headers in the message. 
  480.      *
  481.      * @param   n   an index.
  482.      * @return  the value of the <code>n</code><sup>th</sup> header field.
  483.      * @see     java.net.URLConnection#getHeaderFieldKey(int)
  484.      * @since   JDK1.0
  485.      */
  486.     public String getHeaderField(int n) {
  487.     return null;
  488.     }
  489.  
  490.     /**
  491.      * Retrieves the contents of this URL connection. 
  492.      * <p>
  493.      * This method first determines the content type of the object by 
  494.      * calling the <code>getContentType</code> method. If this is 
  495.      * the first time that the application has seen that specific content 
  496.      * type, a content handler for that content type is created: 
  497.      * <ol>
  498.      * <li>If the application has set up a content handler factory instance
  499.      *     using the <code>setContentHandlerFactory</code> method, the
  500.      *     <code>createContentHandler</code> method of that instance is called
  501.      *     with the content type as an argument; the result is a content
  502.      *     handler for that content type.
  503.      * <li>If no content handler factory has yet been set up, or if the
  504.      *     factory's <code>createContentHandler</code> method returns
  505.      *     <code>null</code>, then the application loads the class named:
  506.      *     <ul><code>
  507.      *         sun.net.www.content.<<i>contentType</i>>
  508.      *     </code></ul>
  509.      *     where <<i>contentType</i>> is formed by taking the
  510.      *     content-type string, replacing all slash characters with a
  511.      *     <code>period</code> ('.'), and all other non-alphanumeric characters
  512.      *     with the underscore character '<code>_</code>'. The alphanumeric
  513.      *     characters are specifically the 26 uppercase ASCII letters
  514.      *     '<code>A</code>' through '<code>Z</code>', the 26 lowercase ASCII
  515.      *     letters '<code>a</code>' through '<code>z</code>', and the 10 ASCII
  516.      *     digits '<code>0</code>' through '<code>9</code>'. If the specified
  517.      *     class does not exist, or is not a subclass of
  518.      *     <code>ContentHandler</code>, then an
  519.      *     <code>UnknownServiceException</code> is thrown.
  520.      * </ol>
  521.      *
  522.      * @return     the object fetched. The <code>instanceOf</code> operation
  523.      *               should be used to determine the specific kind of object
  524.      *               returned.
  525.      * @exception  IOException              if an I/O error occurs while
  526.      *               getting the content.
  527.      * @exception  UnknownServiceException  if the protocol does not support
  528.      *               the content type.
  529.      * @see        java.net.ContentHandlerFactory#createContentHandler(java.lang.String)
  530.      * @see        java.net.URLConnection#getContentType()
  531.      * @see        java.net.URLConnection#setContentHandlerFactory(java.net.ContentHandlerFactory)
  532.      * @since      JDK1.0
  533.      */
  534.     public Object getContent() throws IOException {
  535.     return getContentHandler().getContent(this);
  536.     }
  537.  
  538.     /**
  539.      * Returns an input stream that reads from this open connection.
  540.      *
  541.      * @return     an input stream that reads from this open connection.
  542.      * @exception  IOException              if an I/O error occurs while
  543.      *               creating the input stream.
  544.      * @exception  UnknownServiceException  if the protocol does not support
  545.      *               input.
  546.      * @since   JDK1.0
  547.      */
  548.     public InputStream getInputStream() throws IOException {
  549.     throw new UnknownServiceException("protocol doesn't support input");
  550.     }
  551.  
  552.     /**
  553.      * Returns an output stream that writes to this connection.
  554.      *
  555.      * @return     an output stream that writes to this connection.
  556.      * @exception  IOException              if an I/O error occurs while
  557.      *               creating the output stream.
  558.      * @exception  UnknownServiceException  if the protocol does not support
  559.      *               output.
  560.      * @since   JDK1.0
  561.      */
  562.     public OutputStream getOutputStream() throws IOException {
  563.     throw new UnknownServiceException("protocol doesn't support output");
  564.     }
  565.  
  566.     /**
  567.      * Returns a <code>String</code> representation of this URL connection.
  568.      *
  569.      * @return  a string representation of this <code>URLConnection</code>.
  570.      * @since   JDK1.0
  571.      */
  572.     public String toString() {
  573.     return this.getClass().getName() + ":" + url;
  574.     }
  575.  
  576.     /**
  577.      * Sets the value of the <code>doInput</code> field for this 
  578.      * <code>URLConnection</code> to the specified value. 
  579.      * <p>
  580.      * A URL connection can be used for input and/or output.  Set the DoInput
  581.      * flag to true if you intend to use the URL connection for input,
  582.      * false if not.  The default is true unless DoOutput is explicitly
  583.      * set to true, in which case DoInput defaults to false.
  584.      *
  585.      * @param   value   the new value.
  586.      * @see     java.net.URLConnection#doInput
  587.      * @since   JDK1.0
  588.      */
  589.     public void setDoInput(boolean doinput) {
  590.     if (connected)
  591.         throw new IllegalAccessError("Already connected");
  592.     doInput = doinput;
  593.     }
  594.  
  595.     /**
  596.      * Returns the value of this <code>URLConnection</code>'s
  597.      * <code>doInput</code> flag.
  598.      *
  599.      * @return  the value of this <code>URLConnection</code>'s
  600.      *          <code>doInput</code> flag.
  601.      * @see     java.net.URLConnection#doInput
  602.      * @since   JDK1.0
  603.      */
  604.     public boolean getDoInput() {
  605.     return doInput;
  606.     }
  607.  
  608.     /**
  609.      * Sets the value of the <code>doOutput</code> field for this 
  610.      * <code>URLConnection</code> to the specified value. 
  611.      * <p>
  612.      * A URL connection can be used for input and/or output.  Set the DoOutput
  613.      * flag to true if you intend to use the URL connection for output,
  614.      * false if not.  The default is false.
  615.      *
  616.      * @param   value   the new value.
  617.      * @see     java.net.URLConnection#doOutput
  618.      * @since   JDK1.0
  619.      */
  620.     public void setDoOutput(boolean dooutput) {
  621.     if (connected)
  622.         throw new IllegalAccessError("Already connected");
  623.     doOutput = dooutput;
  624.     }
  625.  
  626.     /**
  627.      * Returns the value of this <code>URLConnection</code>'s
  628.      * <code>doOutput</code> flag.
  629.      *
  630.      * @return  the value of this <code>URLConnection</code>'s
  631.      *          <code>doOutput</code> flag.
  632.      * @see     java.net.URLConnection#doOutput
  633.      * @since   JDK1.0
  634.      */
  635.     public boolean getDoOutput() {
  636.     return doOutput;
  637.     }
  638.  
  639.     /**
  640.      * Set the value of the <code>allowUserInteraction</code> field of 
  641.      * this <code>URLConnection</code>. 
  642.      *
  643.      * @param   allowuserinteraction   the new value.
  644.      * @see     java.net.URLConnection#allowUserInteraction
  645.      * @since   JDK1.0
  646.      */
  647.     public void setAllowUserInteraction(boolean allowuserinteraction) {
  648.     if (connected)
  649.         throw new IllegalAccessError("Already connected");
  650.     allowUserInteraction = allowuserinteraction;
  651.     }
  652.  
  653.     /**
  654.      * Returns the value of the <code>allowUserInteraction</code> field for
  655.      * this object.
  656.      *
  657.      * @return  the value of the <code>allowUserInteraction</code> field for
  658.      *          this object.
  659.      * @see     java.net.URLConnection#allowUserInteraction
  660.      * @since   JDK1.0
  661.      */
  662.     public boolean getAllowUserInteraction() {
  663.     return allowUserInteraction;
  664.     }
  665.  
  666.     /**
  667.      * Sets the default value of the 
  668.      * <code>allowUserInteraction</code> field for all future 
  669.      * <code>URLConnection</code> objects to the specified value. 
  670.      *
  671.      * @param   defaultallowuserinteraction   the new value.
  672.      * @see     java.net.URLConnection#allowUserInteraction
  673.      * @since   JDK1.0
  674.      */
  675.     public static void setDefaultAllowUserInteraction(boolean defaultallowuserinteraction) {
  676.     defaultAllowUserInteraction = defaultallowuserinteraction;
  677.     }
  678.  
  679.     /**
  680.      * Returns the default value of the <code>allowUserInteraction</code>
  681.      * field.
  682.      * <p>
  683.      * Ths default is "sticky", being a part of the static state of all
  684.      * URLConnections.  This flag applies to the next, and all following
  685.      * URLConnections that are created.
  686.      *
  687.      * @return  the default value of the <code>allowUserInteraction</code>
  688.      *          field.
  689.      * @see     java.net.URLConnection#allowUserInteraction
  690.      * @since   JDK1.0
  691.      */
  692.     public static boolean getDefaultAllowUserInteraction() {
  693.     return defaultAllowUserInteraction;
  694.     }
  695.  
  696.     /**
  697.      * Sets the value of the <code>useCaches</code> field of this 
  698.      * <code>URLConnection</code> to the specified value. 
  699.      * <p>
  700.      * Some protocols do caching of documents.  Occasionally, it is important
  701.      * to be able to "tunnel through" and ignore the caches (e.g., the
  702.      * "reload" button in a browser).  If the UseCaches flag on a connection
  703.      * is true, the connection is allowed to use whatever caches it can.
  704.      *  If false, caches are to be ignored.
  705.      *  The default value comes from DefaultUseCaches, which defaults to
  706.      * true.
  707.      *
  708.      * @see     java.net.URLConnection#useCaches
  709.      * @since   JDK1.0
  710.      */
  711.     public void setUseCaches(boolean usecaches) {
  712.     if (connected)
  713.         throw new IllegalAccessError("Already connected");
  714.     useCaches = usecaches;
  715.     }
  716.  
  717.     /**
  718.      * Returns the value of this <code>URLConnection</code>'s
  719.      * <code>useCaches</code> field.
  720.      *
  721.      * @return  the value of this <code>URLConnection</code>'s
  722.      *          <code>useCaches</code> field.
  723.      * @see     java.net.URLConnection#useCaches
  724.      * @since   JDK1.0
  725.      */
  726.     public boolean getUseCaches() {
  727.     return useCaches;
  728.     }
  729.  
  730.     /**
  731.      * Sets the value of the <code>ifModifiedSince</code> field of 
  732.      * this <code>URLConnection</code> to the specified value.
  733.      *
  734.      * @param   value   the new value.
  735.      * @see     java.net.URLConnection#ifModifiedSince
  736.      * @since   JDK1.0
  737.      */
  738.     public void setIfModifiedSince(long ifmodifiedsince) {
  739.     if (connected)
  740.         throw new IllegalAccessError("Already connected");
  741.     ifModifiedSince = ifmodifiedsince;
  742.     }
  743.  
  744.     /**
  745.      * Returns the value of this object's <code>ifModifiedSince</code> field.
  746.      *
  747.      * @return  the value of this object's <code>ifModifiedSince</code> field.
  748.      * @see     java.net.URLConnection#ifModifiedSince
  749.      * @since   JDK1.0
  750.      */
  751.     public long getIfModifiedSince() {
  752.     return ifModifiedSince;
  753.     }
  754.  
  755.    /**
  756.      * Returns the default value of a <code>URLConnection</code>'s
  757.      * <code>useCaches</code> flag.
  758.      * <p>
  759.      * Ths default is "sticky", being a part of the static state of all
  760.      * URLConnections.  This flag applies to the next, and all following
  761.      * URLConnections that are created.
  762.      *
  763.      * @return  the default value of a <code>URLConnection</code>'s
  764.      *          <code>useCaches</code> flag.
  765.      * @see     java.net.URLConnection#useCaches
  766.      * @since   JDK1.0
  767.      */
  768.     public boolean getDefaultUseCaches() {
  769.     return defaultUseCaches;
  770.     }
  771.  
  772.    /**
  773.      * Sets the default value of the <code>useCaches</code> field to the 
  774.      * specified value. 
  775.      *
  776.      * @param   defaultusecaches   the new value.
  777.      * @see     java.net.URLConnection#useCaches
  778.      * @since   JDK1.0
  779.      */
  780.     public void setDefaultUseCaches(boolean defaultusecaches) {
  781.     defaultUseCaches = defaultusecaches;
  782.     }
  783.  
  784.     /**
  785.      * Sets the general request property. 
  786.      *
  787.      * @param   key     the keyword by which the request is known
  788.      *                  (e.g., "<code>accept</code>").
  789.      * @param   value   the value associated with it.
  790.      * @since   JDK1.0
  791.      */
  792.     public void setRequestProperty(String key, String value) {
  793.     if (connected)
  794.         throw new IllegalAccessError("Already connected");
  795.     }
  796.  
  797.     /**
  798.      * Returns the value of the named general request property for this
  799.      * connection.
  800.      *
  801.      * @return  the value of the named general request property for this
  802.      *           connection.
  803.      * @since   JDK1.0
  804.      */
  805.     public String getRequestProperty(String key) {
  806.     if (connected)
  807.         throw new IllegalAccessError("Already connected");
  808.     return null;
  809.     }
  810.  
  811.     /**
  812.      * Sets the default value of a general request property. When a 
  813.      * <code>URLConnection</code> is created, it is initialized with 
  814.      * these properties. 
  815.      *
  816.      * @param   key     the keyword by which the request is known
  817.      *                  (e.g., "<code>accept</code>").
  818.      * @param   value   the value associated with the key.
  819.      * @since   JDK1.0
  820.      */
  821.     public static void setDefaultRequestProperty(String key, String value) {
  822.     }
  823.  
  824.     /**
  825.      * Returns the value of the default request property. Default request 
  826.      * properties are set for every connection. 
  827.      *
  828.      * @return  the value of the default request property for the specified key.
  829.      * @see     java.net.URLConnection#setDefaultRequestProperty(java.lang.String, java.lang.String)
  830.      * @since   JDK1.0
  831.      */
  832.     public static String getDefaultRequestProperty(String key) {
  833.     return null;
  834.     }
  835.  
  836.     /**
  837.      * The ContentHandler factory.
  838.      */
  839.     static ContentHandlerFactory factory;
  840.  
  841.     /**
  842.      * Sets the <code>ContentHandlerFactory</code> of an 
  843.      * application. It can be called at most once by an application. 
  844.      * <p>
  845.      * The <code>ContentHandlerFactory</code> instance is used to 
  846.      * construct a content handler from a content type 
  847.      *
  848.      * @param      fac   the desired factory.
  849.      * @exception  Error  if the factory has already been defined.
  850.      * @see        java.net.ContentHandlerFactory
  851.      * @see        java.net.URLConnection#getContent()
  852.      * @since      JDK1.0
  853.      */
  854.     public static synchronized void setContentHandlerFactory(ContentHandlerFactory fac) {
  855.     if (factory != null) {
  856.         throw new Error("factory already defined");
  857.     }
  858.     SecurityManager security = System.getSecurityManager();
  859.     if (security != null) {
  860.         security.checkSetFactory();
  861.     }
  862.     factory = fac;
  863.     }
  864.  
  865.     private static Hashtable handlers = new Hashtable();
  866.     private static ContentHandler UnknownContentHandlerP = new UnknownContentHandler();
  867.  
  868.     /**
  869.      * Gets the Content Handler appropriate for this connection.
  870.      * @param connection the connection to use.
  871.      */
  872.     synchronized ContentHandler getContentHandler()
  873.     throws UnknownServiceException
  874.     {
  875.     String contentType = getContentType();
  876.     ContentHandler handler = null;
  877.     if (contentType == null)
  878.         throw new UnknownServiceException("no content-type");
  879.     try {
  880.         handler = (ContentHandler) handlers.get(contentType);
  881.         if (handler != null)
  882.         return handler;
  883.     } catch(Exception e) {
  884.     }
  885.     if (factory != null)
  886.         handler = factory.createContentHandler(contentType);
  887.     if (handler == null) {
  888.         try {
  889.         handler = lookupContentHandlerClassFor(contentType);
  890.         } catch(Exception e) {
  891.         e.printStackTrace();
  892.         handler = UnknownContentHandlerP;
  893.         }
  894.         handlers.put(contentType, handler);
  895.     }
  896.     return handler;
  897.     }
  898.  
  899.     private static final String contentClassPrefix = "sun.net.www.content";
  900.     private static final String contentPathProp = "java.content.handler.pkgs";
  901.  
  902.     /**
  903.      * Looks for a content handler in a user-defineable set of places.
  904.      * By default it looks in sun.net.www.content, but users can define a 
  905.      * vertical-bar delimited set of class prefixes to search through in 
  906.      * addition by defining the java.content.handler.pkgs property.
  907.      * The class name must be of the form:
  908.      * <pre>
  909.      *     {package-prefix}.{major}.{minor}
  910.      * e.g.
  911.      *     YoyoDyne.experimental.text.plain
  912.      * </pre>
  913.      */
  914.     private ContentHandler lookupContentHandlerClassFor(String contentType)
  915.     throws InstantiationException, IllegalAccessException, ClassNotFoundException {
  916.     String contentHandlerClassName = typeToPackageName(contentType);
  917.  
  918.     String contentHandlerPkgPrefixes = getContentHandlerPkgPrefixes();
  919.  
  920.     StringTokenizer packagePrefixIter =
  921.         new StringTokenizer(contentHandlerPkgPrefixes, "|");
  922.     
  923.     while (packagePrefixIter.hasMoreTokens()) {
  924.         String packagePrefix = packagePrefixIter.nextToken().trim();
  925.  
  926.         try {
  927.         String name = packagePrefix + "." + contentHandlerClassName;
  928.         ContentHandler handler =
  929.             (ContentHandler) Class.forName(name).newInstance();
  930.         return handler;
  931.         } catch(Exception e) {
  932.         }
  933.     }
  934.     
  935.     return UnknownContentHandlerP;
  936.     }
  937.  
  938.     /**
  939.      * Utility function to map a MIME content type into an equivalent
  940.      * pair of class name components.  For example: "text/html" would
  941.      * be returned as "text.html"
  942.      */
  943.     private String typeToPackageName(String contentType) {
  944.     int len = contentType.length();
  945.     char nm[] = new char[len];
  946.     contentType.getChars(0, len, nm, 0);
  947.     for (int i = 0; i < len; i++) {
  948.         char c = nm[i];
  949.         if (c == '/') {
  950.         nm[i] = '.';
  951.         } else if (!('A' <= c && c <= 'Z' ||
  952.                'a' <= c && c <= 'z' ||
  953.                '0' <= c && c <= '9')) {
  954.         nm[i] = '_';
  955.         }
  956.     }
  957.     return new String(nm);
  958.     }
  959.  
  960.  
  961.     /**
  962.      * Returns a vertical bar separated list of package prefixes for potential
  963.      * content handlers.  Tries to get the java.content.handler.pkgs property
  964.      * to use as a set of package prefixes to search.  Whether or not
  965.      * that property has been defined, the sun.net.www.content is always
  966.      * the last one on the returned package list.
  967.      */
  968.     private String getContentHandlerPkgPrefixes() {
  969.     String packagePrefixList = System.getProperty(contentPathProp, "");
  970.     if (packagePrefixList != "") {
  971.         packagePrefixList += "|";
  972.     }
  973.     
  974.     return packagePrefixList + contentClassPrefix;
  975.     }
  976.  
  977.     /**
  978.      * Tries to determine the content type of an object, based 
  979.      * on the specified "file" component of a URL.
  980.      * This is a convenience method that can be used by 
  981.      * subclasses that override the <code>getContentType</code> method. 
  982.      *
  983.      * @param   fname   a filename.
  984.      * @return  a guess as to what the content type of the object is,
  985.      *          based upon its file name.
  986.      * @see     java.net.URLConnection#getContentType()
  987.      * @since   JDK1.0
  988.      */
  989.     protected static String guessContentTypeFromName(String fname) {
  990.     String contentType = null;
  991.     if (fileNameMap != null) {
  992.         contentType = fileNameMap.getContentTypeFor(fname);
  993.     }
  994.  
  995.     return contentType;
  996.     }
  997.  
  998.     /**
  999.      * Tries to determine the type of an input stream based on the 
  1000.      * characters at the beginning of the input stream. This method can 
  1001.      * be used by subclasses that override the 
  1002.      * <code>getContentType</code> method. 
  1003.      * <p>
  1004.      * Ideally, this routine would not be needed. But many 
  1005.      * <code>http</code> servers return the incorrect content type; in 
  1006.      * addition, there are many nonstandard extensions. Direct inspection 
  1007.      * of the bytes to determine the content type is often more accurate 
  1008.      * than believing the content type claimed by the <code>http</code> server.
  1009.      *
  1010.      * @param      is   an input stream that supports marks.
  1011.      * @return     a guess at the content type, or <code>null</code> if none
  1012.      *             can be determined.
  1013.      * @exception  IOException  if an I/O error occurs while reading the
  1014.      *               input stream.
  1015.      * @see        java.io.InputStream#mark(int)
  1016.      * @see        java.io.InputStream#markSupported()
  1017.      * @see        java.net.URLConnection#getContentType()
  1018.      * @since      JDK1.0
  1019.      */
  1020.     static public String guessContentTypeFromStream(InputStream is) throws IOException
  1021.     {
  1022.     is.mark(10);
  1023.     int c1 = is.read();
  1024.     int c2 = is.read();
  1025.     int c3 = is.read();
  1026.     int c4 = is.read();
  1027.     int c5 = is.read();
  1028.     int c6 = is.read();
  1029.     is.reset();
  1030.     if (c1 == 0xCA && c2 == 0xFE && c3 == 0xBA && c4 == 0xBE)
  1031.         return "application/java-vm";
  1032.     if (c1 == 0xAC && c2 == 0xED)
  1033.         // next two bytes are version number, currently 0x00 0x05
  1034.         return "application/x-java-serialized-object";
  1035.     if (c1 == 'G' && c2 == 'I' && c3 == 'F' && c4 == '8')
  1036.         return "image/gif";
  1037.     if (c1 == '#' && c2 == 'd' && c3 == 'e' && c4 == 'f')
  1038.         return "image/x-bitmap";
  1039.     if (c1 == '!' && c2 == ' ' && c3 == 'X' && c4 == 'P' && c5 == 'M' && c6 == '2')
  1040.         return "image/x-pixmap";
  1041.     if (c1 == '<')
  1042.         if (c2 == '!'
  1043.             || (c6 == '>'
  1044.             && (c2 == 'h' && (c3 == 't' && c4 == 'm' && c5 == 'l' ||
  1045.                       c3 == 'e' && c4 == 'a' && c5 == 'd')
  1046.               || c2 == 'b' && c3 == 'o' && c4 == 'd' && c5 == 'y')))
  1047.         return "text/html";
  1048.  
  1049.     if (c1 == 0x2E && c2 == 0x73 && c3 == 0x6E && c4 == 0x64)
  1050.         return "audio/basic";  // .au format, big endian
  1051.     if (c1 == 0x64 && c2 == 0x6E && c3 == 0x73 && c4 == 0x2E)
  1052.         return "audio/basic";  // .au format, little endian
  1053.     if (c1 == '<')
  1054.         if (c2 == '!'
  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.         || ((c2 == 'H' && (c3 == 'T' && c4 == 'M' && c5 == 'L' ||
  1059.                    c3 == 'E' && c4 == 'A' && c5 == 'D')
  1060.              || c2 == 'B' && c3 == 'O' && c4 == 'D' && c5 == 'Y')))
  1061.         return "text/html";
  1062.  
  1063.     if (c1 == 0xFF && c2 == 0xD8 && c3 == 0xFF && c4 == 0xE0)
  1064.         return "image/jpeg";
  1065.     if (c1 == 0xFF && c2 == 0xD8 && c3 == 0xFF && c4 == 0xEE)
  1066.         return "image/jpg";
  1067.  
  1068.     if (c1 == 'R' && c2 == 'I' && c3 == 'F' && c4 == 'F')
  1069.         /* I don't know if this is official but evidence
  1070.          * suggests that .wav files start with "RIFF" - brown
  1071.          */
  1072.         return "audio/x-wav";  
  1073.     return null;
  1074.     }
  1075. }
  1076.  
  1077. class UnknownContentHandler extends ContentHandler {
  1078.     public Object getContent(URLConnection uc) throws IOException {
  1079.     return uc.getInputStream();
  1080.     }
  1081. }
  1082.