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