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