1. /*
  2. * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/util/HttpURLConnection.java,v 1.15 2004/04/18 23:51:38 jsdever Exp $
  3. * $Revision: 1.15 $
  4. * $Date: 2004/04/18 23:51:38 $
  5. *
  6. * ====================================================================
  7. *
  8. * Copyright 1999-2004 The Apache Software Foundation
  9. *
  10. * Licensed under the Apache License, Version 2.0 (the "License");
  11. * you may not use this file except in compliance with the License.
  12. * You may obtain a copy of the License at
  13. *
  14. * http://www.apache.org/licenses/LICENSE-2.0
  15. *
  16. * Unless required by applicable law or agreed to in writing, software
  17. * distributed under the License is distributed on an "AS IS" BASIS,
  18. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  19. * See the License for the specific language governing permissions and
  20. * limitations under the License.
  21. * ====================================================================
  22. *
  23. * This software consists of voluntary contributions made by many
  24. * individuals on behalf of the Apache Software Foundation. For more
  25. * information on the Apache Software Foundation, please see
  26. * <http://www.apache.org/>.
  27. *
  28. */
  29. package org.apache.commons.httpclient.util;
  30. import org.apache.commons.httpclient.HttpMethod;
  31. import org.apache.commons.httpclient.Header;
  32. import org.apache.commons.logging.LogFactory;
  33. import org.apache.commons.logging.Log;
  34. import java.io.IOException;
  35. import java.io.InputStream;
  36. import java.io.OutputStream;
  37. import java.net.URL;
  38. import java.net.ProtocolException;
  39. import java.security.Permission;
  40. /**
  41. * Provides a <code>HttpURLConnection</code> wrapper around HttpClient's
  42. * <code>HttpMethod</code>. This allows existing code to easily switch to
  43. * HttpClieht without breaking existing interfaces using the JDK
  44. * <code>HttpURLConnection</code>.
  45. *
  46. * Note 1: The current implementations wraps only a connected
  47. * <code>HttpMethod</code>, ie a method that has alreayd been used to connect
  48. * to an HTTP server.
  49. *
  50. * Note 2: It is a best try effort as different version of the JDK have
  51. * different behaviours for <code>HttpURLConnection</code> (And I'm not even
  52. * including the numerous <code>HttpURLConnection</code> bugs!).
  53. *
  54. * @author <a href="mailto:vmassol@apache.org">Vincent Massol</a>
  55. * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
  56. * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
  57. *
  58. * @since 2.0
  59. *
  60. * @version $Id: HttpURLConnection.java,v 1.15 2004/04/18 23:51:38 jsdever Exp $
  61. */
  62. public class HttpURLConnection extends java.net.HttpURLConnection {
  63. // -------------------------------------------------------- Class Variables
  64. /** Log object for this class. */
  65. private static final Log LOG = LogFactory.getLog(HttpURLConnection.class);
  66. // ----------------------------------------------------- Instance Variables
  67. /**
  68. * The <code>HttpMethod</code> object that was used to connect to the
  69. * HTTP server. It contains all the returned data.
  70. */
  71. private HttpMethod method;
  72. /**
  73. * The URL to which we are connected
  74. */
  75. private URL url;
  76. // ----------------------------------------------------------- Constructors
  77. /**
  78. * Creates an <code>HttpURLConnection</code> from a <code>HttpMethod</code>.
  79. *
  80. * @param method the theMethod that was used to connect to the HTTP
  81. * server and which contains the returned data.
  82. * @param url the URL to which we are connected (includes query string)
  83. */
  84. public HttpURLConnection(HttpMethod method, URL url) {
  85. super(url);
  86. this.method = method;
  87. this.url = url;
  88. }
  89. /**
  90. * Create an instance.
  91. * @param url The URL.
  92. * @see java.net.HttpURLConnection#HttpURLConnection(URL)
  93. */
  94. protected HttpURLConnection(URL url) {
  95. super(url);
  96. throw new RuntimeException("An HTTP URL connection can only be "
  97. + "constructed from a HttpMethod class");
  98. }
  99. // --------------------------------------------------------- Public Methods
  100. /**
  101. * Gets an input stream for the HttpMethod response body.
  102. * @throws IOException If an IO problem occurs.
  103. * @return The input stream.
  104. * @see java.net.HttpURLConnection#getInputStream()
  105. * @see org.apache.commons.httpclient.HttpMethod#getResponseBodyAsStream()
  106. */
  107. public InputStream getInputStream() throws IOException {
  108. LOG.trace("enter HttpURLConnection.getInputStream()");
  109. return this.method.getResponseBodyAsStream();
  110. }
  111. /**
  112. * Not yet implemented.
  113. * Return the error stream.
  114. * @see java.net.HttpURLConnection#getErrorStream()
  115. */
  116. public InputStream getErrorStream() {
  117. LOG.trace("enter HttpURLConnection.getErrorStream()");
  118. throw new RuntimeException("Not implemented yet");
  119. }
  120. /**
  121. * Not yet implemented.
  122. * @see java.net.HttpURLConnection#disconnect()
  123. */
  124. public void disconnect() {
  125. LOG.trace("enter HttpURLConnection.disconnect()");
  126. throw new RuntimeException("Not implemented yet");
  127. }
  128. /**
  129. * Not available: the data must have already been retrieved.
  130. * @throws IOException If an IO problem occurs.
  131. * @see java.net.HttpURLConnection#connect()
  132. */
  133. public void connect() throws IOException {
  134. LOG.trace("enter HttpURLConnection.connect()");
  135. throw new RuntimeException("This class can only be used with already"
  136. + "retrieved data");
  137. }
  138. /**
  139. * Not yet implemented.
  140. * @return true if we are using a proxy.
  141. * @see java.net.HttpURLConnection#usingProxy()
  142. */
  143. public boolean usingProxy() {
  144. LOG.trace("enter HttpURLConnection.usingProxy()");
  145. throw new RuntimeException("Not implemented yet");
  146. }
  147. /**
  148. * Return the request method.
  149. * @return The request method.
  150. * @see java.net.HttpURLConnection#getRequestMethod()
  151. * @see org.apache.commons.httpclient.HttpMethod#getName()
  152. */
  153. public String getRequestMethod() {
  154. LOG.trace("enter HttpURLConnection.getRequestMethod()");
  155. return this.method.getName();
  156. }
  157. /**
  158. * Return the response code.
  159. * @return The response code.
  160. * @throws IOException If an IO problem occurs.
  161. * @see java.net.HttpURLConnection#getResponseCode()
  162. * @see org.apache.commons.httpclient.HttpMethod#getStatusCode()
  163. */
  164. public int getResponseCode() throws IOException {
  165. LOG.trace("enter HttpURLConnection.getResponseCode()");
  166. return this.method.getStatusCode();
  167. }
  168. /**
  169. * Return the response message
  170. * @return The response message
  171. * @throws IOException If an IO problem occurs.
  172. * @see java.net.HttpURLConnection#getResponseMessage()
  173. * @see org.apache.commons.httpclient.HttpMethod#getStatusText()
  174. */
  175. public String getResponseMessage() throws IOException {
  176. LOG.trace("enter HttpURLConnection.getResponseMessage()");
  177. return this.method.getStatusText();
  178. }
  179. /**
  180. * Return the header field
  181. * @param name the name of the header
  182. * @return the header field.
  183. * @see java.net.HttpURLConnection#getHeaderField(String)
  184. * @see org.apache.commons.httpclient.HttpMethod#getResponseHeaders()
  185. */
  186. public String getHeaderField(String name) {
  187. LOG.trace("enter HttpURLConnection.getHeaderField(String)");
  188. // Note: Return the last matching header in the Header[] array, as in
  189. // the JDK implementation.
  190. Header[] headers = this.method.getResponseHeaders();
  191. for (int i = headers.length - 1; i >= 0; i--) {
  192. if (headers[i].getName().equalsIgnoreCase(name)) {
  193. return headers[i].getValue();
  194. }
  195. }
  196. return null;
  197. }
  198. /**
  199. * Return the header field key
  200. * @param keyPosition The key position
  201. * @return The header field key.
  202. * @see java.net.HttpURLConnection#getHeaderFieldKey(int)
  203. * @see org.apache.commons.httpclient.HttpMethod#getResponseHeaders()
  204. */
  205. public String getHeaderFieldKey(int keyPosition) {
  206. LOG.trace("enter HttpURLConnection.getHeaderFieldKey(int)");
  207. // Note: HttpClient does not consider the returned Status Line as
  208. // a response header. However, getHeaderFieldKey(0) is supposed to
  209. // return null. Hence the special case below ...
  210. if (keyPosition == 0) {
  211. return null;
  212. }
  213. // Note: HttpClient does not currently keep headers in the same order
  214. // that they are read from the HTTP server.
  215. Header[] headers = this.method.getResponseHeaders();
  216. if (keyPosition < 0 || keyPosition > headers.length) {
  217. return null;
  218. }
  219. return headers[keyPosition - 1].getName();
  220. }
  221. /**
  222. * Return the header field at the specified position
  223. * @param position The position
  224. * @return The header field.
  225. * @see java.net.HttpURLConnection#getHeaderField(int)
  226. * @see org.apache.commons.httpclient.HttpMethod#getResponseHeaders()
  227. */
  228. public String getHeaderField(int position) {
  229. LOG.trace("enter HttpURLConnection.getHeaderField(int)");
  230. // Note: HttpClient does not consider the returned Status Line as
  231. // a response header. However, getHeaderField(0) is supposed to
  232. // return the status line. Hence the special case below ...
  233. if (position == 0) {
  234. return this.method.getStatusLine().toString();
  235. }
  236. // Note: HttpClient does not currently keep headers in the same order
  237. // that they are read from the HTTP server.
  238. Header[] headers = this.method.getResponseHeaders();
  239. if (position < 0 || position > headers.length) {
  240. return null;
  241. }
  242. return headers[position - 1].getValue();
  243. }
  244. /**
  245. * Return the URL
  246. * @return The URL.
  247. * @see java.net.HttpURLConnection#getURL()
  248. */
  249. public URL getURL() {
  250. LOG.trace("enter HttpURLConnection.getURL()");
  251. return this.url;
  252. }
  253. // Note: We don't implement the following methods so that they default to
  254. // the JDK implementation. They will all call
  255. // <code>getHeaderField(String)</code> which we have overridden.
  256. // java.net.HttpURLConnection#getHeaderFieldDate(String, long)
  257. // java.net.HttpURLConnection#getContentLength()
  258. // java.net.HttpURLConnection#getContentType()
  259. // java.net.HttpURLConnection#getContentEncoding()
  260. // java.net.HttpURLConnection#getDate()
  261. // java.net.HttpURLConnection#getHeaderFieldInt(String, int)
  262. // java.net.HttpURLConnection#getExpiration()
  263. // java.net.HttpURLConnection#getLastModified()
  264. /**
  265. * Not available: the data must have already been retrieved.
  266. */
  267. public void setInstanceFollowRedirects(boolean isFollowingRedirects) {
  268. LOG.trace("enter HttpURLConnection.setInstanceFollowRedirects(boolean)");
  269. throw new RuntimeException("This class can only be used with already"
  270. + "retrieved data");
  271. }
  272. /**
  273. * Not yet implemented.
  274. */
  275. public boolean getInstanceFollowRedirects() {
  276. LOG.trace("enter HttpURLConnection.getInstanceFollowRedirects()");
  277. throw new RuntimeException("Not implemented yet");
  278. }
  279. /**
  280. * Not available: the data must have already been retrieved.
  281. * @see java.net.HttpURLConnection#setRequestMethod(String)
  282. */
  283. public void setRequestMethod(String method) throws ProtocolException {
  284. LOG.trace("enter HttpURLConnection.setRequestMethod(String)");
  285. throw new RuntimeException("This class can only be used with already"
  286. + "retrieved data");
  287. }
  288. /**
  289. * Not yet implemented.
  290. * @see java.net.HttpURLConnection#getPermission()
  291. */
  292. public Permission getPermission() throws IOException {
  293. LOG.trace("enter HttpURLConnection.getPermission()");
  294. throw new RuntimeException("Not implemented yet");
  295. }
  296. /**
  297. * Not yet implemented.
  298. * @see java.net.HttpURLConnection#getContent()
  299. */
  300. public Object getContent() throws IOException {
  301. LOG.trace("enter HttpURLConnection.getContent()");
  302. throw new RuntimeException("Not implemented yet");
  303. }
  304. /**
  305. * Not yet implemented.
  306. */
  307. public Object getContent(Class[] classes) throws IOException {
  308. LOG.trace("enter HttpURLConnection.getContent(Class[])");
  309. throw new RuntimeException("Not implemented yet");
  310. }
  311. /**
  312. * @see java.net.HttpURLConnection#getOutputStream()
  313. */
  314. public OutputStream getOutputStream() throws IOException {
  315. LOG.trace("enter HttpURLConnection.getOutputStream()");
  316. throw new RuntimeException("This class can only be used with already"
  317. + "retrieved data");
  318. }
  319. /**
  320. * Not available: the data must have already been retrieved.
  321. * @see java.net.HttpURLConnection#setDoInput(boolean)
  322. */
  323. public void setDoInput(boolean isInput) {
  324. LOG.trace("enter HttpURLConnection.setDoInput()");
  325. throw new RuntimeException("This class can only be used with already"
  326. + "retrieved data");
  327. }
  328. /**
  329. * Not yet implemented.
  330. * @see java.net.HttpURLConnection#getDoInput()
  331. */
  332. public boolean getDoInput() {
  333. LOG.trace("enter HttpURLConnection.getDoInput()");
  334. throw new RuntimeException("Not implemented yet");
  335. }
  336. /**
  337. * Not available: the data must have already been retrieved.
  338. * @see java.net.HttpURLConnection#setDoOutput(boolean)
  339. */
  340. public void setDoOutput(boolean isOutput) {
  341. LOG.trace("enter HttpURLConnection.setDoOutput()");
  342. throw new RuntimeException("This class can only be used with already"
  343. + "retrieved data");
  344. }
  345. /**
  346. * Not yet implemented.
  347. * @see java.net.HttpURLConnection#getDoOutput()
  348. */
  349. public boolean getDoOutput() {
  350. LOG.trace("enter HttpURLConnection.getDoOutput()");
  351. throw new RuntimeException("Not implemented yet");
  352. }
  353. /**
  354. * Not available: the data must have already been retrieved.
  355. * @see java.net.HttpURLConnection#setAllowUserInteraction(boolean)
  356. */
  357. public void setAllowUserInteraction(boolean isAllowInteraction) {
  358. LOG.trace("enter HttpURLConnection.setAllowUserInteraction(boolean)");
  359. throw new RuntimeException("This class can only be used with already"
  360. + "retrieved data");
  361. }
  362. /**
  363. * Not yet implemented.
  364. * @see java.net.HttpURLConnection#getAllowUserInteraction()
  365. */
  366. public boolean getAllowUserInteraction() {
  367. LOG.trace("enter HttpURLConnection.getAllowUserInteraction()");
  368. throw new RuntimeException("Not implemented yet");
  369. }
  370. /**
  371. * Not available: the data must have already been retrieved.
  372. * @see java.net.HttpURLConnection#setUseCaches(boolean)
  373. */
  374. public void setUseCaches(boolean isUsingCaches) {
  375. LOG.trace("enter HttpURLConnection.setUseCaches(boolean)");
  376. throw new RuntimeException("This class can only be used with already"
  377. + "retrieved data");
  378. }
  379. /**
  380. * Not yet implemented.
  381. * @see java.net.HttpURLConnection#getUseCaches()
  382. */
  383. public boolean getUseCaches() {
  384. LOG.trace("enter HttpURLConnection.getUseCaches()");
  385. throw new RuntimeException("Not implemented yet");
  386. }
  387. /**
  388. * Not available: the data must have already been retrieved.
  389. * @see java.net.HttpURLConnection#setIfModifiedSince(long)
  390. */
  391. public void setIfModifiedSince(long modificationDate) {
  392. LOG.trace("enter HttpURLConnection.setIfModifiedSince(long)");
  393. throw new RuntimeException("This class can only be used with already"
  394. + "retrieved data");
  395. }
  396. /**
  397. * Not yet implemented.
  398. * @see java.net.HttpURLConnection#getIfModifiedSince()
  399. */
  400. public long getIfModifiedSince() {
  401. LOG.trace("enter HttpURLConnection.getIfmodifiedSince()");
  402. throw new RuntimeException("Not implemented yet");
  403. }
  404. /**
  405. * Not available: the data must have already been retrieved.
  406. * @see java.net.HttpURLConnection#getDefaultUseCaches()
  407. */
  408. public boolean getDefaultUseCaches() {
  409. LOG.trace("enter HttpURLConnection.getDefaultUseCaches()");
  410. throw new RuntimeException("Not implemented yet");
  411. }
  412. /**
  413. * Not available: the data must have already been retrieved.
  414. * @see java.net.HttpURLConnection#setDefaultUseCaches(boolean)
  415. */
  416. public void setDefaultUseCaches(boolean isUsingCaches) {
  417. LOG.trace("enter HttpURLConnection.setDefaultUseCaches(boolean)");
  418. throw new RuntimeException("This class can only be used with already"
  419. + "retrieved data");
  420. }
  421. /**
  422. * Not available: the data must have already been retrieved.
  423. * @see java.net.HttpURLConnection#setRequestProperty(String,String)
  424. */
  425. public void setRequestProperty(String key, String value) {
  426. LOG.trace("enter HttpURLConnection.setRequestProperty()");
  427. throw new RuntimeException("This class can only be used with already"
  428. + "retrieved data");
  429. }
  430. /**
  431. * Not yet implemented.
  432. * @see java.net.HttpURLConnection#getRequestProperty(String)
  433. */
  434. public String getRequestProperty(String key) {
  435. LOG.trace("enter HttpURLConnection.getRequestProperty()");
  436. throw new RuntimeException("Not implemented yet");
  437. }
  438. }