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