rwaldhoff 01/08/13 15:37:12
Modified: httpclient/src/java/org/apache/commons/httpclient Tag:
rlwrefactoring HttpMethod.java HttpMethodBase.java
httpclient/src/java/org/apache/commons/httpclient/methods
Tag: rlwrefactoring PostMethod.java PutMethod.java
Log:
* have writeRequestBody return boolean, removing the need for "used" depedency
between HttpMethodBase and subclasses
* javadoc and reorder HttpMethod and HttpMethodBase methods
Revision Changes Path
No revision
No revision
1.5.2.3 +34 -17
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethod.java
Index: HttpMethod.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethod.java,v
retrieving revision 1.5.2.2
retrieving revision 1.5.2.3
diff -u -r1.5.2.2 -r1.5.2.3
--- HttpMethod.java 2001/08/13 15:54:31 1.5.2.2
+++ HttpMethod.java 2001/08/13 22:37:12 1.5.2.3
@@ -1,7 +1,7 @@
/*
- * $Header:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethod.java,v
1.5.2.2 2001/08/13 15:54:31 rwaldhoff Exp $
- * $Revision: 1.5.2.2 $
- * $Date: 2001/08/13 15:54:31 $
+ * $Header:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethod.java,v
1.5.2.3 2001/08/13 22:37:12 rwaldhoff Exp $
+ * $Revision: 1.5.2.3 $
+ * $Date: 2001/08/13 22:37:12 $
* ====================================================================
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
@@ -16,7 +16,7 @@
import java.io.OutputStream;
import java.io.IOException;
import java.util.Iterator;
-import java.util.HashMap;
+import java.util.Collection;
import org.apache.commons.httpclient.log.*;
@@ -29,10 +29,19 @@
*/
public interface HttpMethod {
+ // -------------------------------------------------------------- Constants
+
+ /** <tt>HTTP/1.1</tt> */
public static final String PROTOCOL = "HTTP/1.1";
+
+ /** <tt>org.apache.commons.httpclient.HttpMethod</tt> log. */
public static final Log log =
LogSource.getInstance("org.apache.commons.httpclient.HttpMethod");
+
+ /** <tt>httpclient.wire</tt> log. */
public static final Log wireLog = LogSource.getInstance("httpclient.wire");
+ // ------------------------------------------- Property Setters and Getters
+
/**
* Obtain name of this method, suitable for use in the "request line",
* for example <tt>GET</tt> or <tt>POST</tt>.
@@ -90,7 +99,7 @@
public boolean followRedirects();
/**
- * Set whether or not this method should automatically follow
+ * Set whether or not I should automatically follow
* HTTP redirects (status code 302, etc.)
*/
public void setFollowRedirects(boolean followRedirects);
@@ -149,21 +158,14 @@
*/
public Iterator getRequestHeaders();
+ // ---------------------------------------------------------------- Queries
+
/**
* Confirm that I am ready to execute.
*/
public boolean validate();
/**
- * Execute this method.
- * @param state state information to associate with this request
- * @param request the stream to write the request to
- * @param response the stream to read the response from
- * @param baseHeaders an intitial set of headers to use
- */
- public int execute(State state, HttpConnection connection, HashMap baseHeaders)
throws HttpException, IOException;
-
- /**
* Return the status code associated with the latest response.
*/
public int getStatusCode();
@@ -184,14 +186,29 @@
public Header getResponseHeader(String headerName);
/**
- * Return <tt>true</tt> if I have been used but not
- * recycled.
+ * Return <tt>true</tt> if I have been {@link #execute executed}
+ * but not recycled.
*/
public boolean hasBeenUsed();
+ // --------------------------------------------------------- Action Methods
+
+ /**
+ * Execute this method.
+ *
+ * @param state state information to associate with this request
+ * @param request the stream to write the request to
+ * @param response the stream to read the response from
+ * @param baseHeaders an intitial set of headers to use
+ *
+ * @return the integer status code if one was obtained, or <tt>-1</tt>
+ */
+ public int execute(State state, HttpConnection connection, Collection
baseHeaders) throws HttpException, IOException;
+
/**
* Recycle this method so that it can be used again.
- * This method clears my path and query string.
+ * All of my instances variables will be reset
+ * once this method has been called.
*/
public void recycle();
}
1.10.2.7 +524 -152
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.10.2.6
retrieving revision 1.10.2.7
diff -u -r1.10.2.6 -r1.10.2.7
--- HttpMethodBase.java 2001/08/13 17:54:27 1.10.2.6
+++ HttpMethodBase.java 2001/08/13 22:37:12 1.10.2.7
@@ -1,7 +1,7 @@
/*
- * $Header:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v
1.10.2.6 2001/08/13 17:54:27 rwaldhoff Exp $
- * $Revision: 1.10.2.6 $
- * $Date: 2001/08/13 17:54:27 $
+ * $Header:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v
1.10.2.7 2001/08/13 22:37:12 rwaldhoff Exp $
+ * $Revision: 1.10.2.7 $
+ * $Date: 2001/08/13 22:37:12 $
* ====================================================================
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
@@ -22,6 +22,7 @@
import java.util.List;
import java.util.Vector;
import java.net.URLEncoder;
+import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
@@ -35,78 +36,140 @@
* <dt>{@link #getName}</dt>
* <dd>to return the approriate name for this method</dd>
* <dt>{@link #getRequestContentLength}</dt>
- * <dd>when the request has a body</dd>
+ * <dd>when the request may have a body</dd>
+ * <dt>{@link #writeRequestBody}</dt>
+ * <dd>when the request may have a body</dd>
* <dt>...</dt>
* </dl>
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]">Remy Maucherat</a>
+ * @author Rodney Waldhoff
+ * @version $Id: HttpMethodBase.java,v 1.10.2.7 2001/08/13 22:37:12 rwaldhoff Exp $
*/
public abstract class HttpMethodBase implements HttpMethod {
- protected String path = null;
- protected boolean followRedirects = false;
- protected HashMap parameters = new HashMap();
- protected String queryString = null;
- protected HashMap requestHeaders = new HashMap();
- protected HashMap responseHeaders = new HashMap();
- protected int statusCode = -1;
- protected String statusText = "Not executed";
- protected boolean used = false;
- protected boolean http11 = true;
- protected boolean bodySent = false;
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * No-arg constructor.
+ */
public HttpMethodBase() {
}
+ /**
+ * Path-specifying constructor.
+ *
+ * @param path my path
+ */
public HttpMethodBase(String path) {
setPath(path);
}
- public abstract String getName();
-
- protected int getRequestContentLength() {
- return 0;
- }
+ // ------------------------------------------- Property Setters and Getters
- protected void writeRequestBody(State state, HttpConnection conn) throws
IOException, HttpException {
- bodySent = true;
- return;
- }
+ /**
+ * Obtain name of this method, suitable for use in the "request line",
+ * for example <tt>GET</tt> or <tt>POST</tt>.
+ * @return the name of this method
+ */
+ public abstract String getName();
+ /**
+ * Set the path part of my request.
+ * @param path the path to request
+ */
public void setPath(String path) {
this.path = path;
}
+ /**
+ * Get the path part my request.
+ * @return the path to request
+ */
public String getPath() {
return this.path;
}
+ /**
+ * Set the specified request header, overwriting any
+ * previous value.
+ * @param headerName the header's name
+ * @param headerValue the header's value
+ */
public void setRequestHeader(String headerName, String headerValue) {
Header header = new Header(headerName, headerValue);
requestHeaders.put(headerName.toLowerCase(),header);
}
+ /**
+ * Set the specified request header, overwriting any
+ * previous value.
+ * @param header the header
+ */
public void setRequestHeader(Header header) {
requestHeaders.put(header.getName().toLowerCase(),header);
}
+ /**
+ * 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
+ */
public Header getRequestHeader(String headerName) {
return (Header)(requestHeaders.get(headerName.toLowerCase()));
}
+ /**
+ * Remove the request header associated with the given name.
+ * Note that header-name matching is case insensitive.
+ * @param headerName the header name
+ * @return the header
+ */
public void removeRequestHeader(String headerName) {
requestHeaders.remove(headerName.toLowerCase());
}
+ /**
+ * Whether or not I should automatically follow
+ * HTTP redirects (status code 302, etc.)
+ */
public boolean followRedirects() {
return this.followRedirects;
}
+ /**
+ * Set whether or not I should automatically follow
+ * HTTP redirects (status code 302, etc.)
+ */
public void setFollowRedirects(boolean followRedirects) {
this.followRedirects = followRedirects;
}
+ /**
+ * Set the specified request (for GET requests, query string)
+ * parameter, overwriting any previous value associated with the
+ * given <i>parameterName</i>.
+ *
+ * @param parameterName the name of the parameter, which MUST NOT
+ * be <tt>null</tt>
+ * @param parameterValue the name of the parameter, which MAY
+ * be <tt>null</tt>
+ */
public void setParameter(String parameterName, String parameterValue) {
parameters.put(parameterName,parameterValue);
}
+ /**
+ * Set the specified request (for GET requests, query string)
+ * parameter, NOT overwriting any previous value associated
+ * with the given <i>parameterName</i>.
+ *
+ * @param parameterName the name of the parameter, which MUST NOT
+ * be <tt>null</tt>
+ * @param parameterValue the name of the parameter, which MAY
+ * be <tt>null</tt>
+ */
public void addParameter(String parameterName, String parameterValue) {
Object old = parameters.put(parameterName,parameterValue);
if(null != old) {
@@ -127,10 +190,26 @@
}
}
+ /**
+ * Remove all request parameters associated with
+ * the given <i>parameterName</i>.
+ *
+ * @param parameterName the name of the parameter, which MUST NOT
+ * be <tt>null</tt>
+ */
public void removeParameter(String paramName) {
parameters.remove(paramName);
}
+ /**
+ * Remove a single instance of the specified name-value pair
+ * from my request parameters
+ *
+ * @param parameterName the name of the parameter, which MUST NOT
+ * be <tt>null</tt>
+ * @param parameterValue the name of the parameter, which MAY
+ * be <tt>null</tt>
+ */
public void removeParameter(String paramName, String paramValue) {
Object old = parameters.get(paramName);
if(null != old) {
@@ -151,59 +230,85 @@
}
}
+ /**
+ * Set my query string.
+ */
public void setQueryString(String queryString) {
this.queryString = queryString;
}
+ /**
+ * Return an iterator over my headers.
+ */
public Iterator getRequestHeaders() {
- return requestHeaders.entrySet().iterator();
+ return requestHeaders.values().iterator();
}
+ // ---------------------------------------------------------------- Queries
+
+ /**
+ * Confirm that I am ready to execute.
+ * <p>
+ * This implementation always returns <tt>true</tt>.
+ * @return <tt>true</tt>
+ */
public boolean validate() {
return true;
}
+ /**
+ * Return the status code associated with the latest response.
+ */
public int getStatusCode() {
return statusCode;
}
+ /**
+ * Return the status text (or "reason phrase") associated with the latest
response.
+ */
public String getStatusText() {
return statusText;
}
+ /**
+ * Return an interator over my response headers.
+ */
public Iterator getResponseHeaders() {
return responseHeaders.entrySet().iterator();
}
+ /**
+ * Return the specified response headers.
+ */
public Header getResponseHeader(String headerName) {
return (Header)(responseHeaders.get(headerName.toLowerCase()));
}
+ /**
+ * Return <tt>true</tt> if I have been {@link #execute executed}
+ * but not recycled.
+ */
public boolean hasBeenUsed() {
return used;
}
- public void recycle() {
- path = null;
- followRedirects = false;
- parameters.clear();
- queryString = null;
- requestHeaders.clear();
- responseHeaders.clear();
- statusCode = -1;
- statusText = "Not executed";
- used = false;
- http11 = false;
- bodySent = false;
- }
+
+ // --------------------------------------------------------- Action Methods
/**
+ * Execute this method.
+ *
* @param state state information to associate with this request
* @param request the stream to write the request to
* @param response the stream to read the response from
* @param baseHeaders an intitial set of headers to use
+ *
+ * @return the integer status code if one was obtained, or <tt>-1</tt>
+ * @throws HttpException if I have been used but not recycled
+ * @throws HttpExcpetion if I am not {@link #validate valid}
+ * @throws NullPointerException if <i>state</i> or <i>connection</i> is
<tt>null</tt>
*/
- public int execute(State state, HttpConnection connection, HashMap baseHeaders)
throws HttpException, IOException {
+ public int execute(State state, HttpConnection connection, Collection
baseHeaders) throws HttpException, IOException {
log.debug("HttpMethodBase.execute(State,HttpConnection,HashMap)");
if(hasBeenUsed()) {
@@ -252,7 +357,7 @@
if(statusCode < HttpStatus.SC_OK) {
if(HttpStatus.SC_CONTINUE == statusCode) {
if(!bodySent) {
- writeRequestBody(state,connection);
+ bodySent = writeRequestBody(state,connection);
} else {
// error? 100 response, but I've already written the body
return statusCode;
@@ -373,48 +478,228 @@
return statusCode;
}
+ // ------------------------------------------------------ Protected Methods
+
+ /**
+ * Writes my request to the given {@link HttpConnection}.
+ * <p>
+ * The request is written according to the following logic:
+ * <ol>
+ * <li>{@link #writeRequestLine} is invoked to write the request line.</li>
+ * <li>{@link #writeRequestHeaders} is invoked to write the associated
headers.</li>
+ * <li><tt>\r\n</tt> is sent to close the head part of the request.</li>
+ * <li>{@link #writeRequestBody} is invoked to write the body part of the
request.</li>
+ * </ol>
+ * Subclasses may want to override one or more of the above methods to
+ * to customize the processing. (Or they may choose to override this method
+ * if dramatically different processing is required.)
+ *
+ * @param state the client state
+ * @param conn the {@link HttpConnection} to write the request to
+ */
protected void writeRequest(State state, HttpConnection conn) throws
IOException, HttpException {
log.debug("HttpMethodBase.writeRequest(State,HttpConnection)");
writeRequestLine(state,conn);
writeRequestHeaders(state,conn);
conn.writeLine(); // close head
- writeRequestBody(state,conn);
+ bodySent = writeRequestBody(state,conn);
}
- protected void readResponse(State state, HttpConnection conn) throws
IOException, HttpException {
- log.debug("HttpMethodBase.readResponse(State,HttpConnection)");
- readStatusLine(state,conn);
- processStatusLine(state,conn);
- readResponseHeaders(state,conn);
- processResponseHeaders(state,conn);
- readResponseBody(state,conn);
- processResponseBody(state,conn);
+
+ /**
+ * Writes the "request line" to the given {@link HttpConnection}.
+ * <p>
+ * Subclasses may want to override this method to
+ * to customize the processing.
+ *
+ * @see #generateRequestLine
+ *
+ * @param state the client state
+ * @param conn the {@link HttpConnection} to write to
+ */
+ protected void writeRequestLine(State state, HttpConnection conn) throws
IOException, HttpException {
+ log.debug("HttpMethodBase.writeRequestLine(State,HttpConnection)");
+ String requestLine = HttpMethodBase.generateRequestLine(conn,
getName(),getPath(),queryString,parameters,(http11 ? "HTTP/1.1" : "HTTP/1.0"));
+ conn.print(requestLine);
}
- protected void processStatusLine(State state, HttpConnection conn) {
+ /**
+ * Writes the request headers to the given {@link HttpConnection}.
+ * <p>
+ * This implementation invokes {@link #generateRequestHeaders},
+ * and then writes each header to the request stream.
+ * <p>
+ * Subclasses may want to override this method to
+ * to customize the processing.
+ *
+ * @see #generateRequestHeaders
+ * @see #getRequestHeaders
+ *
+ * @param state the client state
+ * @param conn the {@link HttpConnection} to write to
+ */
+ protected void writeRequestHeaders(State state, HttpConnection conn) throws
IOException, HttpException {
+ log.debug("HttpMethodBase.writeRequestHeaders(State,HttpConnection)");
+ generateRequestHeaders(state,conn);
+ Iterator it = getRequestHeaders();
+ while(it.hasNext()) {
+ conn.print(it.next().toString());
+ }
}
- protected void processResponseHeaders(State state, HttpConnection conn) {
- // add cookies, if any
- // should we set cookies?
- Header setCookieHeader = getResponseHeader("set-cookie2");
- if(null == setCookieHeader) { //ignore old-style if new is supported
- setCookieHeader = getResponseHeader("set-cookie");
+ /**
+ * Populates the {@link #requestHeaders} map to
+ * with additional {@link Header headers} to be
+ * submitted to the given {@link HttpConnection}.
+ * <p>
+ * This implementation adds <tt>User-Agent</tt>,
+ * <tt>Host</tt>, <tt>Cookie</tt>, <tt>Content-Length</tt>
+ * <tt>Transfer-Encoding</tt>, and <tt>Authorization</tt>
+ * headers, where appropriate.
+ * <p>
+ * Subclasses may want to override this method to
+ * to add additional headers, and may choose to
+ * invoke this implementation (via <tt>super</tt>)
+ * to add the "standard" headers.
+ *
+ * @see #writeRequestHeaders
+ *
+ * @param state the client state
+ * @param conn the {@link HttpConnection} the headers will eventually be
written to
+ */
+ protected void generateRequestHeaders(State state, HttpConnection conn) throws
IOException, HttpException {
+
+ // add default user agent
+ if (!requestHeaders.containsKey("user-agent")) {
+ setRequestHeader(HttpClient.USER_AGENT);
}
- if(setCookieHeader != null) {
- try {
- Cookie[] cookies = Cookie.parse(conn.getHost(), setCookieHeader);
- state.addCookies(cookies);
- } catch (Exception e) {
- log.error("processResponseHeaders(State,HttpConnection)",e);
+ // add host (should do this conditionally?, i.e., don't send to http/1.0?)
+ if (!requestHeaders.containsKey("host")) {
+ setRequestHeader("Host",conn.getHost());
+ }
+
+ // add cookies
+ if (!requestHeaders.containsKey("cookie")) {
+ Vector cookies = state.getCookies();
+ if (cookies != null && cookies.size() > 0) {
+ setRequestHeader(Cookie.createCookieHeader(conn.getHost(),
getPath(), cookies));
+ }
+ }
+
+ // add content length or chunking
+ int len = getRequestContentLength();
+ if(!requestHeaders.containsKey("content-length")) {
+ if(-1 < len) {
+ setRequestHeader("Content-Length",String.valueOf(len));
+ } else if(http11 && len < 0) {
+ // XXX should this be an "add" rather than a "set"?
+ setRequestHeader("Transfer-Encoding","chunked");
}
}
+
+ // add authorization header, if needed
+ if(!requestHeaders.containsKey("authorization")) {
+ Header wwwAuthenticateHeader =
(Header)(responseHeaders.get("www-authenticate"));
+ if(null != wwwAuthenticateHeader) {
+ String challengeResponse =
Authenticator.challengeResponse(wwwAuthenticateHeader.getValue(),state);
+ if (challengeResponse != null) {
+ setRequestHeader("Authorization",challengeResponse);
+ }
+ }
+ }
}
- protected void processResponseBody(State state, HttpConnection conn) {
+ /**
+ * Return the length (in bytes) of
+ * my request body, suitable for use in
+ * a <tt>Content-Length</tt> header.
+ * <p>
+ * Return <tt>-1</tt> when the content-length
+ * is unknown.
+ * <p>
+ * This implementation returns <tt>0</tt>,
+ * indicating that the request has no
+ * body.
+ * @return <tt>0</tt>, indicating that the request has no body.
+ */
+ protected int getRequestContentLength() {
+ return 0;
+ }
+
+ /**
+ * Write the request body to the given {@link HttpConnection}
+ * <p>
+ * If an expectation is required, this method should
+ * ensure that is has been sent by checking the
+ * {@link #getStatusCode status code}.
+ * <p>
+ * This method should return <tt>true</tt>
+ * if the request body was actually sent (or is empty),
+ * or <tt>false</tt> if it could not be sent for
+ * some reason (for example, expectation required but
+ * not present).
+ * <p>
+ * This implementation always returns <tt>true</tt>.
+ * @return <tt>true</tt>
+ */
+ protected boolean writeRequestBody(State state, HttpConnection conn) throws
IOException, HttpException {
+ return true;
}
+ /**
+ * Reads the response from the given {@link HttpConnection}.
+ * <p>
+ * The response is written according to the following logic:
+ * <ol>
+ * <li>{@link #readStatusLine} is invoked to read the request line.</li>
+ * <li>
+ * {@link #processStatusLine} is invoked, allowing the method
+ * to respond to the status line if desired.
+ * </li>
+ * <li>{@link #readResponseHeaders} is invoked to read the associated
headers.</li>
+ * <li>
+ * {@link #processStatusLine} is invoked, allowing the method
+ * to respond to the headers if desired.
+ * </li>
+ * <li>
+ * {@link #readResponseBody} is invoked to read the associated body (if any).
+ * </li>
+ * <li>
+ * {@link #processResponseBody} is invoked, allowing the method
+ * to respond to the body if desired.
+ * </li>
+ * </ol>
+ * Subclasses may want to override one or more of the above methods to
+ * to customize the processing. (Or they may choose to override this method
+ * if dramatically different processing is required.)
+ *
+ * @param state the client state
+ * @param conn the {@link HttpConnection} to read the response from
+ */
+ protected void readResponse(State state, HttpConnection conn) throws
IOException, HttpException {
+ log.debug("HttpMethodBase.readResponse(State,HttpConnection)");
+ readStatusLine(state,conn);
+ processStatusLine(state,conn);
+ readResponseHeaders(state,conn);
+ processResponseHeaders(state,conn);
+ readResponseBody(state,conn);
+ processResponseBody(state,conn);
+ }
+
+ /**
+ * Read the status line from the given {@link HttpConnection},
+ * setting {@link #statusCode} and {@link #statusText}.
+ * <p>
+ * Subclasses may want to override this method to
+ * to customize the processing.
+ *
+ * @see #readResponse
+ * @see #processStatusLine
+ *
+ * @param state the client state
+ * @param conn the {@link HttpConnection} to read the response from
+ */
protected void readStatusLine(State state, HttpConnection conn) throws
IOException, HttpException {
log.debug("HttpMethodBase.readStatusLine(State,HttpConnection)");
statusCode = -1;
@@ -461,6 +746,36 @@
}
}
+ /**
+ * When this method is invoked, the {@link #statusCode}
+ * and {@link #statusText} values will have been set (in other
+ * words, {@link #readStatusLine} will have been invoked).
+ * <p>
+ * Subclasses may want to override this method to respond to these value.
+ * This implementation does nothing.
+ *
+ * @see #readResponse
+ * @see #readStatusLine
+ *
+ * @param state the client state
+ * @param conn the {@link HttpConnection} to read the response from
+ */
+ protected void processStatusLine(State state, HttpConnection conn) {
+ }
+
+ /**
+ * Read response headers from the given {@link HttpConnection},
+ * populating the {@link #responseHeaders} map.
+ * <p>
+ * Subclasses may want to override this method to
+ * to customize the processing.
+ *
+ * @see #readResponse
+ * @see #processResponseHeaders
+ *
+ * @param state the client state
+ * @param conn the {@link HttpConnection} to read the response from
+ */
protected void readResponseHeaders(State state, HttpConnection conn) throws
IOException, HttpException {
log.debug("HttpMethodBase.readResponseHeaders(State,HttpConnection)");
responseHeaders.clear();
@@ -484,10 +799,67 @@
}
}
+ /**
+ * When this method is invoked, the {@link #responseHeaders}
+ * map will have been populated with the response headers
+ * (in other words, {@link #readResponseHeaders} will have
+ * been invoked).
+ * <p>
+ * This implementation will handle the <tt>Set-Cookie</tt>
+ * and <tt>Set-Cookie2</tt> headers, if any, adding the
+ * relevant cookies to the given {@link State}.
+ * <p>
+ * Subclasses may want to override this method to
+ * specially process additional headers, and/or
+ * invoke this method (via <tt>super</tt>) to process
+ * the <tt>Set-Cookie</tt> and <tt>Set-Cookie2</tt> headers.
+ *
+ * @see #readResponse
+ * @see #readResponseHeaders
+ *
+ * @param state the client state
+ * @param conn the {@link HttpConnection} to read the response from
+ */
+ protected void processResponseHeaders(State state, HttpConnection conn) {
+ // add cookies, if any
+ // should we set cookies?
+ Header setCookieHeader = getResponseHeader("set-cookie2");
+ if(null == setCookieHeader) { //ignore old-style if new is supported
+ setCookieHeader = getResponseHeader("set-cookie");
+ }
+
+ if(setCookieHeader != null) {
+ try {
+ Cookie[] cookies = Cookie.parse(conn.getHost(), setCookieHeader);
+ state.addCookies(cookies);
+ } catch (Exception e) {
+ log.error("processResponseHeaders(State,HttpConnection)",e);
+ }
+ }
+ }
+
+
+ /**
+ * Read the response body from the given {@link HttpConnection}.
+ * <p>
+ * The current implementation simply consumes the expected
+ * response body (according to the values of the
+ * <tt>Content-Length</tt> and <tt>Transfer-Encoding</tt>
+ * headers, if any).
+ * <p>
+ * Subclasses may want to override this method to
+ * to customize the processing.
+ *
+ * @see #readResponse
+ * @see #processResponseBody
+ *
+ * @param state the client state
+ * @param conn the {@link HttpConnection} to read the response from
+ */
protected void readResponseBody(State state, HttpConnection conn) throws
IOException, HttpException {
log.debug("HttpMethodBase.readResponseBody(State,HttpConnection)");
- OutputStream out = new ByteArrayOutputStream();
+ //OutputStream out = new ByteArrayOutputStream();
int expectedLength = 0;
int foundLength = 0;
{
@@ -512,12 +884,12 @@
nb = is.read(buffer);
if (nb == -1)
break;
- if (out == null)
- throw new IOException("Unable to buffer data");
+ //if (out == null)
+ // throw new IOException("Unable to buffer data");
if(wireLog.isInfoEnabled()) {
wireLog.info("<< \"" + new String(buffer,0,nb) + "\"");
}
- out.write(buffer, 0, nb);
+ //out.write(buffer, 0, nb);
foundLength += nb;
if(expectedLength > -1) {
if(foundLength == expectedLength) {
@@ -528,33 +900,85 @@
}
}
}
- out.close();
- //is.close();
+ //out.close();
}
- protected void addRequestHeaders(HashMap headers) {
- Iterator iter = headers.keySet().iterator();
- while(iter.hasNext()) {
- Object name = iter.next();
- Object value = headers.get(name);
- Header h = null;
- if(value instanceof Header) {
- h = (Header)value;
- } else {
- h = new Header(String.valueOf(name),String.valueOf(value));
- }
- setRequestHeader(h);
+ /**
+ * When this method is invoked, {@link #readResponseBody} will
+ * have been invoked.
+ * <p>
+ * This implementation does nothing.
+ * <p>
+ * Subclasses may want to override this method.
+ *
+ * @see #readResponse
+ * @see #readResponseBody
+ *
+ * @param state the client state
+ * @param conn the {@link HttpConnection} to read the response from
+ */
+ protected void processResponseBody(State state, HttpConnection conn) {
+ }
+
+ /**
+ * Recycle this method so that it can be used again.
+ * All of my instances variables will be reset
+ * once this method has been called.
+ */
+ public void recycle() {
+ path = null;
+ followRedirects = false;
+ parameters.clear();
+ queryString = null;
+ requestHeaders.clear();
+ responseHeaders.clear();
+ statusCode = -1;
+ statusText = "Not executed";
+ used = false;
+ http11 = false;
+ bodySent = false;
+ }
+
+ // ---------------------------------------------- Protected Utility Methods
+
+ /**
+ * Throws an {@link IllegalStateException} if
+ * {@link #used}.
+ */
+ protected void checkNotUsed() {
+ if(used) {
+ throw new IllegalStateException("Already used.");
}
}
- // override me if you'd like
- protected void writeRequestLine(State state, HttpConnection conn) throws
IOException, HttpException {
- log.debug("HttpMethodBase.writeRequestLine(State,HttpConnection)");
- String requestLine = HttpMethodBase.generateRequestLine(conn,
getName(),getPath(),queryString,parameters,(http11 ? "HTTP/1.1" : "HTTP/1.0"));
- conn.print(requestLine);
+ /**
+ * Throws an {@link IllegalStateException} if
+ * not {@link #used}.
+ */
+ protected void checkUsed() {
+ if(!used) {
+ throw new IllegalStateException("Not Used.");
+ }
}
- // a util method
+ /**
+ * Add the specified {@link Collection} of
+ * {@link Header}s to my set of request headers.
+ */
+ protected void addRequestHeaders(Collection headers) {
+ Iterator iter = headers.iterator();
+ while(iter.hasNext()) {
+ setRequestHeader((Header)(iter.next()));
+ }
+ }
+
+
+ // ------------------------------------------------- Static Utility Methods
+
+ /**
+ * Generate an HTTP/S request line according to
+ * the specified attributes.
+ */
protected static String generateRequestLine(HttpConnection connection, String
name, String path, String queryString, HashMap queryParams, String protocol) {
boolean addedQmark = false;
StringBuffer buf = new StringBuffer();
@@ -610,72 +1034,20 @@
}
}
}
-
- // override me if you'd like
- protected void writeRequestHeaders(State state, HttpConnection conn) throws
IOException, HttpException {
- log.debug("HttpMethodBase.writeRequestHeaders(State,HttpConnection)");
- generateRequestHeaders(state,conn);
- Iterator it = requestHeaders.keySet().iterator();
- while(it.hasNext()) {
- Header header = (Header)(requestHeaders.get(it.next()));
- conn.print(header.toString());
- }
- }
-
- // use me if you'd like
- protected void generateRequestHeaders(State state, HttpConnection conn) throws
IOException, HttpException {
- // add default user agent
- if (!requestHeaders.containsKey("user-agent")) {
- setRequestHeader(HttpClient.USER_AGENT);
- }
+ // ----------------------------------------------------- Instance Variables
- // add host (should do this conditionally?, i.e., don't send to http/1.0?)
- if (!requestHeaders.containsKey("host")) {
- setRequestHeader("Host",conn.getHost());
- }
-
- // add cookies
- if (!requestHeaders.containsKey("cookie")) {
- Vector cookies = state.getCookies();
- if (cookies != null && cookies.size() > 0) {
- setRequestHeader(Cookie.createCookieHeader(conn.getHost(),
getPath(), cookies));
- }
- }
-
- // add content length or chunking
- int len = getRequestContentLength();
- if(!requestHeaders.containsKey("content-length")) {
- if(-1 < len) {
- setRequestHeader("Content-Length",String.valueOf(len));
- } else if(http11 && len < 0) {
- // XXX should this be an "add" rather than a "set"?
- setRequestHeader("Transfer-Encoding","chunked");
- }
- }
-
- // add authorization header, if needed
- if(!requestHeaders.containsKey("authorization")) {
- Header wwwAuthenticateHeader =
(Header)(responseHeaders.get("www-authenticate"));
- if(null != wwwAuthenticateHeader) {
- String challengeResponse =
Authenticator.challengeResponse(wwwAuthenticateHeader.getValue(),state);
- if (challengeResponse != null) {
- setRequestHeader("Authorization",challengeResponse);
- }
- }
- }
- }
-
- protected void checkNotUsed() {
- if(used) {
- throw new IllegalStateException("Already used.");
- }
- }
-
- protected void checkUsed() {
- if(!used) {
- throw new IllegalStateException("Not Used.");
- }
- }
+ protected String path = null;
+ protected boolean followRedirects = false;
+ protected HashMap parameters = new HashMap();
+ protected String queryString = null;
+ protected HashMap requestHeaders = new HashMap();
+ protected HashMap responseHeaders = new HashMap();
+ protected int statusCode = -1;
+ protected String statusText = null;
+ protected boolean used = false;
+ protected boolean http11 = true;
+ protected boolean bodySent = false;
}
+
No revision
No revision
1.3.2.4 +6 -5
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PostMethod.java
Index: PostMethod.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PostMethod.java,v
retrieving revision 1.3.2.3
retrieving revision 1.3.2.4
diff -u -r1.3.2.3 -r1.3.2.4
--- PostMethod.java 2001/08/13 17:38:56 1.3.2.3
+++ PostMethod.java 2001/08/13 22:37:12 1.3.2.4
@@ -1,7 +1,7 @@
/*
- * $Header:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PostMethod.java,v
1.3.2.3 2001/08/13 17:38:56 rwaldhoff Exp $
- * $Revision: 1.3.2.3 $
- * $Date: 2001/08/13 17:38:56 $
+ * $Header:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PostMethod.java,v
1.3.2.4 2001/08/13 22:37:12 rwaldhoff Exp $
+ * $Revision: 1.3.2.4 $
+ * $Date: 2001/08/13 22:37:12 $
* ====================================================================
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
@@ -131,12 +131,13 @@
}
}
- protected void writeRequestBody(State state, HttpConnection conn) throws
IOException, HttpException {
+ protected boolean writeRequestBody(State state, HttpConnection conn) throws
IOException, HttpException {
+ log.debug("PostMethod.writeRequestBody(State,HttpConnection)");
if(null == requestBody) {
requestBody = generateRequestBody(parameters);
}
conn.print(requestBody);
- bodySent = true;
+ return true;
}
protected int getRequestContentLength() {
1.3.2.4 +7 -8
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PutMethod.java
Index: PutMethod.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PutMethod.java,v
retrieving revision 1.3.2.3
retrieving revision 1.3.2.4
diff -u -r1.3.2.3 -r1.3.2.4
--- PutMethod.java 2001/08/13 17:54:27 1.3.2.3
+++ PutMethod.java 2001/08/13 22:37:12 1.3.2.4
@@ -1,7 +1,7 @@
/*
- * $Header:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PutMethod.java,v
1.3.2.3 2001/08/13 17:54:27 rwaldhoff Exp $
- * $Revision: 1.3.2.3 $
- * $Date: 2001/08/13 17:54:27 $
+ * $Header:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PutMethod.java,v
1.3.2.4 2001/08/13 22:37:12 rwaldhoff Exp $
+ * $Revision: 1.3.2.4 $
+ * $Date: 2001/08/13 22:37:12 $
*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
@@ -193,9 +193,9 @@
}
}
- protected void writeRequestBody(State state, HttpConnection conn) throws
IOException, HttpException {
+ protected boolean writeRequestBody(State state, HttpConnection conn) throws
IOException, HttpException {
if(requestHeaders.containsKey("expect") && statusCode !=
HttpStatus.SC_CONTINUE) {
- return;
+ return false;
}
RequestOutputStream out = conn.getRequestOutputStream();
if((http11) && (getRequestHeader("Content-Length") == null)) {
@@ -210,8 +210,7 @@
} else if(data != null){
inputStream = new ByteArrayInputStream(data);
} else {
- bodySent = true;
- return;
+ return true;
}
byte[] buffer = new byte[4096];
@@ -225,7 +224,7 @@
}
inputStream.close();
out.close();
- bodySent = true;
+ return true;
}
protected int getRequestContentLength() {