History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/net/URLConnection.java (1 of 18352 files). Show all

Unified · Split

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