FSF GCC merge 02/23/03
[official-gcc.git] / libjava / gnu / gcj / protocol / http / Connection.java
blob1a6fc0105f91da83c2dc76b0886fb5c3c90896d2
1 // Connection.java - Implementation of HttpURLConnection for http protocol.
3 /* Copyright (C) 1999, 2000, 2003 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
11 package gnu.gcj.protocol.http;
13 import java.net.*;
14 import java.io.*;
15 import java.util.Map;
16 import java.util.Vector;
17 import java.util.Hashtable;
18 import java.util.Enumeration;
20 /**
21 * @author Warren Levy <warrenl@cygnus.com>
22 * @date March 29, 1999.
25 /**
26 * Written using on-line Java Platform 1.2 API Specification, as well
27 * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
28 * Status: Minimal subset of functionality. Proxies only partially
29 * handled; Redirects not yet handled. FileNameMap handling needs to
30 * be considered. useCaches, ifModifiedSince, and
31 * allowUserInteraction need consideration as well as doInput and
32 * doOutput.
35 class Connection extends HttpURLConnection
37 protected Socket sock = null;
38 private static Hashtable defRequestProperties = new Hashtable();
39 private Hashtable requestProperties;
40 private Hashtable hdrHash = new Hashtable();
41 private Vector hdrVec = new Vector();
42 private BufferedInputStream bufferedIn;
44 private static int proxyPort = 80;
45 private static boolean proxyInUse = false;
46 private static String proxyHost = null;
48 static
50 // Recognize some networking properties listed at
51 // http://java.sun.com/j2se/1.4/docs/guide/net/properties.html.
52 String port = null;
53 proxyHost = System.getProperty("http.proxyHost");
54 if (proxyHost != null)
56 proxyInUse = true;
57 if ((port = System.getProperty("http.proxyPort")) != null)
59 try
61 proxyPort = Integer.parseInt(port);
63 catch (Throwable t)
65 // Nothing.
71 public Connection(URL url)
73 super(url);
74 requestProperties = (Hashtable) defRequestProperties.clone();
77 // Override method in URLConnection.
78 public static void setDefaultRequestProperty(String key, String value)
80 defRequestProperties.put(key, value);
83 // Override method in URLConnection.
84 public static String getDefaultRequestProperty(String key)
86 return (String) defRequestProperties.get(key);
89 // Override method in URLConnection.
90 public void setRequestProperty(String key, String value)
92 if (connected)
93 throw new IllegalAccessError("Connection already established.");
95 requestProperties.put(key, value);
98 // Override method in URLConnection.
99 public String getRequestProperty(String key)
101 if (connected)
102 throw new IllegalAccessError("Connection already established.");
104 return (String) requestProperties.get(key);
107 // Implementation of abstract method.
108 public void connect() throws IOException
110 // Call is ignored if already connected.
111 if (connected)
112 return;
114 // Get address and port number.
115 int port;
116 if (proxyInUse)
118 port = proxyPort;
119 sock = new Socket(proxyHost, port);
121 else
123 InetAddress destAddr = InetAddress.getByName(url.getHost());
124 if ((port = url.getPort()) == -1)
125 port = 80;
126 // Open socket and output stream.
127 sock = new Socket(destAddr, port);
130 PrintWriter out = new PrintWriter(sock.getOutputStream());
132 // Send request including any request properties that were set.
133 out.print(getRequestMethod() + " " + url.getFile() + " HTTP/1.0\n");
134 out.print("Host: " + url.getHost() + ":" + port + "\n");
135 Enumeration reqKeys = requestProperties.keys();
136 Enumeration reqVals = requestProperties.elements();
137 while (reqKeys.hasMoreElements())
138 out.print(reqKeys.nextElement() + ": " + reqVals.nextElement() + "\n");
139 out.print("\n");
140 out.flush();
141 getHttpHeaders();
142 connected = true;
145 // Implementation of abstract method.
146 public void disconnect()
148 if (sock != null)
152 sock.close();
154 catch (IOException ex)
156 ; // Ignore errors in closing socket.
158 sock = null;
162 public boolean usingProxy()
164 return proxyInUse;
167 // Override default method in URLConnection.
168 public InputStream getInputStream() throws IOException
170 if (!connected)
171 connect();
173 if (!doInput)
174 throw new ProtocolException("Can't open InputStream if doInput is false");
175 return bufferedIn;
178 // Override default method in URLConnection.
179 public OutputStream getOutputStream() throws IOException
181 if (!connected)
182 connect();
184 if (! doOutput)
185 throw new
186 ProtocolException("Can't open OutputStream if doOutput is false");
187 return sock.getOutputStream();
190 // Override default method in URLConnection.
191 public String getHeaderField(String name)
193 if (!connected)
196 connect();
198 catch (IOException x)
200 return null;
203 return (String) hdrHash.get(name.toLowerCase());
206 // Override default method in URLConnection.
207 public Map getHeaderFields()
209 if (!connected)
212 connect();
214 catch (IOException x)
216 return null;
219 return hdrHash;
222 // Override default method in URLConnection.
223 public String getHeaderField(int n)
225 if (!connected)
228 connect();
230 catch (IOException x)
232 return null;
235 if (n < hdrVec.size())
236 return getField((String) hdrVec.elementAt(n));
237 return null;
240 // Override default method in URLConnection.
241 public String getHeaderFieldKey(int n)
243 if (!connected)
246 connect();
248 catch (IOException x)
250 return null;
253 if (n < hdrVec.size())
254 return getKey((String) hdrVec.elementAt(n));
255 return null;
258 private String getKey(String str)
260 if (str == null)
261 return null;
262 int index = str.indexOf(':');
263 if (index >= 0)
264 return str.substring(0, index);
265 else
266 return null;
269 private String getField(String str)
271 if (str == null)
272 return null;
273 int index = str.indexOf(':');
274 if (index >= 0)
275 return str.substring(index + 1).trim();
276 else
277 return str;
280 private void getHttpHeaders() throws IOException
282 // Originally tried using a BufferedReader here to take advantage of
283 // the readLine method and avoid the following, but the buffer read
284 // past the end of the headers so the first part of the content was lost.
285 // It is probably more robust than it needs to be, e.g. the byte[]
286 // is unlikely to overflow and a '\r' should always be followed by a '\n',
287 // but it is better to be safe just in case.
288 bufferedIn = new BufferedInputStream(sock.getInputStream());
290 int buflen = 100;
291 byte[] buf = new byte[buflen];
292 String line = "";
293 boolean gotnl = false;
294 byte[] ch = new byte[1];
295 ch[0] = (byte) '\n';
297 while (true)
299 // Check for leftover byte from non-'\n' after a '\r'.
300 if (ch[0] != '\n')
301 line = line + '\r' + new String(ch, 0, 1);
303 int i;
304 // FIXME: This is rather inefficient.
305 for (i = 0; i < buflen; i++)
307 buf[i] = (byte) bufferedIn.read();
308 if (buf[i] == -1)
309 throw new IOException("Malformed HTTP header");
310 if (buf[i] == '\r')
312 bufferedIn.read(ch, 0, 1);
313 if (ch[0] == '\n')
314 gotnl = true;
315 break;
318 line = line + new String(buf, 0, i);
320 // A '\r' '\n' combo indicates the end of the header entry.
321 // If it wasn't found, cycle back through the loop and append
322 // to 'line' until one is found.
323 if (gotnl)
325 // A zero length entry signals the end of the headers.
326 if (line.length() == 0)
327 break;
329 // Store the header and reinitialize for next cycle.
330 hdrVec.addElement(line);
331 String key = getKey(line);
332 if (key != null)
333 hdrHash.put(key.toLowerCase(), getField(line));
334 line = "";
335 ch[0] = (byte) '\n';
336 gotnl = false;