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