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