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