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