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