OSDN Git Service

2004-03-11 Michael Koch <konqueror@gmx.de>
[pf3gnuchains/gcc-fork.git] / libjava / java / net / HttpURLConnection.java
1 /* HttpURLConnection.java - Subclass of communications links using
2                             Hypertext Transfer Protocol.
3    Copyright (C) 1998, 1999, 2000, 2002, 2003  Free Software Foundation
4
5 This file is part of GNU Classpath.
6
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11  
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING.  If not, write to the
19 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307 USA. 
21
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library.  Thus, the terms and
24 conditions of the GNU General Public License cover the whole
25 combination.
26
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module.  An independent module is a module which is not derived from
34 or based on this library.  If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so.  If you do not wish to do so, delete this
37 exception statement from your version. */
38
39
40 package java.net;
41
42 import java.io.InputStream;
43 import java.io.IOException;
44 import java.io.PushbackInputStream;
45 import java.security.Permission;
46
47 /*
48  * Written using on-line Java Platform 1.2 API Specification, as well
49  * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
50  * Status:  Believed complete and correct.
51  */
52
53 /**
54  * This class provides a common abstract implementation for those 
55  * URL connection classes that will connect using the HTTP protocol.
56  * In addition to the functionality provided by the URLConnection
57  * class, it defines constants for HTTP return code values and
58  * methods for setting the HTTP request method and determining whether
59  * or not to follow redirects. 
60  *
61  * @since 1.1
62  *
63  * @author Warren Levy (warrenl@cygnus.com)
64  * @author Aaron M. Renn (arenn@urbanophile.com)
65  */
66 public abstract class HttpURLConnection extends URLConnection
67 {
68   /* HTTP Success Response Codes */
69
70   /**
71    * Indicates that the client may continue with its request.  This value
72    * is specified as part of RFC 2068 but was not included in Sun's JDK, so
73    * beware of using this value
74    */
75   static final int HTTP_CONTINUE = 100;
76   
77   /**
78    * Indicates the request succeeded.
79    */
80   public static final int HTTP_OK               = 200;
81
82   /**
83    * The requested resource has been created.
84    */
85   public static final int HTTP_CREATED          = 201;
86
87   /**
88    * The request has been accepted for processing but has not completed.
89    * There is no guarantee that the requested action will actually ever
90    * be completed succesfully, but everything is ok so far.
91    */
92   public static final int HTTP_ACCEPTED         = 202;
93
94   /**
95    * The meta-information returned in the header is not the actual data
96    * from the original server, but may be from a local or other copy. 
97    * Normally this still indicates a successful completion.
98    */
99   public static final int HTTP_NOT_AUTHORITATIVE = 203;
100
101   /**
102    * The server performed the request, but there is no data to send
103    * back.  This indicates that the user's display should not be changed.
104    */
105   public static final int HTTP_NO_CONTENT       = 204;
106
107   /**
108    * The server performed the request, but there is no data to sent back,
109    * however, the user's display should be "reset" to clear out any form
110    * fields entered.
111    */
112   public static final int HTTP_RESET            = 205;
113
114   /**
115    * The server completed the partial GET request for the resource.
116    */
117   public static final int HTTP_PARTIAL          = 206;
118
119
120   /* HTTP Redirection Response Codes */
121
122   /**
123    * There is a list of choices available for the requested resource.
124    */
125   public static final int HTTP_MULT_CHOICE = 300;
126   
127   /**
128    * The resource has been permanently moved to a new location.
129    */
130   public static final int HTTP_MOVED_PERM = 301;
131   
132   /**
133    * The resource requested has been temporarily moved to a new location.
134    */
135   public static final int HTTP_MOVED_TEMP = 302;
136   
137   /**
138    * The response to the request issued is available at another location.
139    */
140   public static final int HTTP_SEE_OTHER = 303;
141   
142   /**
143    * The document has not been modified since the criteria specified in
144    * a conditional GET.
145    */
146   public static final int HTTP_NOT_MODIFIED = 304;
147
148   /**
149    * The requested resource needs to be accessed through a proxy.
150    */
151   public static final int HTTP_USE_PROXY = 305;
152   
153   
154   /* HTTP Client Error Response Codes */
155
156   /**
157    * The request was misformed or could not be understood.
158    */
159   public static final int HTTP_BAD_REQUEST = 400;
160   
161   /**
162    * The request made requires user authorization.  Try again with
163    * a correct authentication header.
164    */
165   public static final int HTTP_UNAUTHORIZED = 401;
166   
167   /**
168    * Code reserved for future use - I hope way in the future.
169    */
170   public static final int HTTP_PAYMENT_REQUIRED = 402;
171   
172   /**
173    * There is no permission to access the requested resource.
174    */
175   public static final int HTTP_FORBIDDEN = 403;
176   
177   /**
178    * The requested resource was not found.
179    */
180   public static final int HTTP_NOT_FOUND = 404;
181   
182   /**
183    * The specified request method is not allowed for this resource.
184    */
185   public static final int HTTP_BAD_METHOD = 405;
186   
187   /**
188    * Based on the input headers sent, the resource returned in response
189    * to the request would not be acceptable to the client.
190    */
191   public static final int HTTP_NOT_ACCEPTABLE = 406;
192   
193   /**
194    * The client must authenticate with a proxy prior to attempting this
195    * request.
196    */
197   public static final int HTTP_PROXY_AUTH = 407;
198   
199   /**
200    * The request timed out.
201    */
202   public static final int HTTP_CLIENT_TIMEOUT = 408;
203   
204   /**
205    * There is a conflict between the current state of the resource and the
206    * requested action.
207    */
208   public static final int HTTP_CONFLICT = 409;
209   
210   /**
211    * The requested resource is no longer available.  This ususally indicates
212    * a permanent condition.
213    */
214   public static final int HTTP_GONE = 410;
215
216   /**
217    * A Content-Length header is required for this request, but was not
218    * supplied.
219    */
220   public static final int HTTP_LENGTH_REQUIRED = 411;
221   
222   /**
223    * A client specified pre-condition was not met on the server.
224    */
225   public static final int HTTP_PRECON_FAILED = 412;
226   
227   /**
228    * The request sent was too large for the server to handle.
229    */
230   public static final int HTTP_ENTITY_TOO_LARGE = 413;
231   
232   /**
233    * The name of the resource specified was too long.
234    */
235   public static final int HTTP_REQ_TOO_LONG = 414;
236   
237   /**
238    * The request is in a format not supported by the requested resource.
239    */
240   public static final int HTTP_UNSUPPORTED_TYPE = 415;
241
242
243   /* HTTP Server Error Response Codes */
244
245   /**
246    * This error code indicates that some sort of server error occurred.
247    *
248    * @deprecated
249    */
250   public static final int HTTP_SERVER_ERROR    = 500;
251
252   /**
253    * The server encountered an unexpected error (such as a CGI script crash)
254    * that prevents the request from being fulfilled.
255    */
256   public static final int HTTP_INTERNAL_ERROR   = 500;
257
258   /**
259    * The server does not support the requested functionality.  
260    * @since 1.3
261    */
262   public static final int HTTP_NOT_IMPLEMENTED = 501;
263
264   /**
265    * The proxy encountered a bad response from the server it was proxy-ing for
266    */
267   public static final int HTTP_BAD_GATEWAY = 502;
268
269   /**
270    * The HTTP service is not availalble, such as because it is overloaded
271    * and does not want additional requests.
272    */
273   public static final int HTTP_UNAVAILABLE = 503;
274
275   /**
276    * The proxy timed out getting a reply from the remote server it was
277    * proxy-ing for.
278    */
279   public static final int HTTP_GATEWAY_TIMEOUT = 504;
280
281   /**
282    * This server does not support the protocol version requested.
283    */
284   public static final int HTTP_VERSION = 505;
285
286   // Non-HTTP response static variables
287
288   /**
289    * Flag to indicate whether or not redirects should be automatically
290    * followed by default.
291    */
292   private static boolean followRedirects = true;
293
294   /**
295    * This is a list of valid request methods, separated by "|" characters.
296    */
297   private static String valid_methods
298       = "|GET|POST|HEAD|OPTIONS|PUT|DELETE|TRACE|";
299
300   // Instance Variables
301
302   /**
303    * The requested method in use for this connection. Default is GET.
304    */
305   protected String method = "GET";
306
307   /**
308    * The response code received from the server
309    */
310   protected int responseCode = -1;
311
312   /**
313    * The response message string received from the server.
314    */
315   protected String responseMessage = null;
316
317   /**
318    * If this instance should follow redirect requests.
319    */
320   protected boolean instanceFollowRedirects = followRedirects;
321
322   /**
323    * Whether we alreadt got a valid response code for this connection.
324    * Used by <code>getResponseCode()</code> and
325    * <code>getResponseMessage()</code>.
326    */
327   private boolean gotResponseVals = false;
328
329   /**
330    * Create an HttpURLConnection for the specified URL
331    *
332    * @param url The URL to create this connection for.
333    */
334   protected HttpURLConnection(URL url)
335   {
336     super(url);
337   }
338   
339   /**   
340    * Closes the connection to the server.
341    */
342   public abstract void disconnect();
343
344   /** 
345    * Returns a boolean indicating whether or not this connection is going
346    * through a proxy
347    * 
348    * @return true if through a proxy, false otherwise
349    */
350   public abstract boolean usingProxy();
351
352   /**
353    * Sets whether HTTP redirects (requests with response code 3xx) should be
354    * automatically followed by this class. True by default
355    *
356    * @param set true if redirects should be followed, false otherwis.
357    *
358    * @exception SecurityException If a security manager exists and its
359    * checkSetFactory method doesn't allow the operation
360    */
361   public static void setFollowRedirects(boolean set)
362   {
363     // Throw an exception if an extant security mgr precludes
364     // setting the factory.
365     SecurityManager s = System.getSecurityManager();
366     if (s != null)
367       s.checkSetFactory();
368
369     followRedirects = set;
370   }
371
372   /**
373    * Returns a boolean indicating whether or not HTTP redirects will 
374    * automatically be followed or not.
375    *
376    * @return true if redirects will be followed, false otherwise
377    */
378   public static boolean getFollowRedirects()
379   {
380     return followRedirects;
381   }
382
383   /**
384    * Returns the value of this HttpURLConnection's instanceFollowRedirects
385    * field
386    */
387   public boolean getInstanceFollowRedirects ()
388   {
389     return instanceFollowRedirects;
390   }
391
392   /**
393    * Sets the value of this HttpURLConnection's instanceFollowRedirects field
394    */
395   public void setInstanceFollowRedirects (boolean follow)
396   {
397     instanceFollowRedirects = follow;
398   }
399
400   /**
401    * Set the method for the URL request, one of:
402    * GET POST HEAD OPTIONS PUT DELETE TRACE are legal
403    *
404    * @exception ProtocolException If the method cannot be reset or if the
405    * requested method isn't valid for HTTP
406    */
407   public void setRequestMethod(String method) throws ProtocolException
408   {
409     if (connected)
410       throw new ProtocolException("Already connected");
411
412     method = method.toUpperCase();
413     if (valid_methods.indexOf("|" + method + "|") != -1)
414       this.method = method;
415     else
416       throw new ProtocolException("Invalid HTTP request method: " + method);
417
418   }
419
420   /**
421    * The request method currently in use for this connection.
422    *
423    * @return The request method
424    */
425   public String getRequestMethod()
426   {
427     return method;
428   }
429
430   /**
431    * Gets the status code from an HTTP response message, or -1 if
432    * the response code could not be determined.
433    * Note that all valid response codes have class variables
434    * defined for them in this class.
435    *
436    * @return The response code
437    *
438    * @exception IOException If an error occurs
439    */
440   public int getResponseCode() throws IOException
441   {
442     if (!gotResponseVals)
443       getResponseVals();
444     return responseCode;
445   }
446
447   /**
448    * Gets the HTTP response message, if any, returned along with the
449    * response code from a server. Null if no response message was set
450    * or an error occured while connecting.
451    *
452    * @return The response message
453    *
454    * @exception IOException If an error occurs
455    */
456   public String getResponseMessage() throws IOException
457   {
458     if (!gotResponseVals)
459       getResponseVals();
460     return responseMessage;
461   }
462
463   private void getResponseVals() throws IOException
464   {
465     // getHeaderField() will connect for us, but do it here first in
466     // order to pick up IOExceptions.
467     if (!connected)
468       connect();
469       
470     gotResponseVals = true;
471
472     // If responseCode not yet explicitly set by subclass
473     if (responseCode == -1)
474       {
475         // Response is the first header received from the connection.
476         String respField = getHeaderField(0);
477         
478         if (respField == null || ! respField.startsWith("HTTP/"))
479           {
480             // Set to default values on failure.
481             responseCode = -1;
482             responseMessage = null;
483             return;
484           }
485
486         int firstSpc, nextSpc;
487         firstSpc = respField.indexOf(' ');
488         nextSpc = respField.indexOf(' ', firstSpc + 1);
489         responseMessage = respField.substring(nextSpc + 1);
490         String codeStr = respField.substring(firstSpc + 1, nextSpc);
491         try
492           {
493             responseCode = Integer.parseInt(codeStr);
494           }
495         catch (NumberFormatException e)
496           {
497             // Set to default values on failure.
498             responseCode = -1;
499             responseMessage = null;
500           }
501       }
502   }
503
504   /**
505    * Returns a permission object representing the permission necessary to make
506    * the connection represented by this object
507    *
508    * @exception IOException If an error occurs
509    */
510   public Permission getPermission() throws IOException
511   {
512     URL url = getURL();
513     String host = url.getHost();
514     int port = url.getPort();
515     if (port == -1)
516       port = 80;
517     
518     host = host + ":" + port;
519     
520     return new SocketPermission(host, "connect");
521   }
522
523   /**
524    * This method allows the caller to retrieve any data that might have
525    * been sent despite the fact that an error occurred.  For example, the
526    * HTML page sent along with a 404 File Not Found error.  If the socket
527    * is not connected, or if no error occurred or no data was returned,
528    * this method returns <code>null</code>.
529    *
530    * @return An <code>InputStream</code> for reading error data.
531    */
532   public InputStream getErrorStream ()
533   {
534     if (!connected)
535       return(null);
536     
537     int code;
538     try 
539       {
540         code = getResponseCode();
541       }
542     catch(IOException e)
543       {
544         code = -1;
545       }
546     
547     if (code == -1)
548       return(null);
549     
550     if (((code/100) != 4) || ((code/100) != 5))
551       return(null); 
552     
553     try
554       {
555         PushbackInputStream pbis = new PushbackInputStream(getInputStream());
556         
557         int i = pbis.read();
558         if (i == -1)
559           return(null);
560         
561         pbis.unread(i);
562         return(pbis);
563       }
564     catch(IOException e)
565       {
566         return(null);
567       }
568   }
569
570   /**
571    * Returns the value of the named field parsed as date
572    */
573   public long getHeaderFieldDate (String key, long value)
574   {
575     // FIXME: implement this correctly
576     // http://www.w3.org/Protocols/HTTP-NG/ng-notes.txt
577     
578     return super.getHeaderFieldDate (key, value);
579   }
580 }