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