Home » openjdk-7 » java » net » [javadoc | source]

    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.EMPTY_MAP;
  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       public long getHeaderFieldDate(String name, long Default) {
  663           String value = getHeaderField(name);
  664           try {
  665               return Date.parse(value);
  666           } catch (Exception e) { }
  667           return Default;
  668       }
  669   
  670       /**
  671        * Returns the key for the <code>n</code><sup>th</sup> header field.
  672        * It returns <code>null</code> if there are fewer than <code>n+1</code> fields.
  673        *
  674        * @param   n   an index, where n>=0
  675        * @return  the key for the <code>n</code><sup>th</sup> header field,
  676        *          or <code>null</code> if there are fewer than <code>n+1</code>
  677        *          fields.
  678        */
  679       public String getHeaderFieldKey(int n) {
  680           return null;
  681       }
  682   
  683       /**
  684        * Returns the value for the <code>n</code><sup>th</sup> header field.
  685        * It returns <code>null</code> if there are fewer than
  686        * <code>n+1</code>fields.
  687        * <p>
  688        * This method can be used in conjunction with the
  689        * {@link #getHeaderFieldKey(int) getHeaderFieldKey} method to iterate through all
  690        * the headers in the message.
  691        *
  692        * @param   n   an index, where n>=0
  693        * @return  the value of the <code>n</code><sup>th</sup> header field
  694        *          or <code>null</code> if there are fewer than <code>n+1</code> fields
  695        * @see     java.net.URLConnection#getHeaderFieldKey(int)
  696        */
  697       public String getHeaderField(int n) {
  698           return null;
  699       }
  700   
  701       /**
  702        * Retrieves the contents of this URL connection.
  703        * <p>
  704        * This method first determines the content type of the object by
  705        * calling the <code>getContentType</code> method. If this is
  706        * the first time that the application has seen that specific content
  707        * type, a content handler for that content type is created:
  708        * <ol>
  709        * <li>If the application has set up a content handler factory instance
  710        *     using the <code>setContentHandlerFactory</code> method, the
  711        *     <code>createContentHandler</code> method of that instance is called
  712        *     with the content type as an argument; the result is a content
  713        *     handler for that content type.
  714        * <li>If no content handler factory has yet been set up, or if the
  715        *     factory's <code>createContentHandler</code> method returns
  716        *     <code>null</code>, then the application loads the class named:
  717        *     <blockquote><pre>
  718        *         sun.net.www.content.&lt;<i>contentType</i>&gt;
  719        *     </pre></blockquote>
  720        *     where &lt;<i>contentType</i>&gt; is formed by taking the
  721        *     content-type string, replacing all slash characters with a
  722        *     <code>period</code> ('.'), and all other non-alphanumeric characters
  723        *     with the underscore character '<code>_</code>'. The alphanumeric
  724        *     characters are specifically the 26 uppercase ASCII letters
  725        *     '<code>A</code>' through '<code>Z</code>', the 26 lowercase ASCII
  726        *     letters '<code>a</code>' through '<code>z</code>', and the 10 ASCII
  727        *     digits '<code>0</code>' through '<code>9</code>'. If the specified
  728        *     class does not exist, or is not a subclass of
  729        *     <code>ContentHandler</code>, then an
  730        *     <code>UnknownServiceException</code> is thrown.
  731        * </ol>
  732        *
  733        * @return     the object fetched. The <code>instanceof</code> operator
  734        *               should be used to determine the specific kind of object
  735        *               returned.
  736        * @exception  IOException              if an I/O error occurs while
  737        *               getting the content.
  738        * @exception  UnknownServiceException  if the protocol does not support
  739        *               the content type.
  740        * @see        java.net.ContentHandlerFactory#createContentHandler(java.lang.String)
  741        * @see        java.net.URLConnection#getContentType()
  742        * @see        java.net.URLConnection#setContentHandlerFactory(java.net.ContentHandlerFactory)
  743        */
  744       public Object getContent() throws IOException {
  745           // Must call getInputStream before GetHeaderField gets called
  746           // so that FileNotFoundException has a chance to be thrown up
  747           // from here without being caught.
  748           getInputStream();
  749           return getContentHandler().getContent(this);
  750       }
  751   
  752       /**
  753        * Retrieves the contents of this URL connection.
  754        *
  755        * @param classes the <code>Class</code> array
  756        * indicating the requested types
  757        * @return     the object fetched that is the first match of the type
  758        *               specified in the classes array. null if none of
  759        *               the requested types are supported.
  760        *               The <code>instanceof</code> operator should be used to
  761        *               determine the specific kind of object returned.
  762        * @exception  IOException              if an I/O error occurs while
  763        *               getting the content.
  764        * @exception  UnknownServiceException  if the protocol does not support
  765        *               the content type.
  766        * @see        java.net.URLConnection#getContent()
  767        * @see        java.net.ContentHandlerFactory#createContentHandler(java.lang.String)
  768        * @see        java.net.URLConnection#getContent(java.lang.Class[])
  769        * @see        java.net.URLConnection#setContentHandlerFactory(java.net.ContentHandlerFactory)
  770        * @since 1.3
  771        */
  772       public Object getContent(Class[] classes) throws IOException {
  773           // Must call getInputStream before GetHeaderField gets called
  774           // so that FileNotFoundException has a chance to be thrown up
  775           // from here without being caught.
  776           getInputStream();
  777           return getContentHandler().getContent(this, classes);
  778       }
  779   
  780       /**
  781        * Returns a permission object representing the permission
  782        * necessary to make the connection represented by this
  783        * object. This method returns null if no permission is
  784        * required to make the connection. By default, this method
  785        * returns <code>java.security.AllPermission</code>. Subclasses
  786        * should override this method and return the permission
  787        * that best represents the permission required to make a
  788        * a connection to the URL. For example, a <code>URLConnection</code>
  789        * representing a <code>file:</code> URL would return a
  790        * <code>java.io.FilePermission</code> object.
  791        *
  792        * <p>The permission returned may dependent upon the state of the
  793        * connection. For example, the permission before connecting may be
  794        * different from that after connecting. For example, an HTTP
  795        * sever, say foo.com, may redirect the connection to a different
  796        * host, say bar.com. Before connecting the permission returned by
  797        * the connection will represent the permission needed to connect
  798        * to foo.com, while the permission returned after connecting will
  799        * be to bar.com.
  800        *
  801        * <p>Permissions are generally used for two purposes: to protect
  802        * caches of objects obtained through URLConnections, and to check
  803        * the right of a recipient to learn about a particular URL. In
  804        * the first case, the permission should be obtained
  805        * <em>after</em> the object has been obtained. For example, in an
  806        * HTTP connection, this will represent the permission to connect
  807        * to the host from which the data was ultimately fetched. In the
  808        * second case, the permission should be obtained and tested
  809        * <em>before</em> connecting.
  810        *
  811        * @return the permission object representing the permission
  812        * necessary to make the connection represented by this
  813        * URLConnection.
  814        *
  815        * @exception IOException if the computation of the permission
  816        * requires network or file I/O and an exception occurs while
  817        * computing it.
  818        */
  819       public Permission getPermission() throws IOException {
  820           return SecurityConstants.ALL_PERMISSION;
  821       }
  822   
  823       /**
  824        * Returns an input stream that reads from this open connection.
  825        *
  826        * A SocketTimeoutException can be thrown when reading from the
  827        * returned input stream if the read timeout expires before data
  828        * is available for read.
  829        *
  830        * @return     an input stream that reads from this open connection.
  831        * @exception  IOException              if an I/O error occurs while
  832        *               creating the input stream.
  833        * @exception  UnknownServiceException  if the protocol does not support
  834        *               input.
  835        * @see #setReadTimeout(int)
  836        * @see #getReadTimeout()
  837        */
  838       public InputStream getInputStream() throws IOException {
  839           throw new UnknownServiceException("protocol doesn't support input");
  840       }
  841   
  842       /**
  843        * Returns an output stream that writes to this connection.
  844        *
  845        * @return     an output stream that writes to this connection.
  846        * @exception  IOException              if an I/O error occurs while
  847        *               creating the output stream.
  848        * @exception  UnknownServiceException  if the protocol does not support
  849        *               output.
  850        */
  851       public OutputStream getOutputStream() throws IOException {
  852           throw new UnknownServiceException("protocol doesn't support output");
  853       }
  854   
  855       /**
  856        * Returns a <code>String</code> representation of this URL connection.
  857        *
  858        * @return  a string representation of this <code>URLConnection</code>.
  859        */
  860       public String toString() {
  861           return this.getClass().getName() + ":" + url;
  862       }
  863   
  864       /**
  865        * Sets the value of the <code>doInput</code> field for this
  866        * <code>URLConnection</code> to the specified value.
  867        * <p>
  868        * A URL connection can be used for input and/or output.  Set the DoInput
  869        * flag to true if you intend to use the URL connection for input,
  870        * false if not.  The default is true.
  871        *
  872        * @param   doinput   the new value.
  873        * @throws IllegalStateException if already connected
  874        * @see     java.net.URLConnection#doInput
  875        * @see #getDoInput()
  876        */
  877       public void setDoInput(boolean doinput) {
  878           if (connected)
  879               throw new IllegalStateException("Already connected");
  880           doInput = doinput;
  881       }
  882   
  883       /**
  884        * Returns the value of this <code>URLConnection</code>'s
  885        * <code>doInput</code> flag.
  886        *
  887        * @return  the value of this <code>URLConnection</code>'s
  888        *          <code>doInput</code> flag.
  889        * @see     #setDoInput(boolean)
  890        */
  891       public boolean getDoInput() {
  892           return doInput;
  893       }
  894   
  895       /**
  896        * Sets the value of the <code>doOutput</code> field for this
  897        * <code>URLConnection</code> to the specified value.
  898        * <p>
  899        * A URL connection can be used for input and/or output.  Set the DoOutput
  900        * flag to true if you intend to use the URL connection for output,
  901        * false if not.  The default is false.
  902        *
  903        * @param   dooutput   the new value.
  904        * @throws IllegalStateException if already connected
  905        * @see #getDoOutput()
  906        */
  907       public void setDoOutput(boolean dooutput) {
  908           if (connected)
  909               throw new IllegalStateException("Already connected");
  910           doOutput = dooutput;
  911       }
  912   
  913       /**
  914        * Returns the value of this <code>URLConnection</code>'s
  915        * <code>doOutput</code> flag.
  916        *
  917        * @return  the value of this <code>URLConnection</code>'s
  918        *          <code>doOutput</code> flag.
  919        * @see     #setDoOutput(boolean)
  920        */
  921       public boolean getDoOutput() {
  922           return doOutput;
  923       }
  924   
  925       /**
  926        * Set the value of the <code>allowUserInteraction</code> field of
  927        * this <code>URLConnection</code>.
  928        *
  929        * @param   allowuserinteraction   the new value.
  930        * @throws IllegalStateException if already connected
  931        * @see     #getAllowUserInteraction()
  932        */
  933       public void setAllowUserInteraction(boolean allowuserinteraction) {
  934           if (connected)
  935               throw new IllegalStateException("Already connected");
  936           allowUserInteraction = allowuserinteraction;
  937       }
  938   
  939       /**
  940        * Returns the value of the <code>allowUserInteraction</code> field for
  941        * this object.
  942        *
  943        * @return  the value of the <code>allowUserInteraction</code> field for
  944        *          this object.
  945        * @see     #setAllowUserInteraction(boolean)
  946        */
  947       public boolean getAllowUserInteraction() {
  948           return allowUserInteraction;
  949       }
  950   
  951       /**
  952        * Sets the default value of the
  953        * <code>allowUserInteraction</code> field for all future
  954        * <code>URLConnection</code> objects to the specified value.
  955        *
  956        * @param   defaultallowuserinteraction   the new value.
  957        * @see     #getDefaultAllowUserInteraction()
  958        */
  959       public static void setDefaultAllowUserInteraction(boolean defaultallowuserinteraction) {
  960           defaultAllowUserInteraction = defaultallowuserinteraction;
  961       }
  962   
  963       /**
  964        * Returns the default value of the <code>allowUserInteraction</code>
  965        * field.
  966        * <p>
  967        * Ths default is "sticky", being a part of the static state of all
  968        * URLConnections.  This flag applies to the next, and all following
  969        * URLConnections that are created.
  970        *
  971        * @return  the default value of the <code>allowUserInteraction</code>
  972        *          field.
  973        * @see     #setDefaultAllowUserInteraction(boolean)
  974        */
  975       public static boolean getDefaultAllowUserInteraction() {
  976           return defaultAllowUserInteraction;
  977       }
  978   
  979       /**
  980        * Sets the value of the <code>useCaches</code> field of this
  981        * <code>URLConnection</code> to the specified value.
  982        * <p>
  983        * Some protocols do caching of documents.  Occasionally, it is important
  984        * to be able to "tunnel through" and ignore the caches (e.g., the
  985        * "reload" button in a browser).  If the UseCaches flag on a connection
  986        * is true, the connection is allowed to use whatever caches it can.
  987        *  If false, caches are to be ignored.
  988        *  The default value comes from DefaultUseCaches, which defaults to
  989        * true.
  990        *
  991        * @param usecaches a <code>boolean</code> indicating whether
  992        * or not to allow caching
  993        * @throws IllegalStateException if already connected
  994        * @see #getUseCaches()
  995        */
  996       public void setUseCaches(boolean usecaches) {
  997           if (connected)
  998               throw new IllegalStateException("Already connected");
  999           useCaches = usecaches;
 1000       }
 1001   
 1002       /**
 1003        * Returns the value of this <code>URLConnection</code>'s
 1004        * <code>useCaches</code> field.
 1005        *
 1006        * @return  the value of this <code>URLConnection</code>'s
 1007        *          <code>useCaches</code> field.
 1008        * @see #setUseCaches(boolean)
 1009        */
 1010       public boolean getUseCaches() {
 1011           return useCaches;
 1012       }
 1013   
 1014       /**
 1015        * Sets the value of the <code>ifModifiedSince</code> field of
 1016        * this <code>URLConnection</code> to the specified value.
 1017        *
 1018        * @param   ifmodifiedsince   the new value.
 1019        * @throws IllegalStateException if already connected
 1020        * @see     #getIfModifiedSince()
 1021        */
 1022       public void setIfModifiedSince(long ifmodifiedsince) {
 1023           if (connected)
 1024               throw new IllegalStateException("Already connected");
 1025           ifModifiedSince = ifmodifiedsince;
 1026       }
 1027   
 1028       /**
 1029        * Returns the value of this object's <code>ifModifiedSince</code> field.
 1030        *
 1031        * @return  the value of this object's <code>ifModifiedSince</code> field.
 1032        * @see #setIfModifiedSince(long)
 1033        */
 1034       public long getIfModifiedSince() {
 1035           return ifModifiedSince;
 1036       }
 1037   
 1038      /**
 1039        * Returns the default value of a <code>URLConnection</code>'s
 1040        * <code>useCaches</code> flag.
 1041        * <p>
 1042        * Ths default is "sticky", being a part of the static state of all
 1043        * URLConnections.  This flag applies to the next, and all following
 1044        * URLConnections that are created.
 1045        *
 1046        * @return  the default value of a <code>URLConnection</code>'s
 1047        *          <code>useCaches</code> flag.
 1048        * @see     #setDefaultUseCaches(boolean)
 1049        */
 1050       public boolean getDefaultUseCaches() {
 1051           return defaultUseCaches;
 1052       }
 1053   
 1054      /**
 1055        * Sets the default value of the <code>useCaches</code> field to the
 1056        * specified value.
 1057        *
 1058        * @param   defaultusecaches   the new value.
 1059        * @see     #getDefaultUseCaches()
 1060        */
 1061       public void setDefaultUseCaches(boolean defaultusecaches) {
 1062           defaultUseCaches = defaultusecaches;
 1063       }
 1064   
 1065       /**
 1066        * Sets the general request property. If a property with the key already
 1067        * exists, overwrite its value with the new value.
 1068        *
 1069        * <p> NOTE: HTTP requires all request properties which can
 1070        * legally have multiple instances with the same key
 1071        * to use a comma-seperated list syntax which enables multiple
 1072        * properties to be appended into a single property.
 1073        *
 1074        * @param   key     the keyword by which the request is known
 1075        *                  (e.g., "<code>Accept</code>").
 1076        * @param   value   the value associated with it.
 1077        * @throws IllegalStateException if already connected
 1078        * @throws NullPointerException if key is <CODE>null</CODE>
 1079        * @see #getRequestProperty(java.lang.String)
 1080        */
 1081       public void setRequestProperty(String key, String value) {
 1082           if (connected)
 1083               throw new IllegalStateException("Already connected");
 1084           if (key == null)
 1085               throw new NullPointerException ("key is null");
 1086   
 1087           if (requests == null)
 1088               requests = new MessageHeader();
 1089   
 1090           requests.set(key, value);
 1091       }
 1092   
 1093       /**
 1094        * Adds a general request property specified by a
 1095        * key-value pair.  This method will not overwrite
 1096        * existing values associated with the same key.
 1097        *
 1098        * @param   key     the keyword by which the request is known
 1099        *                  (e.g., "<code>Accept</code>").
 1100        * @param   value  the value associated with it.
 1101        * @throws IllegalStateException if already connected
 1102        * @throws NullPointerException if key is null
 1103        * @see #getRequestProperties()
 1104        * @since 1.4
 1105        */
 1106       public void addRequestProperty(String key, String value) {
 1107           if (connected)
 1108               throw new IllegalStateException("Already connected");
 1109           if (key == null)
 1110               throw new NullPointerException ("key is null");
 1111   
 1112           if (requests == null)
 1113               requests = new MessageHeader();
 1114   
 1115           requests.add(key, value);
 1116       }
 1117   
 1118   
 1119       /**
 1120        * Returns the value of the named general request property for this
 1121        * connection.
 1122        *
 1123        * @param key the keyword by which the request is known (e.g., "Accept").
 1124        * @return  the value of the named general request property for this
 1125        *           connection. If key is null, then null is returned.
 1126        * @throws IllegalStateException if already connected
 1127        * @see #setRequestProperty(java.lang.String, java.lang.String)
 1128        */
 1129       public String getRequestProperty(String key) {
 1130           if (connected)
 1131               throw new IllegalStateException("Already connected");
 1132   
 1133           if (requests == null)
 1134               return null;
 1135   
 1136           return requests.findValue(key);
 1137       }
 1138   
 1139       /**
 1140        * Returns an unmodifiable Map of general request
 1141        * properties for this connection. The Map keys
 1142        * are Strings that represent the request-header
 1143        * field names. Each Map value is a unmodifiable List
 1144        * of Strings that represents the corresponding
 1145        * field values.
 1146        *
 1147        * @return  a Map of the general request properties for this connection.
 1148        * @throws IllegalStateException if already connected
 1149        * @since 1.4
 1150        */
 1151       public Map<String,List<String>> getRequestProperties() {
 1152           if (connected)
 1153               throw new IllegalStateException("Already connected");
 1154   
 1155           if (requests == null)
 1156               return Collections.EMPTY_MAP;
 1157   
 1158           return requests.getHeaders(null);
 1159       }
 1160   
 1161       /**
 1162        * Sets the default value of a general request property. When a
 1163        * <code>URLConnection</code> is created, it is initialized with
 1164        * these properties.
 1165        *
 1166        * @param   key     the keyword by which the request is known
 1167        *                  (e.g., "<code>Accept</code>").
 1168        * @param   value   the value associated with the key.
 1169        *
 1170        * @see java.net.URLConnection#setRequestProperty(java.lang.String,java.lang.String)
 1171        *
 1172        * @deprecated The instance specific setRequestProperty method
 1173        * should be used after an appropriate instance of URLConnection
 1174        * is obtained. Invoking this method will have no effect.
 1175        *
 1176        * @see #getDefaultRequestProperty(java.lang.String)
 1177        */
 1178       @Deprecated
 1179       public static void setDefaultRequestProperty(String key, String value) {
 1180       }
 1181   
 1182       /**
 1183        * Returns the value of the default request property. Default request
 1184        * properties are set for every connection.
 1185        *
 1186        * @param key the keyword by which the request is known (e.g., "Accept").
 1187        * @return  the value of the default request property
 1188        * for the specified key.
 1189        *
 1190        * @see java.net.URLConnection#getRequestProperty(java.lang.String)
 1191        *
 1192        * @deprecated The instance specific getRequestProperty method
 1193        * should be used after an appropriate instance of URLConnection
 1194        * is obtained.
 1195        *
 1196        * @see #setDefaultRequestProperty(java.lang.String, java.lang.String)
 1197        */
 1198       @Deprecated
 1199       public static String getDefaultRequestProperty(String key) {
 1200           return null;
 1201       }
 1202   
 1203       /**
 1204        * The ContentHandler factory.
 1205        */
 1206       static ContentHandlerFactory factory;
 1207   
 1208       /**
 1209        * Sets the <code>ContentHandlerFactory</code> of an
 1210        * application. It can be called at most once by an application.
 1211        * <p>
 1212        * The <code>ContentHandlerFactory</code> instance is used to
 1213        * construct a content handler from a content type
 1214        * <p>
 1215        * If there is a security manager, this method first calls
 1216        * the security manager's <code>checkSetFactory</code> method
 1217        * to ensure the operation is allowed.
 1218        * This could result in a SecurityException.
 1219        *
 1220        * @param      fac   the desired factory.
 1221        * @exception  Error  if the factory has already been defined.
 1222        * @exception  SecurityException  if a security manager exists and its
 1223        *             <code>checkSetFactory</code> method doesn't allow the operation.
 1224        * @see        java.net.ContentHandlerFactory
 1225        * @see        java.net.URLConnection#getContent()
 1226        * @see        SecurityManager#checkSetFactory
 1227        */
 1228       public static synchronized void setContentHandlerFactory(ContentHandlerFactory fac) {
 1229           if (factory != null) {
 1230               throw new Error("factory already defined");
 1231           }
 1232           SecurityManager security = System.getSecurityManager();
 1233           if (security != null) {
 1234               security.checkSetFactory();
 1235           }
 1236           factory = fac;
 1237       }
 1238   
 1239       private static Hashtable handlers = new Hashtable();
 1240   
 1241       /**
 1242        * Gets the Content Handler appropriate for this connection.
 1243        * @param connection the connection to use.
 1244        */
 1245       synchronized ContentHandler getContentHandler()
 1246       throws UnknownServiceException
 1247       {
 1248           String contentType = stripOffParameters(getContentType());
 1249           ContentHandler handler = null;
 1250           if (contentType == null)
 1251               throw new UnknownServiceException("no content-type");
 1252           try {
 1253               handler = (ContentHandler) handlers.get(contentType);
 1254               if (handler != null)
 1255                   return handler;
 1256           } catch(Exception e) {
 1257           }
 1258   
 1259           if (factory != null)
 1260               handler = factory.createContentHandler(contentType);
 1261           if (handler == null) {
 1262               try {
 1263                   handler = lookupContentHandlerClassFor(contentType);
 1264               } catch(Exception e) {
 1265                   e.printStackTrace();
 1266                   handler = UnknownContentHandler.INSTANCE;
 1267               }
 1268               handlers.put(contentType, handler);
 1269           }
 1270           return handler;
 1271       }
 1272   
 1273       /*
 1274        * Media types are in the format: type/subtype*(; parameter).
 1275        * For looking up the content handler, we should ignore those
 1276        * parameters.
 1277        */
 1278       private String stripOffParameters(String contentType)
 1279       {
 1280           if (contentType == null)
 1281               return null;
 1282           int index = contentType.indexOf(';');
 1283   
 1284           if (index > 0)
 1285               return contentType.substring(0, index);
 1286           else
 1287               return contentType;
 1288       }
 1289   
 1290       private static final String contentClassPrefix = "sun.net.www.content";
 1291       private static final String contentPathProp = "java.content.handler.pkgs";
 1292   
 1293       /**
 1294        * Looks for a content handler in a user-defineable set of places.
 1295        * By default it looks in sun.net.www.content, but users can define a
 1296        * vertical-bar delimited set of class prefixes to search through in
 1297        * addition by defining the java.content.handler.pkgs property.
 1298        * The class name must be of the form:
 1299        * <pre>
 1300        *     {package-prefix}.{major}.{minor}
 1301        * e.g.
 1302        *     YoyoDyne.experimental.text.plain
 1303        * </pre>
 1304        */
 1305       private ContentHandler lookupContentHandlerClassFor(String contentType)
 1306           throws InstantiationException, IllegalAccessException, ClassNotFoundException {
 1307           String contentHandlerClassName = typeToPackageName(contentType);
 1308   
 1309           String contentHandlerPkgPrefixes =getContentHandlerPkgPrefixes();
 1310   
 1311           StringTokenizer packagePrefixIter =
 1312               new StringTokenizer(contentHandlerPkgPrefixes, "|");
 1313   
 1314           while (packagePrefixIter.hasMoreTokens()) {
 1315               String packagePrefix = packagePrefixIter.nextToken().trim();
 1316   
 1317               try {
 1318                   String clsName = packagePrefix + "." + contentHandlerClassName;
 1319                   Class cls = null;
 1320                   try {
 1321                       cls = Class.forName(clsName);
 1322                   } catch (ClassNotFoundException e) {
 1323                       ClassLoader cl = ClassLoader.getSystemClassLoader();
 1324                       if (cl != null) {
 1325                           cls = cl.loadClass(clsName);
 1326                       }
 1327                   }
 1328                   if (cls != null) {
 1329                       ContentHandler handler =
 1330                           (ContentHandler)cls.newInstance();
 1331                       return handler;
 1332                   }
 1333               } catch(Exception e) {
 1334               }
 1335           }
 1336   
 1337           return UnknownContentHandler.INSTANCE;
 1338       }
 1339   
 1340       /**
 1341        * Utility function to map a MIME content type into an equivalent
 1342        * pair of class name components.  For example: "text/html" would
 1343        * be returned as "text.html"
 1344        */
 1345       private String typeToPackageName(String contentType) {
 1346           // make sure we canonicalize the class name: all lower case
 1347           contentType = contentType.toLowerCase();
 1348           int len = contentType.length();
 1349           char nm[] = new char[len];
 1350           contentType.getChars(0, len, nm, 0);
 1351           for (int i = 0; i < len; i++) {
 1352               char c = nm[i];
 1353               if (c == '/') {
 1354                   nm[i] = '.';
 1355               } else if (!('A' <= c && c <= 'Z' ||
 1356                          'a' <= c && c <= 'z' ||
 1357                          '0' <= c && c <= '9')) {
 1358                   nm[i] = '_';
 1359               }
 1360           }
 1361           return new String(nm);
 1362       }
 1363   
 1364   
 1365       /**
 1366        * Returns a vertical bar separated list of package prefixes for potential
 1367        * content handlers.  Tries to get the java.content.handler.pkgs property
 1368        * to use as a set of package prefixes to search.  Whether or not
 1369        * that property has been defined, the sun.net.www.content is always
 1370        * the last one on the returned package list.
 1371        */
 1372       private String getContentHandlerPkgPrefixes() {
 1373           String packagePrefixList = AccessController.doPrivileged(
 1374               new sun.security.action.GetPropertyAction(contentPathProp, ""));
 1375   
 1376           if (packagePrefixList != "") {
 1377               packagePrefixList += "|";
 1378           }
 1379   
 1380           return packagePrefixList + contentClassPrefix;
 1381       }
 1382   
 1383       /**
 1384        * Tries to determine the content type of an object, based
 1385        * on the specified "file" component of a URL.
 1386        * This is a convenience method that can be used by
 1387        * subclasses that override the <code>getContentType</code> method.
 1388        *
 1389        * @param   fname   a filename.
 1390        * @return  a guess as to what the content type of the object is,
 1391        *          based upon its file name.
 1392        * @see     java.net.URLConnection#getContentType()
 1393        */
 1394       public static String guessContentTypeFromName(String fname) {
 1395           return getFileNameMap().getContentTypeFor(fname);
 1396       }
 1397   
 1398       /**
 1399        * Tries to determine the type of an input stream based on the
 1400        * characters at the beginning of the input stream. This method can
 1401        * be used by subclasses that override the
 1402        * <code>getContentType</code> method.
 1403        * <p>
 1404        * Ideally, this routine would not be needed. But many
 1405        * <code>http</code> servers return the incorrect content type; in
 1406        * addition, there are many nonstandard extensions. Direct inspection
 1407        * of the bytes to determine the content type is often more accurate
 1408        * than believing the content type claimed by the <code>http</code> server.
 1409        *
 1410        * @param      is   an input stream that supports marks.
 1411        * @return     a guess at the content type, or <code>null</code> if none
 1412        *             can be determined.
 1413        * @exception  IOException  if an I/O error occurs while reading the
 1414        *               input stream.
 1415        * @see        java.io.InputStream#mark(int)
 1416        * @see        java.io.InputStream#markSupported()
 1417        * @see        java.net.URLConnection#getContentType()
 1418        */
 1419       static public String guessContentTypeFromStream(InputStream is)
 1420                           throws IOException {
 1421           // If we can't read ahead safely, just give up on guessing
 1422           if (!is.markSupported())
 1423               return null;
 1424   
 1425           is.mark(16);
 1426           int c1 = is.read();
 1427           int c2 = is.read();
 1428           int c3 = is.read();
 1429           int c4 = is.read();
 1430           int c5 = is.read();
 1431           int c6 = is.read();
 1432           int c7 = is.read();
 1433           int c8 = is.read();
 1434           int c9 = is.read();
 1435           int c10 = is.read();
 1436           int c11 = is.read();
 1437           int c12 = is.read();
 1438           int c13 = is.read();
 1439           int c14 = is.read();
 1440           int c15 = is.read();
 1441           int c16 = is.read();
 1442           is.reset();
 1443   
 1444           if (c1 == 0xCA && c2 == 0xFE && c3 == 0xBA && c4 == 0xBE) {
 1445               return "application/java-vm";
 1446           }
 1447   
 1448           if (c1 == 0xAC && c2 == 0xED) {
 1449               // next two bytes are version number, currently 0x00 0x05
 1450               return "application/x-java-serialized-object";
 1451           }
 1452   
 1453           if (c1 == '<') {
 1454               if (c2 == '!'
 1455                   || ((c2 == 'h' && (c3 == 't' && c4 == 'm' && c5 == 'l' ||
 1456                                      c3 == 'e' && c4 == 'a' && c5 == 'd') ||
 1457                   (c2 == 'b' && c3 == 'o' && c4 == 'd' && c5 == 'y'))) ||
 1458                   ((c2 == 'H' && (c3 == 'T' && c4 == 'M' && c5 == 'L' ||
 1459                                   c3 == 'E' && c4 == 'A' && c5 == 'D') ||
 1460                   (c2 == 'B' && c3 == 'O' && c4 == 'D' && c5 == 'Y')))) {
 1461                   return "text/html";
 1462               }
 1463   
 1464               if (c2 == '?' && c3 == 'x' && c4 == 'm' && c5 == 'l' && c6 == ' ') {
 1465                   return "application/xml";
 1466               }
 1467           }
 1468   
 1469           // big and little (identical) endian UTF-8 encodings, with BOM
 1470           if (c1 == 0xef &&  c2 == 0xbb &&  c3 == 0xbf) {
 1471               if (c4 == '<' &&  c5 == '?' &&  c6 == 'x') {
 1472                   return "application/xml";
 1473               }
 1474           }
 1475   
 1476           // big and little endian UTF-16 encodings, with byte order mark
 1477           if (c1 == 0xfe && c2 == 0xff) {
 1478               if (c3 == 0 && c4 == '<' && c5 == 0 && c6 == '?' &&
 1479                   c7 == 0 && c8 == 'x') {
 1480                   return "application/xml";
 1481               }
 1482           }
 1483   
 1484           if (c1 == 0xff && c2 == 0xfe) {
 1485               if (c3 == '<' && c4 == 0 && c5 == '?' && c6 == 0 &&
 1486                   c7 == 'x' && c8 == 0) {
 1487                   return "application/xml";
 1488               }
 1489           }
 1490   
 1491           // big and little endian UTF-32 encodings, with BOM
 1492           if (c1 == 0x00 &&  c2 == 0x00 &&  c3 == 0xfe &&  c4 == 0xff) {
 1493               if (c5  == 0 && c6  == 0 && c7  == 0 && c8  == '<' &&
 1494                   c9  == 0 && c10 == 0 && c11 == 0 && c12 == '?' &&
 1495                   c13 == 0 && c14 == 0 && c15 == 0 && c16 == 'x') {
 1496                   return "application/xml";
 1497               }
 1498           }
 1499   
 1500           if (c1 == 0xff &&  c2 == 0xfe &&  c3 == 0x00 &&  c4 == 0x00) {
 1501               if (c5  == '<' && c6  == 0 && c7  == 0 && c8  == 0 &&
 1502                   c9  == '?' && c10 == 0 && c11 == 0 && c12 == 0 &&
 1503                   c13 == 'x' && c14 == 0 && c15 == 0 && c16 == 0) {
 1504                   return "application/xml";
 1505               }
 1506           }
 1507   
 1508           if (c1 == 'G' && c2 == 'I' && c3 == 'F' && c4 == '8') {
 1509               return "image/gif";
 1510           }
 1511   
 1512           if (c1 == '#' && c2 == 'd' && c3 == 'e' && c4 == 'f') {
 1513               return "image/x-bitmap";
 1514           }
 1515   
 1516           if (c1 == '!' && c2 == ' ' && c3 == 'X' && c4 == 'P' &&
 1517                           c5 == 'M' && c6 == '2') {
 1518               return "image/x-pixmap";
 1519           }
 1520   
 1521           if (c1 == 137 && c2 == 80 && c3 == 78 &&
 1522                   c4 == 71 && c5 == 13 && c6 == 10 &&
 1523                   c7 == 26 && c8 == 10) {
 1524               return "image/png";
 1525           }
 1526   
 1527           if (c1 == 0xFF && c2 == 0xD8 && c3 == 0xFF) {
 1528               if (c4 == 0xE0) {
 1529                   return "image/jpeg";
 1530               }
 1531   
 1532               /**
 1533                * File format used by digital cameras to store images.
 1534                * Exif Format can be read by any application supporting
 1535                * JPEG. Exif Spec can be found at:
 1536                * http://www.pima.net/standards/it10/PIMA15740/Exif_2-1.PDF
 1537                */
 1538               if ((c4 == 0xE1) &&
 1539                   (c7 == 'E' && c8 == 'x' && c9 == 'i' && c10 =='f' &&
 1540                    c11 == 0)) {
 1541                   return "image/jpeg";
 1542               }
 1543   
 1544               if (c4 == 0xEE) {
 1545                   return "image/jpg";
 1546               }
 1547           }
 1548   
 1549           if (c1 == 0xD0 && c2 == 0xCF && c3 == 0x11 && c4 == 0xE0 &&
 1550               c5 == 0xA1 && c6 == 0xB1 && c7 == 0x1A && c8 == 0xE1) {
 1551   
 1552               /* Above is signature of Microsoft Structured Storage.
 1553                * Below this, could have tests for various SS entities.
 1554                * For now, just test for FlashPix.
 1555                */
 1556               if (checkfpx(is)) {
 1557                   return "image/vnd.fpx";
 1558               }
 1559           }
 1560   
 1561           if (c1 == 0x2E && c2 == 0x73 && c3 == 0x6E && c4 == 0x64) {
 1562               return "audio/basic";  // .au format, big endian
 1563           }
 1564   
 1565           if (c1 == 0x64 && c2 == 0x6E && c3 == 0x73 && c4 == 0x2E) {
 1566               return "audio/basic";  // .au format, little endian
 1567           }
 1568   
 1569           if (c1 == 'R' && c2 == 'I' && c3 == 'F' && c4 == 'F') {
 1570               /* I don't know if this is official but evidence
 1571                * suggests that .wav files start with "RIFF" - brown
 1572                */
 1573               return "audio/x-wav";
 1574           }
 1575           return null;
 1576       }
 1577   
 1578       /**
 1579        * Check for FlashPix image data in InputStream is.  Return true if
 1580        * the stream has FlashPix data, false otherwise.  Before calling this
 1581        * method, the stream should have already been checked to be sure it
 1582        * contains Microsoft Structured Storage data.
 1583        */
 1584       static private boolean checkfpx(InputStream is) throws IOException {
 1585   
 1586           /* Test for FlashPix image data in Microsoft Structured Storage format.
 1587            * In general, should do this with calls to an SS implementation.
 1588            * Lacking that, need to dig via offsets to get to the FlashPix
 1589            * ClassID.  Details:
 1590            *
 1591            * Offset to Fpx ClsID from beginning of stream should be:
 1592            *
 1593            * FpxClsidOffset = rootEntryOffset + clsidOffset
 1594            *
 1595            * where: clsidOffset = 0x50.
 1596            *        rootEntryOffset = headerSize + sectorSize*sectDirStart
 1597            *                          + 128*rootEntryDirectory
 1598            *
 1599            *        where:  headerSize = 0x200 (always)
 1600            *                sectorSize = 2 raised to power of uSectorShift,
 1601            *                             which is found in the header at
 1602            *                             offset 0x1E.
 1603            *                sectDirStart = found in the header at offset 0x30.
 1604            *                rootEntryDirectory = in general, should search for
 1605            *                                     directory labelled as root.
 1606            *                                     We will assume value of 0 (i.e.,
 1607            *                                     rootEntry is in first directory)
 1608            */
 1609   
 1610           // Mark the stream so we can reset it. 0x100 is enough for the first
 1611           // few reads, but the mark will have to be reset and set again once
 1612           // the offset to the root directory entry is computed. That offset
 1613           // can be very large and isn't know until the stream has been read from
 1614           is.mark(0x100);
 1615   
 1616           // Get the byte ordering located at 0x1E. 0xFE is Intel,
 1617           // 0xFF is other
 1618           long toSkip = (long)0x1C;
 1619           long posn;
 1620   
 1621           if ((posn = skipForward(is, toSkip)) < toSkip) {
 1622             is.reset();
 1623             return false;
 1624           }
 1625   
 1626           int c[] = new int[16];
 1627           if (readBytes(c, 2, is) < 0) {
 1628               is.reset();
 1629               return false;
 1630           }
 1631   
 1632           int byteOrder = c[0];
 1633   
 1634           posn+=2;
 1635           int uSectorShift;
 1636           if (readBytes(c, 2, is) < 0) {
 1637               is.reset();
 1638               return false;
 1639           }
 1640   
 1641           if(byteOrder == 0xFE) {
 1642               uSectorShift = c[0];
 1643               uSectorShift += c[1] << 8;
 1644           }
 1645           else {
 1646               uSectorShift = c[0] << 8;
 1647               uSectorShift += c[1];
 1648           }
 1649   
 1650           posn += 2;
 1651           toSkip = (long)0x30 - posn;
 1652           long skipped = 0;
 1653           if ((skipped = skipForward(is, toSkip)) < toSkip) {
 1654             is.reset();
 1655             return false;
 1656           }
 1657           posn += skipped;
 1658   
 1659           if (readBytes(c, 4, is) < 0) {
 1660               is.reset();
 1661               return false;
 1662           }
 1663   
 1664           int sectDirStart;
 1665           if(byteOrder == 0xFE) {
 1666               sectDirStart = c[0];
 1667               sectDirStart += c[1] << 8;
 1668               sectDirStart += c[2] << 16;
 1669               sectDirStart += c[3] << 24;
 1670           } else {
 1671               sectDirStart =  c[0] << 24;
 1672               sectDirStart += c[1] << 16;
 1673               sectDirStart += c[2] << 8;
 1674               sectDirStart += c[3];
 1675           }
 1676           posn += 4;
 1677           is.reset(); // Reset back to the beginning
 1678   
 1679           toSkip = 0x200L + (long)(1<<uSectorShift)*sectDirStart + 0x50L;
 1680   
 1681           // Sanity check!
 1682           if (toSkip < 0) {
 1683               return false;
 1684           }
 1685   
 1686           /*
 1687            * How far can we skip? Is there any performance problem here?
 1688            * This skip can be fairly long, at least 0x4c650 in at least
 1689            * one case. Have to assume that the skip will fit in an int.
 1690            * Leave room to read whole root dir
 1691            */
 1692           is.mark((int)toSkip+0x30);
 1693   
 1694           if ((skipForward(is, toSkip)) < toSkip) {
 1695               is.reset();
 1696               return false;
 1697           }
 1698   
 1699           /* should be at beginning of ClassID, which is as follows
 1700            * (in Intel byte order):
 1701            *    00 67 61 56 54 C1 CE 11 85 53 00 AA 00 A1 F9 5B
 1702            *
 1703            * This is stored from Windows as long,short,short,char[8]
 1704            * so for byte order changes, the order only changes for
 1705            * the first 8 bytes in the ClassID.
 1706            *
 1707            * Test against this, ignoring second byte (Intel) since
 1708            * this could change depending on part of Fpx file we have.
 1709            */
 1710   
 1711           if (readBytes(c, 16, is) < 0) {
 1712               is.reset();
 1713               return false;
 1714           }
 1715   
 1716           // intel byte order
 1717           if (byteOrder == 0xFE &&
 1718               c[0] == 0x00 && c[2] == 0x61 && c[3] == 0x56 &&
 1719               c[4] == 0x54 && c[5] == 0xC1 && c[6] == 0xCE &&
 1720               c[7] == 0x11 && c[8] == 0x85 && c[9] == 0x53 &&
 1721               c[10]== 0x00 && c[11]== 0xAA && c[12]== 0x00 &&
 1722               c[13]== 0xA1 && c[14]== 0xF9 && c[15]== 0x5B) {
 1723               is.reset();
 1724               return true;
 1725           }
 1726   
 1727           // non-intel byte order
 1728           else if (c[3] == 0x00 && c[1] == 0x61 && c[0] == 0x56 &&
 1729               c[5] == 0x54 && c[4] == 0xC1 && c[7] == 0xCE &&
 1730               c[6] == 0x11 && c[8] == 0x85 && c[9] == 0x53 &&
 1731               c[10]== 0x00 && c[11]== 0xAA && c[12]== 0x00 &&
 1732               c[13]== 0xA1 && c[14]== 0xF9 && c[15]== 0x5B) {
 1733               is.reset();
 1734               return true;
 1735           }
 1736           is.reset();
 1737           return false;
 1738       }
 1739   
 1740       /**
 1741        * Tries to read the specified number of bytes from the stream
 1742        * Returns -1, If EOF is reached before len bytes are read, returns 0
 1743        * otherwise
 1744        */
 1745       static private int readBytes(int c[], int len, InputStream is)
 1746                   throws IOException {
 1747   
 1748           byte buf[] = new byte[len];
 1749           if (is.read(buf, 0, len) < len) {
 1750               return -1;
 1751           }
 1752   
 1753           // fill the passed in int array
 1754           for (int i = 0; i < len; i++) {
 1755                c[i] = buf[i] & 0xff;
 1756           }
 1757           return 0;
 1758       }
 1759   
 1760   
 1761       /**
 1762        * Skips through the specified number of bytes from the stream
 1763        * until either EOF is reached, or the specified
 1764        * number of bytes have been skipped
 1765        */
 1766       static private long skipForward(InputStream is, long toSkip)
 1767                   throws IOException {
 1768   
 1769           long eachSkip = 0;
 1770           long skipped = 0;
 1771   
 1772           while (skipped != toSkip) {
 1773               eachSkip = is.skip(toSkip - skipped);
 1774   
 1775               // check if EOF is reached
 1776               if (eachSkip <= 0) {
 1777                   if (is.read() == -1) {
 1778                       return skipped ;
 1779                   } else {
 1780                       skipped++;
 1781                   }
 1782               }
 1783               skipped += eachSkip;
 1784           }
 1785           return skipped;
 1786       }
 1787   
 1788   }
 1789   
 1790   
 1791   class UnknownContentHandler extends ContentHandler {
 1792       static final ContentHandler INSTANCE = new UnknownContentHandler();
 1793   
 1794       public Object getContent(URLConnection uc) throws IOException {
 1795           return uc.getInputStream();
 1796       }
 1797   }

Home » openjdk-7 » java » net » [javadoc | source]