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