Home | History | Annotate | Download | only in net
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
      4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      5  *
      6  * This code is free software; you can redistribute it and/or modify it
      7  * under the terms of the GNU General Public License version 2 only, as
      8  * published by the Free Software Foundation.  Oracle designates this
      9  * particular file as subject to the "Classpath" exception as provided
     10  * by Oracle in the LICENSE file that accompanied this code.
     11  *
     12  * This code is distributed in the hope that it will be useful, but WITHOUT
     13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15  * version 2 for more details (a copy is included in the LICENSE file that
     16  * accompanied this code).
     17  *
     18  * You should have received a copy of the GNU General Public License version
     19  * 2 along with this work; if not, write to the Free Software Foundation,
     20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     21  *
     22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     23  * or visit www.oracle.com if you need additional information or have any
     24  * questions.
     25  */
     26 
     27 package java.net;
     28 
     29 import java.io.IOException;
     30 import java.io.InputStream;
     31 import java.io.OutputStream;
     32 import java.util.Hashtable;
     33 import java.util.Date;
     34 import java.util.StringTokenizer;
     35 import java.util.Collections;
     36 import java.util.Map;
     37 import java.util.List;
     38 import java.security.Permission;
     39 import java.security.AccessController;
     40 import sun.security.util.SecurityConstants;
     41 import sun.net.www.MessageHeader;
     42 
     43 /**
     44  * The abstract class {@code URLConnection} is the superclass
     45  * of all classes that represent a communications link between the
     46  * application and a URL. Instances of this class can be used both to
     47  * read from and to write to the resource referenced by the URL. In
     48  * general, creating a connection to a URL is a multistep process:
     49  *
     50  * <center><table border=2 summary="Describes the process of creating a connection to a URL: openConnection() and connect() over time.">
     51  * <tr><th>{@code openConnection()}</th>
     52  *     <th>{@code connect()}</th></tr>
     53  * <tr><td>Manipulate parameters that affect the connection to the remote
     54  *         resource.</td>
     55  *     <td>Interact with the resource; query header fields and
     56  *         contents.</td></tr>
     57  * </table>
     58  * ----------------------------&gt;
     59  * <br>time</center>
     60  *
     61  * <ol>
     62  * <li>The connection object is created by invoking the
     63  *     {@code openConnection} method on a URL.
     64  * <li>The setup parameters and general request properties are manipulated.
     65  * <li>The actual connection to the remote object is made, using the
     66  *    {@code connect} method.
     67  * <li>The remote object becomes available. The header fields and the contents
     68  *     of the remote object can be accessed.
     69  * </ol>
     70  * <p>
     71  * The setup parameters are modified using the following methods:
     72  * <ul>
     73  *   <li>{@code setAllowUserInteraction}
     74  *   <li>{@code setDoInput}
     75  *   <li>{@code setDoOutput}
     76  *   <li>{@code setIfModifiedSince}
     77  *   <li>{@code setUseCaches}
     78  * </ul>
     79  * <p>
     80  * and the general request properties are modified using the method:
     81  * <ul>
     82  *   <li>{@code setRequestProperty}
     83  * </ul>
     84  * <p>
     85  * Default values for the {@code AllowUserInteraction} and
     86  * {@code UseCaches} parameters can be set using the methods
     87  * {@code setDefaultAllowUserInteraction} and
     88  * {@code setDefaultUseCaches}.
     89  * <p>
     90  * Each of the above {@code set} methods has a corresponding
     91  * {@code get} method to retrieve the value of the parameter or
     92  * general request property. The specific parameters and general
     93  * request properties that are applicable are protocol specific.
     94  * <p>
     95  * The following methods are used to access the header fields and
     96  * the contents after the connection is made to the remote object:
     97  * <ul>
     98  *   <li>{@code getContent}
     99  *   <li>{@code getHeaderField}
    100  *   <li>{@code getInputStream}
    101  *   <li>{@code getOutputStream}
    102  * </ul>
    103  * <p>
    104  * Certain header fields are accessed frequently. The methods:
    105  * <ul>
    106  *   <li>{@code getContentEncoding}
    107  *   <li>{@code getContentLength}
    108  *   <li>{@code getContentType}
    109  *   <li>{@code getDate}
    110  *   <li>{@code getExpiration}
    111  *   <li>{@code getLastModifed}
    112  * </ul>
    113  * <p>
    114  * provide convenient access to these fields. The
    115  * {@code getContentType} method is used by the
    116  * {@code getContent} method to determine the type of the remote
    117  * object; subclasses may find it convenient to override the
    118  * {@code getContentType} method.
    119  * <p>
    120  * In the common case, all of the pre-connection parameters and
    121  * general request properties can be ignored: the pre-connection
    122  * parameters and request properties default to sensible values. For
    123  * most clients of this interface, there are only two interesting
    124  * methods: {@code getInputStream} and {@code getContent},
    125  * which are mirrored in the {@code URL} class by convenience methods.
    126  * <p>
    127  * More information on the request properties and header fields of
    128  * an {@code http} connection can be found at:
    129  * <blockquote><pre>
    130  * <a href="http://www.ietf.org/rfc/rfc2616.txt">http://www.ietf.org/rfc/rfc2616.txt</a>
    131  * </pre></blockquote>
    132  *
    133  * Invoking the {@code close()} methods on the {@code InputStream} or {@code OutputStream} of an
    134  * {@code URLConnection} after a request may free network resources associated with this
    135  * instance, unless particular protocol specifications specify different behaviours
    136  * for it.
    137  *
    138  * @author  James Gosling
    139  * @see     java.net.URL#openConnection()
    140  * @see     java.net.URLConnection#connect()
    141  * @see     java.net.URLConnection#getContent()
    142  * @see     java.net.URLConnection#getContentEncoding()
    143  * @see     java.net.URLConnection#getContentLength()
    144  * @see     java.net.URLConnection#getContentType()
    145  * @see     java.net.URLConnection#getDate()
    146  * @see     java.net.URLConnection#getExpiration()
    147  * @see     java.net.URLConnection#getHeaderField(int)
    148  * @see     java.net.URLConnection#getHeaderField(java.lang.String)
    149  * @see     java.net.URLConnection#getInputStream()
    150  * @see     java.net.URLConnection#getLastModified()
    151  * @see     java.net.URLConnection#getOutputStream()
    152  * @see     java.net.URLConnection#setAllowUserInteraction(boolean)
    153  * @see     java.net.URLConnection#setDefaultUseCaches(boolean)
    154  * @see     java.net.URLConnection#setDoInput(boolean)
    155  * @see     java.net.URLConnection#setDoOutput(boolean)
    156  * @see     java.net.URLConnection#setIfModifiedSince(long)
    157  * @see     java.net.URLConnection#setRequestProperty(java.lang.String, java.lang.String)
    158  * @see     java.net.URLConnection#setUseCaches(boolean)
    159  * @since   JDK1.0
    160  */
    161 public abstract class URLConnection {
    162 
    163    /**
    164      * The URL represents the remote object on the World Wide Web to
    165      * which this connection is opened.
    166      * <p>
    167      * The value of this field can be accessed by the
    168      * {@code getURL} method.
    169      * <p>
    170      * The default value of this variable is the value of the URL
    171      * argument in the {@code URLConnection} constructor.
    172      *
    173      * @see     java.net.URLConnection#getURL()
    174      * @see     java.net.URLConnection#url
    175      */
    176     protected URL url;
    177 
    178    /**
    179      * This variable is set by the {@code setDoInput} method. Its
    180      * value is returned by the {@code getDoInput} method.
    181      * <p>
    182      * A URL connection can be used for input and/or output. Setting the
    183      * {@code doInput} flag to {@code true} indicates that
    184      * the application intends to read data from the URL connection.
    185      * <p>
    186      * The default value of this field is {@code true}.
    187      *
    188      * @see     java.net.URLConnection#getDoInput()
    189      * @see     java.net.URLConnection#setDoInput(boolean)
    190      */
    191     protected boolean doInput = true;
    192 
    193    /**
    194      * This variable is set by the {@code setDoOutput} method. Its
    195      * value is returned by the {@code getDoOutput} method.
    196      * <p>
    197      * A URL connection can be used for input and/or output. Setting the
    198      * {@code doOutput} flag to {@code true} indicates
    199      * that the application intends to write data to the URL connection.
    200      * <p>
    201      * The default value of this field is {@code false}.
    202      *
    203      * @see     java.net.URLConnection#getDoOutput()
    204      * @see     java.net.URLConnection#setDoOutput(boolean)
    205      */
    206     protected boolean doOutput = false;
    207 
    208     private static boolean defaultAllowUserInteraction = false;
    209 
    210    /**
    211      * If {@code true}, this {@code URL} is being examined in
    212      * a context in which it makes sense to allow user interactions such
    213      * as popping up an authentication dialog. If {@code false},
    214      * then no user interaction is allowed.
    215      * <p>
    216      * The value of this field can be set by the
    217      * {@code setAllowUserInteraction} method.
    218      * Its value is returned by the
    219      * {@code getAllowUserInteraction} method.
    220      * Its default value is the value of the argument in the last invocation
    221      * of the {@code setDefaultAllowUserInteraction} method.
    222      *
    223      * @see     java.net.URLConnection#getAllowUserInteraction()
    224      * @see     java.net.URLConnection#setAllowUserInteraction(boolean)
    225      * @see     java.net.URLConnection#setDefaultAllowUserInteraction(boolean)
    226      */
    227     protected boolean allowUserInteraction = defaultAllowUserInteraction;
    228 
    229     private static boolean defaultUseCaches = true;
    230 
    231    /**
    232      * If {@code true}, the protocol is allowed to use caching
    233      * whenever it can. If {@code false}, the protocol must always
    234      * try to get a fresh copy of the object.
    235      * <p>
    236      * This field is set by the {@code setUseCaches} method. Its
    237      * value is returned by the {@code getUseCaches} method.
    238      * <p>
    239      * Its default value is the value given in the last invocation of the
    240      * {@code setDefaultUseCaches} method.
    241      *
    242      * @see     java.net.URLConnection#setUseCaches(boolean)
    243      * @see     java.net.URLConnection#getUseCaches()
    244      * @see     java.net.URLConnection#setDefaultUseCaches(boolean)
    245      */
    246     protected boolean useCaches = defaultUseCaches;
    247 
    248    /**
    249      * Some protocols support skipping the fetching of the object unless
    250      * the object has been modified more recently than a certain time.
    251      * <p>
    252      * A nonzero value gives a time as the number of milliseconds since
    253      * January 1, 1970, GMT. The object is fetched only if it has been
    254      * modified more recently than that time.
    255      * <p>
    256      * This variable is set by the {@code setIfModifiedSince}
    257      * method. Its value is returned by the
    258      * {@code getIfModifiedSince} method.
    259      * <p>
    260      * The default value of this field is {@code 0}, indicating
    261      * that the fetching must always occur.
    262      *
    263      * @see     java.net.URLConnection#getIfModifiedSince()
    264      * @see     java.net.URLConnection#setIfModifiedSince(long)
    265      */
    266     protected long ifModifiedSince = 0;
    267 
    268    /**
    269      * If {@code false}, this connection object has not created a
    270      * communications link to the specified URL. If {@code true},
    271      * the communications link has been established.
    272      */
    273     protected boolean connected = false;
    274 
    275     /**
    276      * @since 1.5
    277      */
    278     private int connectTimeout;
    279     private int readTimeout;
    280 
    281     /**
    282      * @since 1.6
    283      */
    284     private MessageHeader requests;
    285 
    286    /**
    287     * @since   JDK1.1
    288     */
    289     private static FileNameMap fileNameMap;
    290 
    291     /**
    292      * Loads filename map (a mimetable) from a data file. It will
    293      * first try to load the user-specific table, defined
    294      * by &quot;content.types.user.table&quot; property. If that fails,
    295      * it tries to load the default built-in table.
    296      *
    297      * @return the FileNameMap
    298      * @since 1.2
    299      * @see #setFileNameMap(java.net.FileNameMap)
    300      */
    301     public static synchronized FileNameMap getFileNameMap() {
    302         if (fileNameMap == null) {
    303             fileNameMap = new DefaultFileNameMap();
    304         }
    305         return fileNameMap;
    306     }
    307 
    308     /**
    309      * Sets the FileNameMap.
    310      * <p>
    311      * If there is a security manager, this method first calls
    312      * the security manager's {@code checkSetFactory} method
    313      * to ensure the operation is allowed.
    314      * This could result in a SecurityException.
    315      *
    316      * @param map the FileNameMap to be set
    317      * @exception  SecurityException  if a security manager exists and its
    318      *             {@code checkSetFactory} method doesn't allow the operation.
    319      * @see        SecurityManager#checkSetFactory
    320      * @see #getFileNameMap()
    321      * @since 1.2
    322      */
    323     public static void setFileNameMap(FileNameMap map) {
    324         SecurityManager sm = System.getSecurityManager();
    325         if (sm != null) sm.checkSetFactory();
    326         fileNameMap = map;
    327     }
    328 
    329     /**
    330      * Opens a communications link to the resource referenced by this
    331      * URL, if such a connection has not already been established.
    332      * <p>
    333      * If the {@code connect} method is called when the connection
    334      * has already been opened (indicated by the {@code connected}
    335      * field having the value {@code true}), the call is ignored.
    336      * <p>
    337      * URLConnection objects go through two phases: first they are
    338      * created, then they are connected.  After being created, and
    339      * before being connected, various options can be specified
    340      * (e.g., doInput and UseCaches).  After connecting, it is an
    341      * error to try to set them.  Operations that depend on being
    342      * connected, like getContentLength, will implicitly perform the
    343      * connection, if necessary.
    344      *
    345      * @throws SocketTimeoutException if the timeout expires before
    346      *               the connection can be established
    347      * @exception  IOException  if an I/O error occurs while opening the
    348      *               connection.
    349      * @see java.net.URLConnection#connected
    350      * @see #getConnectTimeout()
    351      * @see #setConnectTimeout(int)
    352      */
    353     abstract public void connect() throws IOException;
    354 
    355     /**
    356      * Sets a specified timeout value, in milliseconds, to be used
    357      * when opening a communications link to the resource referenced
    358      * by this URLConnection.  If the timeout expires before the
    359      * connection can be established, a
    360      * java.net.SocketTimeoutException is raised. A timeout of zero is
    361      * interpreted as an infinite timeout.
    362 
    363      * <p> Some non-standard implementation of this method may ignore
    364      * the specified timeout. To see the connect timeout set, please
    365      * call getConnectTimeout().
    366      *
    367      * @param timeout an {@code int} that specifies the connect
    368      *               timeout value in milliseconds
    369      * @throws IllegalArgumentException if the timeout parameter is negative
    370      *
    371      * @see #getConnectTimeout()
    372      * @see #connect()
    373      * @since 1.5
    374      */
    375     public void setConnectTimeout(int timeout) {
    376         if (timeout < 0) {
    377             throw new IllegalArgumentException("timeout can not be negative");
    378         }
    379         connectTimeout = timeout;
    380     }
    381 
    382     /**
    383      * Returns setting for connect timeout.
    384      * <p>
    385      * 0 return implies that the option is disabled
    386      * (i.e., timeout of infinity).
    387      *
    388      * @return an {@code int} that indicates the connect timeout
    389      *         value in milliseconds
    390      * @see #setConnectTimeout(int)
    391      * @see #connect()
    392      * @since 1.5
    393      */
    394     public int getConnectTimeout() {
    395         return connectTimeout;
    396     }
    397 
    398     /**
    399      * Sets the read timeout to a specified timeout, in
    400      * milliseconds. A non-zero value specifies the timeout when
    401      * reading from Input stream when a connection is established to a
    402      * resource. If the timeout expires before there is data available
    403      * for read, a java.net.SocketTimeoutException is raised. A
    404      * timeout of zero is interpreted as an infinite timeout.
    405      *
    406      *<p> Some non-standard implementation of this method ignores the
    407      * specified timeout. To see the read timeout set, please call
    408      * getReadTimeout().
    409      *
    410      * @param timeout an {@code int} that specifies the timeout
    411      * value to be used in milliseconds
    412      * @throws IllegalArgumentException if the timeout parameter is negative
    413      *
    414      * @see #getReadTimeout()
    415      * @see InputStream#read()
    416      * @since 1.5
    417      */
    418     public void setReadTimeout(int timeout) {
    419         if (timeout < 0) {
    420             throw new IllegalArgumentException("timeout can not be negative");
    421         }
    422         readTimeout = timeout;
    423     }
    424 
    425     /**
    426      * Returns setting for read timeout. 0 return implies that the
    427      * option is disabled (i.e., timeout of infinity).
    428      *
    429      * @return an {@code int} that indicates the read timeout
    430      *         value in milliseconds
    431      *
    432      * @see #setReadTimeout(int)
    433      * @see InputStream#read()
    434      * @since 1.5
    435      */
    436     public int getReadTimeout() {
    437         return readTimeout;
    438     }
    439 
    440     /**
    441      * Constructs a URL connection to the specified URL. A connection to
    442      * the object referenced by the URL is not created.
    443      *
    444      * @param   url   the specified URL.
    445      */
    446     protected URLConnection(URL url) {
    447         this.url = url;
    448     }
    449 
    450     /**
    451      * Returns the value of this {@code URLConnection}'s {@code URL}
    452      * field.
    453      *
    454      * @return  the value of this {@code URLConnection}'s {@code URL}
    455      *          field.
    456      * @see     java.net.URLConnection#url
    457      */
    458     public URL getURL() {
    459         return url;
    460     }
    461 
    462     /**
    463      * Returns the value of the {@code content-length} header field.
    464      * <P>
    465      * <B>Note</B>: {@link #getContentLengthLong() getContentLengthLong()}
    466      * should be preferred over this method, since it returns a {@code long}
    467      * instead and is therefore more portable.</P>
    468      *
    469      * @return  the content length of the resource that this connection's URL
    470      *          references, {@code -1} if the content length is not known,
    471      *          or if the content length is greater than Integer.MAX_VALUE.
    472      */
    473     public int getContentLength() {
    474         long l = getContentLengthLong();
    475         if (l > Integer.MAX_VALUE)
    476             return -1;
    477         return (int) l;
    478     }
    479 
    480     /**
    481      * Returns the value of the {@code content-length} header field as a
    482      * long.
    483      *
    484      * @return  the content length of the resource that this connection's URL
    485      *          references, or {@code -1} if the content length is
    486      *          not known.
    487      * @since 7.0
    488      */
    489     public long getContentLengthLong() {
    490         return getHeaderFieldLong("content-length", -1);
    491     }
    492 
    493     /**
    494      * Returns the value of the {@code content-type} header field.
    495      *
    496      * @return  the content type of the resource that the URL references,
    497      *          or {@code null} if not known.
    498      * @see     java.net.URLConnection#getHeaderField(java.lang.String)
    499      */
    500     public String getContentType() {
    501         return getHeaderField("content-type");
    502     }
    503 
    504     /**
    505      * Returns the value of the {@code content-encoding} header field.
    506      *
    507      * @return  the content encoding of the resource that the URL references,
    508      *          or {@code null} if not known.
    509      * @see     java.net.URLConnection#getHeaderField(java.lang.String)
    510      */
    511     public String getContentEncoding() {
    512         return getHeaderField("content-encoding");
    513     }
    514 
    515     /**
    516      * Returns the value of the {@code expires} header field.
    517      *
    518      * @return  the expiration date of the resource that this URL references,
    519      *          or 0 if not known. The value is the number of milliseconds since
    520      *          January 1, 1970 GMT.
    521      * @see     java.net.URLConnection#getHeaderField(java.lang.String)
    522      */
    523     public long getExpiration() {
    524         return getHeaderFieldDate("expires", 0);
    525     }
    526 
    527     /**
    528      * Returns the value of the {@code date} header field.
    529      *
    530      * @return  the sending date of the resource that the URL references,
    531      *          or {@code 0} if not known. The value returned is the
    532      *          number of milliseconds since January 1, 1970 GMT.
    533      * @see     java.net.URLConnection#getHeaderField(java.lang.String)
    534      */
    535     public long getDate() {
    536         return getHeaderFieldDate("date", 0);
    537     }
    538 
    539     /**
    540      * Returns the value of the {@code last-modified} header field.
    541      * The result is the number of milliseconds since January 1, 1970 GMT.
    542      *
    543      * @return  the date the resource referenced by this
    544      *          {@code URLConnection} was last modified, or 0 if not known.
    545      * @see     java.net.URLConnection#getHeaderField(java.lang.String)
    546      */
    547     public long getLastModified() {
    548         return getHeaderFieldDate("last-modified", 0);
    549     }
    550 
    551     /**
    552      * Returns the value of the named header field.
    553      * <p>
    554      * If called on a connection that sets the same header multiple times
    555      * with possibly different values, only the last value is returned.
    556      *
    557      *
    558      * @param   name   the name of a header field.
    559      * @return  the value of the named header field, or {@code null}
    560      *          if there is no such field in the header.
    561      */
    562     public String getHeaderField(String name) {
    563         return null;
    564     }
    565 
    566     /**
    567      * Returns an unmodifiable Map of the header fields.
    568      * The Map keys are Strings that represent the
    569      * response-header field names. Each Map value is an
    570      * unmodifiable List of Strings that represents
    571      * the corresponding field values.
    572      *
    573      * @return a Map of header fields
    574      * @since 1.4
    575      */
    576     public Map<String,List<String>> getHeaderFields() {
    577         return Collections.emptyMap();
    578     }
    579 
    580     /**
    581      * Returns the value of the named field parsed as a number.
    582      * <p>
    583      * This form of {@code getHeaderField} exists because some
    584      * connection types (e.g., {@code http-ng}) have pre-parsed
    585      * headers. Classes for that connection type can override this method
    586      * and short-circuit the parsing.
    587      *
    588      * @param   name      the name of the header field.
    589      * @param   Default   the default value.
    590      * @return  the value of the named field, parsed as an integer. The
    591      *          {@code Default} value is returned if the field is
    592      *          missing or malformed.
    593      */
    594     public int getHeaderFieldInt(String name, int Default) {
    595         String value = getHeaderField(name);
    596         try {
    597             return Integer.parseInt(value);
    598         } catch (Exception e) { }
    599         return Default;
    600     }
    601 
    602     /**
    603      * Returns the value of the named field parsed as a number.
    604      * <p>
    605      * This form of {@code getHeaderField} exists because some
    606      * connection types (e.g., {@code http-ng}) have pre-parsed
    607      * headers. Classes for that connection type can override this method
    608      * and short-circuit the parsing.
    609      *
    610      * @param   name      the name of the header field.
    611      * @param   Default   the default value.
    612      * @return  the value of the named field, parsed as a long. The
    613      *          {@code Default} value is returned if the field is
    614      *          missing or malformed.
    615      * @since 7.0
    616      */
    617     public long getHeaderFieldLong(String name, long Default) {
    618         String value = getHeaderField(name);
    619         try {
    620             return Long.parseLong(value);
    621         } catch (Exception e) { }
    622         return Default;
    623     }
    624 
    625     /**
    626      * Returns the value of the named field parsed as date.
    627      * The result is the number of milliseconds since January 1, 1970 GMT
    628      * represented by the named field.
    629      * <p>
    630      * This form of {@code getHeaderField} exists because some
    631      * connection types (e.g., {@code http-ng}) have pre-parsed
    632      * headers. Classes for that connection type can override this method
    633      * and short-circuit the parsing.
    634      *
    635      * @param   name     the name of the header field.
    636      * @param   Default   a default value.
    637      * @return  the value of the field, parsed as a date. The value of the
    638      *          {@code Default} argument is returned if the field is
    639      *          missing or malformed.
    640      */
    641     @SuppressWarnings("deprecation")
    642     public long getHeaderFieldDate(String name, long Default) {
    643         String value = getHeaderField(name);
    644         try {
    645             return Date.parse(value);
    646         } catch (Exception e) { }
    647         return Default;
    648     }
    649 
    650     /**
    651      * Returns the key for the {@code n}<sup>th</sup> header field.
    652      * It returns {@code null} if there are fewer than {@code n+1} fields.
    653      *
    654      * @param   n   an index, where n>=0
    655      * @return  the key for the {@code n}<sup>th</sup> header field,
    656      *          or {@code null} if there are fewer than {@code n+1}
    657      *          fields.
    658      */
    659     public String getHeaderFieldKey(int n) {
    660         return null;
    661     }
    662 
    663     /**
    664      * Returns the value for the {@code n}<sup>th</sup> header field.
    665      * It returns {@code null} if there are fewer than
    666      * {@code n+1}fields.
    667      * <p>
    668      * This method can be used in conjunction with the
    669      * {@link #getHeaderFieldKey(int) getHeaderFieldKey} method to iterate through all
    670      * the headers in the message.
    671      *
    672      * @param   n   an index, where n>=0
    673      * @return  the value of the {@code n}<sup>th</sup> header field
    674      *          or {@code null} if there are fewer than {@code n+1} fields
    675      * @see     java.net.URLConnection#getHeaderFieldKey(int)
    676      */
    677     public String getHeaderField(int n) {
    678         return null;
    679     }
    680 
    681     /**
    682      * Retrieves the contents of this URL connection.
    683      * <p>
    684      * This method first determines the content type of the object by
    685      * calling the {@code getContentType} method. If this is
    686      * the first time that the application has seen that specific content
    687      * type, a content handler for that content type is created:
    688      * <ol>
    689      * <li>If the application has set up a content handler factory instance
    690      *     using the {@code setContentHandlerFactory} method, the
    691      *     {@code createContentHandler} method of that instance is called
    692      *     with the content type as an argument; the result is a content
    693      *     handler for that content type.
    694      * <li>If no content handler factory has yet been set up, or if the
    695      *     factory's {@code createContentHandler} method returns
    696      *     {@code null}, then the application loads the class named:
    697      *     <blockquote><pre>
    698      *         sun.net.www.content.&lt;<i>contentType</i>&gt;
    699      *     </pre></blockquote>
    700      *     where &lt;<i>contentType</i>&gt; is formed by taking the
    701      *     content-type string, replacing all slash characters with a
    702      *     {@code period} ('.'), and all other non-alphanumeric characters
    703      *     with the underscore character '{@code _}'. The alphanumeric
    704      *     characters are specifically the 26 uppercase ASCII letters
    705      *     '{@code A}' through '{@code Z}', the 26 lowercase ASCII
    706      *     letters '{@code a}' through '{@code z}', and the 10 ASCII
    707      *     digits '{@code 0}' through '{@code 9}'. If the specified
    708      *     class does not exist, or is not a subclass of
    709      *     {@code ContentHandler}, then an
    710      *     {@code UnknownServiceException} is thrown.
    711      * </ol>
    712      *
    713      * @return     the object fetched. The {@code instanceof} operator
    714      *               should be used to determine the specific kind of object
    715      *               returned.
    716      * @exception  IOException              if an I/O error occurs while
    717      *               getting the content.
    718      * @exception  UnknownServiceException  if the protocol does not support
    719      *               the content type.
    720      * @see        java.net.ContentHandlerFactory#createContentHandler(java.lang.String)
    721      * @see        java.net.URLConnection#getContentType()
    722      * @see        java.net.URLConnection#setContentHandlerFactory(java.net.ContentHandlerFactory)
    723      */
    724     public Object getContent() throws IOException {
    725         // Must call getInputStream before GetHeaderField gets called
    726         // so that FileNotFoundException has a chance to be thrown up
    727         // from here without being caught.
    728         getInputStream();
    729         return getContentHandler().getContent(this);
    730     }
    731 
    732     /**
    733      * Retrieves the contents of this URL connection.
    734      *
    735      * @param classes the {@code Class} array
    736      * indicating the requested types
    737      * @return     the object fetched that is the first match of the type
    738      *               specified in the classes array. null if none of
    739      *               the requested types are supported.
    740      *               The {@code instanceof} operator should be used to
    741      *               determine the specific kind of object returned.
    742      * @exception  IOException              if an I/O error occurs while
    743      *               getting the content.
    744      * @exception  UnknownServiceException  if the protocol does not support
    745      *               the content type.
    746      * @see        java.net.URLConnection#getContent()
    747      * @see        java.net.ContentHandlerFactory#createContentHandler(java.lang.String)
    748      * @see        java.net.URLConnection#getContent(java.lang.Class[])
    749      * @see        java.net.URLConnection#setContentHandlerFactory(java.net.ContentHandlerFactory)
    750      * @since 1.3
    751      */
    752     public Object getContent(Class[] classes) throws IOException {
    753         // Must call getInputStream before GetHeaderField gets called
    754         // so that FileNotFoundException has a chance to be thrown up
    755         // from here without being caught.
    756         getInputStream();
    757         return getContentHandler().getContent(this, classes);
    758     }
    759 
    760     /**
    761      * Returns a permission object representing the permission
    762      * necessary to make the connection represented by this
    763      * object. This method returns null if no permission is
    764      * required to make the connection. By default, this method
    765      * returns {@code java.security.AllPermission}. Subclasses
    766      * should override this method and return the permission
    767      * that best represents the permission required to make a
    768      * a connection to the URL. For example, a {@code URLConnection}
    769      * representing a {@code file:} URL would return a
    770      * {@code java.io.FilePermission} object.
    771      *
    772      * <p>The permission returned may dependent upon the state of the
    773      * connection. For example, the permission before connecting may be
    774      * different from that after connecting. For example, an HTTP
    775      * sever, say foo.com, may redirect the connection to a different
    776      * host, say bar.com. Before connecting the permission returned by
    777      * the connection will represent the permission needed to connect
    778      * to foo.com, while the permission returned after connecting will
    779      * be to bar.com.
    780      *
    781      * <p>Permissions are generally used for two purposes: to protect
    782      * caches of objects obtained through URLConnections, and to check
    783      * the right of a recipient to learn about a particular URL. In
    784      * the first case, the permission should be obtained
    785      * <em>after</em> the object has been obtained. For example, in an
    786      * HTTP connection, this will represent the permission to connect
    787      * to the host from which the data was ultimately fetched. In the
    788      * second case, the permission should be obtained and tested
    789      * <em>before</em> connecting.
    790      *
    791      * @return the permission object representing the permission
    792      * necessary to make the connection represented by this
    793      * URLConnection.
    794      *
    795      * @exception IOException if the computation of the permission
    796      * requires network or file I/O and an exception occurs while
    797      * computing it.
    798      */
    799     public Permission getPermission() throws IOException {
    800         return SecurityConstants.ALL_PERMISSION;
    801     }
    802 
    803     /**
    804      * Returns an input stream that reads from this open connection.
    805      *
    806      * A SocketTimeoutException can be thrown when reading from the
    807      * returned input stream if the read timeout expires before data
    808      * is available for read.
    809      *
    810      * @return     an input stream that reads from this open connection.
    811      * @exception  IOException              if an I/O error occurs while
    812      *               creating the input stream.
    813      * @exception  UnknownServiceException  if the protocol does not support
    814      *               input.
    815      * @see #setReadTimeout(int)
    816      * @see #getReadTimeout()
    817      */
    818     public InputStream getInputStream() throws IOException {
    819         throw new UnknownServiceException("protocol doesn't support input");
    820     }
    821 
    822     /**
    823      * Returns an output stream that writes to this connection.
    824      *
    825      * @return     an output stream that writes to this connection.
    826      * @exception  IOException              if an I/O error occurs while
    827      *               creating the output stream.
    828      * @exception  UnknownServiceException  if the protocol does not support
    829      *               output.
    830      */
    831     public OutputStream getOutputStream() throws IOException {
    832         throw new UnknownServiceException("protocol doesn't support output");
    833     }
    834 
    835     /**
    836      * Returns a {@code String} representation of this URL connection.
    837      *
    838      * @return  a string representation of this {@code URLConnection}.
    839      */
    840     public String toString() {
    841         return this.getClass().getName() + ":" + url;
    842     }
    843 
    844     /**
    845      * Sets the value of the {@code doInput} field for this
    846      * {@code URLConnection} to the specified value.
    847      * <p>
    848      * A URL connection can be used for input and/or output.  Set the DoInput
    849      * flag to true if you intend to use the URL connection for input,
    850      * false if not.  The default is true.
    851      *
    852      * @param   doinput   the new value.
    853      * @throws IllegalStateException if already connected
    854      * @see     java.net.URLConnection#doInput
    855      * @see #getDoInput()
    856      */
    857     public void setDoInput(boolean doinput) {
    858         if (connected)
    859             throw new IllegalStateException("Already connected");
    860         doInput = doinput;
    861     }
    862 
    863     /**
    864      * Returns the value of this {@code URLConnection}'s
    865      * {@code doInput} flag.
    866      *
    867      * @return  the value of this {@code URLConnection}'s
    868      *          {@code doInput} flag.
    869      * @see     #setDoInput(boolean)
    870      */
    871     public boolean getDoInput() {
    872         return doInput;
    873     }
    874 
    875     /**
    876      * Sets the value of the {@code doOutput} field for this
    877      * {@code URLConnection} to the specified value.
    878      * <p>
    879      * A URL connection can be used for input and/or output.  Set the DoOutput
    880      * flag to true if you intend to use the URL connection for output,
    881      * false if not.  The default is false.
    882      *
    883      * @param   dooutput   the new value.
    884      * @throws IllegalStateException if already connected
    885      * @see #getDoOutput()
    886      */
    887     public void setDoOutput(boolean dooutput) {
    888         if (connected)
    889             throw new IllegalStateException("Already connected");
    890         doOutput = dooutput;
    891     }
    892 
    893     /**
    894      * Returns the value of this {@code URLConnection}'s
    895      * {@code doOutput} flag.
    896      *
    897      * @return  the value of this {@code URLConnection}'s
    898      *          {@code doOutput} flag.
    899      * @see     #setDoOutput(boolean)
    900      */
    901     public boolean getDoOutput() {
    902         return doOutput;
    903     }
    904 
    905     /**
    906      * Set the value of the {@code allowUserInteraction} field of
    907      * this {@code URLConnection}.
    908      *
    909      * @param   allowuserinteraction   the new value.
    910      * @throws IllegalStateException if already connected
    911      * @see     #getAllowUserInteraction()
    912      */
    913     public void setAllowUserInteraction(boolean allowuserinteraction) {
    914         if (connected)
    915             throw new IllegalStateException("Already connected");
    916         allowUserInteraction = allowuserinteraction;
    917     }
    918 
    919     /**
    920      * Returns the value of the {@code allowUserInteraction} field for
    921      * this object.
    922      *
    923      * @return  the value of the {@code allowUserInteraction} field for
    924      *          this object.
    925      * @see     #setAllowUserInteraction(boolean)
    926      */
    927     public boolean getAllowUserInteraction() {
    928         return allowUserInteraction;
    929     }
    930 
    931     /**
    932      * Sets the default value of the
    933      * {@code allowUserInteraction} field for all future
    934      * {@code URLConnection} objects to the specified value.
    935      *
    936      * @param   defaultallowuserinteraction   the new value.
    937      * @see     #getDefaultAllowUserInteraction()
    938      */
    939     public static void setDefaultAllowUserInteraction(boolean defaultallowuserinteraction) {
    940         defaultAllowUserInteraction = defaultallowuserinteraction;
    941     }
    942 
    943     /**
    944      * Returns the default value of the {@code allowUserInteraction}
    945      * field.
    946      * <p>
    947      * Ths default is "sticky", being a part of the static state of all
    948      * URLConnections.  This flag applies to the next, and all following
    949      * URLConnections that are created.
    950      *
    951      * @return  the default value of the {@code allowUserInteraction}
    952      *          field.
    953      * @see     #setDefaultAllowUserInteraction(boolean)
    954      */
    955     public static boolean getDefaultAllowUserInteraction() {
    956         return defaultAllowUserInteraction;
    957     }
    958 
    959     /**
    960      * Sets the value of the {@code useCaches} field of this
    961      * {@code URLConnection} to the specified value.
    962      * <p>
    963      * Some protocols do caching of documents.  Occasionally, it is important
    964      * to be able to "tunnel through" and ignore the caches (e.g., the
    965      * "reload" button in a browser).  If the UseCaches flag on a connection
    966      * is true, the connection is allowed to use whatever caches it can.
    967      *  If false, caches are to be ignored.
    968      *  The default value comes from DefaultUseCaches, which defaults to
    969      * true.
    970      *
    971      * @param usecaches a {@code boolean} indicating whether
    972      * or not to allow caching
    973      * @throws IllegalStateException if already connected
    974      * @see #getUseCaches()
    975      */
    976     public void setUseCaches(boolean usecaches) {
    977         if (connected)
    978             throw new IllegalStateException("Already connected");
    979         useCaches = usecaches;
    980     }
    981 
    982     /**
    983      * Returns the value of this {@code URLConnection}'s
    984      * {@code useCaches} field.
    985      *
    986      * @return  the value of this {@code URLConnection}'s
    987      *          {@code useCaches} field.
    988      * @see #setUseCaches(boolean)
    989      */
    990     public boolean getUseCaches() {
    991         return useCaches;
    992     }
    993 
    994     /**
    995      * Sets the value of the {@code ifModifiedSince} field of
    996      * this {@code URLConnection} to the specified value.
    997      *
    998      * @param   ifmodifiedsince   the new value.
    999      * @throws IllegalStateException if already connected
   1000      * @see     #getIfModifiedSince()
   1001      */
   1002     public void setIfModifiedSince(long ifmodifiedsince) {
   1003         if (connected)
   1004             throw new IllegalStateException("Already connected");
   1005         ifModifiedSince = ifmodifiedsince;
   1006     }
   1007 
   1008     /**
   1009      * Returns the value of this object's {@code ifModifiedSince} field.
   1010      *
   1011      * @return  the value of this object's {@code ifModifiedSince} field.
   1012      * @see #setIfModifiedSince(long)
   1013      */
   1014     public long getIfModifiedSince() {
   1015         return ifModifiedSince;
   1016     }
   1017 
   1018    /**
   1019      * Returns the default value of a {@code URLConnection}'s
   1020      * {@code useCaches} flag.
   1021      * <p>
   1022      * Ths default is "sticky", being a part of the static state of all
   1023      * URLConnections.  This flag applies to the next, and all following
   1024      * URLConnections that are created.
   1025      *
   1026      * @return  the default value of a {@code URLConnection}'s
   1027      *          {@code useCaches} flag.
   1028      * @see     #setDefaultUseCaches(boolean)
   1029      */
   1030     public boolean getDefaultUseCaches() {
   1031         return defaultUseCaches;
   1032     }
   1033 
   1034    /**
   1035      * Sets the default value of the {@code useCaches} field to the
   1036      * specified value.
   1037      *
   1038      * @param   defaultusecaches   the new value.
   1039      * @see     #getDefaultUseCaches()
   1040      */
   1041     public void setDefaultUseCaches(boolean defaultusecaches) {
   1042         defaultUseCaches = defaultusecaches;
   1043     }
   1044 
   1045     /**
   1046      * Sets the general request property. If a property with the key already
   1047      * exists, overwrite its value with the new value.
   1048      *
   1049      * <p> NOTE: HTTP requires all request properties which can
   1050      * legally have multiple instances with the same key
   1051      * to use a comma-separated list syntax which enables multiple
   1052      * properties to be appended into a single property.
   1053      *
   1054      * @param   key     the keyword by which the request is known
   1055      *                  (e.g., "{@code Accept}").
   1056      * @param   value   the value associated with it.
   1057      * @throws IllegalStateException if already connected
   1058      * @throws NullPointerException if key is <CODE>null</CODE>
   1059      * @see #getRequestProperty(java.lang.String)
   1060      */
   1061     public void setRequestProperty(String key, String value) {
   1062         if (connected)
   1063             throw new IllegalStateException("Already connected");
   1064         if (key == null)
   1065             throw new NullPointerException ("key is null");
   1066 
   1067         if (requests == null)
   1068             requests = new MessageHeader();
   1069 
   1070         requests.set(key, value);
   1071     }
   1072 
   1073     /**
   1074      * Adds a general request property specified by a
   1075      * key-value pair.  This method will not overwrite
   1076      * existing values associated with the same key.
   1077      *
   1078      * @param   key     the keyword by which the request is known
   1079      *                  (e.g., "{@code Accept}").
   1080      * @param   value  the value associated with it.
   1081      * @throws IllegalStateException if already connected
   1082      * @throws NullPointerException if key is null
   1083      * @see #getRequestProperties()
   1084      * @since 1.4
   1085      */
   1086     public void addRequestProperty(String key, String value) {
   1087         if (connected)
   1088             throw new IllegalStateException("Already connected");
   1089         if (key == null)
   1090             throw new NullPointerException ("key is null");
   1091 
   1092         if (requests == null)
   1093             requests = new MessageHeader();
   1094 
   1095         requests.add(key, value);
   1096     }
   1097 
   1098 
   1099     /**
   1100      * Returns the value of the named general request property for this
   1101      * connection.
   1102      *
   1103      * @param key the keyword by which the request is known (e.g., "Accept").
   1104      * @return  the value of the named general request property for this
   1105      *           connection. If key is null, then null is returned.
   1106      * @throws IllegalStateException if already connected
   1107      * @see #setRequestProperty(java.lang.String, java.lang.String)
   1108      */
   1109     public String getRequestProperty(String key) {
   1110         if (connected)
   1111             throw new IllegalStateException("Already connected");
   1112 
   1113         if (requests == null)
   1114             return null;
   1115 
   1116         return requests.findValue(key);
   1117     }
   1118 
   1119     /**
   1120      * Returns an unmodifiable Map of general request
   1121      * properties for this connection. The Map keys
   1122      * are Strings that represent the request-header
   1123      * field names. Each Map value is a unmodifiable List
   1124      * of Strings that represents the corresponding
   1125      * field values.
   1126      *
   1127      * @return  a Map of the general request properties for this connection.
   1128      * @throws IllegalStateException if already connected
   1129      * @since 1.4
   1130      */
   1131     public Map<String,List<String>> getRequestProperties() {
   1132         if (connected)
   1133             throw new IllegalStateException("Already connected");
   1134 
   1135         if (requests == null)
   1136             return Collections.emptyMap();
   1137 
   1138         return requests.getHeaders(null);
   1139     }
   1140 
   1141     /**
   1142      * Sets the default value of a general request property. When a
   1143      * {@code URLConnection} is created, it is initialized with
   1144      * these properties.
   1145      *
   1146      * @param   key     the keyword by which the request is known
   1147      *                  (e.g., "{@code Accept}").
   1148      * @param   value   the value associated with the key.
   1149      *
   1150      * @see java.net.URLConnection#setRequestProperty(java.lang.String,java.lang.String)
   1151      *
   1152      * @deprecated The instance specific setRequestProperty method
   1153      * should be used after an appropriate instance of URLConnection
   1154      * is obtained. Invoking this method will have no effect.
   1155      *
   1156      * @see #getDefaultRequestProperty(java.lang.String)
   1157      */
   1158     @Deprecated
   1159     public static void setDefaultRequestProperty(String key, String value) {
   1160     }
   1161 
   1162     /**
   1163      * Returns the value of the default request property. Default request
   1164      * properties are set for every connection.
   1165      *
   1166      * @param key the keyword by which the request is known (e.g., "Accept").
   1167      * @return  the value of the default request property
   1168      * for the specified key.
   1169      *
   1170      * @see java.net.URLConnection#getRequestProperty(java.lang.String)
   1171      *
   1172      * @deprecated The instance specific getRequestProperty method
   1173      * should be used after an appropriate instance of URLConnection
   1174      * is obtained.
   1175      *
   1176      * @see #setDefaultRequestProperty(java.lang.String, java.lang.String)
   1177      */
   1178     @Deprecated
   1179     public static String getDefaultRequestProperty(String key) {
   1180         return null;
   1181     }
   1182 
   1183     /**
   1184      * The ContentHandler factory.
   1185      */
   1186     static ContentHandlerFactory factory;
   1187 
   1188     /**
   1189      * Sets the {@code ContentHandlerFactory} of an
   1190      * application. It can be called at most once by an application.
   1191      * <p>
   1192      * The {@code ContentHandlerFactory} instance is used to
   1193      * construct a content handler from a content type
   1194      * <p>
   1195      * If there is a security manager, this method first calls
   1196      * the security manager's {@code checkSetFactory} method
   1197      * to ensure the operation is allowed.
   1198      * This could result in a SecurityException.
   1199      *
   1200      * @param      fac   the desired factory.
   1201      * @exception  Error  if the factory has already been defined.
   1202      * @exception  SecurityException  if a security manager exists and its
   1203      *             {@code checkSetFactory} method doesn't allow the operation.
   1204      * @see        java.net.ContentHandlerFactory
   1205      * @see        java.net.URLConnection#getContent()
   1206      * @see        SecurityManager#checkSetFactory
   1207      */
   1208     public static synchronized void setContentHandlerFactory(ContentHandlerFactory fac) {
   1209         if (factory != null) {
   1210             throw new Error("factory already defined");
   1211         }
   1212         SecurityManager security = System.getSecurityManager();
   1213         if (security != null) {
   1214             security.checkSetFactory();
   1215         }
   1216         factory = fac;
   1217     }
   1218 
   1219     private static Hashtable<String, ContentHandler> handlers = new Hashtable<>();
   1220 
   1221     /**
   1222      * Gets the Content Handler appropriate for this connection.
   1223      */
   1224     synchronized ContentHandler getContentHandler()
   1225         throws IOException
   1226     {
   1227         String contentType = stripOffParameters(getContentType());
   1228         ContentHandler handler = null;
   1229         if (contentType == null) {
   1230             if ((contentType = guessContentTypeFromName(url.getFile())) == null) {
   1231                 contentType = guessContentTypeFromStream(getInputStream());
   1232             }
   1233         }
   1234 
   1235         if (contentType == null) {
   1236             return UnknownContentHandler.INSTANCE;
   1237         }
   1238         try {
   1239             handler = handlers.get(contentType);
   1240             if (handler != null)
   1241                 return handler;
   1242         } catch(Exception e) {
   1243         }
   1244 
   1245         if (factory != null)
   1246             handler = factory.createContentHandler(contentType);
   1247         if (handler == null) {
   1248             try {
   1249                 handler = lookupContentHandlerClassFor(contentType);
   1250             } catch(Exception e) {
   1251                 e.printStackTrace();
   1252                 handler = UnknownContentHandler.INSTANCE;
   1253             }
   1254             handlers.put(contentType, handler);
   1255         }
   1256         return handler;
   1257     }
   1258 
   1259     /*
   1260      * Media types are in the format: type/subtype*(; parameter).
   1261      * For looking up the content handler, we should ignore those
   1262      * parameters.
   1263      */
   1264     private String stripOffParameters(String contentType)
   1265     {
   1266         if (contentType == null)
   1267             return null;
   1268         int index = contentType.indexOf(';');
   1269 
   1270         if (index > 0)
   1271             return contentType.substring(0, index);
   1272         else
   1273             return contentType;
   1274     }
   1275 
   1276     private static final String contentClassPrefix = "sun.net.www.content";
   1277     private static final String contentPathProp = "java.content.handler.pkgs";
   1278 
   1279     /**
   1280      * Looks for a content handler in a user-defineable set of places.
   1281      * By default it looks in sun.net.www.content, but users can define a
   1282      * vertical-bar delimited set of class prefixes to search through in
   1283      * addition by defining the java.content.handler.pkgs property.
   1284      * The class name must be of the form:
   1285      * <pre>
   1286      *     {package-prefix}.{major}.{minor}
   1287      * e.g.
   1288      *     YoyoDyne.experimental.text.plain
   1289      * </pre>
   1290      */
   1291     private ContentHandler lookupContentHandlerClassFor(String contentType)
   1292         throws InstantiationException, IllegalAccessException, ClassNotFoundException {
   1293         String contentHandlerClassName = typeToPackageName(contentType);
   1294 
   1295         String contentHandlerPkgPrefixes =getContentHandlerPkgPrefixes();
   1296 
   1297         StringTokenizer packagePrefixIter =
   1298             new StringTokenizer(contentHandlerPkgPrefixes, "|");
   1299 
   1300         while (packagePrefixIter.hasMoreTokens()) {
   1301             String packagePrefix = packagePrefixIter.nextToken().trim();
   1302 
   1303             try {
   1304                 String clsName = packagePrefix + "." + contentHandlerClassName;
   1305                 Class<?> cls = null;
   1306                 try {
   1307                     cls = Class.forName(clsName);
   1308                 } catch (ClassNotFoundException e) {
   1309                     ClassLoader cl = ClassLoader.getSystemClassLoader();
   1310                     if (cl != null) {
   1311                         cls = cl.loadClass(clsName);
   1312                     }
   1313                 }
   1314                 if (cls != null) {
   1315                     ContentHandler handler =
   1316                         (ContentHandler)cls.newInstance();
   1317                     return handler;
   1318                 }
   1319             } catch(Exception e) {
   1320             }
   1321         }
   1322 
   1323         return UnknownContentHandler.INSTANCE;
   1324     }
   1325 
   1326     /**
   1327      * Utility function to map a MIME content type into an equivalent
   1328      * pair of class name components.  For example: "text/html" would
   1329      * be returned as "text.html"
   1330      */
   1331     private String typeToPackageName(String contentType) {
   1332         // make sure we canonicalize the class name: all lower case
   1333         contentType = contentType.toLowerCase();
   1334         int len = contentType.length();
   1335         char nm[] = new char[len];
   1336         contentType.getChars(0, len, nm, 0);
   1337         for (int i = 0; i < len; i++) {
   1338             char c = nm[i];
   1339             if (c == '/') {
   1340                 nm[i] = '.';
   1341             } else if (!('A' <= c && c <= 'Z' ||
   1342                        'a' <= c && c <= 'z' ||
   1343                        '0' <= c && c <= '9')) {
   1344                 nm[i] = '_';
   1345             }
   1346         }
   1347         return new String(nm);
   1348     }
   1349 
   1350 
   1351     /**
   1352      * Returns a vertical bar separated list of package prefixes for potential
   1353      * content handlers.  Tries to get the java.content.handler.pkgs property
   1354      * to use as a set of package prefixes to search.  Whether or not
   1355      * that property has been defined, the sun.net.www.content is always
   1356      * the last one on the returned package list.
   1357      */
   1358     private String getContentHandlerPkgPrefixes() {
   1359         String packagePrefixList = AccessController.doPrivileged(
   1360             new sun.security.action.GetPropertyAction(contentPathProp, ""));
   1361 
   1362         if (packagePrefixList != "") {
   1363             packagePrefixList += "|";
   1364         }
   1365 
   1366         return packagePrefixList + contentClassPrefix;
   1367     }
   1368 
   1369     /**
   1370      * Tries to determine the content type of an object, based
   1371      * on the specified "file" component of a URL.
   1372      * This is a convenience method that can be used by
   1373      * subclasses that override the {@code getContentType} method.
   1374      *
   1375      * @param   fname   a filename.
   1376      * @return  a guess as to what the content type of the object is,
   1377      *          based upon its file name.
   1378      * @see     java.net.URLConnection#getContentType()
   1379      */
   1380     public static String guessContentTypeFromName(String fname) {
   1381         return getFileNameMap().getContentTypeFor(fname);
   1382     }
   1383 
   1384     /**
   1385      * Tries to determine the type of an input stream based on the
   1386      * characters at the beginning of the input stream. This method can
   1387      * be used by subclasses that override the
   1388      * {@code getContentType} method.
   1389      * <p>
   1390      * Ideally, this routine would not be needed. But many
   1391      * {@code http} servers return the incorrect content type; in
   1392      * addition, there are many nonstandard extensions. Direct inspection
   1393      * of the bytes to determine the content type is often more accurate
   1394      * than believing the content type claimed by the {@code http} server.
   1395      *
   1396      * @param      is   an input stream that supports marks.
   1397      * @return     a guess at the content type, or {@code null} if none
   1398      *             can be determined.
   1399      * @exception  IOException  if an I/O error occurs while reading the
   1400      *               input stream.
   1401      * @see        java.io.InputStream#mark(int)
   1402      * @see        java.io.InputStream#markSupported()
   1403      * @see        java.net.URLConnection#getContentType()
   1404      */
   1405     static public String guessContentTypeFromStream(InputStream is)
   1406                         throws IOException {
   1407         // If we can't read ahead safely, just give up on guessing
   1408         if (!is.markSupported())
   1409             return null;
   1410 
   1411         is.mark(16);
   1412         int c1 = is.read();
   1413         int c2 = is.read();
   1414         int c3 = is.read();
   1415         int c4 = is.read();
   1416         int c5 = is.read();
   1417         int c6 = is.read();
   1418         int c7 = is.read();
   1419         int c8 = is.read();
   1420         int c9 = is.read();
   1421         int c10 = is.read();
   1422         int c11 = is.read();
   1423         int c12 = is.read();
   1424         int c13 = is.read();
   1425         int c14 = is.read();
   1426         int c15 = is.read();
   1427         int c16 = is.read();
   1428         is.reset();
   1429 
   1430         if (c1 == 0xCA && c2 == 0xFE && c3 == 0xBA && c4 == 0xBE) {
   1431             return "application/java-vm";
   1432         }
   1433 
   1434         if (c1 == 0xAC && c2 == 0xED) {
   1435             // next two bytes are version number, currently 0x00 0x05
   1436             return "application/x-java-serialized-object";
   1437         }
   1438 
   1439         if (c1 == '<') {
   1440             if (c2 == '!'
   1441                 || ((c2 == 'h' && (c3 == 't' && c4 == 'm' && c5 == 'l' ||
   1442                                    c3 == 'e' && c4 == 'a' && c5 == 'd') ||
   1443                 (c2 == 'b' && c3 == 'o' && c4 == 'd' && c5 == 'y'))) ||
   1444                 ((c2 == 'H' && (c3 == 'T' && c4 == 'M' && c5 == 'L' ||
   1445                                 c3 == 'E' && c4 == 'A' && c5 == 'D') ||
   1446                 (c2 == 'B' && c3 == 'O' && c4 == 'D' && c5 == 'Y')))) {
   1447                 return "text/html";
   1448             }
   1449 
   1450             if (c2 == '?' && c3 == 'x' && c4 == 'm' && c5 == 'l' && c6 == ' ') {
   1451                 return "application/xml";
   1452             }
   1453         }
   1454 
   1455         // big and little (identical) endian UTF-8 encodings, with BOM
   1456         if (c1 == 0xef &&  c2 == 0xbb &&  c3 == 0xbf) {
   1457             if (c4 == '<' &&  c5 == '?' &&  c6 == 'x') {
   1458                 return "application/xml";
   1459             }
   1460         }
   1461 
   1462         // big and little endian UTF-16 encodings, with byte order mark
   1463         if (c1 == 0xfe && c2 == 0xff) {
   1464             if (c3 == 0 && c4 == '<' && c5 == 0 && c6 == '?' &&
   1465                 c7 == 0 && c8 == 'x') {
   1466                 return "application/xml";
   1467             }
   1468         }
   1469 
   1470         if (c1 == 0xff && c2 == 0xfe) {
   1471             if (c3 == '<' && c4 == 0 && c5 == '?' && c6 == 0 &&
   1472                 c7 == 'x' && c8 == 0) {
   1473                 return "application/xml";
   1474             }
   1475         }
   1476 
   1477         // big and little endian UTF-32 encodings, with BOM
   1478         if (c1 == 0x00 &&  c2 == 0x00 &&  c3 == 0xfe &&  c4 == 0xff) {
   1479             if (c5  == 0 && c6  == 0 && c7  == 0 && c8  == '<' &&
   1480                 c9  == 0 && c10 == 0 && c11 == 0 && c12 == '?' &&
   1481                 c13 == 0 && c14 == 0 && c15 == 0 && c16 == 'x') {
   1482                 return "application/xml";
   1483             }
   1484         }
   1485 
   1486         if (c1 == 0xff &&  c2 == 0xfe &&  c3 == 0x00 &&  c4 == 0x00) {
   1487             if (c5  == '<' && c6  == 0 && c7  == 0 && c8  == 0 &&
   1488                 c9  == '?' && c10 == 0 && c11 == 0 && c12 == 0 &&
   1489                 c13 == 'x' && c14 == 0 && c15 == 0 && c16 == 0) {
   1490                 return "application/xml";
   1491             }
   1492         }
   1493 
   1494         if (c1 == 'G' && c2 == 'I' && c3 == 'F' && c4 == '8') {
   1495             return "image/gif";
   1496         }
   1497 
   1498         if (c1 == '#' && c2 == 'd' && c3 == 'e' && c4 == 'f') {
   1499             return "image/x-bitmap";
   1500         }
   1501 
   1502         if (c1 == '!' && c2 == ' ' && c3 == 'X' && c4 == 'P' &&
   1503                         c5 == 'M' && c6 == '2') {
   1504             return "image/x-pixmap";
   1505         }
   1506 
   1507         if (c1 == 137 && c2 == 80 && c3 == 78 &&
   1508                 c4 == 71 && c5 == 13 && c6 == 10 &&
   1509                 c7 == 26 && c8 == 10) {
   1510             return "image/png";
   1511         }
   1512 
   1513         if (c1 == 0xFF && c2 == 0xD8 && c3 == 0xFF) {
   1514             if (c4 == 0xE0 || c4 == 0xEE) {
   1515                 return "image/jpeg";
   1516             }
   1517 
   1518             /**
   1519              * File format used by digital cameras to store images.
   1520              * Exif Format can be read by any application supporting
   1521              * JPEG. Exif Spec can be found at:
   1522              * http://www.pima.net/standards/it10/PIMA15740/Exif_2-1.PDF
   1523              */
   1524             if ((c4 == 0xE1) &&
   1525                 (c7 == 'E' && c8 == 'x' && c9 == 'i' && c10 =='f' &&
   1526                  c11 == 0)) {
   1527                 return "image/jpeg";
   1528             }
   1529         }
   1530 
   1531         if (c1 == 0xD0 && c2 == 0xCF && c3 == 0x11 && c4 == 0xE0 &&
   1532             c5 == 0xA1 && c6 == 0xB1 && c7 == 0x1A && c8 == 0xE1) {
   1533 
   1534             /* Above is signature of Microsoft Structured Storage.
   1535              * Below this, could have tests for various SS entities.
   1536              * For now, just test for FlashPix.
   1537              */
   1538             if (checkfpx(is)) {
   1539                 return "image/vnd.fpx";
   1540             }
   1541         }
   1542 
   1543         if (c1 == 0x2E && c2 == 0x73 && c3 == 0x6E && c4 == 0x64) {
   1544             return "audio/basic";  // .au format, big endian
   1545         }
   1546 
   1547         if (c1 == 0x64 && c2 == 0x6E && c3 == 0x73 && c4 == 0x2E) {
   1548             return "audio/basic";  // .au format, little endian
   1549         }
   1550 
   1551         if (c1 == 'R' && c2 == 'I' && c3 == 'F' && c4 == 'F') {
   1552             /* I don't know if this is official but evidence
   1553              * suggests that .wav files start with "RIFF" - brown
   1554              */
   1555             return "audio/x-wav";
   1556         }
   1557         return null;
   1558     }
   1559 
   1560     /**
   1561      * Check for FlashPix image data in InputStream is.  Return true if
   1562      * the stream has FlashPix data, false otherwise.  Before calling this
   1563      * method, the stream should have already been checked to be sure it
   1564      * contains Microsoft Structured Storage data.
   1565      */
   1566     static private boolean checkfpx(InputStream is) throws IOException {
   1567 
   1568         /* Test for FlashPix image data in Microsoft Structured Storage format.
   1569          * In general, should do this with calls to an SS implementation.
   1570          * Lacking that, need to dig via offsets to get to the FlashPix
   1571          * ClassID.  Details:
   1572          *
   1573          * Offset to Fpx ClsID from beginning of stream should be:
   1574          *
   1575          * FpxClsidOffset = rootEntryOffset + clsidOffset
   1576          *
   1577          * where: clsidOffset = 0x50.
   1578          *        rootEntryOffset = headerSize + sectorSize*sectDirStart
   1579          *                          + 128*rootEntryDirectory
   1580          *
   1581          *        where:  headerSize = 0x200 (always)
   1582          *                sectorSize = 2 raised to power of uSectorShift,
   1583          *                             which is found in the header at
   1584          *                             offset 0x1E.
   1585          *                sectDirStart = found in the header at offset 0x30.
   1586          *                rootEntryDirectory = in general, should search for
   1587          *                                     directory labelled as root.
   1588          *                                     We will assume value of 0 (i.e.,
   1589          *                                     rootEntry is in first directory)
   1590          */
   1591 
   1592         // Mark the stream so we can reset it. 0x100 is enough for the first
   1593         // few reads, but the mark will have to be reset and set again once
   1594         // the offset to the root directory entry is computed. That offset
   1595         // can be very large and isn't know until the stream has been read from
   1596         is.mark(0x100);
   1597 
   1598         // Get the byte ordering located at 0x1E. 0xFE is Intel,
   1599         // 0xFF is other
   1600         long toSkip = (long)0x1C;
   1601         long posn;
   1602 
   1603         if ((posn = skipForward(is, toSkip)) < toSkip) {
   1604           is.reset();
   1605           return false;
   1606         }
   1607 
   1608         int c[] = new int[16];
   1609         if (readBytes(c, 2, is) < 0) {
   1610             is.reset();
   1611             return false;
   1612         }
   1613 
   1614         int byteOrder = c[0];
   1615 
   1616         posn+=2;
   1617         int uSectorShift;
   1618         if (readBytes(c, 2, is) < 0) {
   1619             is.reset();
   1620             return false;
   1621         }
   1622 
   1623         if(byteOrder == 0xFE) {
   1624             uSectorShift = c[0];
   1625             uSectorShift += c[1] << 8;
   1626         }
   1627         else {
   1628             uSectorShift = c[0] << 8;
   1629             uSectorShift += c[1];
   1630         }
   1631 
   1632         posn += 2;
   1633         toSkip = (long)0x30 - posn;
   1634         long skipped = 0;
   1635         if ((skipped = skipForward(is, toSkip)) < toSkip) {
   1636           is.reset();
   1637           return false;
   1638         }
   1639         posn += skipped;
   1640 
   1641         if (readBytes(c, 4, is) < 0) {
   1642             is.reset();
   1643             return false;
   1644         }
   1645 
   1646         int sectDirStart;
   1647         if(byteOrder == 0xFE) {
   1648             sectDirStart = c[0];
   1649             sectDirStart += c[1] << 8;
   1650             sectDirStart += c[2] << 16;
   1651             sectDirStart += c[3] << 24;
   1652         } else {
   1653             sectDirStart =  c[0] << 24;
   1654             sectDirStart += c[1] << 16;
   1655             sectDirStart += c[2] << 8;
   1656             sectDirStart += c[3];
   1657         }
   1658         posn += 4;
   1659         is.reset(); // Reset back to the beginning
   1660 
   1661         toSkip = 0x200L + (long)(1<<uSectorShift)*sectDirStart + 0x50L;
   1662 
   1663         // Sanity check!
   1664         if (toSkip < 0) {
   1665             return false;
   1666         }
   1667 
   1668         /*
   1669          * How far can we skip? Is there any performance problem here?
   1670          * This skip can be fairly long, at least 0x4c650 in at least
   1671          * one case. Have to assume that the skip will fit in an int.
   1672          * Leave room to read whole root dir
   1673          */
   1674         is.mark((int)toSkip+0x30);
   1675 
   1676         if ((skipForward(is, toSkip)) < toSkip) {
   1677             is.reset();
   1678             return false;
   1679         }
   1680 
   1681         /* should be at beginning of ClassID, which is as follows
   1682          * (in Intel byte order):
   1683          *    00 67 61 56 54 C1 CE 11 85 53 00 AA 00 A1 F9 5B
   1684          *
   1685          * This is stored from Windows as long,short,short,char[8]
   1686          * so for byte order changes, the order only changes for
   1687          * the first 8 bytes in the ClassID.
   1688          *
   1689          * Test against this, ignoring second byte (Intel) since
   1690          * this could change depending on part of Fpx file we have.
   1691          */
   1692 
   1693         if (readBytes(c, 16, is) < 0) {
   1694             is.reset();
   1695             return false;
   1696         }
   1697 
   1698         // intel byte order
   1699         if (byteOrder == 0xFE &&
   1700             c[0] == 0x00 && c[2] == 0x61 && c[3] == 0x56 &&
   1701             c[4] == 0x54 && c[5] == 0xC1 && c[6] == 0xCE &&
   1702             c[7] == 0x11 && c[8] == 0x85 && c[9] == 0x53 &&
   1703             c[10]== 0x00 && c[11]== 0xAA && c[12]== 0x00 &&
   1704             c[13]== 0xA1 && c[14]== 0xF9 && c[15]== 0x5B) {
   1705             is.reset();
   1706             return true;
   1707         }
   1708 
   1709         // non-intel byte order
   1710         else if (c[3] == 0x00 && c[1] == 0x61 && c[0] == 0x56 &&
   1711             c[5] == 0x54 && c[4] == 0xC1 && c[7] == 0xCE &&
   1712             c[6] == 0x11 && c[8] == 0x85 && c[9] == 0x53 &&
   1713             c[10]== 0x00 && c[11]== 0xAA && c[12]== 0x00 &&
   1714             c[13]== 0xA1 && c[14]== 0xF9 && c[15]== 0x5B) {
   1715             is.reset();
   1716             return true;
   1717         }
   1718         is.reset();
   1719         return false;
   1720     }
   1721 
   1722     /**
   1723      * Tries to read the specified number of bytes from the stream
   1724      * Returns -1, If EOF is reached before len bytes are read, returns 0
   1725      * otherwise
   1726      */
   1727     static private int readBytes(int c[], int len, InputStream is)
   1728                 throws IOException {
   1729 
   1730         byte buf[] = new byte[len];
   1731         if (is.read(buf, 0, len) < len) {
   1732             return -1;
   1733         }
   1734 
   1735         // fill the passed in int array
   1736         for (int i = 0; i < len; i++) {
   1737              c[i] = buf[i] & 0xff;
   1738         }
   1739         return 0;
   1740     }
   1741 
   1742 
   1743     /**
   1744      * Skips through the specified number of bytes from the stream
   1745      * until either EOF is reached, or the specified
   1746      * number of bytes have been skipped
   1747      */
   1748     static private long skipForward(InputStream is, long toSkip)
   1749                 throws IOException {
   1750 
   1751         long eachSkip = 0;
   1752         long skipped = 0;
   1753 
   1754         while (skipped != toSkip) {
   1755             eachSkip = is.skip(toSkip - skipped);
   1756 
   1757             // check if EOF is reached
   1758             if (eachSkip <= 0) {
   1759                 if (is.read() == -1) {
   1760                     return skipped ;
   1761                 } else {
   1762                     skipped++;
   1763                 }
   1764             }
   1765             skipped += eachSkip;
   1766         }
   1767         return skipped;
   1768     }
   1769 
   1770 }
   1771 
   1772 
   1773 class UnknownContentHandler extends ContentHandler {
   1774     static final ContentHandler INSTANCE = new UnknownContentHandler();
   1775 
   1776     public Object getContent(URLConnection uc) throws IOException {
   1777         return uc.getInputStream();
   1778     }
   1779 }
   1780