2003-12-04 Michael Koch <konqueror@gmx.de>
[official-gcc.git] / libjava / gnu / java / net / protocol / http / Connection.java
blobb564afb376f03514ef5e23a19215abdaade7d797
1 /* HttpURLConnection.java -- URLConnection class for HTTP protocol
2 Copyright (C) 1998, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu.java.net.protocol.http;
41 import java.io.BufferedInputStream;
42 import java.io.InputStream;
43 import java.io.IOException;
44 import java.io.OutputStream;
45 import java.io.PrintWriter;
46 import java.net.HttpURLConnection;
47 import java.net.ProtocolException;
48 import java.net.Socket;
49 import java.net.URL;
50 import java.net.URLConnection;
51 import java.util.Iterator;
52 import java.util.Map;
53 import java.util.Vector;
54 import java.util.Hashtable;
56 /**
57 * This subclass of java.net.URLConnection models a URLConnection via
58 * the HTTP protocol.
60 * Status: Minimal subset of functionality. Proxies only partially
61 * handled; Redirects not yet handled. FileNameMap handling needs to
62 * be considered. useCaches, ifModifiedSince, and
63 * allowUserInteraction need consideration as well as doInput and
64 * doOutput.
66 * @author Aaron M. Renn <arenn@urbanophile.com>
67 * @author Warren Levy <warrenl@cygnus.com>
69 public final class Connection extends HttpURLConnection
71 /**
72 * The socket we are connected to
74 private Socket socket;
75 private static int proxyPort = 80;
76 private static boolean proxyInUse = false;
77 private static String proxyHost = null;
79 static
81 // Recognize some networking properties listed at
82 // http://java.sun.com/j2se/1.4/docs/guide/net/properties.html.
83 String port = null;
84 proxyHost = System.getProperty("http.proxyHost");
85 if (proxyHost != null)
87 proxyInUse = true;
88 if ((port = System.getProperty("http.proxyPort")) != null)
90 try
92 proxyPort = Integer.parseInt(port);
94 catch (Throwable t)
96 // Nothing.
103 * The InputStream for this connection.
105 private BufferedInputStream inputStream;
108 * This is the object that holds the header field information
110 private Hashtable requestProperties = new Hashtable();
111 private Hashtable hdrHash = new Hashtable();
112 private Vector hdrVec = new Vector();
115 * Calls superclass constructor to initialize
117 protected Connection(URL url)
119 super(url);
121 /* Set up some variables */
122 doOutput = false;
125 public void setRequestProperty(String key, String value)
127 if (connected)
128 throw new IllegalAccessError("Connection already established.");
130 requestProperties.put(key, value);
133 public String getRequestProperty(String key)
135 if (connected)
136 throw new IllegalAccessError("Connection already established.");
138 return (String) requestProperties.get(key);
142 * Connects to the remote host, sends the request, and parses the reply
143 * code and header information returned
145 public void connect() throws IOException
147 // Call is ignored if already connected.
148 if (connected)
149 return;
151 // Get address and port number.
152 int port;
153 if (proxyInUse)
155 port = proxyPort;
156 socket = new Socket(proxyHost, port);
158 else
160 if ((port = url.getPort()) == -1)
161 port = 80;
162 // Open socket and output stream.
163 socket = new Socket(url.getHost(), port);
166 // Originally tried using a BufferedReader here to take advantage of
167 // the readLine method and avoid the following, but the buffer read
168 // past the end of the headers so the first part of the content was lost.
169 // It is probably more robust than it needs to be, e.g. the byte[]
170 // is unlikely to overflow and a '\r' should always be followed by a '\n',
171 // but it is better to be safe just in case.
172 inputStream = new BufferedInputStream(socket.getInputStream());
174 sendRequest();
175 getHttpHeaders();
176 connected = true;
180 * Disconnects from the remote server.
182 public void disconnect()
184 if (socket != null)
188 socket.close();
190 catch (IOException e)
192 // Ignore errors in closing socket.
194 socket = null;
199 * Write HTTP request header and content to outputWriter.
201 void sendRequest() throws IOException
203 // Create PrintWriter for easier sending of headers.
204 PrintWriter outputWriter = new PrintWriter(socket.getOutputStream());
206 // Send request including any request properties that were set.
207 outputWriter.print (getRequestMethod() + " " + url.getFile()
208 + " HTTP/1.0\r\n");
210 // Set additional HTTP headers.
211 if (getRequestProperty ("Host") == null)
212 setRequestProperty ("Host", url.getHost());
214 // Write all req_props name-value pairs to the output writer.
215 Iterator itr = getRequestProperties().entrySet().iterator();
217 while (itr.hasNext())
219 Map.Entry e = (Map.Entry) itr.next();
220 outputWriter.print (e.getKey() + ": " + e.getValue() + "\r\n");
223 // One more CR-LF indicates end of header.
224 outputWriter.print ("\r\n");
225 outputWriter.flush();
229 * Return a boolean indicating whether or not this connection is
230 * going through a proxy
232 * @return true if using a proxy, false otherwise
234 public boolean usingProxy()
236 return proxyInUse;
240 * Returns an InputStream for reading from this connection. This stream
241 * will be "queued up" for reading just the contents of the requested file.
242 * Overrides URLConnection.getInputStream()
244 * @return An InputStream for this connection.
246 * @exception IOException If an error occurs
248 public InputStream getInputStream() throws IOException
250 if (!connected)
251 connect();
253 if (!doInput)
254 throw new ProtocolException("Can't open InputStream if doInput is false");
256 return inputStream;
259 public OutputStream getOutputStream() throws IOException
261 if (!connected)
262 connect();
264 if (! doOutput)
265 throw new ProtocolException("Can't open OutputStream if doOutput is false");
267 return socket.getOutputStream();
271 * Overrides java.net.HttpURLConnection.setRequestMethod() in order to
272 * restrict the available methods to only those we support.
274 * @param method The RequestMethod to use
276 * @exception ProtocolException If the specified method is not valid
278 public void setRequestMethod (String method) throws ProtocolException
280 method = method.toUpperCase();
282 if (method.equals("GET"))
283 super.setRequestMethod (method);
284 else
285 throw new ProtocolException ("Unsupported or unknown request method " +
286 method);
289 public String getHeaderField(String name)
291 if (!connected)
294 connect();
296 catch (IOException x)
298 return null;
301 return (String) hdrHash.get(name.toLowerCase());
304 public Map getHeaderFields()
306 if (!connected)
309 connect();
311 catch (IOException x)
313 return null;
316 return hdrHash;
320 * This method returns the header field value at the specified numeric
321 * index.
323 * @param n The index into the header field array
325 * @return The value of the specified header field, or <code>null</code>
326 * if the specified index is not valid.
328 public String getHeaderField(int n)
330 if (!connected)
333 connect();
335 catch (IOException x)
337 return null;
340 if (n < hdrVec.size())
341 return getField ((String) hdrVec.elementAt(n));
342 return null;
346 * This method returns the header field key at the specified numeric
347 * index.
349 * @param n The index into the header field array
351 * @return The name of the header field key, or <code>null</code> if the
352 * specified index is not valid.
354 public String getHeaderFieldKey(int n)
356 if (!connected)
359 connect();
361 catch (IOException x)
363 return null;
366 if (n < hdrVec.size())
367 return getKey ((String) hdrVec.elementAt(n));
368 return null;
371 private String getKey(String str)
373 if (str == null)
374 return null;
375 int index = str.indexOf(':');
376 if (index >= 0)
377 return str.substring(0, index);
378 else
379 return null;
382 private String getField(String str)
384 if (str == null)
385 return null;
386 int index = str.indexOf(':');
387 if (index >= 0)
388 return str.substring(index + 1).trim();
389 else
390 return str;
394 * Read HTTP reply from inputStream.
396 private void getHttpHeaders() throws IOException
398 int buflen = 100;
399 byte[] buf = new byte[buflen];
400 String line = "";
401 boolean gotnl = false;
402 byte[] ch = new byte[1];
403 ch[0] = (byte) '\n';
405 while (true)
407 // Check for leftover byte from non-'\n' after a '\r'.
408 if (ch[0] != '\n')
409 line = line + '\r' + new String(ch, 0, 1);
411 int i;
412 // FIXME: This is rather inefficient.
413 for (i = 0; i < buflen; i++)
415 buf[i] = (byte) inputStream.read();
416 if (buf[i] == -1)
417 throw new IOException("Malformed HTTP header");
418 if (buf[i] == '\r')
420 inputStream.read(ch, 0, 1);
421 if (ch[0] == '\n')
422 gotnl = true;
423 break;
426 line = line + new String(buf, 0, i);
428 // A '\r' '\n' combo indicates the end of the header entry.
429 // If it wasn't found, cycle back through the loop and append
430 // to 'line' until one is found.
431 if (gotnl)
433 // A zero length entry signals the end of the headers.
434 if (line.length() == 0)
435 break;
437 // Store the header and reinitialize for next cycle.
438 hdrVec.addElement(line);
439 String key = getKey(line);
440 if (key != null)
441 hdrHash.put(key.toLowerCase(), getField(line));
442 line = "";
443 ch[0] = (byte) '\n';
444 gotnl = false;