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