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