Javac by default uses URLConnection jdk7-b147
authorJaroslav Tulach <jtulach@netbeans.org>
Thu, 31 Oct 2013 10:50:19 +0100
branchjdk7-b147
changeset 13961c64f76edaa7
parent 1385 e9af27858d02
child 1397 b39985a73b71
child 1399 07587a260d68
Javac by default uses URLConnection
rt/emul/compact/src/main/java/java/net/URLConnection.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/rt/emul/compact/src/main/java/java/net/URLConnection.java	Thu Oct 31 10:50:19 2013 +0100
     1.3 @@ -0,0 +1,1797 @@
     1.4 +/*
     1.5 + * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Oracle designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Oracle in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 + * or visit www.oracle.com if you need additional information or have any
    1.26 + * questions.
    1.27 + */
    1.28 +
    1.29 +package java.net;
    1.30 +
    1.31 +import java.io.IOException;
    1.32 +import java.io.InputStream;
    1.33 +import java.io.OutputStream;
    1.34 +import java.util.Hashtable;
    1.35 +import java.util.Date;
    1.36 +import java.util.StringTokenizer;
    1.37 +import java.util.Collections;
    1.38 +import java.util.Map;
    1.39 +import java.util.List;
    1.40 +import java.security.Permission;
    1.41 +import java.security.AccessController;
    1.42 +import sun.security.util.SecurityConstants;
    1.43 +import sun.net.www.MessageHeader;
    1.44 +
    1.45 +/**
    1.46 + * The abstract class <code>URLConnection</code> is the superclass
    1.47 + * of all classes that represent a communications link between the
    1.48 + * application and a URL. Instances of this class can be used both to
    1.49 + * read from and to write to the resource referenced by the URL. In
    1.50 + * general, creating a connection to a URL is a multistep process:
    1.51 + * <p>
    1.52 + * <center><table border=2 summary="Describes the process of creating a connection to a URL: openConnection() and connect() over time.">
    1.53 + * <tr><th><code>openConnection()</code></th>
    1.54 + *     <th><code>connect()</code></th></tr>
    1.55 + * <tr><td>Manipulate parameters that affect the connection to the remote
    1.56 + *         resource.</td>
    1.57 + *     <td>Interact with the resource; query header fields and
    1.58 + *         contents.</td></tr>
    1.59 + * </table>
    1.60 + * ----------------------------&gt;
    1.61 + * <br>time</center>
    1.62 + *
    1.63 + * <ol>
    1.64 + * <li>The connection object is created by invoking the
    1.65 + *     <code>openConnection</code> method on a URL.
    1.66 + * <li>The setup parameters and general request properties are manipulated.
    1.67 + * <li>The actual connection to the remote object is made, using the
    1.68 + *    <code>connect</code> method.
    1.69 + * <li>The remote object becomes available. The header fields and the contents
    1.70 + *     of the remote object can be accessed.
    1.71 + * </ol>
    1.72 + * <p>
    1.73 + * The setup parameters are modified using the following methods:
    1.74 + * <ul>
    1.75 + *   <li><code>setAllowUserInteraction</code>
    1.76 + *   <li><code>setDoInput</code>
    1.77 + *   <li><code>setDoOutput</code>
    1.78 + *   <li><code>setIfModifiedSince</code>
    1.79 + *   <li><code>setUseCaches</code>
    1.80 + * </ul>
    1.81 + * <p>
    1.82 + * and the general request properties are modified using the method:
    1.83 + * <ul>
    1.84 + *   <li><code>setRequestProperty</code>
    1.85 + * </ul>
    1.86 + * <p>
    1.87 + * Default values for the <code>AllowUserInteraction</code> and
    1.88 + * <code>UseCaches</code> parameters can be set using the methods
    1.89 + * <code>setDefaultAllowUserInteraction</code> and
    1.90 + * <code>setDefaultUseCaches</code>.
    1.91 + * <p>
    1.92 + * Each of the above <code>set</code> methods has a corresponding
    1.93 + * <code>get</code> method to retrieve the value of the parameter or
    1.94 + * general request property. The specific parameters and general
    1.95 + * request properties that are applicable are protocol specific.
    1.96 + * <p>
    1.97 + * The following methods are used to access the header fields and
    1.98 + * the contents after the connection is made to the remote object:
    1.99 + * <ul>
   1.100 + *   <li><code>getContent</code>
   1.101 + *   <li><code>getHeaderField</code>
   1.102 + *   <li><code>getInputStream</code>
   1.103 + *   <li><code>getOutputStream</code>
   1.104 + * </ul>
   1.105 + * <p>
   1.106 + * Certain header fields are accessed frequently. The methods:
   1.107 + * <ul>
   1.108 + *   <li><code>getContentEncoding</code>
   1.109 + *   <li><code>getContentLength</code>
   1.110 + *   <li><code>getContentType</code>
   1.111 + *   <li><code>getDate</code>
   1.112 + *   <li><code>getExpiration</code>
   1.113 + *   <li><code>getLastModifed</code>
   1.114 + * </ul>
   1.115 + * <p>
   1.116 + * provide convenient access to these fields. The
   1.117 + * <code>getContentType</code> method is used by the
   1.118 + * <code>getContent</code> method to determine the type of the remote
   1.119 + * object; subclasses may find it convenient to override the
   1.120 + * <code>getContentType</code> method.
   1.121 + * <p>
   1.122 + * In the common case, all of the pre-connection parameters and
   1.123 + * general request properties can be ignored: the pre-connection
   1.124 + * parameters and request properties default to sensible values. For
   1.125 + * most clients of this interface, there are only two interesting
   1.126 + * methods: <code>getInputStream</code> and <code>getContent</code>,
   1.127 + * which are mirrored in the <code>URL</code> class by convenience methods.
   1.128 + * <p>
   1.129 + * More information on the request properties and header fields of
   1.130 + * an <code>http</code> connection can be found at:
   1.131 + * <blockquote><pre>
   1.132 + * <a href="http://www.ietf.org/rfc/rfc2616.txt">http://www.ietf.org/rfc/rfc2616.txt</a>
   1.133 + * </pre></blockquote>
   1.134 + *
   1.135 + * Note about <code>fileNameMap</code>: In versions prior to JDK 1.1.6,
   1.136 + * field <code>fileNameMap</code> of <code>URLConnection</code> was public.
   1.137 + * In JDK 1.1.6 and later, <code>fileNameMap</code> is private; accessor
   1.138 + * and mutator methods {@link #getFileNameMap() getFileNameMap} and
   1.139 + * {@link #setFileNameMap(java.net.FileNameMap) setFileNameMap} are added
   1.140 + * to access it.  This change is also described on the <a href=
   1.141 + * "http://java.sun.com/products/jdk/1.2/compatibility.html">
   1.142 + * Compatibility</a> page.
   1.143 + *
   1.144 + * Invoking the <tt>close()</tt> methods on the <tt>InputStream</tt> or <tt>OutputStream</tt> of an
   1.145 + * <tt>URLConnection</tt> after a request may free network resources associated with this
   1.146 + * instance, unless particular protocol specifications specify different behaviours
   1.147 + * for it.
   1.148 + *
   1.149 + * @author  James Gosling
   1.150 + * @see     java.net.URL#openConnection()
   1.151 + * @see     java.net.URLConnection#connect()
   1.152 + * @see     java.net.URLConnection#getContent()
   1.153 + * @see     java.net.URLConnection#getContentEncoding()
   1.154 + * @see     java.net.URLConnection#getContentLength()
   1.155 + * @see     java.net.URLConnection#getContentType()
   1.156 + * @see     java.net.URLConnection#getDate()
   1.157 + * @see     java.net.URLConnection#getExpiration()
   1.158 + * @see     java.net.URLConnection#getHeaderField(int)
   1.159 + * @see     java.net.URLConnection#getHeaderField(java.lang.String)
   1.160 + * @see     java.net.URLConnection#getInputStream()
   1.161 + * @see     java.net.URLConnection#getLastModified()
   1.162 + * @see     java.net.URLConnection#getOutputStream()
   1.163 + * @see     java.net.URLConnection#setAllowUserInteraction(boolean)
   1.164 + * @see     java.net.URLConnection#setDefaultUseCaches(boolean)
   1.165 + * @see     java.net.URLConnection#setDoInput(boolean)
   1.166 + * @see     java.net.URLConnection#setDoOutput(boolean)
   1.167 + * @see     java.net.URLConnection#setIfModifiedSince(long)
   1.168 + * @see     java.net.URLConnection#setRequestProperty(java.lang.String, java.lang.String)
   1.169 + * @see     java.net.URLConnection#setUseCaches(boolean)
   1.170 + * @since   JDK1.0
   1.171 + */
   1.172 +public abstract class URLConnection {
   1.173 +
   1.174 +   /**
   1.175 +     * The URL represents the remote object on the World Wide Web to
   1.176 +     * which this connection is opened.
   1.177 +     * <p>
   1.178 +     * The value of this field can be accessed by the
   1.179 +     * <code>getURL</code> method.
   1.180 +     * <p>
   1.181 +     * The default value of this variable is the value of the URL
   1.182 +     * argument in the <code>URLConnection</code> constructor.
   1.183 +     *
   1.184 +     * @see     java.net.URLConnection#getURL()
   1.185 +     * @see     java.net.URLConnection#url
   1.186 +     */
   1.187 +    protected URL url;
   1.188 +
   1.189 +   /**
   1.190 +     * This variable is set by the <code>setDoInput</code> method. Its
   1.191 +     * value is returned by the <code>getDoInput</code> method.
   1.192 +     * <p>
   1.193 +     * A URL connection can be used for input and/or output. Setting the
   1.194 +     * <code>doInput</code> flag to <code>true</code> indicates that
   1.195 +     * the application intends to read data from the URL connection.
   1.196 +     * <p>
   1.197 +     * The default value of this field is <code>true</code>.
   1.198 +     *
   1.199 +     * @see     java.net.URLConnection#getDoInput()
   1.200 +     * @see     java.net.URLConnection#setDoInput(boolean)
   1.201 +     */
   1.202 +    protected boolean doInput = true;
   1.203 +
   1.204 +   /**
   1.205 +     * This variable is set by the <code>setDoOutput</code> method. Its
   1.206 +     * value is returned by the <code>getDoOutput</code> method.
   1.207 +     * <p>
   1.208 +     * A URL connection can be used for input and/or output. Setting the
   1.209 +     * <code>doOutput</code> flag to <code>true</code> indicates
   1.210 +     * that the application intends to write data to the URL connection.
   1.211 +     * <p>
   1.212 +     * The default value of this field is <code>false</code>.
   1.213 +     *
   1.214 +     * @see     java.net.URLConnection#getDoOutput()
   1.215 +     * @see     java.net.URLConnection#setDoOutput(boolean)
   1.216 +     */
   1.217 +    protected boolean doOutput = false;
   1.218 +
   1.219 +    private static boolean defaultAllowUserInteraction = false;
   1.220 +
   1.221 +   /**
   1.222 +     * If <code>true</code>, this <code>URL</code> is being examined in
   1.223 +     * a context in which it makes sense to allow user interactions such
   1.224 +     * as popping up an authentication dialog. If <code>false</code>,
   1.225 +     * then no user interaction is allowed.
   1.226 +     * <p>
   1.227 +     * The value of this field can be set by the
   1.228 +     * <code>setAllowUserInteraction</code> method.
   1.229 +     * Its value is returned by the
   1.230 +     * <code>getAllowUserInteraction</code> method.
   1.231 +     * Its default value is the value of the argument in the last invocation
   1.232 +     * of the <code>setDefaultAllowUserInteraction</code> method.
   1.233 +     *
   1.234 +     * @see     java.net.URLConnection#getAllowUserInteraction()
   1.235 +     * @see     java.net.URLConnection#setAllowUserInteraction(boolean)
   1.236 +     * @see     java.net.URLConnection#setDefaultAllowUserInteraction(boolean)
   1.237 +     */
   1.238 +    protected boolean allowUserInteraction = defaultAllowUserInteraction;
   1.239 +
   1.240 +    private static boolean defaultUseCaches = true;
   1.241 +
   1.242 +   /**
   1.243 +     * If <code>true</code>, the protocol is allowed to use caching
   1.244 +     * whenever it can. If <code>false</code>, the protocol must always
   1.245 +     * try to get a fresh copy of the object.
   1.246 +     * <p>
   1.247 +     * This field is set by the <code>setUseCaches</code> method. Its
   1.248 +     * value is returned by the <code>getUseCaches</code> method.
   1.249 +     * <p>
   1.250 +     * Its default value is the value given in the last invocation of the
   1.251 +     * <code>setDefaultUseCaches</code> method.
   1.252 +     *
   1.253 +     * @see     java.net.URLConnection#setUseCaches(boolean)
   1.254 +     * @see     java.net.URLConnection#getUseCaches()
   1.255 +     * @see     java.net.URLConnection#setDefaultUseCaches(boolean)
   1.256 +     */
   1.257 +    protected boolean useCaches = defaultUseCaches;
   1.258 +
   1.259 +   /**
   1.260 +     * Some protocols support skipping the fetching of the object unless
   1.261 +     * the object has been modified more recently than a certain time.
   1.262 +     * <p>
   1.263 +     * A nonzero value gives a time as the number of milliseconds since
   1.264 +     * January 1, 1970, GMT. The object is fetched only if it has been
   1.265 +     * modified more recently than that time.
   1.266 +     * <p>
   1.267 +     * This variable is set by the <code>setIfModifiedSince</code>
   1.268 +     * method. Its value is returned by the
   1.269 +     * <code>getIfModifiedSince</code> method.
   1.270 +     * <p>
   1.271 +     * The default value of this field is <code>0</code>, indicating
   1.272 +     * that the fetching must always occur.
   1.273 +     *
   1.274 +     * @see     java.net.URLConnection#getIfModifiedSince()
   1.275 +     * @see     java.net.URLConnection#setIfModifiedSince(long)
   1.276 +     */
   1.277 +    protected long ifModifiedSince = 0;
   1.278 +
   1.279 +   /**
   1.280 +     * If <code>false</code>, this connection object has not created a
   1.281 +     * communications link to the specified URL. If <code>true</code>,
   1.282 +     * the communications link has been established.
   1.283 +     */
   1.284 +    protected boolean connected = false;
   1.285 +
   1.286 +    /**
   1.287 +     * @since 1.5
   1.288 +     */
   1.289 +    private int connectTimeout;
   1.290 +    private int readTimeout;
   1.291 +
   1.292 +    /**
   1.293 +     * @since 1.6
   1.294 +     */
   1.295 +    private MessageHeader requests;
   1.296 +
   1.297 +   /**
   1.298 +    * @since   JDK1.1
   1.299 +    */
   1.300 +    private static FileNameMap fileNameMap;
   1.301 +
   1.302 +    /**
   1.303 +     * @since 1.2.2
   1.304 +     */
   1.305 +    private static boolean fileNameMapLoaded = false;
   1.306 +
   1.307 +    /**
   1.308 +     * Loads filename map (a mimetable) from a data file. It will
   1.309 +     * first try to load the user-specific table, defined
   1.310 +     * by &quot;content.types.user.table&quot; property. If that fails,
   1.311 +     * it tries to load the default built-in table at
   1.312 +     * lib/content-types.properties under java home.
   1.313 +     *
   1.314 +     * @return the FileNameMap
   1.315 +     * @since 1.2
   1.316 +     * @see #setFileNameMap(java.net.FileNameMap)
   1.317 +     */
   1.318 +    public static synchronized FileNameMap getFileNameMap() {
   1.319 +        if ((fileNameMap == null) && !fileNameMapLoaded) {
   1.320 +            fileNameMap = sun.net.www.MimeTable.loadTable();
   1.321 +            fileNameMapLoaded = true;
   1.322 +        }
   1.323 +
   1.324 +        return new FileNameMap() {
   1.325 +            private FileNameMap map = fileNameMap;
   1.326 +            public String getContentTypeFor(String fileName) {
   1.327 +                return map.getContentTypeFor(fileName);
   1.328 +            }
   1.329 +        };
   1.330 +    }
   1.331 +
   1.332 +    /**
   1.333 +     * Sets the FileNameMap.
   1.334 +     * <p>
   1.335 +     * If there is a security manager, this method first calls
   1.336 +     * the security manager's <code>checkSetFactory</code> method
   1.337 +     * to ensure the operation is allowed.
   1.338 +     * This could result in a SecurityException.
   1.339 +     *
   1.340 +     * @param map the FileNameMap to be set
   1.341 +     * @exception  SecurityException  if a security manager exists and its
   1.342 +     *             <code>checkSetFactory</code> method doesn't allow the operation.
   1.343 +     * @see        SecurityManager#checkSetFactory
   1.344 +     * @see #getFileNameMap()
   1.345 +     * @since 1.2
   1.346 +     */
   1.347 +    public static void setFileNameMap(FileNameMap map) {
   1.348 +        SecurityManager sm = System.getSecurityManager();
   1.349 +        if (sm != null) sm.checkSetFactory();
   1.350 +        fileNameMap = map;
   1.351 +    }
   1.352 +
   1.353 +    /**
   1.354 +     * Opens a communications link to the resource referenced by this
   1.355 +     * URL, if such a connection has not already been established.
   1.356 +     * <p>
   1.357 +     * If the <code>connect</code> method is called when the connection
   1.358 +     * has already been opened (indicated by the <code>connected</code>
   1.359 +     * field having the value <code>true</code>), the call is ignored.
   1.360 +     * <p>
   1.361 +     * URLConnection objects go through two phases: first they are
   1.362 +     * created, then they are connected.  After being created, and
   1.363 +     * before being connected, various options can be specified
   1.364 +     * (e.g., doInput and UseCaches).  After connecting, it is an
   1.365 +     * error to try to set them.  Operations that depend on being
   1.366 +     * connected, like getContentLength, will implicitly perform the
   1.367 +     * connection, if necessary.
   1.368 +     *
   1.369 +     * @throws SocketTimeoutException if the timeout expires before
   1.370 +     *               the connection can be established
   1.371 +     * @exception  IOException  if an I/O error occurs while opening the
   1.372 +     *               connection.
   1.373 +     * @see java.net.URLConnection#connected
   1.374 +     * @see #getConnectTimeout()
   1.375 +     * @see #setConnectTimeout(int)
   1.376 +     */
   1.377 +    abstract public void connect() throws IOException;
   1.378 +
   1.379 +    /**
   1.380 +     * Sets a specified timeout value, in milliseconds, to be used
   1.381 +     * when opening a communications link to the resource referenced
   1.382 +     * by this URLConnection.  If the timeout expires before the
   1.383 +     * connection can be established, a
   1.384 +     * java.net.SocketTimeoutException is raised. A timeout of zero is
   1.385 +     * interpreted as an infinite timeout.
   1.386 +
   1.387 +     * <p> Some non-standard implmentation of this method may ignore
   1.388 +     * the specified timeout. To see the connect timeout set, please
   1.389 +     * call getConnectTimeout().
   1.390 +     *
   1.391 +     * @param timeout an <code>int</code> that specifies the connect
   1.392 +     *               timeout value in milliseconds
   1.393 +     * @throws IllegalArgumentException if the timeout parameter is negative
   1.394 +     *
   1.395 +     * @see #getConnectTimeout()
   1.396 +     * @see #connect()
   1.397 +     * @since 1.5
   1.398 +     */
   1.399 +    public void setConnectTimeout(int timeout) {
   1.400 +        if (timeout < 0) {
   1.401 +            throw new IllegalArgumentException("timeout can not be negative");
   1.402 +        }
   1.403 +        connectTimeout = timeout;
   1.404 +    }
   1.405 +
   1.406 +    /**
   1.407 +     * Returns setting for connect timeout.
   1.408 +     * <p>
   1.409 +     * 0 return implies that the option is disabled
   1.410 +     * (i.e., timeout of infinity).
   1.411 +     *
   1.412 +     * @return an <code>int</code> that indicates the connect timeout
   1.413 +     *         value in milliseconds
   1.414 +     * @see #setConnectTimeout(int)
   1.415 +     * @see #connect()
   1.416 +     * @since 1.5
   1.417 +     */
   1.418 +    public int getConnectTimeout() {
   1.419 +        return connectTimeout;
   1.420 +    }
   1.421 +
   1.422 +    /**
   1.423 +     * Sets the read timeout to a specified timeout, in
   1.424 +     * milliseconds. A non-zero value specifies the timeout when
   1.425 +     * reading from Input stream when a connection is established to a
   1.426 +     * resource. If the timeout expires before there is data available
   1.427 +     * for read, a java.net.SocketTimeoutException is raised. A
   1.428 +     * timeout of zero is interpreted as an infinite timeout.
   1.429 +     *
   1.430 +     *<p> Some non-standard implementation of this method ignores the
   1.431 +     * specified timeout. To see the read timeout set, please call
   1.432 +     * getReadTimeout().
   1.433 +     *
   1.434 +     * @param timeout an <code>int</code> that specifies the timeout
   1.435 +     * value to be used in milliseconds
   1.436 +     * @throws IllegalArgumentException if the timeout parameter is negative
   1.437 +     *
   1.438 +     * @see #getReadTimeout()
   1.439 +     * @see InputStream#read()
   1.440 +     * @since 1.5
   1.441 +     */
   1.442 +    public void setReadTimeout(int timeout) {
   1.443 +        if (timeout < 0) {
   1.444 +            throw new IllegalArgumentException("timeout can not be negative");
   1.445 +        }
   1.446 +        readTimeout = timeout;
   1.447 +    }
   1.448 +
   1.449 +    /**
   1.450 +     * Returns setting for read timeout. 0 return implies that the
   1.451 +     * option is disabled (i.e., timeout of infinity).
   1.452 +     *
   1.453 +     * @return an <code>int</code> that indicates the read timeout
   1.454 +     *         value in milliseconds
   1.455 +     *
   1.456 +     * @see #setReadTimeout(int)
   1.457 +     * @see InputStream#read()
   1.458 +     * @since 1.5
   1.459 +     */
   1.460 +    public int getReadTimeout() {
   1.461 +        return readTimeout;
   1.462 +    }
   1.463 +
   1.464 +    /**
   1.465 +     * Constructs a URL connection to the specified URL. A connection to
   1.466 +     * the object referenced by the URL is not created.
   1.467 +     *
   1.468 +     * @param   url   the specified URL.
   1.469 +     */
   1.470 +    protected URLConnection(URL url) {
   1.471 +        this.url = url;
   1.472 +    }
   1.473 +
   1.474 +    /**
   1.475 +     * Returns the value of this <code>URLConnection</code>'s <code>URL</code>
   1.476 +     * field.
   1.477 +     *
   1.478 +     * @return  the value of this <code>URLConnection</code>'s <code>URL</code>
   1.479 +     *          field.
   1.480 +     * @see     java.net.URLConnection#url
   1.481 +     */
   1.482 +    public URL getURL() {
   1.483 +        return url;
   1.484 +    }
   1.485 +
   1.486 +    /**
   1.487 +     * Returns the value of the <code>content-length</code> header field.
   1.488 +     * <P>
   1.489 +     * <B>Note</B>: {@link #getContentLengthLong() getContentLengthLong()}
   1.490 +     * should be preferred over this method, since it returns a {@code long}
   1.491 +     * instead and is therefore more portable.</P>
   1.492 +     *
   1.493 +     * @return  the content length of the resource that this connection's URL
   1.494 +     *          references, {@code -1} if the content length is not known,
   1.495 +     *          or if the content length is greater than Integer.MAX_VALUE.
   1.496 +     */
   1.497 +    public int getContentLength() {
   1.498 +        long l = getContentLengthLong();
   1.499 +        if (l > Integer.MAX_VALUE)
   1.500 +            return -1;
   1.501 +        return (int) l;
   1.502 +    }
   1.503 +
   1.504 +    /**
   1.505 +     * Returns the value of the <code>content-length</code> header field as a
   1.506 +     * long.
   1.507 +     *
   1.508 +     * @return  the content length of the resource that this connection's URL
   1.509 +     *          references, or <code>-1</code> if the content length is
   1.510 +     *          not known.
   1.511 +     * @since 7.0
   1.512 +     */
   1.513 +    public long getContentLengthLong() {
   1.514 +        return getHeaderFieldLong("content-length", -1);
   1.515 +    }
   1.516 +
   1.517 +    /**
   1.518 +     * Returns the value of the <code>content-type</code> header field.
   1.519 +     *
   1.520 +     * @return  the content type of the resource that the URL references,
   1.521 +     *          or <code>null</code> if not known.
   1.522 +     * @see     java.net.URLConnection#getHeaderField(java.lang.String)
   1.523 +     */
   1.524 +    public String getContentType() {
   1.525 +        return getHeaderField("content-type");
   1.526 +    }
   1.527 +
   1.528 +    /**
   1.529 +     * Returns the value of the <code>content-encoding</code> header field.
   1.530 +     *
   1.531 +     * @return  the content encoding of the resource that the URL references,
   1.532 +     *          or <code>null</code> if not known.
   1.533 +     * @see     java.net.URLConnection#getHeaderField(java.lang.String)
   1.534 +     */
   1.535 +    public String getContentEncoding() {
   1.536 +        return getHeaderField("content-encoding");
   1.537 +    }
   1.538 +
   1.539 +    /**
   1.540 +     * Returns the value of the <code>expires</code> header field.
   1.541 +     *
   1.542 +     * @return  the expiration date of the resource that this URL references,
   1.543 +     *          or 0 if not known. The value is the number of milliseconds since
   1.544 +     *          January 1, 1970 GMT.
   1.545 +     * @see     java.net.URLConnection#getHeaderField(java.lang.String)
   1.546 +     */
   1.547 +    public long getExpiration() {
   1.548 +        return getHeaderFieldDate("expires", 0);
   1.549 +    }
   1.550 +
   1.551 +    /**
   1.552 +     * Returns the value of the <code>date</code> header field.
   1.553 +     *
   1.554 +     * @return  the sending date of the resource that the URL references,
   1.555 +     *          or <code>0</code> if not known. The value returned is the
   1.556 +     *          number of milliseconds since January 1, 1970 GMT.
   1.557 +     * @see     java.net.URLConnection#getHeaderField(java.lang.String)
   1.558 +     */
   1.559 +    public long getDate() {
   1.560 +        return getHeaderFieldDate("date", 0);
   1.561 +    }
   1.562 +
   1.563 +    /**
   1.564 +     * Returns the value of the <code>last-modified</code> header field.
   1.565 +     * The result is the number of milliseconds since January 1, 1970 GMT.
   1.566 +     *
   1.567 +     * @return  the date the resource referenced by this
   1.568 +     *          <code>URLConnection</code> was last modified, or 0 if not known.
   1.569 +     * @see     java.net.URLConnection#getHeaderField(java.lang.String)
   1.570 +     */
   1.571 +    public long getLastModified() {
   1.572 +        return getHeaderFieldDate("last-modified", 0);
   1.573 +    }
   1.574 +
   1.575 +    /**
   1.576 +     * Returns the value of the named header field.
   1.577 +     * <p>
   1.578 +     * If called on a connection that sets the same header multiple times
   1.579 +     * with possibly different values, only the last value is returned.
   1.580 +     *
   1.581 +     *
   1.582 +     * @param   name   the name of a header field.
   1.583 +     * @return  the value of the named header field, or <code>null</code>
   1.584 +     *          if there is no such field in the header.
   1.585 +     */
   1.586 +    public String getHeaderField(String name) {
   1.587 +        return null;
   1.588 +    }
   1.589 +
   1.590 +    /**
   1.591 +     * Returns an unmodifiable Map of the header fields.
   1.592 +     * The Map keys are Strings that represent the
   1.593 +     * response-header field names. Each Map value is an
   1.594 +     * unmodifiable List of Strings that represents
   1.595 +     * the corresponding field values.
   1.596 +     *
   1.597 +     * @return a Map of header fields
   1.598 +     * @since 1.4
   1.599 +     */
   1.600 +    public Map<String,List<String>> getHeaderFields() {
   1.601 +        return Collections.EMPTY_MAP;
   1.602 +    }
   1.603 +
   1.604 +    /**
   1.605 +     * Returns the value of the named field parsed as a number.
   1.606 +     * <p>
   1.607 +     * This form of <code>getHeaderField</code> exists because some
   1.608 +     * connection types (e.g., <code>http-ng</code>) have pre-parsed
   1.609 +     * headers. Classes for that connection type can override this method
   1.610 +     * and short-circuit the parsing.
   1.611 +     *
   1.612 +     * @param   name      the name of the header field.
   1.613 +     * @param   Default   the default value.
   1.614 +     * @return  the value of the named field, parsed as an integer. The
   1.615 +     *          <code>Default</code> value is returned if the field is
   1.616 +     *          missing or malformed.
   1.617 +     */
   1.618 +    public int getHeaderFieldInt(String name, int Default) {
   1.619 +        String value = getHeaderField(name);
   1.620 +        try {
   1.621 +            return Integer.parseInt(value);
   1.622 +        } catch (Exception e) { }
   1.623 +        return Default;
   1.624 +    }
   1.625 +
   1.626 +    /**
   1.627 +     * Returns the value of the named field parsed as a number.
   1.628 +     * <p>
   1.629 +     * This form of <code>getHeaderField</code> exists because some
   1.630 +     * connection types (e.g., <code>http-ng</code>) have pre-parsed
   1.631 +     * headers. Classes for that connection type can override this method
   1.632 +     * and short-circuit the parsing.
   1.633 +     *
   1.634 +     * @param   name      the name of the header field.
   1.635 +     * @param   Default   the default value.
   1.636 +     * @return  the value of the named field, parsed as a long. The
   1.637 +     *          <code>Default</code> value is returned if the field is
   1.638 +     *          missing or malformed.
   1.639 +     * @since 7.0
   1.640 +     */
   1.641 +    public long getHeaderFieldLong(String name, long Default) {
   1.642 +        String value = getHeaderField(name);
   1.643 +        try {
   1.644 +            return Long.parseLong(value);
   1.645 +        } catch (Exception e) { }
   1.646 +        return Default;
   1.647 +    }
   1.648 +
   1.649 +    /**
   1.650 +     * Returns the value of the named field parsed as date.
   1.651 +     * The result is the number of milliseconds since January 1, 1970 GMT
   1.652 +     * represented by the named field.
   1.653 +     * <p>
   1.654 +     * This form of <code>getHeaderField</code> exists because some
   1.655 +     * connection types (e.g., <code>http-ng</code>) have pre-parsed
   1.656 +     * headers. Classes for that connection type can override this method
   1.657 +     * and short-circuit the parsing.
   1.658 +     *
   1.659 +     * @param   name     the name of the header field.
   1.660 +     * @param   Default   a default value.
   1.661 +     * @return  the value of the field, parsed as a date. The value of the
   1.662 +     *          <code>Default</code> argument is returned if the field is
   1.663 +     *          missing or malformed.
   1.664 +     */
   1.665 +    public long getHeaderFieldDate(String name, long Default) {
   1.666 +        String value = getHeaderField(name);
   1.667 +        try {
   1.668 +            return Date.parse(value);
   1.669 +        } catch (Exception e) { }
   1.670 +        return Default;
   1.671 +    }
   1.672 +
   1.673 +    /**
   1.674 +     * Returns the key for the <code>n</code><sup>th</sup> header field.
   1.675 +     * It returns <code>null</code> if there are fewer than <code>n+1</code> fields.
   1.676 +     *
   1.677 +     * @param   n   an index, where n>=0
   1.678 +     * @return  the key for the <code>n</code><sup>th</sup> header field,
   1.679 +     *          or <code>null</code> if there are fewer than <code>n+1</code>
   1.680 +     *          fields.
   1.681 +     */
   1.682 +    public String getHeaderFieldKey(int n) {
   1.683 +        return null;
   1.684 +    }
   1.685 +
   1.686 +    /**
   1.687 +     * Returns the value for the <code>n</code><sup>th</sup> header field.
   1.688 +     * It returns <code>null</code> if there are fewer than
   1.689 +     * <code>n+1</code>fields.
   1.690 +     * <p>
   1.691 +     * This method can be used in conjunction with the
   1.692 +     * {@link #getHeaderFieldKey(int) getHeaderFieldKey} method to iterate through all
   1.693 +     * the headers in the message.
   1.694 +     *
   1.695 +     * @param   n   an index, where n>=0
   1.696 +     * @return  the value of the <code>n</code><sup>th</sup> header field
   1.697 +     *          or <code>null</code> if there are fewer than <code>n+1</code> fields
   1.698 +     * @see     java.net.URLConnection#getHeaderFieldKey(int)
   1.699 +     */
   1.700 +    public String getHeaderField(int n) {
   1.701 +        return null;
   1.702 +    }
   1.703 +
   1.704 +    /**
   1.705 +     * Retrieves the contents of this URL connection.
   1.706 +     * <p>
   1.707 +     * This method first determines the content type of the object by
   1.708 +     * calling the <code>getContentType</code> method. If this is
   1.709 +     * the first time that the application has seen that specific content
   1.710 +     * type, a content handler for that content type is created:
   1.711 +     * <ol>
   1.712 +     * <li>If the application has set up a content handler factory instance
   1.713 +     *     using the <code>setContentHandlerFactory</code> method, the
   1.714 +     *     <code>createContentHandler</code> method of that instance is called
   1.715 +     *     with the content type as an argument; the result is a content
   1.716 +     *     handler for that content type.
   1.717 +     * <li>If no content handler factory has yet been set up, or if the
   1.718 +     *     factory's <code>createContentHandler</code> method returns
   1.719 +     *     <code>null</code>, then the application loads the class named:
   1.720 +     *     <blockquote><pre>
   1.721 +     *         sun.net.www.content.&lt;<i>contentType</i>&gt;
   1.722 +     *     </pre></blockquote>
   1.723 +     *     where &lt;<i>contentType</i>&gt; is formed by taking the
   1.724 +     *     content-type string, replacing all slash characters with a
   1.725 +     *     <code>period</code> ('.'), and all other non-alphanumeric characters
   1.726 +     *     with the underscore character '<code>_</code>'. The alphanumeric
   1.727 +     *     characters are specifically the 26 uppercase ASCII letters
   1.728 +     *     '<code>A</code>' through '<code>Z</code>', the 26 lowercase ASCII
   1.729 +     *     letters '<code>a</code>' through '<code>z</code>', and the 10 ASCII
   1.730 +     *     digits '<code>0</code>' through '<code>9</code>'. If the specified
   1.731 +     *     class does not exist, or is not a subclass of
   1.732 +     *     <code>ContentHandler</code>, then an
   1.733 +     *     <code>UnknownServiceException</code> is thrown.
   1.734 +     * </ol>
   1.735 +     *
   1.736 +     * @return     the object fetched. The <code>instanceof</code> operator
   1.737 +     *               should be used to determine the specific kind of object
   1.738 +     *               returned.
   1.739 +     * @exception  IOException              if an I/O error occurs while
   1.740 +     *               getting the content.
   1.741 +     * @exception  UnknownServiceException  if the protocol does not support
   1.742 +     *               the content type.
   1.743 +     * @see        java.net.ContentHandlerFactory#createContentHandler(java.lang.String)
   1.744 +     * @see        java.net.URLConnection#getContentType()
   1.745 +     * @see        java.net.URLConnection#setContentHandlerFactory(java.net.ContentHandlerFactory)
   1.746 +     */
   1.747 +    public Object getContent() throws IOException {
   1.748 +        // Must call getInputStream before GetHeaderField gets called
   1.749 +        // so that FileNotFoundException has a chance to be thrown up
   1.750 +        // from here without being caught.
   1.751 +        getInputStream();
   1.752 +        return getContentHandler().getContent(this);
   1.753 +    }
   1.754 +
   1.755 +    /**
   1.756 +     * Retrieves the contents of this URL connection.
   1.757 +     *
   1.758 +     * @param classes the <code>Class</code> array
   1.759 +     * indicating the requested types
   1.760 +     * @return     the object fetched that is the first match of the type
   1.761 +     *               specified in the classes array. null if none of
   1.762 +     *               the requested types are supported.
   1.763 +     *               The <code>instanceof</code> operator should be used to
   1.764 +     *               determine the specific kind of object returned.
   1.765 +     * @exception  IOException              if an I/O error occurs while
   1.766 +     *               getting the content.
   1.767 +     * @exception  UnknownServiceException  if the protocol does not support
   1.768 +     *               the content type.
   1.769 +     * @see        java.net.URLConnection#getContent()
   1.770 +     * @see        java.net.ContentHandlerFactory#createContentHandler(java.lang.String)
   1.771 +     * @see        java.net.URLConnection#getContent(java.lang.Class[])
   1.772 +     * @see        java.net.URLConnection#setContentHandlerFactory(java.net.ContentHandlerFactory)
   1.773 +     * @since 1.3
   1.774 +     */
   1.775 +    public Object getContent(Class[] classes) throws IOException {
   1.776 +        // Must call getInputStream before GetHeaderField gets called
   1.777 +        // so that FileNotFoundException has a chance to be thrown up
   1.778 +        // from here without being caught.
   1.779 +        getInputStream();
   1.780 +        return getContentHandler().getContent(this, classes);
   1.781 +    }
   1.782 +
   1.783 +    /**
   1.784 +     * Returns a permission object representing the permission
   1.785 +     * necessary to make the connection represented by this
   1.786 +     * object. This method returns null if no permission is
   1.787 +     * required to make the connection. By default, this method
   1.788 +     * returns <code>java.security.AllPermission</code>. Subclasses
   1.789 +     * should override this method and return the permission
   1.790 +     * that best represents the permission required to make a
   1.791 +     * a connection to the URL. For example, a <code>URLConnection</code>
   1.792 +     * representing a <code>file:</code> URL would return a
   1.793 +     * <code>java.io.FilePermission</code> object.
   1.794 +     *
   1.795 +     * <p>The permission returned may dependent upon the state of the
   1.796 +     * connection. For example, the permission before connecting may be
   1.797 +     * different from that after connecting. For example, an HTTP
   1.798 +     * sever, say foo.com, may redirect the connection to a different
   1.799 +     * host, say bar.com. Before connecting the permission returned by
   1.800 +     * the connection will represent the permission needed to connect
   1.801 +     * to foo.com, while the permission returned after connecting will
   1.802 +     * be to bar.com.
   1.803 +     *
   1.804 +     * <p>Permissions are generally used for two purposes: to protect
   1.805 +     * caches of objects obtained through URLConnections, and to check
   1.806 +     * the right of a recipient to learn about a particular URL. In
   1.807 +     * the first case, the permission should be obtained
   1.808 +     * <em>after</em> the object has been obtained. For example, in an
   1.809 +     * HTTP connection, this will represent the permission to connect
   1.810 +     * to the host from which the data was ultimately fetched. In the
   1.811 +     * second case, the permission should be obtained and tested
   1.812 +     * <em>before</em> connecting.
   1.813 +     *
   1.814 +     * @return the permission object representing the permission
   1.815 +     * necessary to make the connection represented by this
   1.816 +     * URLConnection.
   1.817 +     *
   1.818 +     * @exception IOException if the computation of the permission
   1.819 +     * requires network or file I/O and an exception occurs while
   1.820 +     * computing it.
   1.821 +     */
   1.822 +    public Permission getPermission() throws IOException {
   1.823 +        return SecurityConstants.ALL_PERMISSION;
   1.824 +    }
   1.825 +
   1.826 +    /**
   1.827 +     * Returns an input stream that reads from this open connection.
   1.828 +     *
   1.829 +     * A SocketTimeoutException can be thrown when reading from the
   1.830 +     * returned input stream if the read timeout expires before data
   1.831 +     * is available for read.
   1.832 +     *
   1.833 +     * @return     an input stream that reads from this open connection.
   1.834 +     * @exception  IOException              if an I/O error occurs while
   1.835 +     *               creating the input stream.
   1.836 +     * @exception  UnknownServiceException  if the protocol does not support
   1.837 +     *               input.
   1.838 +     * @see #setReadTimeout(int)
   1.839 +     * @see #getReadTimeout()
   1.840 +     */
   1.841 +    public InputStream getInputStream() throws IOException {
   1.842 +        throw new UnknownServiceException("protocol doesn't support input");
   1.843 +    }
   1.844 +
   1.845 +    /**
   1.846 +     * Returns an output stream that writes to this connection.
   1.847 +     *
   1.848 +     * @return     an output stream that writes to this connection.
   1.849 +     * @exception  IOException              if an I/O error occurs while
   1.850 +     *               creating the output stream.
   1.851 +     * @exception  UnknownServiceException  if the protocol does not support
   1.852 +     *               output.
   1.853 +     */
   1.854 +    public OutputStream getOutputStream() throws IOException {
   1.855 +        throw new UnknownServiceException("protocol doesn't support output");
   1.856 +    }
   1.857 +
   1.858 +    /**
   1.859 +     * Returns a <code>String</code> representation of this URL connection.
   1.860 +     *
   1.861 +     * @return  a string representation of this <code>URLConnection</code>.
   1.862 +     */
   1.863 +    public String toString() {
   1.864 +        return this.getClass().getName() + ":" + url;
   1.865 +    }
   1.866 +
   1.867 +    /**
   1.868 +     * Sets the value of the <code>doInput</code> field for this
   1.869 +     * <code>URLConnection</code> to the specified value.
   1.870 +     * <p>
   1.871 +     * A URL connection can be used for input and/or output.  Set the DoInput
   1.872 +     * flag to true if you intend to use the URL connection for input,
   1.873 +     * false if not.  The default is true.
   1.874 +     *
   1.875 +     * @param   doinput   the new value.
   1.876 +     * @throws IllegalStateException if already connected
   1.877 +     * @see     java.net.URLConnection#doInput
   1.878 +     * @see #getDoInput()
   1.879 +     */
   1.880 +    public void setDoInput(boolean doinput) {
   1.881 +        if (connected)
   1.882 +            throw new IllegalStateException("Already connected");
   1.883 +        doInput = doinput;
   1.884 +    }
   1.885 +
   1.886 +    /**
   1.887 +     * Returns the value of this <code>URLConnection</code>'s
   1.888 +     * <code>doInput</code> flag.
   1.889 +     *
   1.890 +     * @return  the value of this <code>URLConnection</code>'s
   1.891 +     *          <code>doInput</code> flag.
   1.892 +     * @see     #setDoInput(boolean)
   1.893 +     */
   1.894 +    public boolean getDoInput() {
   1.895 +        return doInput;
   1.896 +    }
   1.897 +
   1.898 +    /**
   1.899 +     * Sets the value of the <code>doOutput</code> field for this
   1.900 +     * <code>URLConnection</code> to the specified value.
   1.901 +     * <p>
   1.902 +     * A URL connection can be used for input and/or output.  Set the DoOutput
   1.903 +     * flag to true if you intend to use the URL connection for output,
   1.904 +     * false if not.  The default is false.
   1.905 +     *
   1.906 +     * @param   dooutput   the new value.
   1.907 +     * @throws IllegalStateException if already connected
   1.908 +     * @see #getDoOutput()
   1.909 +     */
   1.910 +    public void setDoOutput(boolean dooutput) {
   1.911 +        if (connected)
   1.912 +            throw new IllegalStateException("Already connected");
   1.913 +        doOutput = dooutput;
   1.914 +    }
   1.915 +
   1.916 +    /**
   1.917 +     * Returns the value of this <code>URLConnection</code>'s
   1.918 +     * <code>doOutput</code> flag.
   1.919 +     *
   1.920 +     * @return  the value of this <code>URLConnection</code>'s
   1.921 +     *          <code>doOutput</code> flag.
   1.922 +     * @see     #setDoOutput(boolean)
   1.923 +     */
   1.924 +    public boolean getDoOutput() {
   1.925 +        return doOutput;
   1.926 +    }
   1.927 +
   1.928 +    /**
   1.929 +     * Set the value of the <code>allowUserInteraction</code> field of
   1.930 +     * this <code>URLConnection</code>.
   1.931 +     *
   1.932 +     * @param   allowuserinteraction   the new value.
   1.933 +     * @throws IllegalStateException if already connected
   1.934 +     * @see     #getAllowUserInteraction()
   1.935 +     */
   1.936 +    public void setAllowUserInteraction(boolean allowuserinteraction) {
   1.937 +        if (connected)
   1.938 +            throw new IllegalStateException("Already connected");
   1.939 +        allowUserInteraction = allowuserinteraction;
   1.940 +    }
   1.941 +
   1.942 +    /**
   1.943 +     * Returns the value of the <code>allowUserInteraction</code> field for
   1.944 +     * this object.
   1.945 +     *
   1.946 +     * @return  the value of the <code>allowUserInteraction</code> field for
   1.947 +     *          this object.
   1.948 +     * @see     #setAllowUserInteraction(boolean)
   1.949 +     */
   1.950 +    public boolean getAllowUserInteraction() {
   1.951 +        return allowUserInteraction;
   1.952 +    }
   1.953 +
   1.954 +    /**
   1.955 +     * Sets the default value of the
   1.956 +     * <code>allowUserInteraction</code> field for all future
   1.957 +     * <code>URLConnection</code> objects to the specified value.
   1.958 +     *
   1.959 +     * @param   defaultallowuserinteraction   the new value.
   1.960 +     * @see     #getDefaultAllowUserInteraction()
   1.961 +     */
   1.962 +    public static void setDefaultAllowUserInteraction(boolean defaultallowuserinteraction) {
   1.963 +        defaultAllowUserInteraction = defaultallowuserinteraction;
   1.964 +    }
   1.965 +
   1.966 +    /**
   1.967 +     * Returns the default value of the <code>allowUserInteraction</code>
   1.968 +     * field.
   1.969 +     * <p>
   1.970 +     * Ths default is "sticky", being a part of the static state of all
   1.971 +     * URLConnections.  This flag applies to the next, and all following
   1.972 +     * URLConnections that are created.
   1.973 +     *
   1.974 +     * @return  the default value of the <code>allowUserInteraction</code>
   1.975 +     *          field.
   1.976 +     * @see     #setDefaultAllowUserInteraction(boolean)
   1.977 +     */
   1.978 +    public static boolean getDefaultAllowUserInteraction() {
   1.979 +        return defaultAllowUserInteraction;
   1.980 +    }
   1.981 +
   1.982 +    /**
   1.983 +     * Sets the value of the <code>useCaches</code> field of this
   1.984 +     * <code>URLConnection</code> to the specified value.
   1.985 +     * <p>
   1.986 +     * Some protocols do caching of documents.  Occasionally, it is important
   1.987 +     * to be able to "tunnel through" and ignore the caches (e.g., the
   1.988 +     * "reload" button in a browser).  If the UseCaches flag on a connection
   1.989 +     * is true, the connection is allowed to use whatever caches it can.
   1.990 +     *  If false, caches are to be ignored.
   1.991 +     *  The default value comes from DefaultUseCaches, which defaults to
   1.992 +     * true.
   1.993 +     *
   1.994 +     * @param usecaches a <code>boolean</code> indicating whether
   1.995 +     * or not to allow caching
   1.996 +     * @throws IllegalStateException if already connected
   1.997 +     * @see #getUseCaches()
   1.998 +     */
   1.999 +    public void setUseCaches(boolean usecaches) {
  1.1000 +        if (connected)
  1.1001 +            throw new IllegalStateException("Already connected");
  1.1002 +        useCaches = usecaches;
  1.1003 +    }
  1.1004 +
  1.1005 +    /**
  1.1006 +     * Returns the value of this <code>URLConnection</code>'s
  1.1007 +     * <code>useCaches</code> field.
  1.1008 +     *
  1.1009 +     * @return  the value of this <code>URLConnection</code>'s
  1.1010 +     *          <code>useCaches</code> field.
  1.1011 +     * @see #setUseCaches(boolean)
  1.1012 +     */
  1.1013 +    public boolean getUseCaches() {
  1.1014 +        return useCaches;
  1.1015 +    }
  1.1016 +
  1.1017 +    /**
  1.1018 +     * Sets the value of the <code>ifModifiedSince</code> field of
  1.1019 +     * this <code>URLConnection</code> to the specified value.
  1.1020 +     *
  1.1021 +     * @param   ifmodifiedsince   the new value.
  1.1022 +     * @throws IllegalStateException if already connected
  1.1023 +     * @see     #getIfModifiedSince()
  1.1024 +     */
  1.1025 +    public void setIfModifiedSince(long ifmodifiedsince) {
  1.1026 +        if (connected)
  1.1027 +            throw new IllegalStateException("Already connected");
  1.1028 +        ifModifiedSince = ifmodifiedsince;
  1.1029 +    }
  1.1030 +
  1.1031 +    /**
  1.1032 +     * Returns the value of this object's <code>ifModifiedSince</code> field.
  1.1033 +     *
  1.1034 +     * @return  the value of this object's <code>ifModifiedSince</code> field.
  1.1035 +     * @see #setIfModifiedSince(long)
  1.1036 +     */
  1.1037 +    public long getIfModifiedSince() {
  1.1038 +        return ifModifiedSince;
  1.1039 +    }
  1.1040 +
  1.1041 +   /**
  1.1042 +     * Returns the default value of a <code>URLConnection</code>'s
  1.1043 +     * <code>useCaches</code> flag.
  1.1044 +     * <p>
  1.1045 +     * Ths default is "sticky", being a part of the static state of all
  1.1046 +     * URLConnections.  This flag applies to the next, and all following
  1.1047 +     * URLConnections that are created.
  1.1048 +     *
  1.1049 +     * @return  the default value of a <code>URLConnection</code>'s
  1.1050 +     *          <code>useCaches</code> flag.
  1.1051 +     * @see     #setDefaultUseCaches(boolean)
  1.1052 +     */
  1.1053 +    public boolean getDefaultUseCaches() {
  1.1054 +        return defaultUseCaches;
  1.1055 +    }
  1.1056 +
  1.1057 +   /**
  1.1058 +     * Sets the default value of the <code>useCaches</code> field to the
  1.1059 +     * specified value.
  1.1060 +     *
  1.1061 +     * @param   defaultusecaches   the new value.
  1.1062 +     * @see     #getDefaultUseCaches()
  1.1063 +     */
  1.1064 +    public void setDefaultUseCaches(boolean defaultusecaches) {
  1.1065 +        defaultUseCaches = defaultusecaches;
  1.1066 +    }
  1.1067 +
  1.1068 +    /**
  1.1069 +     * Sets the general request property. If a property with the key already
  1.1070 +     * exists, overwrite its value with the new value.
  1.1071 +     *
  1.1072 +     * <p> NOTE: HTTP requires all request properties which can
  1.1073 +     * legally have multiple instances with the same key
  1.1074 +     * to use a comma-seperated list syntax which enables multiple
  1.1075 +     * properties to be appended into a single property.
  1.1076 +     *
  1.1077 +     * @param   key     the keyword by which the request is known
  1.1078 +     *                  (e.g., "<code>Accept</code>").
  1.1079 +     * @param   value   the value associated with it.
  1.1080 +     * @throws IllegalStateException if already connected
  1.1081 +     * @throws NullPointerException if key is <CODE>null</CODE>
  1.1082 +     * @see #getRequestProperty(java.lang.String)
  1.1083 +     */
  1.1084 +    public void setRequestProperty(String key, String value) {
  1.1085 +        if (connected)
  1.1086 +            throw new IllegalStateException("Already connected");
  1.1087 +        if (key == null)
  1.1088 +            throw new NullPointerException ("key is null");
  1.1089 +
  1.1090 +        if (requests == null)
  1.1091 +            requests = new MessageHeader();
  1.1092 +
  1.1093 +        requests.set(key, value);
  1.1094 +    }
  1.1095 +
  1.1096 +    /**
  1.1097 +     * Adds a general request property specified by a
  1.1098 +     * key-value pair.  This method will not overwrite
  1.1099 +     * existing values associated with the same key.
  1.1100 +     *
  1.1101 +     * @param   key     the keyword by which the request is known
  1.1102 +     *                  (e.g., "<code>Accept</code>").
  1.1103 +     * @param   value  the value associated with it.
  1.1104 +     * @throws IllegalStateException if already connected
  1.1105 +     * @throws NullPointerException if key is null
  1.1106 +     * @see #getRequestProperties()
  1.1107 +     * @since 1.4
  1.1108 +     */
  1.1109 +    public void addRequestProperty(String key, String value) {
  1.1110 +        if (connected)
  1.1111 +            throw new IllegalStateException("Already connected");
  1.1112 +        if (key == null)
  1.1113 +            throw new NullPointerException ("key is null");
  1.1114 +
  1.1115 +        if (requests == null)
  1.1116 +            requests = new MessageHeader();
  1.1117 +
  1.1118 +        requests.add(key, value);
  1.1119 +    }
  1.1120 +
  1.1121 +
  1.1122 +    /**
  1.1123 +     * Returns the value of the named general request property for this
  1.1124 +     * connection.
  1.1125 +     *
  1.1126 +     * @param key the keyword by which the request is known (e.g., "Accept").
  1.1127 +     * @return  the value of the named general request property for this
  1.1128 +     *           connection. If key is null, then null is returned.
  1.1129 +     * @throws IllegalStateException if already connected
  1.1130 +     * @see #setRequestProperty(java.lang.String, java.lang.String)
  1.1131 +     */
  1.1132 +    public String getRequestProperty(String key) {
  1.1133 +        if (connected)
  1.1134 +            throw new IllegalStateException("Already connected");
  1.1135 +
  1.1136 +        if (requests == null)
  1.1137 +            return null;
  1.1138 +
  1.1139 +        return requests.findValue(key);
  1.1140 +    }
  1.1141 +
  1.1142 +    /**
  1.1143 +     * Returns an unmodifiable Map of general request
  1.1144 +     * properties for this connection. The Map keys
  1.1145 +     * are Strings that represent the request-header
  1.1146 +     * field names. Each Map value is a unmodifiable List
  1.1147 +     * of Strings that represents the corresponding
  1.1148 +     * field values.
  1.1149 +     *
  1.1150 +     * @return  a Map of the general request properties for this connection.
  1.1151 +     * @throws IllegalStateException if already connected
  1.1152 +     * @since 1.4
  1.1153 +     */
  1.1154 +    public Map<String,List<String>> getRequestProperties() {
  1.1155 +        if (connected)
  1.1156 +            throw new IllegalStateException("Already connected");
  1.1157 +
  1.1158 +        if (requests == null)
  1.1159 +            return Collections.EMPTY_MAP;
  1.1160 +
  1.1161 +        return requests.getHeaders(null);
  1.1162 +    }
  1.1163 +
  1.1164 +    /**
  1.1165 +     * Sets the default value of a general request property. When a
  1.1166 +     * <code>URLConnection</code> is created, it is initialized with
  1.1167 +     * these properties.
  1.1168 +     *
  1.1169 +     * @param   key     the keyword by which the request is known
  1.1170 +     *                  (e.g., "<code>Accept</code>").
  1.1171 +     * @param   value   the value associated with the key.
  1.1172 +     *
  1.1173 +     * @see java.net.URLConnection#setRequestProperty(java.lang.String,java.lang.String)
  1.1174 +     *
  1.1175 +     * @deprecated The instance specific setRequestProperty method
  1.1176 +     * should be used after an appropriate instance of URLConnection
  1.1177 +     * is obtained. Invoking this method will have no effect.
  1.1178 +     *
  1.1179 +     * @see #getDefaultRequestProperty(java.lang.String)
  1.1180 +     */
  1.1181 +    @Deprecated
  1.1182 +    public static void setDefaultRequestProperty(String key, String value) {
  1.1183 +    }
  1.1184 +
  1.1185 +    /**
  1.1186 +     * Returns the value of the default request property. Default request
  1.1187 +     * properties are set for every connection.
  1.1188 +     *
  1.1189 +     * @param key the keyword by which the request is known (e.g., "Accept").
  1.1190 +     * @return  the value of the default request property
  1.1191 +     * for the specified key.
  1.1192 +     *
  1.1193 +     * @see java.net.URLConnection#getRequestProperty(java.lang.String)
  1.1194 +     *
  1.1195 +     * @deprecated The instance specific getRequestProperty method
  1.1196 +     * should be used after an appropriate instance of URLConnection
  1.1197 +     * is obtained.
  1.1198 +     *
  1.1199 +     * @see #setDefaultRequestProperty(java.lang.String, java.lang.String)
  1.1200 +     */
  1.1201 +    @Deprecated
  1.1202 +    public static String getDefaultRequestProperty(String key) {
  1.1203 +        return null;
  1.1204 +    }
  1.1205 +
  1.1206 +    /**
  1.1207 +     * The ContentHandler factory.
  1.1208 +     */
  1.1209 +    static ContentHandlerFactory factory;
  1.1210 +
  1.1211 +    /**
  1.1212 +     * Sets the <code>ContentHandlerFactory</code> of an
  1.1213 +     * application. It can be called at most once by an application.
  1.1214 +     * <p>
  1.1215 +     * The <code>ContentHandlerFactory</code> instance is used to
  1.1216 +     * construct a content handler from a content type
  1.1217 +     * <p>
  1.1218 +     * If there is a security manager, this method first calls
  1.1219 +     * the security manager's <code>checkSetFactory</code> method
  1.1220 +     * to ensure the operation is allowed.
  1.1221 +     * This could result in a SecurityException.
  1.1222 +     *
  1.1223 +     * @param      fac   the desired factory.
  1.1224 +     * @exception  Error  if the factory has already been defined.
  1.1225 +     * @exception  SecurityException  if a security manager exists and its
  1.1226 +     *             <code>checkSetFactory</code> method doesn't allow the operation.
  1.1227 +     * @see        java.net.ContentHandlerFactory
  1.1228 +     * @see        java.net.URLConnection#getContent()
  1.1229 +     * @see        SecurityManager#checkSetFactory
  1.1230 +     */
  1.1231 +    public static synchronized void setContentHandlerFactory(ContentHandlerFactory fac) {
  1.1232 +        if (factory != null) {
  1.1233 +            throw new Error("factory already defined");
  1.1234 +        }
  1.1235 +        SecurityManager security = System.getSecurityManager();
  1.1236 +        if (security != null) {
  1.1237 +            security.checkSetFactory();
  1.1238 +        }
  1.1239 +        factory = fac;
  1.1240 +    }
  1.1241 +
  1.1242 +    private static Hashtable handlers = new Hashtable();
  1.1243 +
  1.1244 +    /**
  1.1245 +     * Gets the Content Handler appropriate for this connection.
  1.1246 +     * @param connection the connection to use.
  1.1247 +     */
  1.1248 +    synchronized ContentHandler getContentHandler()
  1.1249 +    throws UnknownServiceException
  1.1250 +    {
  1.1251 +        String contentType = stripOffParameters(getContentType());
  1.1252 +        ContentHandler handler = null;
  1.1253 +        if (contentType == null)
  1.1254 +            throw new UnknownServiceException("no content-type");
  1.1255 +        try {
  1.1256 +            handler = (ContentHandler) handlers.get(contentType);
  1.1257 +            if (handler != null)
  1.1258 +                return handler;
  1.1259 +        } catch(Exception e) {
  1.1260 +        }
  1.1261 +
  1.1262 +        if (factory != null)
  1.1263 +            handler = factory.createContentHandler(contentType);
  1.1264 +        if (handler == null) {
  1.1265 +            try {
  1.1266 +                handler = lookupContentHandlerClassFor(contentType);
  1.1267 +            } catch(Exception e) {
  1.1268 +                e.printStackTrace();
  1.1269 +                handler = UnknownContentHandler.INSTANCE;
  1.1270 +            }
  1.1271 +            handlers.put(contentType, handler);
  1.1272 +        }
  1.1273 +        return handler;
  1.1274 +    }
  1.1275 +
  1.1276 +    /*
  1.1277 +     * Media types are in the format: type/subtype*(; parameter).
  1.1278 +     * For looking up the content handler, we should ignore those
  1.1279 +     * parameters.
  1.1280 +     */
  1.1281 +    private String stripOffParameters(String contentType)
  1.1282 +    {
  1.1283 +        if (contentType == null)
  1.1284 +            return null;
  1.1285 +        int index = contentType.indexOf(';');
  1.1286 +
  1.1287 +        if (index > 0)
  1.1288 +            return contentType.substring(0, index);
  1.1289 +        else
  1.1290 +            return contentType;
  1.1291 +    }
  1.1292 +
  1.1293 +    private static final String contentClassPrefix = "sun.net.www.content";
  1.1294 +    private static final String contentPathProp = "java.content.handler.pkgs";
  1.1295 +
  1.1296 +    /**
  1.1297 +     * Looks for a content handler in a user-defineable set of places.
  1.1298 +     * By default it looks in sun.net.www.content, but users can define a
  1.1299 +     * vertical-bar delimited set of class prefixes to search through in
  1.1300 +     * addition by defining the java.content.handler.pkgs property.
  1.1301 +     * The class name must be of the form:
  1.1302 +     * <pre>
  1.1303 +     *     {package-prefix}.{major}.{minor}
  1.1304 +     * e.g.
  1.1305 +     *     YoyoDyne.experimental.text.plain
  1.1306 +     * </pre>
  1.1307 +     */
  1.1308 +    private ContentHandler lookupContentHandlerClassFor(String contentType)
  1.1309 +        throws InstantiationException, IllegalAccessException, ClassNotFoundException {
  1.1310 +        String contentHandlerClassName = typeToPackageName(contentType);
  1.1311 +
  1.1312 +        String contentHandlerPkgPrefixes =getContentHandlerPkgPrefixes();
  1.1313 +
  1.1314 +        StringTokenizer packagePrefixIter =
  1.1315 +            new StringTokenizer(contentHandlerPkgPrefixes, "|");
  1.1316 +
  1.1317 +        while (packagePrefixIter.hasMoreTokens()) {
  1.1318 +            String packagePrefix = packagePrefixIter.nextToken().trim();
  1.1319 +
  1.1320 +            try {
  1.1321 +                String clsName = packagePrefix + "." + contentHandlerClassName;
  1.1322 +                Class cls = null;
  1.1323 +                try {
  1.1324 +                    cls = Class.forName(clsName);
  1.1325 +                } catch (ClassNotFoundException e) {
  1.1326 +                    ClassLoader cl = ClassLoader.getSystemClassLoader();
  1.1327 +                    if (cl != null) {
  1.1328 +                        cls = cl.loadClass(clsName);
  1.1329 +                    }
  1.1330 +                }
  1.1331 +                if (cls != null) {
  1.1332 +                    ContentHandler handler =
  1.1333 +                        (ContentHandler)cls.newInstance();
  1.1334 +                    return handler;
  1.1335 +                }
  1.1336 +            } catch(Exception e) {
  1.1337 +            }
  1.1338 +        }
  1.1339 +
  1.1340 +        return UnknownContentHandler.INSTANCE;
  1.1341 +    }
  1.1342 +
  1.1343 +    /**
  1.1344 +     * Utility function to map a MIME content type into an equivalent
  1.1345 +     * pair of class name components.  For example: "text/html" would
  1.1346 +     * be returned as "text.html"
  1.1347 +     */
  1.1348 +    private String typeToPackageName(String contentType) {
  1.1349 +        // make sure we canonicalize the class name: all lower case
  1.1350 +        contentType = contentType.toLowerCase();
  1.1351 +        int len = contentType.length();
  1.1352 +        char nm[] = new char[len];
  1.1353 +        contentType.getChars(0, len, nm, 0);
  1.1354 +        for (int i = 0; i < len; i++) {
  1.1355 +            char c = nm[i];
  1.1356 +            if (c == '/') {
  1.1357 +                nm[i] = '.';
  1.1358 +            } else if (!('A' <= c && c <= 'Z' ||
  1.1359 +                       'a' <= c && c <= 'z' ||
  1.1360 +                       '0' <= c && c <= '9')) {
  1.1361 +                nm[i] = '_';
  1.1362 +            }
  1.1363 +        }
  1.1364 +        return new String(nm);
  1.1365 +    }
  1.1366 +
  1.1367 +
  1.1368 +    /**
  1.1369 +     * Returns a vertical bar separated list of package prefixes for potential
  1.1370 +     * content handlers.  Tries to get the java.content.handler.pkgs property
  1.1371 +     * to use as a set of package prefixes to search.  Whether or not
  1.1372 +     * that property has been defined, the sun.net.www.content is always
  1.1373 +     * the last one on the returned package list.
  1.1374 +     */
  1.1375 +    private String getContentHandlerPkgPrefixes() {
  1.1376 +        String packagePrefixList = AccessController.doPrivileged(
  1.1377 +            new sun.security.action.GetPropertyAction(contentPathProp, ""));
  1.1378 +
  1.1379 +        if (packagePrefixList != "") {
  1.1380 +            packagePrefixList += "|";
  1.1381 +        }
  1.1382 +
  1.1383 +        return packagePrefixList + contentClassPrefix;
  1.1384 +    }
  1.1385 +
  1.1386 +    /**
  1.1387 +     * Tries to determine the content type of an object, based
  1.1388 +     * on the specified "file" component of a URL.
  1.1389 +     * This is a convenience method that can be used by
  1.1390 +     * subclasses that override the <code>getContentType</code> method.
  1.1391 +     *
  1.1392 +     * @param   fname   a filename.
  1.1393 +     * @return  a guess as to what the content type of the object is,
  1.1394 +     *          based upon its file name.
  1.1395 +     * @see     java.net.URLConnection#getContentType()
  1.1396 +     */
  1.1397 +    public static String guessContentTypeFromName(String fname) {
  1.1398 +        return getFileNameMap().getContentTypeFor(fname);
  1.1399 +    }
  1.1400 +
  1.1401 +    /**
  1.1402 +     * Tries to determine the type of an input stream based on the
  1.1403 +     * characters at the beginning of the input stream. This method can
  1.1404 +     * be used by subclasses that override the
  1.1405 +     * <code>getContentType</code> method.
  1.1406 +     * <p>
  1.1407 +     * Ideally, this routine would not be needed. But many
  1.1408 +     * <code>http</code> servers return the incorrect content type; in
  1.1409 +     * addition, there are many nonstandard extensions. Direct inspection
  1.1410 +     * of the bytes to determine the content type is often more accurate
  1.1411 +     * than believing the content type claimed by the <code>http</code> server.
  1.1412 +     *
  1.1413 +     * @param      is   an input stream that supports marks.
  1.1414 +     * @return     a guess at the content type, or <code>null</code> if none
  1.1415 +     *             can be determined.
  1.1416 +     * @exception  IOException  if an I/O error occurs while reading the
  1.1417 +     *               input stream.
  1.1418 +     * @see        java.io.InputStream#mark(int)
  1.1419 +     * @see        java.io.InputStream#markSupported()
  1.1420 +     * @see        java.net.URLConnection#getContentType()
  1.1421 +     */
  1.1422 +    static public String guessContentTypeFromStream(InputStream is)
  1.1423 +                        throws IOException {
  1.1424 +        // If we can't read ahead safely, just give up on guessing
  1.1425 +        if (!is.markSupported())
  1.1426 +            return null;
  1.1427 +
  1.1428 +        is.mark(16);
  1.1429 +        int c1 = is.read();
  1.1430 +        int c2 = is.read();
  1.1431 +        int c3 = is.read();
  1.1432 +        int c4 = is.read();
  1.1433 +        int c5 = is.read();
  1.1434 +        int c6 = is.read();
  1.1435 +        int c7 = is.read();
  1.1436 +        int c8 = is.read();
  1.1437 +        int c9 = is.read();
  1.1438 +        int c10 = is.read();
  1.1439 +        int c11 = is.read();
  1.1440 +        int c12 = is.read();
  1.1441 +        int c13 = is.read();
  1.1442 +        int c14 = is.read();
  1.1443 +        int c15 = is.read();
  1.1444 +        int c16 = is.read();
  1.1445 +        is.reset();
  1.1446 +
  1.1447 +        if (c1 == 0xCA && c2 == 0xFE && c3 == 0xBA && c4 == 0xBE) {
  1.1448 +            return "application/java-vm";
  1.1449 +        }
  1.1450 +
  1.1451 +        if (c1 == 0xAC && c2 == 0xED) {
  1.1452 +            // next two bytes are version number, currently 0x00 0x05
  1.1453 +            return "application/x-java-serialized-object";
  1.1454 +        }
  1.1455 +
  1.1456 +        if (c1 == '<') {
  1.1457 +            if (c2 == '!'
  1.1458 +                || ((c2 == 'h' && (c3 == 't' && c4 == 'm' && c5 == 'l' ||
  1.1459 +                                   c3 == 'e' && c4 == 'a' && c5 == 'd') ||
  1.1460 +                (c2 == 'b' && c3 == 'o' && c4 == 'd' && c5 == 'y'))) ||
  1.1461 +                ((c2 == 'H' && (c3 == 'T' && c4 == 'M' && c5 == 'L' ||
  1.1462 +                                c3 == 'E' && c4 == 'A' && c5 == 'D') ||
  1.1463 +                (c2 == 'B' && c3 == 'O' && c4 == 'D' && c5 == 'Y')))) {
  1.1464 +                return "text/html";
  1.1465 +            }
  1.1466 +
  1.1467 +            if (c2 == '?' && c3 == 'x' && c4 == 'm' && c5 == 'l' && c6 == ' ') {
  1.1468 +                return "application/xml";
  1.1469 +            }
  1.1470 +        }
  1.1471 +
  1.1472 +        // big and little (identical) endian UTF-8 encodings, with BOM
  1.1473 +        if (c1 == 0xef &&  c2 == 0xbb &&  c3 == 0xbf) {
  1.1474 +            if (c4 == '<' &&  c5 == '?' &&  c6 == 'x') {
  1.1475 +                return "application/xml";
  1.1476 +            }
  1.1477 +        }
  1.1478 +
  1.1479 +        // big and little endian UTF-16 encodings, with byte order mark
  1.1480 +        if (c1 == 0xfe && c2 == 0xff) {
  1.1481 +            if (c3 == 0 && c4 == '<' && c5 == 0 && c6 == '?' &&
  1.1482 +                c7 == 0 && c8 == 'x') {
  1.1483 +                return "application/xml";
  1.1484 +            }
  1.1485 +        }
  1.1486 +
  1.1487 +        if (c1 == 0xff && c2 == 0xfe) {
  1.1488 +            if (c3 == '<' && c4 == 0 && c5 == '?' && c6 == 0 &&
  1.1489 +                c7 == 'x' && c8 == 0) {
  1.1490 +                return "application/xml";
  1.1491 +            }
  1.1492 +        }
  1.1493 +
  1.1494 +        // big and little endian UTF-32 encodings, with BOM
  1.1495 +        if (c1 == 0x00 &&  c2 == 0x00 &&  c3 == 0xfe &&  c4 == 0xff) {
  1.1496 +            if (c5  == 0 && c6  == 0 && c7  == 0 && c8  == '<' &&
  1.1497 +                c9  == 0 && c10 == 0 && c11 == 0 && c12 == '?' &&
  1.1498 +                c13 == 0 && c14 == 0 && c15 == 0 && c16 == 'x') {
  1.1499 +                return "application/xml";
  1.1500 +            }
  1.1501 +        }
  1.1502 +
  1.1503 +        if (c1 == 0xff &&  c2 == 0xfe &&  c3 == 0x00 &&  c4 == 0x00) {
  1.1504 +            if (c5  == '<' && c6  == 0 && c7  == 0 && c8  == 0 &&
  1.1505 +                c9  == '?' && c10 == 0 && c11 == 0 && c12 == 0 &&
  1.1506 +                c13 == 'x' && c14 == 0 && c15 == 0 && c16 == 0) {
  1.1507 +                return "application/xml";
  1.1508 +            }
  1.1509 +        }
  1.1510 +
  1.1511 +        if (c1 == 'G' && c2 == 'I' && c3 == 'F' && c4 == '8') {
  1.1512 +            return "image/gif";
  1.1513 +        }
  1.1514 +
  1.1515 +        if (c1 == '#' && c2 == 'd' && c3 == 'e' && c4 == 'f') {
  1.1516 +            return "image/x-bitmap";
  1.1517 +        }
  1.1518 +
  1.1519 +        if (c1 == '!' && c2 == ' ' && c3 == 'X' && c4 == 'P' &&
  1.1520 +                        c5 == 'M' && c6 == '2') {
  1.1521 +            return "image/x-pixmap";
  1.1522 +        }
  1.1523 +
  1.1524 +        if (c1 == 137 && c2 == 80 && c3 == 78 &&
  1.1525 +                c4 == 71 && c5 == 13 && c6 == 10 &&
  1.1526 +                c7 == 26 && c8 == 10) {
  1.1527 +            return "image/png";
  1.1528 +        }
  1.1529 +
  1.1530 +        if (c1 == 0xFF && c2 == 0xD8 && c3 == 0xFF) {
  1.1531 +            if (c4 == 0xE0) {
  1.1532 +                return "image/jpeg";
  1.1533 +            }
  1.1534 +
  1.1535 +            /**
  1.1536 +             * File format used by digital cameras to store images.
  1.1537 +             * Exif Format can be read by any application supporting
  1.1538 +             * JPEG. Exif Spec can be found at:
  1.1539 +             * http://www.pima.net/standards/it10/PIMA15740/Exif_2-1.PDF
  1.1540 +             */
  1.1541 +            if ((c4 == 0xE1) &&
  1.1542 +                (c7 == 'E' && c8 == 'x' && c9 == 'i' && c10 =='f' &&
  1.1543 +                 c11 == 0)) {
  1.1544 +                return "image/jpeg";
  1.1545 +            }
  1.1546 +
  1.1547 +            if (c4 == 0xEE) {
  1.1548 +                return "image/jpg";
  1.1549 +            }
  1.1550 +        }
  1.1551 +
  1.1552 +        if (c1 == 0xD0 && c2 == 0xCF && c3 == 0x11 && c4 == 0xE0 &&
  1.1553 +            c5 == 0xA1 && c6 == 0xB1 && c7 == 0x1A && c8 == 0xE1) {
  1.1554 +
  1.1555 +            /* Above is signature of Microsoft Structured Storage.
  1.1556 +             * Below this, could have tests for various SS entities.
  1.1557 +             * For now, just test for FlashPix.
  1.1558 +             */
  1.1559 +            if (checkfpx(is)) {
  1.1560 +                return "image/vnd.fpx";
  1.1561 +            }
  1.1562 +        }
  1.1563 +
  1.1564 +        if (c1 == 0x2E && c2 == 0x73 && c3 == 0x6E && c4 == 0x64) {
  1.1565 +            return "audio/basic";  // .au format, big endian
  1.1566 +        }
  1.1567 +
  1.1568 +        if (c1 == 0x64 && c2 == 0x6E && c3 == 0x73 && c4 == 0x2E) {
  1.1569 +            return "audio/basic";  // .au format, little endian
  1.1570 +        }
  1.1571 +
  1.1572 +        if (c1 == 'R' && c2 == 'I' && c3 == 'F' && c4 == 'F') {
  1.1573 +            /* I don't know if this is official but evidence
  1.1574 +             * suggests that .wav files start with "RIFF" - brown
  1.1575 +             */
  1.1576 +            return "audio/x-wav";
  1.1577 +        }
  1.1578 +        return null;
  1.1579 +    }
  1.1580 +
  1.1581 +    /**
  1.1582 +     * Check for FlashPix image data in InputStream is.  Return true if
  1.1583 +     * the stream has FlashPix data, false otherwise.  Before calling this
  1.1584 +     * method, the stream should have already been checked to be sure it
  1.1585 +     * contains Microsoft Structured Storage data.
  1.1586 +     */
  1.1587 +    static private boolean checkfpx(InputStream is) throws IOException {
  1.1588 +
  1.1589 +        /* Test for FlashPix image data in Microsoft Structured Storage format.
  1.1590 +         * In general, should do this with calls to an SS implementation.
  1.1591 +         * Lacking that, need to dig via offsets to get to the FlashPix
  1.1592 +         * ClassID.  Details:
  1.1593 +         *
  1.1594 +         * Offset to Fpx ClsID from beginning of stream should be:
  1.1595 +         *
  1.1596 +         * FpxClsidOffset = rootEntryOffset + clsidOffset
  1.1597 +         *
  1.1598 +         * where: clsidOffset = 0x50.
  1.1599 +         *        rootEntryOffset = headerSize + sectorSize*sectDirStart
  1.1600 +         *                          + 128*rootEntryDirectory
  1.1601 +         *
  1.1602 +         *        where:  headerSize = 0x200 (always)
  1.1603 +         *                sectorSize = 2 raised to power of uSectorShift,
  1.1604 +         *                             which is found in the header at
  1.1605 +         *                             offset 0x1E.
  1.1606 +         *                sectDirStart = found in the header at offset 0x30.
  1.1607 +         *                rootEntryDirectory = in general, should search for
  1.1608 +         *                                     directory labelled as root.
  1.1609 +         *                                     We will assume value of 0 (i.e.,
  1.1610 +         *                                     rootEntry is in first directory)
  1.1611 +         */
  1.1612 +
  1.1613 +        // Mark the stream so we can reset it. 0x100 is enough for the first
  1.1614 +        // few reads, but the mark will have to be reset and set again once
  1.1615 +        // the offset to the root directory entry is computed. That offset
  1.1616 +        // can be very large and isn't know until the stream has been read from
  1.1617 +        is.mark(0x100);
  1.1618 +
  1.1619 +        // Get the byte ordering located at 0x1E. 0xFE is Intel,
  1.1620 +        // 0xFF is other
  1.1621 +        long toSkip = (long)0x1C;
  1.1622 +        long posn;
  1.1623 +
  1.1624 +        if ((posn = skipForward(is, toSkip)) < toSkip) {
  1.1625 +          is.reset();
  1.1626 +          return false;
  1.1627 +        }
  1.1628 +
  1.1629 +        int c[] = new int[16];
  1.1630 +        if (readBytes(c, 2, is) < 0) {
  1.1631 +            is.reset();
  1.1632 +            return false;
  1.1633 +        }
  1.1634 +
  1.1635 +        int byteOrder = c[0];
  1.1636 +
  1.1637 +        posn+=2;
  1.1638 +        int uSectorShift;
  1.1639 +        if (readBytes(c, 2, is) < 0) {
  1.1640 +            is.reset();
  1.1641 +            return false;
  1.1642 +        }
  1.1643 +
  1.1644 +        if(byteOrder == 0xFE) {
  1.1645 +            uSectorShift = c[0];
  1.1646 +            uSectorShift += c[1] << 8;
  1.1647 +        }
  1.1648 +        else {
  1.1649 +            uSectorShift = c[0] << 8;
  1.1650 +            uSectorShift += c[1];
  1.1651 +        }
  1.1652 +
  1.1653 +        posn += 2;
  1.1654 +        toSkip = (long)0x30 - posn;
  1.1655 +        long skipped = 0;
  1.1656 +        if ((skipped = skipForward(is, toSkip)) < toSkip) {
  1.1657 +          is.reset();
  1.1658 +          return false;
  1.1659 +        }
  1.1660 +        posn += skipped;
  1.1661 +
  1.1662 +        if (readBytes(c, 4, is) < 0) {
  1.1663 +            is.reset();
  1.1664 +            return false;
  1.1665 +        }
  1.1666 +
  1.1667 +        int sectDirStart;
  1.1668 +        if(byteOrder == 0xFE) {
  1.1669 +            sectDirStart = c[0];
  1.1670 +            sectDirStart += c[1] << 8;
  1.1671 +            sectDirStart += c[2] << 16;
  1.1672 +            sectDirStart += c[3] << 24;
  1.1673 +        } else {
  1.1674 +            sectDirStart =  c[0] << 24;
  1.1675 +            sectDirStart += c[1] << 16;
  1.1676 +            sectDirStart += c[2] << 8;
  1.1677 +            sectDirStart += c[3];
  1.1678 +        }
  1.1679 +        posn += 4;
  1.1680 +        is.reset(); // Reset back to the beginning
  1.1681 +
  1.1682 +        toSkip = 0x200L + (long)(1<<uSectorShift)*sectDirStart + 0x50L;
  1.1683 +
  1.1684 +        // Sanity check!
  1.1685 +        if (toSkip < 0) {
  1.1686 +            return false;
  1.1687 +        }
  1.1688 +
  1.1689 +        /*
  1.1690 +         * How far can we skip? Is there any performance problem here?
  1.1691 +         * This skip can be fairly long, at least 0x4c650 in at least
  1.1692 +         * one case. Have to assume that the skip will fit in an int.
  1.1693 +         * Leave room to read whole root dir
  1.1694 +         */
  1.1695 +        is.mark((int)toSkip+0x30);
  1.1696 +
  1.1697 +        if ((skipForward(is, toSkip)) < toSkip) {
  1.1698 +            is.reset();
  1.1699 +            return false;
  1.1700 +        }
  1.1701 +
  1.1702 +        /* should be at beginning of ClassID, which is as follows
  1.1703 +         * (in Intel byte order):
  1.1704 +         *    00 67 61 56 54 C1 CE 11 85 53 00 AA 00 A1 F9 5B
  1.1705 +         *
  1.1706 +         * This is stored from Windows as long,short,short,char[8]
  1.1707 +         * so for byte order changes, the order only changes for
  1.1708 +         * the first 8 bytes in the ClassID.
  1.1709 +         *
  1.1710 +         * Test against this, ignoring second byte (Intel) since
  1.1711 +         * this could change depending on part of Fpx file we have.
  1.1712 +         */
  1.1713 +
  1.1714 +        if (readBytes(c, 16, is) < 0) {
  1.1715 +            is.reset();
  1.1716 +            return false;
  1.1717 +        }
  1.1718 +
  1.1719 +        // intel byte order
  1.1720 +        if (byteOrder == 0xFE &&
  1.1721 +            c[0] == 0x00 && c[2] == 0x61 && c[3] == 0x56 &&
  1.1722 +            c[4] == 0x54 && c[5] == 0xC1 && c[6] == 0xCE &&
  1.1723 +            c[7] == 0x11 && c[8] == 0x85 && c[9] == 0x53 &&
  1.1724 +            c[10]== 0x00 && c[11]== 0xAA && c[12]== 0x00 &&
  1.1725 +            c[13]== 0xA1 && c[14]== 0xF9 && c[15]== 0x5B) {
  1.1726 +            is.reset();
  1.1727 +            return true;
  1.1728 +        }
  1.1729 +
  1.1730 +        // non-intel byte order
  1.1731 +        else if (c[3] == 0x00 && c[1] == 0x61 && c[0] == 0x56 &&
  1.1732 +            c[5] == 0x54 && c[4] == 0xC1 && c[7] == 0xCE &&
  1.1733 +            c[6] == 0x11 && c[8] == 0x85 && c[9] == 0x53 &&
  1.1734 +            c[10]== 0x00 && c[11]== 0xAA && c[12]== 0x00 &&
  1.1735 +            c[13]== 0xA1 && c[14]== 0xF9 && c[15]== 0x5B) {
  1.1736 +            is.reset();
  1.1737 +            return true;
  1.1738 +        }
  1.1739 +        is.reset();
  1.1740 +        return false;
  1.1741 +    }
  1.1742 +
  1.1743 +    /**
  1.1744 +     * Tries to read the specified number of bytes from the stream
  1.1745 +     * Returns -1, If EOF is reached before len bytes are read, returns 0
  1.1746 +     * otherwise
  1.1747 +     */
  1.1748 +    static private int readBytes(int c[], int len, InputStream is)
  1.1749 +                throws IOException {
  1.1750 +
  1.1751 +        byte buf[] = new byte[len];
  1.1752 +        if (is.read(buf, 0, len) < len) {
  1.1753 +            return -1;
  1.1754 +        }
  1.1755 +
  1.1756 +        // fill the passed in int array
  1.1757 +        for (int i = 0; i < len; i++) {
  1.1758 +             c[i] = buf[i] & 0xff;
  1.1759 +        }
  1.1760 +        return 0;
  1.1761 +    }
  1.1762 +
  1.1763 +
  1.1764 +    /**
  1.1765 +     * Skips through the specified number of bytes from the stream
  1.1766 +     * until either EOF is reached, or the specified
  1.1767 +     * number of bytes have been skipped
  1.1768 +     */
  1.1769 +    static private long skipForward(InputStream is, long toSkip)
  1.1770 +                throws IOException {
  1.1771 +
  1.1772 +        long eachSkip = 0;
  1.1773 +        long skipped = 0;
  1.1774 +
  1.1775 +        while (skipped != toSkip) {
  1.1776 +            eachSkip = is.skip(toSkip - skipped);
  1.1777 +
  1.1778 +            // check if EOF is reached
  1.1779 +            if (eachSkip <= 0) {
  1.1780 +                if (is.read() == -1) {
  1.1781 +                    return skipped ;
  1.1782 +                } else {
  1.1783 +                    skipped++;
  1.1784 +                }
  1.1785 +            }
  1.1786 +            skipped += eachSkip;
  1.1787 +        }
  1.1788 +        return skipped;
  1.1789 +    }
  1.1790 +
  1.1791 +}
  1.1792 +
  1.1793 +
  1.1794 +class UnknownContentHandler extends ContentHandler {
  1.1795 +    static final ContentHandler INSTANCE = new UnknownContentHandler();
  1.1796 +
  1.1797 +    public Object getContent(URLConnection uc) throws IOException {
  1.1798 +        return uc.getInputStream();
  1.1799 +    }
  1.1800 +}