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