You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by js...@apache.org on 2003/02/11 04:23:05 UTC
cvs commit: jakarta-commons/httpclient/src/test/org/apache/commons/httpclient SimpleHttpConnection.java SimpleHttpMethod.java TestStreams.java
jsdever 2003/02/10 19:23:05
Modified: httpclient/src/java/org/apache/commons/httpclient
ChunkedInputStream.java HttpConnection.java
HttpMethodBase.java
httpclient/src/test/org/apache/commons/httpclient
SimpleHttpConnection.java SimpleHttpMethod.java
TestStreams.java
Log:
Multivalued headers.
Bug: http://nagoya.apache.org/bugzilla/show_bug.cgi?id=11218
Contributed by: Mike Becke
changeLog:
- HeaderGroup, a new class for storing headers. This class supports multiple
headers with the same name and it remembers header order. I'm not a huge fan of
the name, but it was the best I could come up with.
- HeaderParser, a new class for parsing headers. Header parsing code was
duplicated in HttpMethodBase and ChunkedInputStream and was placed here.
- HttpMethod has 3 new methods. getRequestHeaderGroup(),
getResponseHeaderGroup(), and getResponseFooterGroup(). This will break an
existing extension of HttpMethod.
- Some of the methods for accessing headers in HttpMethod have been deprecated.
- Classes in the general codebase that use the newly deprecated methods have
been fixed. Some of the test cases are still using deprecated methods.
- SimpleHttpConnection and SimpleHttpMethod have been changed to work correctly
with the new header storage method.
Revision Changes Path
1.13 +18 -44 jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/ChunkedInputStream.java
Index: ChunkedInputStream.java
===================================================================
RCS file: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/ChunkedInputStream.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- ChunkedInputStream.java 28 Jan 2003 04:40:20 -0000 1.12
+++ ChunkedInputStream.java 11 Feb 2003 03:23:05 -0000 1.13
@@ -67,6 +67,8 @@
import java.io.IOException;
import java.io.InputStream;
+import org.apache.commons.httpclient.util.HeaderParser;
+
/**
* <p>Transparently coalesces chunks of a HTTP stream that uses
* Transfer-Encoding chunked.</p>
@@ -84,6 +86,7 @@
* @author Martin Elwin
* @author Eric Johnson
* @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
+ * @author Michael Becke
*
* @since 2.0
*
@@ -130,7 +133,7 @@
this.chunkSize = getChunkSizeFromInputStream(in);
if (chunkSize == 0) {
eof = true;
- parseFooters();
+ parseTrailerHeaders();
}
this.pos = 0;
}
@@ -140,12 +143,14 @@
* is followed by a CRLF. The method returns -1 as soon as a chunksize of 0
* is detected.</p>
*
- * <p> Footers are read automcatically at the end of the stream and can be
- * obtained with the getFooters() method.</p>
+ * <p> Trailer headers are read automcatically at the end of the stream and
+ * can be obtained with the getResponseFooters() method.</p>
*
* @return -1 of the end of the stream has been reached or the next data
* byte
* @throws IOException If an IO problem occurs
+ *
+ * @see HttpMethod#getResponseFooters()
*/
public int read() throws IOException {
@@ -224,7 +229,7 @@
pos = 0;
if (chunkSize == 0) {
eof = true;
- parseFooters();
+ parseTrailerHeaders();
}
}
@@ -306,46 +311,15 @@
}
/**
- * Stores the footers into map of Headers
+ * Reads and stores the Trailer headers.
* @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);
+ private void parseTrailerHeaders() throws IOException {
+ Header[] footers = HeaderParser.parseHeaders(in);
+
+ for (int i = 0; i < footers.length; i++) {
+ method.addResponseFooter(footers[i]);
}
- return (buf.toString());
}
/**
1.43 +42 -22 jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpConnection.java
Index: HttpConnection.java
===================================================================
RCS file: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpConnection.java,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -r1.42 -r1.43
--- HttpConnection.java 8 Feb 2003 19:22:49 -0000 1.42
+++ HttpConnection.java 11 Feb 2003 03:23:05 -0000 1.43
@@ -104,11 +104,48 @@
* @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
* @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
* @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
+ * @author Michael Becke
*
* @version $Revision$ $Date$
*/
public class HttpConnection {
+ /**
+ * Read up to <tt>"\r\n"</tt> from an (unchunked) input stream.
+ * If the stream ends before the line terminator is found,
+ * the last part of the string will still be returned.
+ * '\r' and '\n' are allowed to appear individually in the stream.
+ *
+ * @param inputStream the stream to read from
+ *
+ * @throws IOException if an I/O problem occurs
+ * @return a line from the stream
+ *
+ * @since 2.0beta1
+ */
+ public static String readLine(InputStream inputStream) throws IOException {
+ LOG.trace("enter HttpConnection.readLine()");
+
+ StringBuffer buf = new StringBuffer();
+ int ch = inputStream.read();
+ while (ch >= 0) {
+ if (ch == '\r') {
+ ch = inputStream.read();
+ if (ch == '\n') {
+ break;
+ } else {
+ buf.append('\r');
+ }
+ }
+ buf.append((char) ch);
+ ch = inputStream.read();
+ }
+ if (WIRE_LOG.isDebugEnabled()) {
+ WIRE_LOG.debug("<< \"" + buf.toString() + (ch>0 ? "\" [\\r\\n]" : ""));
+ }
+ return (buf.toString());
+ }
+
// ----------------------------------------------------------- Constructors
/**
@@ -857,24 +894,7 @@
LOG.trace("enter HttpConnection.readLine()");
assertOpen();
- StringBuffer buf = new StringBuffer();
- int ch = inputStream.read();
- while (ch >= 0) {
- if (ch == '\r') {
- ch = inputStream.read();
- if (ch == '\n') {
- break;
- } else {
- buf.append('\r');
- }
- }
- buf.append((char) ch);
- ch = inputStream.read();
- }
- if (WIRE_LOG.isDebugEnabled()) {
- WIRE_LOG.debug("<< \"" + buf.toString() + (ch>0 ? "\" [\\r\\n]" : ""));
- }
- return (buf.toString());
+ return HttpConnection.readLine(inputStream);
}
/**
1.111 +95 -158 jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java
Index: HttpMethodBase.java
===================================================================
RCS file: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v
retrieving revision 1.110
retrieving revision 1.111
diff -u -r1.110 -r1.111
--- HttpMethodBase.java 8 Feb 2003 19:22:49 -0000 1.110
+++ HttpMethodBase.java 11 Feb 2003 03:23:05 -0000 1.111
@@ -69,15 +69,13 @@
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;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.cookie.CookieSpec;
+import org.apache.commons.httpclient.util.HeaderParser;
import org.apache.commons.httpclient.util.URIUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -165,16 +163,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;
+ /** My response trailer headers, if any. */
+ private HeaderGroup responseTrailerHeaders = new HeaderGroup();
/** Realms that we tried to authenticate to */
private Set realms = null;
@@ -416,12 +414,9 @@
}
/**
- * Add the specified request header.
- *
- * If a header of the same name already exists, the new value will be
- * appended onto the the existing value list.
- * A <i>header</i> value of <code>null</code> will be ignored.
- * Note that header-name matching is case insensitive.
+ * Add the specified request header. A <i>header</i> value of
+ * <code>null</code> will be ignored. Note that header-name matching is case
+ * insensitive.
*
* @param header the header to add to the request
*/
@@ -429,9 +424,9 @@
LOG.trace("HttpMethodBase.addRequestHeader(Header)");
if (header == null) {
- LOG.debug("null header value ignored");
+ LOG.debug("null header value ignored");
} else {
- addRequestHeader(header.getName(), header.getValue());
+ getRequestHeaderGroup().addHeader(header);
}
}
@@ -440,10 +435,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);
+ getResponseTrailerHeaderGroup().addHeader(footer);
}
/**
@@ -537,7 +529,15 @@
* @param header the header
*/
public void setRequestHeader(Header header) {
- requestHeaders.put(header.getName().toLowerCase(), header);
+
+ Header[] headers = getRequestHeaderGroup().getHeaders(header.getName());
+
+ for (int i = 0; i < headers.length; i++) {
+ getRequestHeaderGroup().removeHeader(headers[i]);
+ }
+
+ getRequestHeaderGroup().addHeader(header);
+
}
/**
@@ -551,8 +551,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 getRequestHeaderGroup().getCondensedHeader(headerName);
+ }
}
/**
@@ -561,11 +564,44 @@
* @return an array of my request headers.
*/
public Header[] getRequestHeaders() {
- return (Header[]) (requestHeaders.values().toArray(
- new Header[requestHeaders.size()]));
+ return getRequestHeaderGroup().getAllHeaders();
+ }
+
+ /**
+ * Gets the HeaderGroup storing the request headers.
+ *
+ * @return a HeaderGroup
+ *
+ * @since 2.0beta1
+ */
+ protected HeaderGroup getRequestHeaderGroup() {
+ return requestHeaders;
+ }
+
+ /**
+ * Gets the HeaderGroup storing the response trailer headers as per RFC
+ * 2616 section 3.6.1.
+ *
+ * @return a HeaderGroup
+ *
+ * @since 2.0beta1
+ */
+ protected HeaderGroup getResponseTrailerHeaderGroup() {
+ return responseTrailerHeaders;
}
/**
+ * Gets the HeaderGroup storing the response headers.
+ *
+ * @return a HeaderGroup
+ *
+ * @since 2.0beta1
+ */
+ protected HeaderGroup getResponseHeaderGroup() {
+ return responseHeaders;
+ }
+
+ /**
* Convenience method top provide access to the status code.
*
* @return the status code associated with the latest response.
@@ -593,13 +629,12 @@
}
/**
- * Provide access to the response headers
+ * Gets the response headers in the order in which they were read.
*
* @return an array of my response headers.
*/
public Header[] getResponseHeaders() {
- return (Header[]) (responseHeaders.values().toArray(
- new Header[responseHeaders.size()]));
+ return getResponseHeaderGroup().getAllHeaders();
}
/**
@@ -612,10 +647,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 getResponseHeaderGroup().getCondensedHeader(headerName);
+ }
}
/**
@@ -690,15 +727,11 @@
}
/**
- * Return an array of response footers.
- * @return <tt>null</tt> if no footers are available
+ * Gets the response footers in the order in which they were read.
+ * @return an array of headers
*/
public Header[] getResponseFooters() {
- if (responseFooters == null) {
- return null;
- }
- return (Header[]) (responseFooters.values().toArray(
- new Header[responseFooters.size()]));
+ return getResponseTrailerHeaderGroup().getAllHeaders();
}
/**
@@ -711,11 +744,11 @@
* @return the matching footer
*/
public Header getResponseFooter(String footerName) {
- if (responseFooters == null) {
+ if (footerName == null) {
return null;
+ } else {
+ return getResponseTrailerHeaderGroup().getCondensedHeader(footerName);
}
- return (footerName == null) ? null
- : (Header) (responseFooters.get(footerName.toLowerCase()));
}
/**
@@ -768,20 +801,7 @@
* @param headerValue the header's value
*/
public void addRequestHeader(String headerName, String headerValue) {
- // "It must be possible to combine the multiple header fields into
- // one "field-name: field-value" pair, without changing the
- // semantics of the message, by appending each subsequent field-value
- // to the first, each separated by a comma."
- // - HTTP/1.0 (4.3)
- Header header = getRequestHeader(headerName);
- if (null == header) {
- // header doesn't exist already, simply create with name and value
- header = new Header(headerName, headerValue);
- } else {
- // header exists, add this value to the comma separated list
- header.setValue(getNewHeaderValue(header, headerValue));
- }
- setRequestHeader(header);
+ addRequestHeader(new Header(headerName, headerValue));
}
/**
@@ -1137,8 +1157,9 @@
followRedirects = false;
doAuthentication = true;
queryString = null;
- requestHeaders.clear();
- responseHeaders.clear();
+ getRequestHeaderGroup().clear();
+ getResponseHeaderGroup().clear();
+ getResponseTrailerHeaderGroup().clear();
statusLine = null;
used = false;
http11 = true;
@@ -1174,7 +1195,12 @@
* @param headerName the header name
*/
public void removeRequestHeader(String headerName) {
- requestHeaders.remove(headerName.toLowerCase());
+
+ Header[] headers = getRequestHeaderGroup().getHeaders(headerName);
+ for (int i = 0; i < headers.length; i++) {
+ getRequestHeaderGroup().removeHeader(headers[i]);
+ }
+
}
// ---------------------------------------------------------------- Queries
@@ -1835,55 +1861,9 @@
LOG.trace("enter HttpMethodBase.readResponseHeaders(HttpState,"
+ "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);
- }
+ getResponseHeaderGroup().clear();
+ Header[] headers = HeaderParser.parseHeaders(conn.getResponseInputStream());
+ getResponseHeaderGroup().setHeaders(headers);
}
/**
@@ -2048,9 +2028,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());
}
}
@@ -2136,50 +2117,6 @@
return false;
}
return true;
- }
-
-
- /**
- * "It must be possible to combine the multiple header fields into one
- * "field-name: field-value" pair, without changing the semantics of the
- * message, by appending each subsequent field-value to the first, each
- * separated by a comma."
- * //TODO: This method is trying to make up for deficiencies in Header.
- *
- * @param existingHeader the current header
- * @param value DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- private String getNewHeaderValue(Header existingHeader, String value) {
- String existingValue = existingHeader.getValue();
- if (existingValue == null) {
- existingValue = "";
- }
- String newValue = value;
- if (value == null) {
- newValue = "";
- }
- return existingValue + ", " + newValue;
- }
-
- /**
- * Sets the specified response header.
- * Logs a warning if the header name is null.
- *
- * @param header the header to set.
- *
- * @since 2.0
- */
- private void setResponseHeader(Header header) {
- if (header == null) {
- return;
- }
- if (header.getName() == null) {
- LOG.warn("Invalid header found");
- } else {
- responseHeaders.put(header.getName().toLowerCase(), header);
- }
}
/**
1.9 +38 -27 jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/SimpleHttpConnection.java
Index: SimpleHttpConnection.java
===================================================================
RCS file: /home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/SimpleHttpConnection.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- SimpleHttpConnection.java 31 Jan 2003 23:23:17 -0000 1.8
+++ SimpleHttpConnection.java 11 Feb 2003 03:23:05 -0000 1.9
@@ -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 <a href="mailto:jsdever@apache.org">Jeff Dever</a>
+ * @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 = HttpConnection.readLine(inputStream);
log.debug("read: " + str);
return str;
}
@@ -187,7 +198,7 @@
public InputStream getResponseInputStream() {
- return bodyInputStream;
+ return inputStream;
}
public OutputStream getRequestOutputStream() {
1.5 +42 -20 jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/SimpleHttpMethod.java
Index: SimpleHttpMethod.java
===================================================================
RCS file: /home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/SimpleHttpMethod.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- SimpleHttpMethod.java 23 Jan 2003 22:48:25 -0000 1.4
+++ SimpleHttpMethod.java 11 Feb 2003 03:23:05 -0000 1.5
@@ -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 HttpMethod#execute(HttpState, HttpConnection)
+ */
+ public int execute(HttpState state, HttpConnection connection)
+ throws HttpException, IOException {
+ return super.execute(state, connection);
+ }
+
+ /**
+ * @see HttpMethod#getResponseHeader(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 HttpMethod#getResponseHeaderGroup()
+ */
+ protected HeaderGroup getResponseHeaderGroup() {
+ ensureResponseHeaderIsSet();
+ return super.getResponseHeaderGroup();
+ }
+
+ /**
+ * @see HttpMethod#getResponseHeaders()
+ */
+ public Header[] getResponseHeaders() {
+ ensureResponseHeaderIsSet();
+ return super.getResponseHeaders();
+ }
- public void addRequestHeaders(HttpState state, HttpConnection conn)
- throws HttpException, IOException{
- super.addRequestHeaders(state, conn);
- }
}
1.9 +5 -3 jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestStreams.java
Index: TestStreams.java
===================================================================
RCS file: /home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestStreams.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- TestStreams.java 23 Jan 2003 22:48:27 -0000 1.8
+++ TestStreams.java 11 Feb 2003 03:23:05 -0000 1.9
@@ -101,6 +101,8 @@
footer = method.getResponseFooter("footer2");
assertEquals(footer.getValue(), "fghij");
+ // recycle the method so that it can be reused below
+ method.recycle();
//Test for when buffer is smaller than chunk size.
in = new ChunkedInputStream(new ByteArrayInputStream(HttpConstants.getBytes(correctInput)), method);
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org
Re: cvs commit: jakarta-commons/httpclient/src/test/org/apache/commons/httpclient SimpleHttpConnection.java SimpleHttpMethod.java TestStreams.java
Posted by Michael Becke <be...@u.washington.edu>.
Jeff,
Looks like HeaderGroup and HeaderParser didn't make it into cvs:)
Mike
On Monday, February 10, 2003, at 10:23 PM, jsdever@apache.org wrote:
> jsdever 2003/02/10 19:23:05
>
> Modified: httpclient/src/java/org/apache/commons/httpclient
> ChunkedInputStream.java HttpConnection.java
> HttpMethodBase.java
> httpclient/src/test/org/apache/commons/httpclient
> SimpleHttpConnection.java SimpleHttpMethod.java
> TestStreams.java
> Log:
> Multivalued headers.
>
> Bug: http://nagoya.apache.org/bugzilla/show_bug.cgi?id=11218
> Contributed by: Mike Becke
>
> changeLog:
> - HeaderGroup, a new class for storing headers. This class
> supports multiple
> headers with the same name and it remembers header order. I'm
> not a huge fan of
> the name, but it was the best I could come up with.
> - HeaderParser, a new class for parsing headers. Header parsing
> code was
> duplicated in HttpMethodBase and ChunkedInputStream and was
> placed here.
> - HttpMethod has 3 new methods. getRequestHeaderGroup(),
> getResponseHeaderGroup(), and getResponseFooterGroup(). This
> will break an
> existing extension of HttpMethod.
> - Some of the methods for accessing headers in HttpMethod have been
> deprecated.
> - Classes in the general codebase that use the newly deprecated
> methods have
> been fixed. Some of the test cases are still using deprecated
> methods.
> - SimpleHttpConnection and SimpleHttpMethod have been changed to
> work correctly
> with the new header storage method.
>
> Revision Changes Path
> 1.13 +18 -44
> jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/
> ChunkedInputStream.java
>
> Index: ChunkedInputStream.java
> ===================================================================
> RCS file:
> /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/
> httpclient/ChunkedInputStream.java,v
> retrieving revision 1.12
> retrieving revision 1.13
> diff -u -r1.12 -r1.13
> --- ChunkedInputStream.java 28 Jan 2003 04:40:20 -0000 1.12
> +++ ChunkedInputStream.java 11 Feb 2003 03:23:05 -0000 1.13
> @@ -67,6 +67,8 @@
> import java.io.IOException;
> import java.io.InputStream;
>
> +import org.apache.commons.httpclient.util.HeaderParser;
> +
> /**
> * <p>Transparently coalesces chunks of a HTTP stream that uses
> * Transfer-Encoding chunked.</p>
> @@ -84,6 +86,7 @@
> * @author Martin Elwin
> * @author Eric Johnson
> * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike
> Bowler</a>
> + * @author Michael Becke
> *
> * @since 2.0
> *
> @@ -130,7 +133,7 @@
> this.chunkSize = getChunkSizeFromInputStream(in);
> if (chunkSize == 0) {
> eof = true;
> - parseFooters();
> + parseTrailerHeaders();
> }
> this.pos = 0;
> }
> @@ -140,12 +143,14 @@
> * is followed by a CRLF. The method returns -1 as soon as a
> chunksize of 0
> * is detected.</p>
> *
> - * <p> Footers are read automcatically at the end of the stream
> and can be
> - * obtained with the getFooters() method.</p>
> + * <p> Trailer headers are read automcatically at the end of
> the stream and
> + * can be obtained with the getResponseFooters() method.</p>
> *
> * @return -1 of the end of the stream has been reached or the
> next data
> * byte
> * @throws IOException If an IO problem occurs
> + *
> + * @see HttpMethod#getResponseFooters()
> */
> public int read() throws IOException {
>
> @@ -224,7 +229,7 @@
> pos = 0;
> if (chunkSize == 0) {
> eof = true;
> - parseFooters();
> + parseTrailerHeaders();
> }
> }
>
> @@ -306,46 +311,15 @@
> }
>
> /**
> - * Stores the footers into map of Headers
> + * Reads and stores the Trailer headers.
> * @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);
> + private void parseTrailerHeaders() throws IOException {
> + Header[] footers = HeaderParser.parseHeaders(in);
> +
> + for (int i = 0; i < footers.length; i++) {
> + method.addResponseFooter(footers[i]);
> }
> - return (buf.toString());
> }
>
> /**
>
>
>
> 1.43 +42 -22
> jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/
> HttpConnection.java
>
> Index: HttpConnection.java
> ===================================================================
> RCS file:
> /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/
> httpclient/HttpConnection.java,v
> retrieving revision 1.42
> retrieving revision 1.43
> diff -u -r1.42 -r1.43
> --- HttpConnection.java 8 Feb 2003 19:22:49 -0000 1.42
> +++ HttpConnection.java 11 Feb 2003 03:23:05 -0000 1.43
> @@ -104,11 +104,48 @@
> * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
> * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike
> Bowler</a>
> * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
> + * @author Michael Becke
> *
> * @version $Revision$ $Date$
> */
> public class HttpConnection {
>
> + /**
> + * Read up to <tt>"\r\n"</tt> from an (unchunked) input stream.
> + * If the stream ends before the line terminator is found,
> + * the last part of the string will still be returned.
> + * '\r' and '\n' are allowed to appear individually in the
> stream.
> + *
> + * @param inputStream the stream to read from
> + *
> + * @throws IOException if an I/O problem occurs
> + * @return a line from the stream
> + *
> + * @since 2.0beta1
> + */
> + public static String readLine(InputStream inputStream) throws
> IOException {
> + LOG.trace("enter HttpConnection.readLine()");
> +
> + StringBuffer buf = new StringBuffer();
> + int ch = inputStream.read();
> + while (ch >= 0) {
> + if (ch == '\r') {
> + ch = inputStream.read();
> + if (ch == '\n') {
> + break;
> + } else {
> + buf.append('\r');
> + }
> + }
> + buf.append((char) ch);
> + ch = inputStream.read();
> + }
> + if (WIRE_LOG.isDebugEnabled()) {
> + WIRE_LOG.debug("<< \"" + buf.toString() + (ch>0 ? "\"
> [\\r\\n]" : ""));
> + }
> + return (buf.toString());
> + }
> +
> // -----------------------------------------------------------
> Constructors
>
> /**
> @@ -857,24 +894,7 @@
> LOG.trace("enter HttpConnection.readLine()");
>
> assertOpen();
> - StringBuffer buf = new StringBuffer();
> - int ch = inputStream.read();
> - while (ch >= 0) {
> - if (ch == '\r') {
> - ch = inputStream.read();
> - if (ch == '\n') {
> - break;
> - } else {
> - buf.append('\r');
> - }
> - }
> - buf.append((char) ch);
> - ch = inputStream.read();
> - }
> - if (WIRE_LOG.isDebugEnabled()) {
> - WIRE_LOG.debug("<< \"" + buf.toString() + (ch>0 ? "\"
> [\\r\\n]" : ""));
> - }
> - return (buf.toString());
> + return HttpConnection.readLine(inputStream);
> }
>
> /**
>
>
>
> 1.111 +95 -158
> jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/
> HttpMethodBase.java
>
> Index: HttpMethodBase.java
> ===================================================================
> RCS file:
> /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/
> httpclient/HttpMethodBase.java,v
> retrieving revision 1.110
> retrieving revision 1.111
> diff -u -r1.110 -r1.111
> --- HttpMethodBase.java 8 Feb 2003 19:22:49 -0000 1.110
> +++ HttpMethodBase.java 11 Feb 2003 03:23:05 -0000 1.111
> @@ -69,15 +69,13 @@
> 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;
>
> import org.apache.commons.httpclient.cookie.CookiePolicy;
> import org.apache.commons.httpclient.cookie.CookieSpec;
> +import org.apache.commons.httpclient.util.HeaderParser;
> import org.apache.commons.httpclient.util.URIUtil;
> import org.apache.commons.logging.Log;
> import org.apache.commons.logging.LogFactory;
> @@ -165,16 +163,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;
> + /** My response trailer headers, if any. */
> + private HeaderGroup responseTrailerHeaders = new HeaderGroup();
>
> /** Realms that we tried to authenticate to */
> private Set realms = null;
> @@ -416,12 +414,9 @@
> }
>
> /**
> - * Add the specified request header.
> - *
> - * If a header of the same name already exists, the new value
> will be
> - * appended onto the the existing value list.
> - * A <i>header</i> value of <code>null</code> will be ignored.
> - * Note that header-name matching is case insensitive.
> + * Add the specified request header. A <i>header</i> value of
> + * <code>null</code> will be ignored. Note that header-name
> matching is case
> + * insensitive.
> *
> * @param header the header to add to the request
> */
> @@ -429,9 +424,9 @@
> LOG.trace("HttpMethodBase.addRequestHeader(Header)");
>
> if (header == null) {
> - LOG.debug("null header value ignored");
> + LOG.debug("null header value ignored");
> } else {
> - addRequestHeader(header.getName(), header.getValue());
> + getRequestHeaderGroup().addHeader(header);
> }
> }
>
> @@ -440,10 +435,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);
> + getResponseTrailerHeaderGroup().addHeader(footer);
> }
>
> /**
> @@ -537,7 +529,15 @@
> * @param header the header
> */
> public void setRequestHeader(Header header) {
> - requestHeaders.put(header.getName().toLowerCase(), header);
> +
> + Header[] headers =
> getRequestHeaderGroup().getHeaders(header.getName());
> +
> + for (int i = 0; i < headers.length; i++) {
> + getRequestHeaderGroup().removeHeader(headers[i]);
> + }
> +
> + getRequestHeaderGroup().addHeader(header);
> +
> }
>
> /**
> @@ -551,8 +551,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
> getRequestHeaderGroup().getCondensedHeader(headerName);
> + }
> }
>
> /**
> @@ -561,11 +564,44 @@
> * @return an array of my request headers.
> */
> public Header[] getRequestHeaders() {
> - return (Header[]) (requestHeaders.values().toArray(
> - new Header[requestHeaders.size()]));
> + return getRequestHeaderGroup().getAllHeaders();
> + }
> +
> + /**
> + * Gets the HeaderGroup storing the request headers.
> + *
> + * @return a HeaderGroup
> + *
> + * @since 2.0beta1
> + */
> + protected HeaderGroup getRequestHeaderGroup() {
> + return requestHeaders;
> + }
> +
> + /**
> + * Gets the HeaderGroup storing the response trailer headers as
> per RFC
> + * 2616 section 3.6.1.
> + *
> + * @return a HeaderGroup
> + *
> + * @since 2.0beta1
> + */
> + protected HeaderGroup getResponseTrailerHeaderGroup() {
> + return responseTrailerHeaders;
> }
>
> /**
> + * Gets the HeaderGroup storing the response headers.
> + *
> + * @return a HeaderGroup
> + *
> + * @since 2.0beta1
> + */
> + protected HeaderGroup getResponseHeaderGroup() {
> + return responseHeaders;
> + }
> +
> + /**
> * Convenience method top provide access to the status code.
> *
> * @return the status code associated with the latest response.
> @@ -593,13 +629,12 @@
> }
>
> /**
> - * Provide access to the response headers
> + * Gets the response headers in the order in which they were
> read.
> *
> * @return an array of my response headers.
> */
> public Header[] getResponseHeaders() {
> - return (Header[]) (responseHeaders.values().toArray(
> - new Header[responseHeaders.size()]));
> + return getResponseHeaderGroup().getAllHeaders();
> }
>
> /**
> @@ -612,10 +647,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
> getResponseHeaderGroup().getCondensedHeader(headerName);
> + }
> }
>
> /**
> @@ -690,15 +727,11 @@
> }
>
> /**
> - * Return an array of response footers.
> - * @return <tt>null</tt> if no footers are available
> + * Gets the response footers in the order in which they were
> read.
> + * @return an array of headers
> */
> public Header[] getResponseFooters() {
> - if (responseFooters == null) {
> - return null;
> - }
> - return (Header[]) (responseFooters.values().toArray(
> - new Header[responseFooters.size()]));
> + return getResponseTrailerHeaderGroup().getAllHeaders();
> }
>
> /**
> @@ -711,11 +744,11 @@
> * @return the matching footer
> */
> public Header getResponseFooter(String footerName) {
> - if (responseFooters == null) {
> + if (footerName == null) {
> return null;
> + } else {
> + return
> getResponseTrailerHeaderGroup().getCondensedHeader(footerName);
> }
> - return (footerName == null) ? null
> - : (Header)
> (responseFooters.get(footerName.toLowerCase()));
> }
>
> /**
> @@ -768,20 +801,7 @@
> * @param headerValue the header's value
> */
> public void addRequestHeader(String headerName, String
> headerValue) {
> - // "It must be possible to combine the multiple header
> fields into
> - // one "field-name: field-value" pair, without changing the
> - // semantics of the message, by appending each subsequent
> field-value
> - // to the first, each separated by a comma."
> - // - HTTP/1.0 (4.3)
> - Header header = getRequestHeader(headerName);
> - if (null == header) {
> - // header doesn't exist already, simply create with
> name and value
> - header = new Header(headerName, headerValue);
> - } else {
> - // header exists, add this value to the comma separated
> list
> - header.setValue(getNewHeaderValue(header, headerValue));
> - }
> - setRequestHeader(header);
> + addRequestHeader(new Header(headerName, headerValue));
> }
>
> /**
> @@ -1137,8 +1157,9 @@
> followRedirects = false;
> doAuthentication = true;
> queryString = null;
> - requestHeaders.clear();
> - responseHeaders.clear();
> + getRequestHeaderGroup().clear();
> + getResponseHeaderGroup().clear();
> + getResponseTrailerHeaderGroup().clear();
> statusLine = null;
> used = false;
> http11 = true;
> @@ -1174,7 +1195,12 @@
> * @param headerName the header name
> */
> public void removeRequestHeader(String headerName) {
> - requestHeaders.remove(headerName.toLowerCase());
> +
> + Header[] headers =
> getRequestHeaderGroup().getHeaders(headerName);
> + for (int i = 0; i < headers.length; i++) {
> + getRequestHeaderGroup().removeHeader(headers[i]);
> + }
> +
> }
>
> //
> ----------------------------------------------------------------
> Queries
> @@ -1835,55 +1861,9 @@
> LOG.trace("enter
> HttpMethodBase.readResponseHeaders(HttpState,"
> + "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);
> - }
> + getResponseHeaderGroup().clear();
> + Header[] headers =
> HeaderParser.parseHeaders(conn.getResponseInputStream());
> + getResponseHeaderGroup().setHeaders(headers);
> }
>
> /**
> @@ -2048,9 +2028,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());
> }
> }
>
> @@ -2136,50 +2117,6 @@
> return false;
> }
> return true;
> - }
> -
> -
> - /**
> - * "It must be possible to combine the multiple header fields
> into one
> - * "field-name: field-value" pair, without changing the
> semantics of the
> - * message, by appending each subsequent field-value to the
> first, each
> - * separated by a comma."
> - * //TODO: This method is trying to make up for deficiencies in
> Header.
> - *
> - * @param existingHeader the current header
> - * @param value DOCUMENT ME!
> - *
> - * @return DOCUMENT ME!
> - */
> - private String getNewHeaderValue(Header existingHeader, String
> value) {
> - String existingValue = existingHeader.getValue();
> - if (existingValue == null) {
> - existingValue = "";
> - }
> - String newValue = value;
> - if (value == null) {
> - newValue = "";
> - }
> - return existingValue + ", " + newValue;
> - }
> -
> - /**
> - * Sets the specified response header.
> - * Logs a warning if the header name is null.
> - *
> - * @param header the header to set.
> - *
> - * @since 2.0
> - */
> - private void setResponseHeader(Header header) {
> - if (header == null) {
> - return;
> - }
> - if (header.getName() == null) {
> - LOG.warn("Invalid header found");
> - } else {
> - responseHeaders.put(header.getName().toLowerCase(),
> header);
> - }
> }
>
> /**
>
>
>
> 1.9 +38 -27
> jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/
> SimpleHttpConnection.java
>
> Index: SimpleHttpConnection.java
> ===================================================================
> RCS file:
> /home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/
> httpclient/SimpleHttpConnection.java,v
> retrieving revision 1.8
> retrieving revision 1.9
> diff -u -r1.8 -r1.9
> --- SimpleHttpConnection.java 31 Jan 2003 23:23:17 -0000 1.8
> +++ SimpleHttpConnection.java 11 Feb 2003 03:23:05 -0000 1.9
> @@ -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 <a href="mailto:jsdever@apache.org">Jeff Dever</a>
> + * @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 = HttpConnection.readLine(inputStream);
> log.debug("read: " + str);
> return str;
> }
> @@ -187,7 +198,7 @@
>
>
> public InputStream getResponseInputStream() {
> - return bodyInputStream;
> + return inputStream;
> }
>
> public OutputStream getRequestOutputStream() {
>
>
>
> 1.5 +42 -20
> jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/
> SimpleHttpMethod.java
>
> Index: SimpleHttpMethod.java
> ===================================================================
> RCS file:
> /home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/
> httpclient/SimpleHttpMethod.java,v
> retrieving revision 1.4
> retrieving revision 1.5
> diff -u -r1.4 -r1.5
> --- SimpleHttpMethod.java 23 Jan 2003 22:48:25 -0000 1.4
> +++ SimpleHttpMethod.java 11 Feb 2003 03:23:05 -0000 1.5
> @@ -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 HttpMethod#execute(HttpState, HttpConnection)
> + */
> + public int execute(HttpState state, HttpConnection connection)
> + throws HttpException, IOException {
> + return super.execute(state, connection);
> + }
> +
> + /**
> + * @see HttpMethod#getResponseHeader(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 HttpMethod#getResponseHeaderGroup()
> + */
> + protected HeaderGroup getResponseHeaderGroup() {
> + ensureResponseHeaderIsSet();
> + return super.getResponseHeaderGroup();
> + }
> +
> + /**
> + * @see HttpMethod#getResponseHeaders()
> + */
> + public Header[] getResponseHeaders() {
> + ensureResponseHeaderIsSet();
> + return super.getResponseHeaders();
> + }
>
> - public void addRequestHeaders(HttpState state, HttpConnection conn)
> - throws HttpException, IOException{
> - super.addRequestHeaders(state, conn);
> - }
> }
>
>
>
> 1.9 +5 -3
> jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/
> TestStreams.java
>
> Index: TestStreams.java
> ===================================================================
> RCS file:
> /home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/
> httpclient/TestStreams.java,v
> retrieving revision 1.8
> retrieving revision 1.9
> diff -u -r1.8 -r1.9
> --- TestStreams.java 23 Jan 2003 22:48:27 -0000 1.8
> +++ TestStreams.java 11 Feb 2003 03:23:05 -0000 1.9
> @@ -101,6 +101,8 @@
> footer = method.getResponseFooter("footer2");
> assertEquals(footer.getValue(), "fghij");
>
> + // recycle the method so that it can be reused below
> + method.recycle();
>
> //Test for when buffer is smaller than chunk size.
> in = new ChunkedInputStream(new
> ByteArrayInputStream(HttpConstants.getBytes(correctInput)), method);
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org