Index: java/org/apache/commons/httpclient/Authenticator.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/Authenticator.java,v retrieving revision 1.39 diff -u -r1.39 Authenticator.java --- java/org/apache/commons/httpclient/Authenticator.java 28 Jan 2003 04:40:20 -0000 1.39 +++ java/org/apache/commons/httpclient/Authenticator.java 4 Feb 2003 03:13:06 -0000 @@ -246,7 +246,7 @@ LOG.trace("enter Authenticator.authenticate(HttpMethod, HttpState)"); - Header challengeHeader = method.getResponseHeader(WWW_AUTH); + Header challengeHeader = method.getResponseHeaderGroup().getCondensedHeader(WWW_AUTH); return authenticate(method, state, challengeHeader, WWW_AUTH_RESP); } @@ -270,7 +270,7 @@ LOG.trace("enter Authenticator.authenticateProxy(HttpMethod, " + "HttpState)"); - Header challengeHeader = method.getResponseHeader(PROXY_AUTH); + Header challengeHeader = method.getResponseHeaderGroup().getCondensedHeader(PROXY_AUTH); return authenticate(method, state, challengeHeader, PROXY_AUTH_RESP); } @@ -356,8 +356,8 @@ NTCredentials credentials = null; - if (method.getRequestHeader("Host") != null) { - String host = method.getRequestHeader("Host").getValue(); + if (method.getRequestHeaderGroup().containsHeader("Host")) { + String host = method.getRequestHeaderGroup().getFirstHeader("Host").getValue(); try { credentials = (NTCredentials) (proxy ? state.getProxyCredentials(host) @@ -518,7 +518,7 @@ //Get the authorization header value try { - authHeader = method.getResponseHeader(authName).getValue(); + authHeader = method.getResponseHeaderGroup().getCondensedHeader(authName).getValue(); authHeader = authHeader.substring(7).trim(); } catch (NullPointerException npe) { return (Map) (new java.util.Hashtable(0)); Index: java/org/apache/commons/httpclient/ChunkedInputStream.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/ChunkedInputStream.java,v retrieving revision 1.12 diff -u -r1.12 ChunkedInputStream.java --- java/org/apache/commons/httpclient/ChunkedInputStream.java 28 Jan 2003 04:40:20 -0000 1.12 +++ java/org/apache/commons/httpclient/ChunkedInputStream.java 4 Feb 2003 03:12:59 -0000 @@ -84,6 +84,7 @@ * @author Martin Elwin * @author Eric Johnson * @author Mike Bowler + * @author Michael Becke * * @since 2.0 * @@ -306,46 +307,12 @@ } /** - * Stores the footers into map of Headers + * Stores the footers to the method. * @throws IOException If an IO problem occurs */ private void parseFooters() throws IOException { - String line = readLine(); - while ((line != null) && (!line.equals(""))) { - int colonPos = line.indexOf(':'); - if (colonPos != -1) { - String key = line.substring(0, colonPos).trim(); - String val = line.substring(colonPos + 1).trim(); - Header footer = new Header(key, val); - method.addResponseFooter(footer); - } - line = readLine(); - } - } - - /** - * Read the next line from {@link #in}. - * @return String The next line. - * @throws IOException If an IO problem occurs. - */ - private String readLine() throws IOException { - StringBuffer buf = new StringBuffer(); - while (true) { - int ch = in.read(); - if (ch < 0) { - if (buf.length() == 0) { - return null; - } else { - break; - } - } else if (ch == '\r') { - continue; - } else if (ch == '\n') { - break; - } - buf.append((char) ch); - } - return (buf.toString()); + method.getResponseFooterGroup().clear(); + HeaderParser.parseHeaders(in, method.getResponseFooterGroup()); } /** Index: java/org/apache/commons/httpclient/ConnectMethod.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/ConnectMethod.java,v retrieving revision 1.7 diff -u -r1.7 ConnectMethod.java --- java/org/apache/commons/httpclient/ConnectMethod.java 28 Jan 2003 04:40:20 -0000 1.7 +++ java/org/apache/commons/httpclient/ConnectMethod.java 4 Feb 2003 03:13:00 -0000 @@ -138,8 +138,10 @@ if (method instanceof HttpMethodBase) { ((HttpMethodBase) method).addRequestHeaders(state, conn); } - conn.print(method.getRequestHeader("Host").toExternalForm()); - Header header = method.getRequestHeader(Authenticator.PROXY_AUTH_RESP); + conn.print(method.getRequestHeaderGroup().getFirstHeader("Host").toExternalForm()); + Header header = method.getRequestHeaderGroup().getFirstHeader( + Authenticator.PROXY_AUTH_RESP + ); if (header == null) { header = getRequestHeader(Authenticator.PROXY_AUTH_RESP); } Index: java/org/apache/commons/httpclient/HeaderGroup.java =================================================================== RCS file: java/org/apache/commons/httpclient/HeaderGroup.java diff -N java/org/apache/commons/httpclient/HeaderGroup.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ java/org/apache/commons/httpclient/HeaderGroup.java 4 Feb 2003 03:13:06 -0000 @@ -0,0 +1,187 @@ +package org.apache.commons.httpclient; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * A class for combining a set of headers. This class allows for multiple + * headers with the same name and keeps track of the order in which headers were + * added. + * + * @author Michael Becke + */ +public class HeaderGroup { + + private List headers; + + /** + * Constructor for HeaderGroup. + */ + public HeaderGroup() { + this.headers = new ArrayList(); + } + + /** + * Removes any contained headers. + */ + public void clear() { + headers.clear(); + } + + /** + * Adds the given header to the group. The order in which this header was + * added is preserved. + * + * @param header the header to add + */ + public void addHeader(Header header) { + headers.add(header); + } + + /** + * Removes the given header. + * + * @param header the header to remove + */ + public void removeHeader(Header header) { + headers.remove(header); + } + + /** + * Sets all of the headers contained within this group overriding any + * existing headers. The headers are added in the order in which they appear + * in the array. + * + * @param headers the headers to set + */ + public void setHeaders(Header[] headers) { + clear(); + + for (int i = 0; i < headers.length; i++) { + addHeader(headers[i]); + } + } + + /** + * Gets a header representing all of the header values with the given name. + * If more that one header with the given name exists the values will be + * combined with a "," as per RFC 1945. + * + *
Header name comparison is case insensitive.
+ *
+ * @param name the name of the header(s) to get
+ * @return a header with a condensed value or null if no
+ * headers by the given name are present
+ */
+ public Header getCondensedHeader(String name) {
+ Header[] headers = getHeaders(name);
+
+ if (headers.length == 0) {
+ return null;
+ } else if (headers.length == 1) {
+ return headers[0];
+ } else {
+ StringBuffer valueBuffer = new StringBuffer(headers[0].getValue());
+
+ for (int i = 1; i < headers.length; i++) {
+ valueBuffer.append(", ");
+ valueBuffer.append(headers[i].getValue());
+ }
+
+ return new Header(name.toLowerCase(), valueBuffer.toString());
+ }
+ }
+
+ /**
+ * Gets all of the headers with the given name. The returned array
+ * maintains the relative order in which the headers were added.
+ *
+ *
Header name comparison is case insensitive. + * + * @param name the name of the header(s) to get + * + * @return an array of length >= 0 + */ + public Header[] getHeaders(String name) { + ArrayList headersFound = new ArrayList(); + + for (Iterator headerIter = headers.iterator(); headerIter.hasNext();) { + Header header = (Header) headerIter.next(); + if (header.getName().equalsIgnoreCase(name)) { + headersFound.add(header); + } + } + + return (Header[]) headersFound.toArray(new Header[headersFound.size()]); + } + + /** + * Gets the first header with the given name. + * + *
Header name comparison is case insensitive.
+ *
+ * @param name the name of the header to get
+ * @return the first header or null
+ */
+ public Header getFirstHeader(String name) {
+ for (Iterator headerIter = headers.iterator(); headerIter.hasNext();) {
+ Header header = (Header) headerIter.next();
+ if (header.getName().equalsIgnoreCase(name)) {
+ return header;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Gets the last header with the given name.
+ *
+ *
Header name comparison is case insensitive.
+ *
+ * @param name the name of the header to get
+ * @return the last header or null
+ */
+ public Header getLastHeader(String name) {
+ // start at the end of the list and work backwards
+ for (int i = headers.size() - 1; i >= 0; i--) {
+ Header header = (Header) headers.get(i);
+ if (header.getName().equalsIgnoreCase(name)) {
+ return header;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Gets all of the headers contained within this group.
+ *
+ * @return an array of length >= 0
+ */
+ public Header[] getAllHeaders() {
+ return (Header[]) headers.toArray(new Header[headers.size()]);
+ }
+
+ /**
+ * Tests if headers with the given name are contained within this group.
+ *
+ *
Header name comparison is case insensitive.
+ *
+ * @param name the header name to test for
+ * @return true if at least one header with the name is
+ * contained, false otherwise
+ */
+ public boolean containsHeader(String name) {
+ for (Iterator headerIter = headers.iterator(); headerIter.hasNext();) {
+ Header header = (Header) headerIter.next();
+ if (header.getName().equalsIgnoreCase(name)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+}
Index: java/org/apache/commons/httpclient/HeaderParser.java
===================================================================
RCS file: java/org/apache/commons/httpclient/HeaderParser.java
diff -N java/org/apache/commons/httpclient/HeaderParser.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ java/org/apache/commons/httpclient/HeaderParser.java 4 Feb 2003 03:12:59 -0000
@@ -0,0 +1,115 @@
+package org.apache.commons.httpclient;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * A utility class for parsing http header values.
+ *
+ * @author Michael Becke
+ */
+public class HeaderParser {
+
+ /** Log object for this class. */
+ private static final Log LOG = LogFactory.getLog(HeaderParser.class);
+ /** Log for any wire messages. */
+ private static final Log WIRE_LOG = LogFactory.getLog("httpclient.wire");
+
+ /**
+ * Constructor for HeaderParser.
+ */
+ private HeaderParser() {}
+
+ /**
+ * Parses headers from the given stream and adds them to the headerGroup.
+ *
+ * @param is the stream to read headers from
+ * @param headerGroup the group to add the headers to
+ * @throws IOException if an IO error occurs while reading from the stream
+ * @throws HttpException if there is an error parsing a header value
+ */
+ public static void parseHeaders(
+ InputStream is,
+ HeaderGroup headerGroup
+ ) throws IOException, HttpException {
+ LOG.trace("enter HeaderParser.parseHeaders(HttpConnection, HeaderGroup)");
+
+ String name = null;
+ StringBuffer value = null;
+ for (; ;) {
+ String line = readLine(is);
+ if ((line == null) || (line.length() < 1)) {
+ break;
+ }
+
+ // Parse the header name and value
+ // Check for folded headers first
+ // Detect LWS-char see HTTP/1.0 or HTTP/1.1 Section 2.2
+ // discussion on folded headers
+ if ((line.charAt(0) == ' ') || (line.charAt(0) == '\t')) {
+ // we have continuation folded header
+ // so append value
+ value.append(' ');
+ value.append(line.trim());
+ } else {
+ // make sure we save the previous name,value pair if present
+ if (name != null) {
+ headerGroup.addHeader(new Header(name, value.toString()));
+ }
+
+ // Otherwise we should have normal HTTP header line
+ // Parse the header name and value
+ int colon = line.indexOf(":");
+ if (colon < 0) {
+ throw new HttpException("Unable to parse header: " + line);
+ }
+ name = line.substring(0, colon).trim();
+ value = new StringBuffer(line.substring(colon + 1).trim());
+ }
+
+ }
+
+ // make sure we save the last name,value pair if present
+ if (name != null) {
+ headerGroup.addHeader(new Header(name, value.toString()));
+ }
+ }
+
+ /**
+ * Reads a single line from a stream.
+ *
+ * @param is the stream to read from
+ *
+ * @return the line read or null if the line was empty
+ *
+ * @throws IOException if an error occurs while reading from the stream
+ */
+ public static String readLine(InputStream is) throws IOException {
+ LOG.trace("enter HeaderParser.readLine()");
+
+ StringBuffer buf = new StringBuffer();
+ while (true) {
+ int ch = is.read();
+ if (ch < 0) {
+ if (buf.length() == 0) {
+ return null;
+ } else {
+ break;
+ }
+ } else if (ch == '\r') {
+ continue;
+ } else if (ch == '\n') {
+ break;
+ }
+ buf.append((char) ch);
+ }
+ if (WIRE_LOG.isDebugEnabled() && buf.length() > 0) {
+ WIRE_LOG.debug("<< \"" + buf.toString() + "\" [\\r\\n]");
+ }
+ return (buf.toString());
+ }
+
+}
Index: java/org/apache/commons/httpclient/HttpMethod.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethod.java,v
retrieving revision 1.23
diff -u -r1.23 HttpMethod.java
--- java/org/apache/commons/httpclient/HttpMethod.java 28 Jan 2003 04:40:20 -0000 1.23
+++ java/org/apache/commons/httpclient/HttpMethod.java 4 Feb 2003 03:13:04 -0000
@@ -75,6 +75,7 @@
* @author Rod Waldhoff
* @author Jeff Dever
* @author Mike Bowler
+ * @author Michael Becke
*
* @version $Revision: 1.23 $ $Date: 2003/01/28 04:40:20 $
* @since 1.0
@@ -146,53 +147,77 @@
* @return true if strict mode is enabled.
*/
boolean isStrictMode();
-
+
/**
+ * @deprecated use request HeaderGroup
+ *
* Set the specified request header, overwriting any
* previous value.
* Note that header-name matching is case insensitive.
* @param headerName the header's name
* @param headerValue the header's value
+ *
+ * @see #getRequestHeaderGroup()
+ * @see HeaderGroup#addHeader(Header)
*/
void setRequestHeader(String headerName, String headerValue);
/**
+ * @deprecated use request HeaderGroup
+ *
* Set the specified request header, overwriting any
* previous value.
* Note that header-name matching is case insensitive.
* @param header the header
+ *
+ * @see #getRequestHeaderGroup()
+ * @see HeaderGroup#addHeader(Header)
*/
void setRequestHeader(Header header);
/**
- * Adds the specified request header, NOT overwriting any
- * previous value.
+ * Adds the specified request header, NOT overwriting any previous value.
* Note that header-name matching is case insensitive.
* @param headerName the header's name
* @param headerValue the header's value
+ *
+ * @see #getRequestHeaderGroup()
+ * @see HeaderGroup#addHeader(Header)
*/
void addRequestHeader(String headerName, String headerValue);
/**
- * Adds the specified request header, NOT overwriting any
- * previous value.
+ * Adds the specified request header, NOT overwriting any previous value.
* Note that header-name matching is case insensitive.
* @param header the header
+ *
+ * @see #getRequestHeaderGroup()
+ * @see HeaderGroup#addHeader(Header)
*/
void addRequestHeader(Header header);
/**
+ * @deprecated use request HeaderGroup
+ *
* Get the request header associated with the given name.
* Note that header-name matching is case insensitive.
* @param headerName the header name
* @return the header
+ *
+ * @see #getRequestHeaderGroup()
+ * @see HeaderGroup#getHeaders(String)
*/
Header getRequestHeader(String headerName);
/**
+ * @deprecated use request HeaderGroup
+ *
* Remove all request headers associated with the given name.
* Note that header-name matching is case insensitive.
* @param headerName the header name
+ *
+ * @see #getRequestHeaderGroup()
+ * @see HeaderGroup#removeHeader(Header)
*/
void removeRequestHeader(String headerName);
@@ -232,9 +257,20 @@
/**
* Return an array of my request headers.
* @return an array of request headers.
+ *
+ * @see #getRequestHeaderGroup()
+ * @see HeaderGroup#getAllHeaders()
*/
Header[] getRequestHeaders();
+ /**
+ * Gets the HeaderGroup representing the request headers.
+ * @return the request headers
+ *
+ * @since 2.0
+ */
+ HeaderGroup getRequestHeaderGroup();
+
// ---------------------------------------------------------------- Queries
/**
@@ -259,28 +295,60 @@
/**
* Return an array of my response headers.
* @return An array of all the response headers.
+ *
+ * @see #getRequestHeaderGroup()
+ * @see HeaderGroup#getAllHeaders()
*/
Header[] getResponseHeaders();
/**
+ * Gets the HeaderGroup representing the response headers.
+ * @return the response headers
+ *
+ * @since 2.0
+ */
+ HeaderGroup getResponseHeaderGroup();
+
+ /**
+ * @deprecated use response HeaderGroup
+ *
* Return the specified response header. Note that header-name matching is
* case insensitive.
* @param headerName The name of the header to be returned.
* @return The specified response header.
+ *
+ * @see #getRequestHeaderGroup()
+ * @see HeaderGroup#getHeaders(String)
*/
Header getResponseHeader(String headerName);
/**
* Return an array of my response footers
* @return null if no footers are available
+ *
+ * @see #getResponseFooterGroup()
+ * @see HeaderGroup#getAllHeaders()
*/
Header[] getResponseFooters();
/**
+ * Gets the HeaderGroup representing the response footers.
+ * @return the response footers
+ *
+ * @since 2.0
+ */
+ HeaderGroup getResponseFooterGroup();
+
+ /**
+ * @deprecated use response footer HeaderGroup
+ *
* Return the specified response footer. Note that footer-name matching is
* case insensitive.
* @param footerName The name of the footer.
* @return The response footer.
+ *
+ * @see #getResponseFooterGroup()
+ * @see HeaderGroup#getHeaders(String)
*/
Header getResponseFooter(String footerName);
Index: java/org/apache/commons/httpclient/HttpMethodBase.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v
retrieving revision 1.108
diff -u -r1.108 HttpMethodBase.java
--- java/org/apache/commons/httpclient/HttpMethodBase.java 2 Feb 2003 04:30:13 -0000 1.108
+++ java/org/apache/commons/httpclient/HttpMethodBase.java 4 Feb 2003 03:13:12 -0000
@@ -69,10 +69,7 @@
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
@@ -165,16 +162,16 @@
// ----------------------------------------------------- Instance variables
/** My request headers, if any. */
- private Map requestHeaders = new HashMap();
+ private HeaderGroup requestHeaders = new HeaderGroup();
/** The Status-Line from the response. */
private StatusLine statusLine = null;
/** My response headers, if any. */
- private Map responseHeaders = new HashMap();
+ private HeaderGroup responseHeaders = new HeaderGroup();
/** My response footers, if any. */
- private Map responseFooters = null;
+ private HeaderGroup responseFooters = new HeaderGroup();
/** Realms that we tried to authenticate to */
private Set realms = null;
@@ -440,10 +437,7 @@
* @param footer The new footer to add.
*/
public void addResponseFooter(Header footer) {
- if (responseFooters == null) {
- responseFooters = new HashMap();
- }
- responseFooters.put(footer.getName().toLowerCase(), footer);
+ responseFooters.addHeader(footer);
}
/**
@@ -537,7 +531,15 @@
* @param header the header
*/
public void setRequestHeader(Header header) {
- requestHeaders.put(header.getName().toLowerCase(), header);
+
+ Header[] headers = requestHeaders.getHeaders(header.getName());
+
+ for (int i = 0; i < headers.length; i++) {
+ requestHeaders.removeHeader(headers[i]);
+ }
+
+ requestHeaders.addHeader(header);
+
}
/**
@@ -551,8 +553,11 @@
* @return the matching header
*/
public Header getRequestHeader(String headerName) {
- return (headerName == null)
- ? null : (Header) (requestHeaders.get(headerName.toLowerCase()));
+ if (headerName == null) {
+ return null;
+ } else {
+ return requestHeaders.getCondensedHeader(headerName);
+ }
}
/**
@@ -561,11 +566,31 @@
* @return an array of my request headers.
*/
public Header[] getRequestHeaders() {
- return (Header[]) (requestHeaders.values().toArray(
- new Header[requestHeaders.size()]));
+ return requestHeaders.getAllHeaders();
+ }
+
+ /**
+ * @see org.apache.commons.httpclient.HttpMethod#getRequestHeaderGroup()
+ */
+ public HeaderGroup getRequestHeaderGroup() {
+ return requestHeaders;
+ }
+
+ /**
+ * @see org.apache.commons.httpclient.HttpMethod#getResponseFooterGroup()
+ */
+ public HeaderGroup getResponseFooterGroup() {
+ return responseFooters;
}
/**
+ * @see org.apache.commons.httpclient.HttpMethod#getResponseHeaderGroup()
+ */
+ public HeaderGroup getResponseHeaderGroup() {
+ return responseHeaders;
+ }
+
+ /**
* Convenience method top provide access to the status code.
*
* @return the status code associated with the latest response.
@@ -598,8 +623,7 @@
* @return an array of my response headers.
*/
public Header[] getResponseHeaders() {
- return (Header[]) (responseHeaders.values().toArray(
- new Header[responseHeaders.size()]));
+ return responseHeaders.getAllHeaders();
}
/**
@@ -612,10 +636,12 @@
*
* @return the matching header
*/
- public Header getResponseHeader(String headerName) {
- return (headerName == null)
- ? null
- : (Header) (responseHeaders.get(headerName.toLowerCase()));
+ public Header getResponseHeader(String headerName) {
+ if (headerName == null) {
+ return null;
+ } else {
+ return responseHeaders.getCondensedHeader(headerName);
+ }
}
/**
@@ -694,11 +720,7 @@
* @return null if no footers are available
*/
public Header[] getResponseFooters() {
- if (responseFooters == null) {
- return null;
- }
- return (Header[]) (responseFooters.values().toArray(
- new Header[responseFooters.size()]));
+ return responseFooters.getAllHeaders();
}
/**
@@ -711,11 +733,11 @@
* @return the matching footer
*/
public Header getResponseFooter(String footerName) {
- if (responseFooters == null) {
+ if (footerName == null) {
return null;
+ } else {
+ return responseFooters.getCondensedHeader(footerName);
}
- return (footerName == null) ? null
- : (Header) (responseFooters.get(footerName.toLowerCase()));
}
/**
@@ -1139,6 +1161,7 @@
queryString = null;
requestHeaders.clear();
responseHeaders.clear();
+ responseFooters.clear();
statusLine = null;
used = false;
http11 = true;
@@ -1174,7 +1197,12 @@
* @param headerName the header name
*/
public void removeRequestHeader(String headerName) {
- requestHeaders.remove(headerName.toLowerCase());
+
+ Header[] headers = requestHeaders.getHeaders(headerName);
+ for (int i = 0; i < headers.length; i++) {
+ requestHeaders.removeHeader(headers[i]);
+ }
+
}
// ---------------------------------------------------------------- Queries
@@ -1682,6 +1710,7 @@
readResponseBody(state, conn);
processResponseBody(state, conn);
} catch (IOException e) {
+ LOG.warn("error reading response", e);
throw new HttpRecoverableException(e.toString());
}
}
@@ -1836,54 +1865,7 @@
+ "HttpConnection)");
responseHeaders.clear();
-
- String name = null;
- String value = null;
- for (; ;) {
- String line = conn.readLine();
- if ((line == null) || (line.length() < 1)) {
- break;
- }
-
- // Parse the header name and value
- // Check for folded headers first
- // Detect LWS-char see HTTP/1.0 or HTTP/1.1 Section 2.2
- // discussion on folded headers
- boolean isFolded = false;
- if ((line.charAt(0) == ' ') || (line.charAt(0) == '\t')) {
- // we have continuation folded header
- // so append value
- isFolded = true;
- value = line.substring(1).trim();
- } else {
- // Otherwise we should have normal HTTP header line
- // Parse the header name and value
- int colon = line.indexOf(":");
- if (colon < 0) {
- throw new HttpException("Unable to parse header: " + line);
- }
- name = line.substring(0, colon).trim();
- value = line.substring(colon + 1).trim();
- }
- Header header = getResponseHeader(name);
- if (null == header) {
- header = new Header(name, value);
- } else {
- String oldvalue = header.getValue();
- if (null != oldvalue) {
- if (isFolded) {
- // LWS becomes space plus extended value
- header = new Header(name, oldvalue + " " + value);
- } else {
- // Append additional header value
- header = new Header(name, oldvalue + ", " + value);
- }
- } else {
- header = new Header(name, value);
- }
- }
- setResponseHeader(header);
- }
+ HeaderParser.parseHeaders(conn.getResponseInputStream(), responseHeaders);
}
/**
@@ -2049,9 +2031,10 @@
LOG.trace("enter HttpMethodBase.writeRequestHeaders(HttpState,"
+ "HttpConnection)");
addRequestHeaders(state, conn);
- Iterator it = requestHeaders.values().iterator();
- while (it.hasNext()) {
- conn.print(((Header) it.next()).toExternalForm());
+
+ Header[] headers = getRequestHeaders();
+ for (int i = 0; i < headers.length; i++) {
+ conn.print(headers[i].toExternalForm());
}
}
@@ -2162,20 +2145,6 @@
newValue = "";
}
return existingValue + ", " + newValue;
- }
-
- /**
- * Sets the specified response header.
- *
- * @param header the header to set.
- *
- * @since 2.0
- */
- private void setResponseHeader(Header header) {
- if (header == null) {
- return;
- }
- responseHeaders.put(header.getName().toLowerCase(), header);
}
/**
Index: java/org/apache/commons/httpclient/ResponseInputStream.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/ResponseInputStream.java,v
retrieving revision 1.22
diff -u -r1.22 ResponseInputStream.java
--- java/org/apache/commons/httpclient/ResponseInputStream.java 30 Jan 2003 05:01:54 -0000 1.22
+++ java/org/apache/commons/httpclient/ResponseInputStream.java 4 Feb 2003 03:13:01 -0000
@@ -137,14 +137,18 @@
count = 0;
// Retrieving transfer encoding header
- Header transferEncoding = method.getResponseHeader("transfer-encoding");
+ Header transferEncoding = method.getResponseHeaderGroup().getFirstHeader(
+ "transfer-encoding"
+ );
if ((null != transferEncoding) && (transferEncoding.getValue().
toLowerCase().indexOf("chunked") != -1)) {
chunk = true;
}
// Retrieving content length header
- Header contentLengthHeader = method.getResponseHeader("content-length");
+ Header contentLengthHeader = method.getResponseHeaderGroup().getFirstHeader(
+ "content-length"
+ );
if (null != contentLengthHeader) {
try {
this.contentLength =
Index: java/org/apache/commons/httpclient/util/HttpURLConnection.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/util/HttpURLConnection.java,v
retrieving revision 1.11
diff -u -r1.11 HttpURLConnection.java
--- java/org/apache/commons/httpclient/util/HttpURLConnection.java 31 Jan 2003 00:33:37 -0000 1.11
+++ java/org/apache/commons/httpclient/util/HttpURLConnection.java 4 Feb 2003 03:13:15 -0000
@@ -247,14 +247,8 @@
LOG.trace("enter HttpURLConnection.getHeaderField(String)");
// Note: Return the last matching header in the Header[] array, as in
// the JDK implementation.
- Header[] headers = this.method.getResponseHeaders();
- for (int i = headers.length - 1; i >= 0; i--) {
- if (headers[i].getName().equalsIgnoreCase(name)) {
- return headers[i].getValue();
- }
- }
-
- return null;
+ Header header = this.method.getRequestHeaderGroup().getLastHeader(name);
+ return (header == null ? null : header.getValue());
}
/**
@@ -275,10 +269,7 @@
return null;
}
- // Note: HttpClient does not currently keep headers in the same order
- // that they are read from the HTTP server.
-
- Header[] headers = this.method.getResponseHeaders();
+ Header[] headers = this.method.getResponseHeaderGroup().getAllHeaders();
if (keyPosition < 0 || keyPosition > headers.length) {
return null;
}
@@ -307,7 +298,7 @@
// Note: HttpClient does not currently keep headers in the same order
// that they are read from the HTTP server.
- Header[] headers = this.method.getResponseHeaders();
+ Header[] headers = this.method.getResponseHeaderGroup().getAllHeaders();
if (position < 0 || position > headers.length) {
return null;
}
Index: test/org/apache/commons/httpclient/SimpleHttpConnection.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/SimpleHttpConnection.java,v
retrieving revision 1.8
diff -u -r1.8 SimpleHttpConnection.java
--- test/org/apache/commons/httpclient/SimpleHttpConnection.java 31 Jan 2003 23:23:17 -0000 1.8
+++ test/org/apache/commons/httpclient/SimpleHttpConnection.java 4 Feb 2003 03:12:58 -0000
@@ -63,24 +63,24 @@
package org.apache.commons.httpclient;
-import org.apache.commons.httpclient.protocol.Protocol;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.StringReader;
+import java.io.OutputStreamWriter;
import java.util.Vector;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
/**
* For test-nohost testing purposes only.
*
* @author Jeff Dever
+ * @author Michael Becke
*/
class SimpleHttpConnection extends HttpConnection {
@@ -90,8 +90,9 @@
Vector headers = new Vector();
Vector bodies = new Vector();
- BufferedReader headerReader = null;
- ByteArrayInputStream bodyInputStream = null;
+
+ ByteArrayInputStream inputStream;
+
ByteArrayOutputStream bodyOutputStream = null;
public void addResponse(String header) {
@@ -122,26 +123,40 @@
}
public void assertOpen() throws IllegalStateException {
- if (bodyInputStream == null) {
+ if (inputStream == null) {
throw new IllegalStateException();
}
}
public void assertNotOpen() throws IllegalStateException{
- if (bodyInputStream != null) {
+ if (inputStream != null) {
throw new IllegalStateException();
}
}
public void open() throws IOException {
- if (headerReader != null) return;
+ if (inputStream != null) return;
try{
log.debug("hit: " + hits);
- headerReader = new BufferedReader(
- new StringReader((String)headers.elementAt(hits)));
- bodyInputStream = new ByteArrayInputStream(
- HttpConstants.getContentBytes((String)bodies.elementAt(hits)));
+
+ // write the header to a byte array
+ ByteArrayOutputStream headerOutputStream = new ByteArrayOutputStream();
+ OutputStreamWriter writer = new OutputStreamWriter( headerOutputStream );
+ writer.write((String) headers.elementAt(hits));
+ // terminate the headers
+ writer.write("\r\n");
+ writer.close();
+
+ byte[] headerContent = headerOutputStream.toByteArray();
+ byte[] bodyContent = HttpConstants.getContentBytes((String)bodies.elementAt(hits));
+
+ // combine the header and body content so they can be read from one steam
+ byte[] content = new byte[headerContent.length + bodyContent.length];
+ System.arraycopy(headerContent, 0, content, 0, headerContent.length);
+ System.arraycopy(bodyContent, 0, content, headerContent.length, bodyContent.length);
+
+ inputStream = new ByteArrayInputStream( content );
bodyOutputStream = new ByteArrayOutputStream();
hits++;
} catch (ArrayIndexOutOfBoundsException aiofbe) {
@@ -151,13 +166,9 @@
}
public void close() {
- if (headerReader != null) {
- try { headerReader.close(); } catch(IOException e) {}
- headerReader = null;
- }
- if (bodyInputStream != null) {
- try { bodyInputStream.close(); } catch(IOException e) {}
- bodyInputStream = null;
+ if (inputStream != null) {
+ try { inputStream.close(); } catch(IOException e) {}
+ inputStream = null;
}
if (bodyOutputStream != null) {
try { bodyOutputStream.close(); } catch(IOException e) {}
@@ -175,7 +186,7 @@
public String readLine()
throws IOException, IllegalStateException {
- String str = headerReader.readLine();
+ String str = HeaderParser.readLine(inputStream);
log.debug("read: " + str);
return str;
}
@@ -187,7 +198,7 @@
public InputStream getResponseInputStream() {
- return bodyInputStream;
+ return inputStream;
}
public OutputStream getRequestOutputStream() {
Index: test/org/apache/commons/httpclient/SimpleHttpMethod.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/SimpleHttpMethod.java,v
retrieving revision 1.4
diff -u -r1.4 SimpleHttpMethod.java
--- test/org/apache/commons/httpclient/SimpleHttpMethod.java 23 Jan 2003 22:48:25 -0000 1.4
+++ test/org/apache/commons/httpclient/SimpleHttpMethod.java 4 Feb 2003 03:12:57 -0000
@@ -96,26 +96,48 @@
return "Simple";
}
- public Header getResponseHeader(String name) {
- try {
- if(name.equalsIgnoreCase(header.getName())) {
- return header;
- } else {
- return super.getResponseHeader(name);
- }
- } catch(NullPointerException e) {
- return super.getResponseHeader(name);
+ /**
+ * Makes sure any respose header that exists has been added to the response
+ * header group.
+ */
+ private void ensureResponseHeaderIsSet() {
+ if ( header != null ) {
+ super.getResponseHeaderGroup().addHeader(header);
+ header = null;
}
}
+ /**
+ * @see org.apache.commons.httpclient.HttpMethod#execute(org.apache.commons.httpclient.HttpState, org.apache.commons.httpclient.HttpConnection)
+ */
+ public int execute(HttpState state, HttpConnection connection)
+ throws HttpException, IOException {
+ return super.execute(state, connection);
+ }
+
+ /**
+ * @see org.apache.commons.httpclient.HttpMethod#getResponseHeader(java.lang.String)
+ * @deprecated
+ */
+ public Header getResponseHeader(String headerName) {
+ ensureResponseHeaderIsSet();
+ return super.getResponseHeader(headerName);
+ }
- public int execute(HttpState state, HttpConnection conn)
- throws HttpException, IOException{
- return super.execute(state, conn);
- }
+ /**
+ * @see org.apache.commons.httpclient.HttpMethod#getResponseHeaderGroup()
+ */
+ public HeaderGroup getResponseHeaderGroup() {
+ ensureResponseHeaderIsSet();
+ return super.getResponseHeaderGroup();
+ }
+
+ /**
+ * @see org.apache.commons.httpclient.HttpMethod#getResponseHeaders()
+ */
+ public Header[] getResponseHeaders() {
+ ensureResponseHeaderIsSet();
+ return super.getResponseHeaders();
+ }
- public void addRequestHeaders(HttpState state, HttpConnection conn)
- throws HttpException, IOException{
- super.addRequestHeaders(state, conn);
- }
}
Index: test/org/apache/commons/httpclient/TestResponseHeaders.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestResponseHeaders.java,v
retrieving revision 1.6
diff -u -r1.6 TestResponseHeaders.java
--- test/org/apache/commons/httpclient/TestResponseHeaders.java 23 Jan 2003 22:48:27 -0000 1.6
+++ test/org/apache/commons/httpclient/TestResponseHeaders.java 4 Feb 2003 03:12:57 -0000
@@ -119,11 +119,14 @@
HttpMethod method = new SimpleHttpMethod();
SimpleHttpConnection conn = new SimpleHttpConnection(headers, body);
method.execute(state, conn);
- assertEquals("close", method.getResponseHeader("Connection").getValue());
- assertEquals(body.length(), Integer.parseInt(method.getResponseHeader("Content-Length").getValue()));
- assertEquals("text/xml; charset=utf-8", method.getResponseHeader("Content-Type").getValue());
- assertEquals("Wed, 28 Mar 2001 05:05:04 GMT", method.getResponseHeader("Date").getValue());
- assertEquals("UserLand Frontier/7.0-WinNT", method.getResponseHeader("Server").getValue());
+
+ HeaderGroup responseHeaders = method.getResponseHeaderGroup();
+
+ assertEquals("close", responseHeaders.getFirstHeader("Connection").getValue());
+ assertEquals(body.length(), Integer.parseInt(responseHeaders.getFirstHeader("Content-Length").getValue()));
+ assertEquals("text/xml; charset=utf-8", responseHeaders.getFirstHeader("Content-Type").getValue());
+ assertEquals("Wed, 28 Mar 2001 05:05:04 GMT", responseHeaders.getFirstHeader("Date").getValue());
+ assertEquals("UserLand Frontier/7.0-WinNT", responseHeaders.getFirstHeader("Server").getValue());
}
/**
@@ -153,8 +156,8 @@
HttpMethod method = new SimpleHttpMethod();
SimpleHttpConnection conn = new SimpleHttpConnection(headers, body);
method.execute(state, conn);
- assertEquals(null, method.getResponseHeader(null));
- assertEquals(null, method.getResponseHeader("bogus"));
+ assertEquals(null, method.getResponseHeaderGroup().getFirstHeader(null));
+ assertEquals(null, method.getResponseHeaderGroup().getFirstHeader("bogus"));
}
public void testFoldedHeaders() throws Exception {
@@ -172,11 +175,28 @@
HttpMethod method = new SimpleHttpMethod();
SimpleHttpConnection conn = new SimpleHttpConnection(headers, body);
method.execute(state, conn);
- assertEquals("close", method.getResponseHeader("Connection").getValue());
- assertEquals(body.length(), Integer.parseInt(method.getResponseHeader("Content-Length").getValue()));
- assertEquals("text/xml; charset=utf-8 boundary=XXXX", method.getResponseHeader("Content-Type").getValue());
- assertEquals("Wed, 28 Mar 2001 05:05:04 GMT", method.getResponseHeader("Date").getValue());
- assertEquals("UserLand Frontier/7.0-WinNT", method.getResponseHeader("Server").getValue());
- assertTrue(method.getResponseHeader("Content-Type").toString().indexOf("boundary") != -1);
+
+ HeaderGroup responseHeaders = method.getResponseHeaderGroup();
+
+ assertEquals("close", responseHeaders.getFirstHeader("Connection").getValue());
+ assertEquals(
+ body.length(),
+ Integer.parseInt(responseHeaders.getFirstHeader("Content-Length").getValue())
+ );
+ assertEquals(
+ "text/xml; charset=utf-8 boundary=XXXX",
+ responseHeaders.getFirstHeader("Content-Type").getValue()
+ );
+ assertEquals(
+ "Wed, 28 Mar 2001 05:05:04 GMT",
+ responseHeaders.getFirstHeader("Date").getValue()
+ );
+ assertEquals(
+ "UserLand Frontier/7.0-WinNT",
+ responseHeaders.getFirstHeader("Server").getValue()
+ );
+ assertTrue(
+ responseHeaders.getFirstHeader("Content-Type").toString().indexOf("boundary") != -1
+ );
}
}