View Javadoc

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