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