diff options
-rw-r--r-- | libjava/ChangeLog | 20 | ||||
-rw-r--r-- | libjava/Makefile.am | 1 | ||||
-rw-r--r-- | libjava/Makefile.in | 4 | ||||
-rw-r--r-- | libjava/gnu/java/net/HeaderFieldHelper.java | 138 | ||||
-rw-r--r-- | libjava/gnu/java/net/protocol/http/Connection.java | 183 |
5 files changed, 257 insertions, 89 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 493c3bb3407..a0d172557ae 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,23 @@ +2003-12-28 Michael Koch <konqueror@gmx.de> + + * gnu/java/net/protocol/http/Connection.java + (inputStream): Made it a DataInputStream. + (requestProperties): Removed. + (hdrHash): Removed. + (hdrVec): Removed. + (headers): New field to store headers. + (connect): Initialize inputStream. + (receiveReply): Merged from classpath. The new algorithm is line based + instead of character based. + (getHeaderField): Use headers. + (getHeaderFields): Use headers. + (getKey): Removed. + (getField): Removed. + * gnu/java/net/HeaderFieldHelper.java: New file. + * Makefile.am (ordinary_java_source_files): + Added gnu/java/net/HeaderFieldHelper.java. + * Makefile.in: Regenerated. + 2003-12-28 Guilhem Lavaux <guilhem@kaffe.org> * java/io/LineNumberReader.java diff --git a/libjava/Makefile.am b/libjava/Makefile.am index fd72074b138..70c9cb52a2e 100644 --- a/libjava/Makefile.am +++ b/libjava/Makefile.am @@ -2238,6 +2238,7 @@ gnu/java/locale/LocaleInformation_zh_HK.java \ gnu/java/locale/LocaleInformation_zh_SG.java \ gnu/java/locale/LocaleInformation_zh_TW.java \ gnu/java/math/MPN.java \ +gnu/java/net/HeaderFieldHelper.java \ gnu/java/net/PlainDatagramSocketImpl.java \ gnu/java/net/PlainSocketImpl.java \ gnu/java/net/URLParseError.java \ diff --git a/libjava/Makefile.in b/libjava/Makefile.in index 4456250cbb2..9702b28a3ec 100644 --- a/libjava/Makefile.in +++ b/libjava/Makefile.in @@ -1945,6 +1945,7 @@ gnu/java/locale/LocaleInformation_zh_HK.java \ gnu/java/locale/LocaleInformation_zh_SG.java \ gnu/java/locale/LocaleInformation_zh_TW.java \ gnu/java/math/MPN.java \ +gnu/java/net/HeaderFieldHelper.java \ gnu/java/net/PlainDatagramSocketImpl.java \ gnu/java/net/PlainSocketImpl.java \ gnu/java/net/URLParseError.java \ @@ -3085,7 +3086,8 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \ .deps/gnu/java/locale/LocaleInformation_zh_HK.P \ .deps/gnu/java/locale/LocaleInformation_zh_SG.P \ .deps/gnu/java/locale/LocaleInformation_zh_TW.P \ -.deps/gnu/java/math/MPN.P .deps/gnu/java/net/PlainDatagramSocketImpl.P \ +.deps/gnu/java/math/MPN.P .deps/gnu/java/net/HeaderFieldHelper.P \ +.deps/gnu/java/net/PlainDatagramSocketImpl.P \ .deps/gnu/java/net/PlainSocketImpl.P .deps/gnu/java/net/URLParseError.P \ .deps/gnu/java/net/natPlainDatagramSocketImpl.P \ .deps/gnu/java/net/natPlainSocketImpl.P \ diff --git a/libjava/gnu/java/net/HeaderFieldHelper.java b/libjava/gnu/java/net/HeaderFieldHelper.java new file mode 100644 index 00000000000..2bcfd17fd7d --- /dev/null +++ b/libjava/gnu/java/net/HeaderFieldHelper.java @@ -0,0 +1,138 @@ +/* HeaderFieldHelper.java -- Helps manage headers fields + Copyright (C) 1998, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.java.net; + +import java.util.HashMap; +import java.util.Map; +import java.util.Vector; + +/** + * This class manages header field keys and values. + * + * @author Aaron M. Renn <arenn@urbanophile.com> + */ +public class HeaderFieldHelper +{ + private Vector headerFieldKeys; + private Vector headerFieldValues; + + public HeaderFieldHelper() + { + this (10); + } + + public HeaderFieldHelper (int size) + { + headerFieldKeys = new Vector (size); + headerFieldValues = new Vector (size); + } + + public void addHeaderField (String key, String value) + { + headerFieldKeys.addElement (key); + headerFieldValues.addElement (value); + } + + public String getHeaderFieldKeyByIndex (int index) + { + String key = null; + + try + { + key = (String) headerFieldKeys.elementAt (index); + } + catch (ArrayIndexOutOfBoundsException e) + { + } + + return key; + } + + public String getHeaderFieldValueByIndex(int index) + { + String value = null; + + try + { + value = (String) headerFieldValues.elementAt (index); + } + catch (ArrayIndexOutOfBoundsException e) + { + } + + return value; + } + + public String getHeaderFieldValueByKey(String key) + { + String value = null; + + try + { + value = (String) headerFieldValues.elementAt + (headerFieldKeys.indexOf(key)); + } + catch (ArrayIndexOutOfBoundsException e) + { + } + + return value; + } + + public Map getHeaderFields() + { + HashMap headers = new HashMap(); + int max = headerFieldKeys.size(); + + for (int index = 0; index < max; index++) + { + headers.put(headerFieldKeys.elementAt(index), + headerFieldValues.elementAt(index)); + } + + return headers; + } + + public int getNumberOfEntries() + { + return headerFieldKeys.size(); + } + +} // class HeaderFieldHelper + diff --git a/libjava/gnu/java/net/protocol/http/Connection.java b/libjava/gnu/java/net/protocol/http/Connection.java index 677ba7f1e65..5cced5cf0a2 100644 --- a/libjava/gnu/java/net/protocol/http/Connection.java +++ b/libjava/gnu/java/net/protocol/http/Connection.java @@ -39,6 +39,7 @@ exception statement from your version. */ package gnu.java.net.protocol.http; import java.io.BufferedInputStream; +import java.io.DataInputStream; import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; @@ -50,8 +51,7 @@ import java.net.URL; import java.net.URLConnection; import java.util.Iterator; import java.util.Map; -import java.util.Vector; -import java.util.Hashtable; +import gnu.java.net.HeaderFieldHelper; /** * This subclass of java.net.URLConnection models a URLConnection via @@ -102,14 +102,12 @@ public final class Connection extends HttpURLConnection /** * The InputStream for this connection. */ - private BufferedInputStream inputStream; + private DataInputStream inputStream; /** * This is the object that holds the header field information */ - private Hashtable requestProperties = new Hashtable(); - private Hashtable hdrHash = new Hashtable(); - private Vector hdrVec = new Vector(); + private HeaderFieldHelper headers = new HeaderFieldHelper(); /** * Calls superclass constructor to initialize @@ -147,13 +145,8 @@ public final class Connection extends HttpURLConnection socket = new Socket(url.getHost(), port); } - // Originally tried using a BufferedReader here to take advantage of - // the readLine method and avoid the following, but the buffer read - // past the end of the headers so the first part of the content was lost. - // It is probably more robust than it needs to be, e.g. the byte[] - // is unlikely to overflow and a '\r' should always be followed by a '\n', - // but it is better to be safe just in case. - inputStream = new BufferedInputStream(socket.getInputStream()); + inputStream = + new DataInputStream(new BufferedInputStream(socket.getInputStream())); sendRequest(); receiveReply(); @@ -215,54 +208,94 @@ public final class Connection extends HttpURLConnection */ private void receiveReply() throws IOException { - int buflen = 100; - byte[] buf = new byte[buflen]; - String line = ""; - boolean gotnl = false; - byte[] ch = new byte[1]; - ch[0] = (byte) '\n'; + // Parse the reply + String line = inputStream.readLine(); + String saveline = line; + int idx = line.indexOf (" "); - while (true) - { - // Check for leftover byte from non-'\n' after a '\r'. - if (ch[0] != '\n') - line = line + '\r' + new String(ch, 0, 1); + if ((idx == -1) + || (line.length() < (idx + 6))) + throw new IOException ("Server reply was unparseable: " + saveline); - int i; - // FIXME: This is rather inefficient. - for (i = 0; i < buflen; i++) - { - buf[i] = (byte) inputStream.read(); - if (buf[i] == -1) - throw new IOException("Malformed HTTP header"); - if (buf[i] == '\r') - { - inputStream.read(ch, 0, 1); - if (ch[0] == '\n') - gotnl = true; - break; - } - } - line = line + new String(buf, 0, i); + headers.addHeaderField (null, line); - // A '\r' '\n' combo indicates the end of the header entry. - // If it wasn't found, cycle back through the loop and append - // to 'line' until one is found. - if (gotnl) - { - // A zero length entry signals the end of the headers. - if (line.length() == 0) - break; - - // Store the header and reinitialize for next cycle. - hdrVec.addElement(line); - String key = getKey(line); - if (key != null) - hdrHash.put(key.toLowerCase(), getField(line)); - line = ""; - ch[0] = (byte) '\n'; - gotnl = false; - } + line = line.substring (idx + 1); + String code = line.substring (0, 3); + + try + { + responseCode = Integer.parseInt (code); + } + catch (NumberFormatException e) + { + throw new IOException ("Server reply was unparseable: " + saveline); + } + + responseMessage = line.substring (4); + + // Now read the header lines + String key = null, value = null; + + while (true) + { + line = inputStream.readLine(); + + if (line.equals("")) + break; + + // Check for folded lines + if (line.startsWith (" ") + || line.startsWith("\t")) + { + // Trim off leading space + do + { + if (line.length() == 1) + throw new IOException("Server header lines were unparseable: " + + line); + + line = line.substring (1); + } + while (line.startsWith(" ") + || line.startsWith("\t")); + + value = value + " " + line; + } + else + { + if (key != null) + { + headers.addHeaderField (key.toLowerCase(), value); + key = null; + value = null; + } + + // Parse out key and value + idx = line.indexOf (":"); + if ((idx == -1) + || (line.length() < (idx + 2))) + throw new IOException ("Server header lines were unparseable: " + + line); + + key = line.substring (0, idx); + value = line.substring (idx + 1); + + // Trim off leading space + while (value.startsWith (" ") + || value.startsWith ("\t")) + { + if (value.length() == 1) + throw new IOException ("Server header lines were unparseable: " + + line); + + value = value.substring (1); + } + } + } + + if (key != null) + { + headers.addHeaderField (key.toLowerCase(), value.toLowerCase()); } } @@ -347,7 +380,7 @@ public final class Connection extends HttpURLConnection return null; } - return (String) hdrHash.get(name.toLowerCase()); + return (String) headers.getHeaderFieldValueByKey(name.toLowerCase()); } public Map getHeaderFields() @@ -362,7 +395,7 @@ public final class Connection extends HttpURLConnection return null; } - return hdrHash; + return headers.getHeaderFields(); } /** @@ -386,9 +419,7 @@ public final class Connection extends HttpURLConnection return null; } - if (n < hdrVec.size()) - return getField ((String) hdrVec.elementAt(n)); - return null; + return headers.getHeaderFieldValueByIndex (n); } /** @@ -412,30 +443,6 @@ public final class Connection extends HttpURLConnection return null; } - if (n < hdrVec.size()) - return getKey ((String) hdrVec.elementAt(n)); - return null; - } - - private String getKey(String str) - { - if (str == null) - return null; - int index = str.indexOf(':'); - if (index >= 0) - return str.substring(0, index); - else - return null; - } - - private String getField(String str) - { - if (str == null) - return null; - int index = str.indexOf(':'); - if (index >= 0) - return str.substring(index + 1).trim(); - else - return str; + return headers.getHeaderFieldKeyByIndex (n); } } |