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