1. /*
  2. * @(#)URLConnection.java 1.61 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.net;
  8. import java.io.IOException;
  9. import java.io.InputStream;
  10. import java.io.OutputStream;
  11. import java.util.Hashtable;
  12. import java.util.Date;
  13. import java.util.StringTokenizer;
  14. import java.security.Permission;
  15. import java.security.AccessController;
  16. /**
  17. * The abstract class <code>URLConnection</code> is the superclass
  18. * of all classes that represent a communications link between the
  19. * application and a URL. Instances of this class can be used both to
  20. * read from and to write to the resource referenced by the URL. In
  21. * general, creating a connection to a URL is a multistep process:
  22. * <p>
  23. * <center><table border=2>
  24. * <tr><th><code>openConnection()</code></th>
  25. * <th><code>connect()</code></th></tr>
  26. * <tr><td>Manipulate parameters that affect the connection to the remote
  27. * resource.</td>
  28. * <td>Interact with the resource; query header fields and
  29. * contents.</td></tr>
  30. * </table>
  31. * ---------------------------->
  32. * <br>time</center>
  33. *
  34. * <ol>
  35. * <li>The connection object is created by invoking the
  36. * <code>openConnection</code> method on a URL.
  37. * <li>The setup parameters and general request properties are manipulated.
  38. * <li>The actual connection to the remote object is made, using the
  39. * <code>connect</code> method.
  40. * <li>The remote object becomes available. The header fields and the contents
  41. * of the remote object can be accessed.
  42. * </ol>
  43. * <p>
  44. * The setup parameters are modified using the following methods:
  45. * <ul>
  46. * <li><code>setAllowUserInteraction</code>
  47. * <li><code>setDoInput</code>
  48. * <li><code>setDoOutput</code>
  49. * <li><code>setIfModifiedSince</code>
  50. * <li><code>setUseCaches</code>
  51. * </ul>
  52. * <p>
  53. * and the general request properties are modified using the method:
  54. * <ul>
  55. * <li><code>setRequestProperty</code>
  56. * </ul>
  57. * <p>
  58. * Default values for the <code>AllowUserInteraction</code> and
  59. * <code>UseCaches</code> parameters can be set using the methods
  60. * <code>setDefaultAllowUserInteraction</code> and
  61. * <code>setDefaultUseCaches</code>. Default values for general
  62. * request properties can be set using the
  63. * <code>setDefaultRequestProperty</code> method.
  64. * <p>
  65. * Each of the above <code>set</code> methods has a corresponding
  66. * <code>get</code> method to retrieve the value of the parameter or
  67. * general request property. The specific parameters and general
  68. * request properties that are applicable are protocol specific.
  69. * <p>
  70. * The following methods are used to access the header fields and
  71. * the contents after the connection is made to the remote object:
  72. * <ul>
  73. * <li><code>getContent</code>
  74. * <li><code>getHeaderField</code>
  75. * <li><code>getInputStream</code>
  76. * <li><code>getOutputStream</code>
  77. * </ul>
  78. * <p>
  79. * Certain header fields are accessed frequently. The methods:
  80. * <ul>
  81. * <li><code>getContentEncoding</code>
  82. * <li><code>getContentLength</code>
  83. * <li><code>getContentType</code>
  84. * <li><code>getDate</code>
  85. * <li><code>getExpiration</code>
  86. * <li><code>getLastModifed</code>
  87. * </ul>
  88. * <p>
  89. * provide convenient access to these fields. The
  90. * <code>getContentType</code> method is used by the
  91. * <code>getContent</code> method to determine the type of the remote
  92. * object; subclasses may find it convenient to override the
  93. * <code>getContentType</code> method.
  94. * <p>
  95. * In the common case, all of the pre-connection parameters and
  96. * general request properties can be ignored: the pre-connection
  97. * parameters and request properties default to sensible values. For
  98. * most clients of this interface, there are only two interesting
  99. * methods: <code>getInputStream</code> and <code>getObject</code>,
  100. * which are mirrored in the <code>URL</code> class by convenience methods.
  101. * <p>
  102. * More information on the request properties and header fields of
  103. * an <code>http</code> connection can be found at:
  104. * <blockquote><pre>
  105. * http://www.w3.org/hypertext/WWW/Protocols/HTTP1.0/draft-ietf-http-spec.html
  106. * </pre></blockquote>
  107. *
  108. * Note about <code>fileNameMap</code>: In versions prior to JDK 1.1.6,
  109. * field <code>fileNameMap</code> of <code>URLConnection</code> was public.
  110. * In JDK 1.1.6 and later, <code>fileNameMap</code> is private; accessor
  111. * and mutator methods {@link #getFileNameMap() getFileNameMap} and
  112. * {@link #setFileNameMap(java.net.FileNameMap) setFileNameMap} are added
  113. * to access it. This change is also described on the <a href=
  114. * "http://java.sun.com/products/jdk/1.2/compatibility.html#incompatibilities1.1">
  115. * JDK Compatibility</a> page.
  116. *
  117. * @author James Gosling
  118. * @version 1.61, 11/29/01
  119. * @see java.net.URL#openConnection()
  120. * @see java.net.URLConnection#connect()
  121. * @see java.net.URLConnection#getContent()
  122. * @see java.net.URLConnection#getContentEncoding()
  123. * @see java.net.URLConnection#getContentLength()
  124. * @see java.net.URLConnection#getContentType()
  125. * @see java.net.URLConnection#getDate()
  126. * @see java.net.URLConnection#getExpiration()
  127. * @see java.net.URLConnection#getHeaderField(int)
  128. * @see java.net.URLConnection#getHeaderField(java.lang.String)
  129. * @see java.net.URLConnection#getInputStream()
  130. * @see java.net.URLConnection#getLastModified()
  131. * @see java.net.URLConnection#getOutputStream()
  132. * @see java.net.URLConnection#setAllowUserInteraction(boolean)
  133. * @see java.net.URLConnection#setDefaultRequestProperty(java.lang.String, java.lang.String)
  134. * @see java.net.URLConnection#setDefaultUseCaches(boolean)
  135. * @see java.net.URLConnection#setDoInput(boolean)
  136. * @see java.net.URLConnection#setDoOutput(boolean)
  137. * @see java.net.URLConnection#setIfModifiedSince(long)
  138. * @see java.net.URLConnection#setRequestProperty(java.lang.String, java.lang.String)
  139. * @see java.net.URLConnection#setUseCaches(boolean)
  140. * @since JDK1.0
  141. */
  142. public abstract class URLConnection {
  143. /**
  144. * The URL represents the remote object on the World Wide Web to
  145. * which this connection is opened.
  146. * <p>
  147. * The value of this field can be accessed by the
  148. * <code>getURL</code> method.
  149. * <p>
  150. * The default value of this variable is the value of the URL
  151. * argument in the <code>URLConnection</code> constructor.
  152. *
  153. * @see java.net.URLConnection#getURL()
  154. * @see java.net.URLConnection#url
  155. */
  156. protected URL url;
  157. /**
  158. * This variable is set by the <code>setDoInput</code> method. Its
  159. * value is returned by the <code>getDoInput</code> method.
  160. * <p>
  161. * A URL connection can be used for input and/or output. Setting the
  162. * <code>doInput</code> flag to <code>true</code> indicates that
  163. * the application intends to read data from the URL connection.
  164. * <p>
  165. * The default value of this field is <code>true</code>.
  166. *
  167. * @see java.net.URLConnection#getDoInput()
  168. * @see java.net.URLConnection#setDoInput(boolean)
  169. */
  170. protected boolean doInput = true;
  171. /**
  172. * This variable is set by the <code>setDoOutput</code> method. Its
  173. * value is returned by the <code>getDoInput</code> method.
  174. * <p>
  175. * A URL connection can be used for input and/or output. Setting the
  176. * <code>doOutput</code> flag to <code>true</code> indicates
  177. * that the application intends to write data to the URL connection.
  178. * <p>
  179. * The default value of this field is <code>false</code>.
  180. *
  181. * @see java.net.URLConnection#getDoOutput()
  182. * @see java.net.URLConnection#setDoOutput(boolean)
  183. */
  184. protected boolean doOutput = false;
  185. private static boolean defaultAllowUserInteraction = false;
  186. /**
  187. * If <code>true</code>, this <code>URL</code> is being examined in
  188. * a context in which it makes sense to allow user interactions such
  189. * as popping up an authentication dialog. If <code>false</code>,
  190. * then no user interaction is allowed.
  191. * <p>
  192. * The value of this field can be set by the
  193. * <code>setAllowUserInteraction</code> method.
  194. * Its value is returned by the
  195. * <code>getAllowUserInteraction</code> method.
  196. * Its default value is the value of the argument in the last invocation
  197. * of the <code>setDefaultAllowUserInteraction</code> method.
  198. *
  199. * @see java.net.URLConnection#getAllowUserInteraction()
  200. * @see java.net.URLConnection#setAllowUserInteraction(boolean)
  201. * @see java.net.URLConnection#setDefaultAllowUserInteraction(boolean)
  202. */
  203. protected boolean allowUserInteraction = defaultAllowUserInteraction;
  204. private static boolean defaultUseCaches = true;
  205. /**
  206. * If <code>true</code>, the protocol is allowed to use caching
  207. * whenever it can. If <code>false</code>, the protocol must always
  208. * try to get a fresh copy of the object.
  209. * <p>
  210. * This field is set by the <code>setUseCaches</code> method. Its
  211. * value is returned by the <code>getUseCaches</code> method.
  212. * <p>
  213. * Its default value is the value given in the last invocation of the
  214. * <code>setDefaultUseCaches</code> method.
  215. *
  216. * @see java.net.URLConnection#setUseCaches(boolean)
  217. * @see java.net.URLConnection#getUseCaches()
  218. * @see java.net.URLConnection#setDefaultUseCaches(boolean)
  219. */
  220. protected boolean useCaches = defaultUseCaches;
  221. /**
  222. * Some protocols support skipping the fetching of the object unless
  223. * the object has been modified more recently than a certain time.
  224. * <p>
  225. * A nonzero value gives a time as the number of milliseconds since
  226. * January 1, 1970, GMT. The object is fetched only if it has been
  227. * modified more recently than that time.
  228. * <p>
  229. * This variable is set by the <code>setIfModifiedSince</code>
  230. * method. Its value is returned by the
  231. * <code>getIfModifiedSince</code> method.
  232. * <p>
  233. * The default value of this field is <code>0</code>, indicating
  234. * that the fetching must always occur.
  235. *
  236. * @see java.net.URLConnection#getIfModifiedSince()
  237. * @see java.net.URLConnection#setIfModifiedSince(long)
  238. */
  239. protected long ifModifiedSince = 0;
  240. /**
  241. * If <code>false</code>, this connection object has not created a
  242. * communications link to the specified URL. If <code>true</code>,
  243. * the communications link has been established.
  244. */
  245. protected boolean connected = false;
  246. /**
  247. * @since JDK1.1
  248. */
  249. private static FileNameMap fileNameMap;
  250. /**
  251. * @since JDK1.2.2
  252. */
  253. private static boolean fileNameMapLoaded = false;
  254. /**
  255. * Returns the FileNameMap.
  256. *
  257. * @returns the FileNameMap
  258. * @since JDK1.2
  259. */
  260. public static synchronized FileNameMap getFileNameMap() {
  261. if ((fileNameMap == null) && !fileNameMapLoaded) {
  262. fileNameMap = sun.net.www.MimeTable.loadTable();
  263. fileNameMapLoaded = true;
  264. }
  265. return new FileNameMap() {
  266. private FileNameMap map = fileNameMap;
  267. public String getContentTypeFor(String fileName) {
  268. return map.getContentTypeFor(fileName);
  269. }
  270. };
  271. }
  272. /**
  273. * Sets the FileNameMap.
  274. * <p>
  275. * If there is a security manager, this method first calls
  276. * the security manager's <code>checkSetFactory</code> method
  277. * to ensure the operation is allowed.
  278. * This could result in a SecurityException.
  279. *
  280. * @param map the FileNameMap to be set
  281. * @exception SecurityException if a security manager exists and its
  282. * <code>checkSetFactory</code> method doesn't allow the operation.
  283. * @see SecurityManager#checkSetFactory
  284. * @since JDK1.2
  285. */
  286. public static void setFileNameMap(FileNameMap map) {
  287. SecurityManager sm = System.getSecurityManager();
  288. if (sm != null) sm.checkSetFactory();
  289. fileNameMap = map;
  290. }
  291. /**
  292. * Opens a communications link to the resource referenced by this
  293. * URL, if such a connection has not already been established.
  294. * <p>
  295. * If the <code>connect</code> method is called when the connection
  296. * has already been opened (indicated by the <code>connected</code>
  297. * field having the value <code>true</code>), the call is ignored.
  298. * <p>
  299. * URLConnection objects go through two phases: first they are
  300. * created, then they are connected. After being created, and
  301. * before being connected, various options can be specified
  302. * (e.g., doInput and UseCaches). After connecting, it is an
  303. * error to try to set them. Operations that depend on being
  304. * connected, like getContentLength, will implicitly perform the
  305. * connection, if necessary.
  306. *
  307. * @exception IOException if an I/O error occurs while opening the
  308. * connection.
  309. * @see java.net.URLConnection#connected */
  310. abstract public void connect() throws IOException;
  311. /**
  312. * Constructs a URL connection to the specified URL. A connection to
  313. * the object referenced by the URL is not created.
  314. *
  315. * @param url the specified URL.
  316. */
  317. protected URLConnection(URL url) {
  318. this.url = url;
  319. }
  320. /**
  321. * Returns the value of this <code>URLConnection</code>'s <code>URL</code>
  322. * field.
  323. *
  324. * @return the value of this <code>URLConnection</code>'s <code>URL</code>
  325. * field.
  326. * @see java.net.URLConnection#url
  327. */
  328. public URL getURL() {
  329. return url;
  330. }
  331. /**
  332. * Returns the value of the <code>content-length</code> header field.
  333. *
  334. * @return the content length of the resource that this connection's URL
  335. * references, or <code>-1</code> if the content length is
  336. * not known.
  337. */
  338. public int getContentLength() {
  339. return getHeaderFieldInt("content-length", -1);
  340. }
  341. /**
  342. * Returns the value of the <code>content-type</code> header field.
  343. *
  344. * @return the content type of the resource that the URL references,
  345. * or <code>null</code> if not known.
  346. * @see java.net.URLConnection#getHeaderField(java.lang.String)
  347. */
  348. public String getContentType() {
  349. return getHeaderField("content-type");
  350. }
  351. /**
  352. * Returns the value of the <code>content-encoding</code> header field.
  353. *
  354. * @return the content encoding of the resource that the URL references,
  355. * or <code>null</code> if not known.
  356. * @see java.net.URLConnection#getHeaderField(java.lang.String)
  357. */
  358. public String getContentEncoding() {
  359. return getHeaderField("content-encoding");
  360. }
  361. /**
  362. * Returns the value of the <code>expires</code> header field.
  363. *
  364. * @return the expiration date of the resource that this URL references,
  365. * or 0 if not known. The value is the number of milliseconds since
  366. * January 1, 1970 GMT.
  367. * @see java.net.URLConnection#getHeaderField(java.lang.String)
  368. */
  369. public long getExpiration() {
  370. return getHeaderFieldDate("expires", 0);
  371. }
  372. /**
  373. * Returns the value of the <code>date</code> header field.
  374. *
  375. * @return the sending date of the resource that the URL references,
  376. * or <code>0</code> if not known. The value returned is the
  377. * number of milliseconds since January 1, 1970 GMT.
  378. * @see java.net.URLConnection#getHeaderField(java.lang.String)
  379. */
  380. public long getDate() {
  381. return getHeaderFieldDate("date", 0);
  382. }
  383. /**
  384. * Returns the value of the <code>last-modified</code> header field.
  385. * The result is the number of milliseconds since January 1, 1970 GMT.
  386. *
  387. * @return the date the resource referenced by this
  388. * <code>URLConnection</code> was last modified, or 0 if not known.
  389. * @see java.net.URLConnection#getHeaderField(java.lang.String)
  390. */
  391. public long getLastModified() {
  392. return getHeaderFieldDate("last-modified", 0);
  393. }
  394. /**
  395. * Returns the name of the specified header field.
  396. *
  397. * @param name the name of a header field.
  398. * @return the value of the named header field, or <code>null</code>
  399. * if there is no such field in the header.
  400. */
  401. public String getHeaderField(String name) {
  402. return null;
  403. }
  404. /**
  405. * Returns the value of the named field parsed as a number.
  406. * <p>
  407. * This form of <code>getHeaderField</code> exists because some
  408. * connection types (e.g., <code>http-ng</code>) have pre-parsed
  409. * headers. Classes for that connection type can override this method
  410. * and short-circuit the parsing.
  411. *
  412. * @param name the name of the header field.
  413. * @param Default the default value.
  414. * @return the value of the named field, parsed as an integer. The
  415. * <code>Default</code> value is returned if the field is
  416. * missing or malformed.
  417. */
  418. public int getHeaderFieldInt(String name, int Default) {
  419. try {
  420. return Integer.parseInt(getHeaderField(name));
  421. } catch(Throwable t) {}
  422. return Default;
  423. }
  424. /**
  425. * Returns the value of the named field parsed as date.
  426. * The result is the number of milliseconds since January 1, 1970 GMT
  427. * represented by the named field.
  428. * <p>
  429. * This form of <code>getHeaderField</code> exists because some
  430. * connection types (e.g., <code>http-ng</code>) have pre-parsed
  431. * headers. Classes for that connection type can override this method
  432. * and short-circuit the parsing.
  433. *
  434. * @param name the name of the header field.
  435. * @param Default a default value.
  436. * @return the value of the field, parsed as a date. The value of the
  437. * <code>Default</code> argument is returned if the field is
  438. * missing or malformed.
  439. */
  440. public long getHeaderFieldDate(String name, long Default) {
  441. try {
  442. return Date.parse(getHeaderField(name));
  443. } catch(Throwable t) {}
  444. return Default;
  445. }
  446. /**
  447. * Returns the key for the <code>n</code><sup>th</sup> header field.
  448. *
  449. * @param n an index.
  450. * @return the key for the <code>n</code><sup>th</sup> header field,
  451. * or <code>null</code> if there are fewer than <code>n</code>
  452. * fields.
  453. */
  454. public String getHeaderFieldKey(int n) {
  455. return null;
  456. }
  457. /**
  458. * Returns the value for the <code>n</code><sup>th</sup> header field.
  459. * It returns <code>null</code> if there are fewer than
  460. * <code>n</code> fields.
  461. * <p>
  462. * This method can be used in conjunction with the
  463. * <code>getHeaderFieldKey</code> method to iterate through all
  464. * the headers in the message.
  465. *
  466. * @param n an index.
  467. * @return the value of the <code>n</code><sup>th</sup> header field.
  468. * @see java.net.URLConnection#getHeaderFieldKey(int)
  469. */
  470. public String getHeaderField(int n) {
  471. return null;
  472. }
  473. /**
  474. * Retrieves the contents of this URL connection.
  475. * <p>
  476. * This method first determines the content type of the object by
  477. * calling the <code>getContentType</code> method. If this is
  478. * the first time that the application has seen that specific content
  479. * type, a content handler for that content type is created:
  480. * <ol>
  481. * <li>If the application has set up a content handler factory instance
  482. * using the <code>setContentHandlerFactory</code> method, the
  483. * <code>createContentHandler</code> method of that instance is called
  484. * with the content type as an argument; the result is a content
  485. * handler for that content type.
  486. * <li>If no content handler factory has yet been set up, or if the
  487. * factory's <code>createContentHandler</code> method returns
  488. * <code>null</code>, then the application loads the class named:
  489. * <blockquote><pre>
  490. * sun.net.www.content.<<i>contentType</i>>
  491. * </pre></blockquote>
  492. * where <<i>contentType</i>> is formed by taking the
  493. * content-type string, replacing all slash characters with a
  494. * <code>period</code> ('.'), and all other non-alphanumeric characters
  495. * with the underscore character '<code>_</code>'. The alphanumeric
  496. * characters are specifically the 26 uppercase ASCII letters
  497. * '<code>A</code>' through '<code>Z</code>', the 26 lowercase ASCII
  498. * letters '<code>a</code>' through '<code>z</code>', and the 10 ASCII
  499. * digits '<code>0</code>' through '<code>9</code>'. If the specified
  500. * class does not exist, or is not a subclass of
  501. * <code>ContentHandler</code>, then an
  502. * <code>UnknownServiceException</code> is thrown.
  503. * </ol>
  504. *
  505. * @return the object fetched. The <code>instanceOf</code> operation
  506. * should be used to determine the specific kind of object
  507. * returned.
  508. * @exception IOException if an I/O error occurs while
  509. * getting the content.
  510. * @exception UnknownServiceException if the protocol does not support
  511. * the content type.
  512. * @see java.net.ContentHandlerFactory#createContentHandler(java.lang.String)
  513. * @see java.net.URLConnection#getContentType()
  514. * @see java.net.URLConnection#setContentHandlerFactory(java.net.ContentHandlerFactory)
  515. */
  516. public Object getContent() throws IOException {
  517. // Must call getInputStream before GetHeaderField gets called
  518. // so that FileNotFoundException has a chance to be thrown up
  519. // from here without being caught.
  520. getInputStream();
  521. return getContentHandler().getContent(this);
  522. }
  523. /**
  524. * Returns a permission object representing the permission
  525. * necessary to make the connection represented by this
  526. * object. This method returns null if no permission is
  527. * required to make the connection. By default, this method
  528. * returns <code>java.security.AllPermission</code>. Subclasses
  529. * should override this method and return the permission
  530. * that best represents the permission required to make a
  531. * a connection to the URL. For example, a <code>URLConnection</code>
  532. * representing a <code>file:</code> URL would return a
  533. * <code>java.io.FilePermission</code> object.
  534. *
  535. * <p>The permission returned may dependent upon the state of the
  536. * connection. For example, the permission before connecting may be
  537. * different from that after connecting. For example, an HTTP
  538. * sever, say foo.com, may redirect the connection to a different
  539. * host, say bar.com. Before connecting the permission returned by
  540. * the connection will represent the permission needed to connect
  541. * to foo.com, while the permission returned after connecting will
  542. * be to bar.com.
  543. *
  544. * <p>Permissions are generally used for two purposes: to protect
  545. * caches of objects obtained through URLConnections, and to check
  546. * the right of a recipient to learn about a particular URL. In
  547. * the first case, the permission should be obtained
  548. * <em>after</em> the object has been obtained. For example, in an
  549. * HTTP connection, this will represent the permission to connect
  550. * to the host from which the data was ultimately fetched. In the
  551. * second case, the permission should be obtained and tested
  552. * <em>before</em> connecting.
  553. *
  554. * @return the permission object representing the permission
  555. * necessary to make the connection represented by this
  556. * URLConnection.
  557. *
  558. * @exception IOException if the computation of the permission
  559. * requires network or file I/O and an exception occurs while
  560. * computing it.
  561. */
  562. public Permission getPermission() throws IOException {
  563. return new java.security.AllPermission();
  564. }
  565. /**
  566. * Returns an input stream that reads from this open connection.
  567. *
  568. * @return an input stream that reads from this open connection.
  569. * @exception IOException if an I/O error occurs while
  570. * creating the input stream.
  571. * @exception UnknownServiceException if the protocol does not support
  572. * input.
  573. */
  574. public InputStream getInputStream() throws IOException {
  575. throw new UnknownServiceException("protocol doesn't support input");
  576. }
  577. /**
  578. * Returns an output stream that writes to this connection.
  579. *
  580. * @return an output stream that writes to this connection.
  581. * @exception IOException if an I/O error occurs while
  582. * creating the output stream.
  583. * @exception UnknownServiceException if the protocol does not support
  584. * output.
  585. */
  586. public OutputStream getOutputStream() throws IOException {
  587. throw new UnknownServiceException("protocol doesn't support output");
  588. }
  589. /**
  590. * Returns a <code>String</code> representation of this URL connection.
  591. *
  592. * @return a string representation of this <code>URLConnection</code>.
  593. */
  594. public String toString() {
  595. return this.getClass().getName() + ":" + url;
  596. }
  597. /**
  598. * Sets the value of the <code>doInput</code> field for this
  599. * <code>URLConnection</code> to the specified value.
  600. * <p>
  601. * A URL connection can be used for input and/or output. Set the DoInput
  602. * flag to true if you intend to use the URL connection for input,
  603. * false if not. The default is true unless DoOutput is explicitly
  604. * set to true, in which case DoInput defaults to false.
  605. *
  606. * @param value the new value.
  607. * @see java.net.URLConnection#doInput
  608. */
  609. public void setDoInput(boolean doinput) {
  610. if (connected)
  611. throw new IllegalAccessError("Already connected");
  612. doInput = doinput;
  613. }
  614. /**
  615. * Returns the value of this <code>URLConnection</code>'s
  616. * <code>doInput</code> flag.
  617. *
  618. * @return the value of this <code>URLConnection</code>'s
  619. * <code>doInput</code> flag.
  620. * @see java.net.URLConnection#doInput
  621. */
  622. public boolean getDoInput() {
  623. return doInput;
  624. }
  625. /**
  626. * Sets the value of the <code>doOutput</code> field for this
  627. * <code>URLConnection</code> to the specified value.
  628. * <p>
  629. * A URL connection can be used for input and/or output. Set the DoOutput
  630. * flag to true if you intend to use the URL connection for output,
  631. * false if not. The default is false.
  632. *
  633. * @param value the new value.
  634. * @see java.net.URLConnection#doOutput
  635. */
  636. public void setDoOutput(boolean dooutput) {
  637. if (connected)
  638. throw new IllegalAccessError("Already connected");
  639. doOutput = dooutput;
  640. }
  641. /**
  642. * Returns the value of this <code>URLConnection</code>'s
  643. * <code>doOutput</code> flag.
  644. *
  645. * @return the value of this <code>URLConnection</code>'s
  646. * <code>doOutput</code> flag.
  647. * @see java.net.URLConnection#doOutput
  648. */
  649. public boolean getDoOutput() {
  650. return doOutput;
  651. }
  652. /**
  653. * Set the value of the <code>allowUserInteraction</code> field of
  654. * this <code>URLConnection</code>.
  655. *
  656. * @param allowuserinteraction the new value.
  657. * @see java.net.URLConnection#allowUserInteraction
  658. */
  659. public void setAllowUserInteraction(boolean allowuserinteraction) {
  660. if (connected)
  661. throw new IllegalAccessError("Already connected");
  662. allowUserInteraction = allowuserinteraction;
  663. }
  664. /**
  665. * Returns the value of the <code>allowUserInteraction</code> field for
  666. * this object.
  667. *
  668. * @return the value of the <code>allowUserInteraction</code> field for
  669. * this object.
  670. * @see java.net.URLConnection#allowUserInteraction
  671. */
  672. public boolean getAllowUserInteraction() {
  673. return allowUserInteraction;
  674. }
  675. /**
  676. * Sets the default value of the
  677. * <code>allowUserInteraction</code> field for all future
  678. * <code>URLConnection</code> objects to the specified value.
  679. *
  680. * @param defaultallowuserinteraction the new value.
  681. * @see java.net.URLConnection#allowUserInteraction
  682. */
  683. public static void setDefaultAllowUserInteraction(boolean defaultallowuserinteraction) {
  684. defaultAllowUserInteraction = defaultallowuserinteraction;
  685. }
  686. /**
  687. * Returns the default value of the <code>allowUserInteraction</code>
  688. * field.
  689. * <p>
  690. * Ths default is "sticky", being a part of the static state of all
  691. * URLConnections. This flag applies to the next, and all following
  692. * URLConnections that are created.
  693. *
  694. * @return the default value of the <code>allowUserInteraction</code>
  695. * field.
  696. * @see java.net.URLConnection#allowUserInteraction
  697. */
  698. public static boolean getDefaultAllowUserInteraction() {
  699. return defaultAllowUserInteraction;
  700. }
  701. /**
  702. * Sets the value of the <code>useCaches</code> field of this
  703. * <code>URLConnection</code> to the specified value.
  704. * <p>
  705. * Some protocols do caching of documents. Occasionally, it is important
  706. * to be able to "tunnel through" and ignore the caches (e.g., the
  707. * "reload" button in a browser). If the UseCaches flag on a connection
  708. * is true, the connection is allowed to use whatever caches it can.
  709. * If false, caches are to be ignored.
  710. * The default value comes from DefaultUseCaches, which defaults to
  711. * true.
  712. *
  713. * @see java.net.URLConnection#useCaches
  714. */
  715. public void setUseCaches(boolean usecaches) {
  716. if (connected)
  717. throw new IllegalAccessError("Already connected");
  718. useCaches = usecaches;
  719. }
  720. /**
  721. * Returns the value of this <code>URLConnection</code>'s
  722. * <code>useCaches</code> field.
  723. *
  724. * @return the value of this <code>URLConnection</code>'s
  725. * <code>useCaches</code> field.
  726. * @see java.net.URLConnection#useCaches
  727. */
  728. public boolean getUseCaches() {
  729. return useCaches;
  730. }
  731. /**
  732. * Sets the value of the <code>ifModifiedSince</code> field of
  733. * this <code>URLConnection</code> to the specified value.
  734. *
  735. * @param value the new value.
  736. * @see java.net.URLConnection#ifModifiedSince
  737. */
  738. public void setIfModifiedSince(long ifmodifiedsince) {
  739. if (connected)
  740. throw new IllegalAccessError("Already connected");
  741. ifModifiedSince = ifmodifiedsince;
  742. }
  743. /**
  744. * Returns the value of this object's <code>ifModifiedSince</code> field.
  745. *
  746. * @return the value of this object's <code>ifModifiedSince</code> field.
  747. * @see java.net.URLConnection#ifModifiedSince
  748. */
  749. public long getIfModifiedSince() {
  750. return ifModifiedSince;
  751. }
  752. /**
  753. * Returns the default value of a <code>URLConnection</code>'s
  754. * <code>useCaches</code> flag.
  755. * <p>
  756. * Ths default is "sticky", being a part of the static state of all
  757. * URLConnections. This flag applies to the next, and all following
  758. * URLConnections that are created.
  759. *
  760. * @return the default value of a <code>URLConnection</code>'s
  761. * <code>useCaches</code> flag.
  762. * @see java.net.URLConnection#useCaches
  763. */
  764. public boolean getDefaultUseCaches() {
  765. return defaultUseCaches;
  766. }
  767. /**
  768. * Sets the default value of the <code>useCaches</code> field to the
  769. * specified value.
  770. *
  771. * @param defaultusecaches the new value.
  772. * @see java.net.URLConnection#useCaches
  773. */
  774. public void setDefaultUseCaches(boolean defaultusecaches) {
  775. defaultUseCaches = defaultusecaches;
  776. }
  777. /**
  778. * Sets the general request property.
  779. *
  780. * @param key the keyword by which the request is known
  781. * (e.g., "<code>accept</code>").
  782. * @param value the value associated with it.
  783. */
  784. public void setRequestProperty(String key, String value) {
  785. if (connected)
  786. throw new IllegalAccessError("Already connected");
  787. }
  788. /**
  789. * Returns the value of the named general request property for this
  790. * connection.
  791. *
  792. * @return the value of the named general request property for this
  793. * connection.
  794. */
  795. public String getRequestProperty(String key) {
  796. if (connected)
  797. throw new IllegalAccessError("Already connected");
  798. return null;
  799. }
  800. /**
  801. * Sets the default value of a general request property. When a
  802. * <code>URLConnection</code> is created, it is initialized with
  803. * these properties.
  804. *
  805. * @param key the keyword by which the request is known
  806. * (e.g., "<code>accept</code>").
  807. * @param value the value associated with the key.
  808. */
  809. public static void setDefaultRequestProperty(String key, String value) {
  810. }
  811. /**
  812. * Returns the value of the default request property. Default request
  813. * properties are set for every connection.
  814. *
  815. * @return the value of the default request property for the specified key.
  816. * @see java.net.URLConnection#setDefaultRequestProperty(java.lang.String, java.lang.String)
  817. */
  818. public static String getDefaultRequestProperty(String key) {
  819. return null;
  820. }
  821. /**
  822. * The ContentHandler factory.
  823. */
  824. static ContentHandlerFactory factory;
  825. /**
  826. * Sets the <code>ContentHandlerFactory</code> of an
  827. * application. It can be called at most once by an application.
  828. * <p>
  829. * The <code>ContentHandlerFactory</code> instance is used to
  830. * construct a content handler from a content type
  831. * <p>
  832. * If there is a security manager, this method first calls
  833. * the security manager's <code>checkSetFactory</code> method
  834. * to ensure the operation is allowed.
  835. * This could result in a SecurityException.
  836. *
  837. * @param fac the desired factory.
  838. * @exception Error if the factory has already been defined.
  839. * @exception SecurityException if a security manager exists and its
  840. * <code>checkSetFactory</code> method doesn't allow the operation.
  841. * @see java.net.ContentHandlerFactory
  842. * @see java.net.URLConnection#getContent()
  843. * @see SecurityManager#checkSetFactory
  844. */
  845. public static synchronized void setContentHandlerFactory(ContentHandlerFactory fac) {
  846. if (factory != null) {
  847. throw new Error("factory already defined");
  848. }
  849. SecurityManager security = System.getSecurityManager();
  850. if (security != null) {
  851. security.checkSetFactory();
  852. }
  853. factory = fac;
  854. }
  855. private static Hashtable handlers = new Hashtable();
  856. private static final ContentHandler UnknownContentHandlerP = new UnknownContentHandler();
  857. /**
  858. * Gets the Content Handler appropriate for this connection.
  859. * @param connection the connection to use.
  860. */
  861. synchronized ContentHandler getContentHandler()
  862. throws UnknownServiceException
  863. {
  864. String contentType = stripOffParameters(getContentType());
  865. ContentHandler handler = null;
  866. if (contentType == null)
  867. throw new UnknownServiceException("no content-type");
  868. try {
  869. handler = (ContentHandler) handlers.get(contentType);
  870. if (handler != null)
  871. return handler;
  872. } catch(Exception e) {
  873. }
  874. if (factory != null)
  875. handler = factory.createContentHandler(contentType);
  876. if (handler == null) {
  877. try {
  878. handler = lookupContentHandlerClassFor(contentType);
  879. } catch(Exception e) {
  880. e.printStackTrace();
  881. handler = UnknownContentHandlerP;
  882. }
  883. handlers.put(contentType, handler);
  884. }
  885. return handler;
  886. }
  887. /*
  888. * Media types are in the format: type/subtype*(; parameter).
  889. * For looking up the content handler, we should ignore those
  890. * parameters.
  891. */
  892. private String stripOffParameters(String contentType)
  893. {
  894. int index = contentType.indexOf(';');
  895. if (index > 0)
  896. return contentType.substring(0, index);
  897. else
  898. return contentType;
  899. }
  900. private static final String contentClassPrefix = "sun.net.www.content";
  901. private static final String contentPathProp = "java.content.handler.pkgs";
  902. /**
  903. * Looks for a content handler in a user-defineable set of places.
  904. * By default it looks in sun.net.www.content, but users can define a
  905. * vertical-bar delimited set of class prefixes to search through in
  906. * addition by defining the java.content.handler.pkgs property.
  907. * The class name must be of the form:
  908. * <pre>
  909. * {package-prefix}.{major}.{minor}
  910. * e.g.
  911. * YoyoDyne.experimental.text.plain
  912. * </pre>
  913. */
  914. private ContentHandler lookupContentHandlerClassFor(String contentType)
  915. throws InstantiationException, IllegalAccessException, ClassNotFoundException {
  916. String contentHandlerClassName = typeToPackageName(contentType);
  917. String contentHandlerPkgPrefixes =getContentHandlerPkgPrefixes();
  918. StringTokenizer packagePrefixIter =
  919. new StringTokenizer(contentHandlerPkgPrefixes, "|");
  920. while (packagePrefixIter.hasMoreTokens()) {
  921. String packagePrefix = packagePrefixIter.nextToken().trim();
  922. try {
  923. String name = packagePrefix + "." + contentHandlerClassName;
  924. ContentHandler handler =
  925. (ContentHandler) Class.forName(name).newInstance();
  926. return handler;
  927. } catch(Exception e) {
  928. }
  929. }
  930. return UnknownContentHandlerP;
  931. }
  932. /**
  933. * Utility function to map a MIME content type into an equivalent
  934. * pair of class name components. For example: "text/html" would
  935. * be returned as "text.html"
  936. */
  937. private String typeToPackageName(String contentType) {
  938. // make sure we canonicalize the class name: all lower case
  939. contentType = contentType.toLowerCase();
  940. int len = contentType.length();
  941. char nm[] = new char[len];
  942. contentType.getChars(0, len, nm, 0);
  943. for (int i = 0; i < len; i++) {
  944. char c = nm[i];
  945. if (c == '/') {
  946. nm[i] = '.';
  947. } else if (!('A' <= c && c <= 'Z' ||
  948. 'a' <= c && c <= 'z' ||
  949. '0' <= c && c <= '9')) {
  950. nm[i] = '_';
  951. }
  952. }
  953. return new String(nm);
  954. }
  955. /**
  956. * Returns a vertical bar separated list of package prefixes for potential
  957. * content handlers. Tries to get the java.content.handler.pkgs property
  958. * to use as a set of package prefixes to search. Whether or not
  959. * that property has been defined, the sun.net.www.content is always
  960. * the last one on the returned package list.
  961. */
  962. private String getContentHandlerPkgPrefixes() {
  963. String packagePrefixList = (String) AccessController.doPrivileged(
  964. new sun.security.action.GetPropertyAction(contentPathProp, ""));
  965. if (packagePrefixList != "") {
  966. packagePrefixList += "|";
  967. }
  968. return packagePrefixList + contentClassPrefix;
  969. }
  970. /**
  971. * Tries to determine the content type of an object, based
  972. * on the specified "file" component of a URL.
  973. * This is a convenience method that can be used by
  974. * subclasses that override the <code>getContentType</code> method.
  975. *
  976. * @param fname a filename.
  977. * @return a guess as to what the content type of the object is,
  978. * based upon its file name.
  979. * @see java.net.URLConnection#getContentType()
  980. */
  981. protected static String guessContentTypeFromName(String fname) {
  982. String contentType = null;
  983. contentType = getFileNameMap().getContentTypeFor(fname);
  984. return contentType;
  985. }
  986. /**
  987. * Tries to determine the type of an input stream based on the
  988. * characters at the beginning of the input stream. This method can
  989. * be used by subclasses that override the
  990. * <code>getContentType</code> method.
  991. * <p>
  992. * Ideally, this routine would not be needed. But many
  993. * <code>http</code> servers return the incorrect content type; in
  994. * addition, there are many nonstandard extensions. Direct inspection
  995. * of the bytes to determine the content type is often more accurate
  996. * than believing the content type claimed by the <code>http</code> server.
  997. *
  998. * @param is an input stream that supports marks.
  999. * @return a guess at the content type, or <code>null</code> if none
  1000. * can be determined.
  1001. * @exception IOException if an I/O error occurs while reading the
  1002. * input stream.
  1003. * @see java.io.InputStream#mark(int)
  1004. * @see java.io.InputStream#markSupported()
  1005. * @see java.net.URLConnection#getContentType()
  1006. */
  1007. static public String guessContentTypeFromStream(InputStream is) throws IOException
  1008. {
  1009. is.mark(10);
  1010. int c1 = is.read();
  1011. int c2 = is.read();
  1012. int c3 = is.read();
  1013. int c4 = is.read();
  1014. int c5 = is.read();
  1015. int c6 = is.read();
  1016. int c7 = is.read();
  1017. int c8 = is.read();
  1018. is.reset();
  1019. if (c1 == 0xCA && c2 == 0xFE && c3 == 0xBA && c4 == 0xBE)
  1020. return "application/java-vm";
  1021. if (c1 == 0xAC && c2 == 0xED)
  1022. // next two bytes are version number, currently 0x00 0x05
  1023. return "application/x-java-serialized-object";
  1024. if (c1 == 'G' && c2 == 'I' && c3 == 'F' && c4 == '8')
  1025. return "image/gif";
  1026. if (c1 == '#' && c2 == 'd' && c3 == 'e' && c4 == 'f')
  1027. return "image/x-bitmap";
  1028. if (c1 == '!' && c2 == ' ' && c3 == 'X' && c4 == 'P' && c5 == 'M' && c6 == '2')
  1029. return "image/x-pixmap";
  1030. if (c1 == 0x2E && c2 == 0x73 && c3 == 0x6E && c4 == 0x64)
  1031. return "audio/basic"; // .au format, big endian
  1032. if (c1 == 0x64 && c2 == 0x6E && c3 == 0x73 && c4 == 0x2E)
  1033. return "audio/basic"; // .au format, little endian
  1034. if (c1 == '<') {
  1035. if (c2 == '!'
  1036. || ((c2 == 'h' && (c3 == 't' && c4 == 'm' && c5 == 'l' ||
  1037. c3 == 'e' && c4 == 'a' && c5 == 'd')
  1038. || c2 == 'b' && c3 == 'o' && c4 == 'd' && c5 == 'y'))
  1039. || ((c2 == 'H' && (c3 == 'T' && c4 == 'M' && c5 == 'L' ||
  1040. c3 == 'E' && c4 == 'A' && c5 == 'D')
  1041. || c2 == 'B' && c3 == 'O' && c4 == 'D' && c5 == 'Y')))
  1042. return "text/html";
  1043. if (c2 == '?' && c3 == 'x' && c4 == 'm' && c5 == 'l' && c6 == ' ')
  1044. return "application/xml";
  1045. }
  1046. // big and little endian UTF-16 encodings, with byte order mark
  1047. if (c1 == 0xfe && c2 == 0xff) {
  1048. if (c3 == 0 && c4 == '<' && c5 == 0 && c6 == '?' &&
  1049. c7 == 0 && c8 == 'x')
  1050. return "application/xml";
  1051. }
  1052. if (c1 == 0xff && c2 == 0xfe) {
  1053. if (c3 == '<' && c4 == 0 && c5 == '?' && c6 == 0 &&
  1054. c7 == 'x' && c8 == 0)
  1055. return "application/xml";
  1056. }
  1057. if (c1 == 0xFF && c2 == 0xD8 && c3 == 0xFF && c4 == 0xE0)
  1058. return "image/jpeg";
  1059. if (c1 == 0xFF && c2 == 0xD8 && c3 == 0xFF && c4 == 0xEE)
  1060. return "image/jpg";
  1061. if (c1 == 'R' && c2 == 'I' && c3 == 'F' && c4 == 'F')
  1062. /* I don't know if this is official but evidence
  1063. * suggests that .wav files start with "RIFF" - brown
  1064. */
  1065. return "audio/x-wav";
  1066. if (c1 == 0xD0 && c2 == 0xCF && c3 == 0x11 && c4 == 0xE0 &&
  1067. c5 == 0xA1 && c6 == 0xB1 && c7 == 0x1A && c8 == 0xE1) {
  1068. /* Above is signature of Microsoft Structured Storage.
  1069. * Below this, could have tests for various SS entities.
  1070. * For now, just test for FlashPix.
  1071. */
  1072. if (checkfpx(is))
  1073. return "image/vnd.fpx";
  1074. }
  1075. return null;
  1076. }
  1077. /**
  1078. * Check for FlashPix image data in InputStream is. Return true if
  1079. * the stream has FlashPix data, false otherwise. Before calling this
  1080. * method, the stream should have already been checked to be sure it
  1081. * contains Microsoft Structured Storage data.
  1082. */
  1083. static private boolean checkfpx(InputStream is) throws IOException {
  1084. /* Test for FlashPix image data in Microsoft Structured Storage format.
  1085. * In general, should do this with calls to an SS implementation.
  1086. * Lacking that, need to dig via offsets to get to the FlashPix
  1087. * ClassID. Details:
  1088. *
  1089. * Offset to Fpx ClsID from beginning of stream should be:
  1090. *
  1091. * FpxClsidOffset = rootEntryOffset + clsidOffset
  1092. *
  1093. * where: clsidOffset = 0x50.
  1094. * rootEntryOffset = headerSize + sectorSize*sectDirStart
  1095. * + 128*rootEntryDirectory
  1096. *
  1097. * where: headerSize = 0x200 (always)
  1098. * sectorSize = 2 raised to power of uSectorShift,
  1099. * which is found in the header at
  1100. * offset 0x1E.
  1101. * sectDirStart = found in the header at offset 0x30.
  1102. * rootEntryDirectory = in general, should search for
  1103. * directory labelled as root.
  1104. * We will assume value of 0 (i.e.,
  1105. * rootEntry is in first directory)
  1106. */
  1107. // Mark the stream so we can reset it. 0x100 is enough for the first
  1108. // few reads, but the mark will have to be reset and set again once
  1109. // the offset to the root directory entry is computed. That offset
  1110. // can be very large and isn't know until the stream has been read from
  1111. is.mark(0x100);
  1112. // Get the byte ordering located at 0x1E. 0xFE is Intel,
  1113. // 0xFF is other
  1114. long toSkip = (long)0x1C;
  1115. long skipped = 0;
  1116. while (skipped != toSkip) {
  1117. skipped += is.skip(toSkip - skipped);
  1118. }
  1119. long posn = skipped;
  1120. int byteOrder = is.read();
  1121. is.read();
  1122. posn+=2;
  1123. int uSectorShift;
  1124. if(byteOrder == 0xFE) {
  1125. uSectorShift = is.read();
  1126. uSectorShift += is.read() << 8;
  1127. }
  1128. else {
  1129. uSectorShift = is.read() << 8;
  1130. uSectorShift += is.read();
  1131. }
  1132. posn += 2;
  1133. toSkip = (long)0x30 - posn;
  1134. skipped = 0;
  1135. while (skipped != toSkip) {
  1136. skipped += is.skip(toSkip - skipped);
  1137. }
  1138. posn += skipped;
  1139. int sectDirStart;
  1140. if(byteOrder == 0xFE) {
  1141. sectDirStart = is.read();
  1142. sectDirStart += is.read()<<8;
  1143. sectDirStart += is.read()<<16;
  1144. sectDirStart += is.read()<<24;
  1145. }
  1146. else {
  1147. sectDirStart = is.read()<<24;
  1148. sectDirStart += is.read()<<16;
  1149. sectDirStart += is.read()<<8;
  1150. sectDirStart += is.read();
  1151. }
  1152. posn += 4;
  1153. is.reset(); // Reset back to the beginning
  1154. toSkip = (long)0x200 +
  1155. (long)((int)1<<uSectorShift)*sectDirStart + (long)0x50;
  1156. // How far can we skip? Is there any performance problem here?
  1157. // This skip can be fairly long, at least 0x4c650 in at least
  1158. // one case. Have to assume that the skip will fit in an int.
  1159. is.mark((int)toSkip+0x30); // Leave room to read whole root dir
  1160. skipped = 0;
  1161. while (skipped != toSkip) {
  1162. skipped += is.skip(toSkip - skipped);
  1163. }
  1164. /* should be at beginning of ClassID, which is as follows
  1165. * (in Intel byte order):
  1166. * 00 67 61 56 54 C1 CE 11 85 53 00 AA 00 A1 F9 5B
  1167. *
  1168. * This is stored from Windows as long,short,short,char[8]
  1169. * so for byte order changes, the order only changes for
  1170. * the first 8 bytes in the ClassID.
  1171. *
  1172. * Test against this, ignoring second byte (Intel) since
  1173. * this could change depending on part of Fpx file we have.
  1174. */
  1175. int c[] = new int[16];
  1176. for (int i=0; i<16; i++) c[i] = is.read();
  1177. // intel byte order
  1178. if (byteOrder == 0xFE &&
  1179. c[0] == 0x00 && c[2] == 0x61 && c[3] == 0x56 &&
  1180. c[4] == 0x54 && c[5] == 0xC1 && c[6] == 0xCE &&
  1181. c[7] == 0x11 && c[8] == 0x85 && c[9] == 0x53 &&
  1182. c[10]== 0x00 && c[11]== 0xAA && c[12]== 0x00 &&
  1183. c[13]== 0xA1 && c[14]== 0xF9 && c[15]== 0x5B) {
  1184. is.reset();
  1185. return true;
  1186. }
  1187. // non-intel byte order
  1188. else if (c[3] == 0x00 && c[1] == 0x61 && c[0] == 0x56 &&
  1189. c[5] == 0x54 && c[4] == 0xC1 && c[7] == 0xCE &&
  1190. c[6] == 0x11 && c[8] == 0x85 && c[9] == 0x53 &&
  1191. c[10]== 0x00 && c[11]== 0xAA && c[12]== 0x00 &&
  1192. c[13]== 0xA1 && c[14]== 0xF9 && c[15]== 0x5B) {
  1193. is.reset();
  1194. return true;
  1195. }
  1196. is.reset();
  1197. return false;
  1198. }
  1199. }
  1200. class UnknownContentHandler extends ContentHandler {
  1201. public Object getContent(URLConnection uc) throws IOException {
  1202. return uc.getInputStream();
  1203. }
  1204. }