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() {
  
  
  

Reply via email to