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