Index: java/org/apache/commons/httpclient/HttpMethodBase.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v retrieving revision 1.172 diff -u -r1.172 HttpMethodBase.java --- java/org/apache/commons/httpclient/HttpMethodBase.java 22 Jul 2003 18:17:48 -0000 1.172 +++ java/org/apache/commons/httpclient/HttpMethodBase.java 25 Jul 2003 15:24:22 -0000 @@ -207,8 +207,8 @@ /** Whether or not I should automatically process authentication. */ private boolean doAuthentication = true; - /** Whether or not I should use the HTTP/1.1 protocol. The default is true. */ - private boolean http11 = true; + /** Version of the HTTP protocol to be used. */ + private HttpVersion version = HttpVersion.HTTP_1_1; /** True if we're in strict mode. The default is false. */ private boolean strictMode = false; @@ -374,9 +374,15 @@ * Set whether or not I should use the HTTP/1.1 protocol. * * @param http11 true to use HTTP/1.1, false to use 1.0 + * + * @deprecated Use @{link #setHttpVersion(HttpVersion)} */ public void setHttp11(boolean http11) { - this.http11 = http11; + if (http11) { + this.version = HttpVersion.HTTP_1_1; + } else { + this.version = HttpVersion.HTTP_1_0; + } } /** @@ -408,9 +414,11 @@ * HTTP/1.1 protocol. The default is true. * * @return true if I should use the HTTP/1.1 protocol + * + * @deprecated Use {@link #getHttpVersion()} */ public boolean isHttp11() { - return http11; + return this.version.equals(HttpVersion.HTTP_1_1); } /** @@ -905,12 +913,16 @@ } LOG.debug("Resorting to protocol version default close connection policy"); // missing or invalid connection header, do the default - if (http11) { - LOG.debug("Should NOT close connection, using HTTP/1.1."); + if (this.version.greaterEquals(HttpVersion.HTTP_1_1)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Should NOT close connection, using " + this.version.toString()); + } } else { - LOG.debug("Should close connection, using HTTP/1.0."); + if (LOG.isDebugEnabled()) { + LOG.debug("Should close connection, using " + this.version.toString()); + } } - return !http11; + return this.version.lessEquals(HttpVersion.HTTP_1_0); } /** @@ -1267,7 +1279,7 @@ getResponseTrailerHeaderGroup().clear(); statusLine = null; used = false; - http11 = true; + version = HttpVersion.HTTP_1_1; responseBody = null; recoverableExceptionCount = 0; inExecute = false; @@ -1408,7 +1420,7 @@ if (getRequestHeader("content-length") == null) { if (0 < len) { setRequestHeader("Content-Length", String.valueOf(len)); - } else if (http11 && (len < 0)) { + } else if (this.version.greaterEquals(HttpVersion.HTTP_1_1) && (len < 0)) { setRequestHeader("Transfer-Encoding", "chunked"); } } @@ -2113,19 +2125,16 @@ statusLine = new StatusLine(statusString); //check for a valid HTTP-Version - String httpVersion = statusLine.getHttpVersion(); - if (httpVersion.equals("HTTP/1.0")) { - http11 = false; - } else if (httpVersion.equals("HTTP/1.1")) { - http11 = true; - } else if (httpVersion.equals("HTTP")) { - // some servers do not specify the version correctly, we will just assume 1.0 - http11 = false; + String versionStr = statusLine.getHttpVersion(); + if (!this.strictMode && versionStr.equals("HTTP")) { + this.version = HttpVersion.HTTP_1_0; + if (LOG.isWarnEnabled()) { + LOG.warn("Ambiguous status line (HTTP protocol version missing):" + + statusLine.toString()); + } } else { - throw new ProtocolException("Unrecognized server protocol: '" - + httpVersion + "'"); + this.version = HttpVersion.parse(versionStr); } - } // ------------------------------------------------------ Protected Methods @@ -2330,18 +2339,31 @@ */ private String getRequestLine(HttpConnection conn) { return HttpMethodBase.generateRequestLine(conn, getName(), - getPath(), getQueryString(), getHttpVersion()); + getPath(), getQueryString(), getHttpVersion().toString()); } /** - * Get the HTTP version. + * Get the HTTP version to be used with this method. * - * @return HTTP/1.1 if http11, HTTP/1.0 otherwise + * @return HTTP version. * - * @since 2.0 + * @since 2.1 */ - private String getHttpVersion() { - return (http11 ? "HTTP/1.1" : "HTTP/1.0"); + public HttpVersion getHttpVersion() { + return this.version; + } + + /** + * Set the HTTP version to be used with this method. + * + * @since 2.1 + */ + public void setHttpVersion(HttpVersion version) { + if (version == null) { + this.version = HttpVersion.HTTP_1_1; + } else { + this.version = version; + } } /** Index: java/org/apache/commons/httpclient/HttpRecoverableException.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpRecoverableException.java,v retrieving revision 1.9 diff -u -r1.9 HttpRecoverableException.java --- java/org/apache/commons/httpclient/HttpRecoverableException.java 16 Jul 2003 20:48:27 -0000 1.9 +++ java/org/apache/commons/httpclient/HttpRecoverableException.java 25 Jul 2003 15:24:22 -0000 @@ -70,7 +70,7 @@ * Signals that an HTTP or HttpClient exception has occurred. This * exception may have been caused by a transient error and the request * may be retried. It may be possible to retrieve the underlying transient - * error via the inherited {@link TransportException#getCause()} method. + * error via the inherited {@link HttpException#getCause()} method. *
* @author Unascribed * @version $Revision: 1.9 $ $Date: 2003/07/16 20:48:27 $ Index: java/org/apache/commons/httpclient/HttpVersion.java =================================================================== RCS file: java/org/apache/commons/httpclient/HttpVersion.java diff -N java/org/apache/commons/httpclient/HttpVersion.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ java/org/apache/commons/httpclient/HttpVersion.java 25 Jul 2003 15:24:22 -0000 @@ -0,0 +1,267 @@ +/* + * $Header$ + * $Revision$ + * $Date$ + * + * ==================================================================== + * + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999-2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + *HTTP version, as specified in RFC 2616.
+ *+ * HTTP uses a "<major>.<minor>" numbering scheme to indicate versions + * of the protocol. The protocol versioning policy is intended to allow + * the sender to indicate the format of a message and its capacity for + * understanding further HTTP communication, rather than the features + * obtained via that communication. No change is made to the version + * number for the addition of message components which do not affect + * communication behavior or which only add to extensible field values. + * The <minor> number is incremented when the changes made to the + * protocol add features which do not change the general message parsing + * algorithm, but which may add to the message semantics and imply + * additional capabilities of the sender. The <major> number is + * incremented when the format of a message within the protocol is + * changed. See RFC 2145 [36] for a fuller explanation. + *
+ *+ * The version of an HTTP message is indicated by an HTTP-Version field + * in the first line of the message. + *
+ *+ * HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT + *+ *
+ * Note that the major and minor numbers MUST be treated as separate + * integers and that each MAY be incremented higher than a single digit. + * Thus, HTTP/2.4 is a lower version than HTTP/2.13, which in turn is + * lower than HTTP/12.3. Leading zeros MUST be ignored by recipients and + * MUST NOT be sent. + *
+ * + * @author Oleg Kalnichevski + * + * @version $Revision$ $Date$ +* + */ +public class HttpVersion { + + /** Major version number of the HTTP protocol */ + private int major = 0; + + /** Minor version number of the HTTP protocol */ + private int minor = 0; + + /** HTTP protocol version 0.9 */ + public static final HttpVersion HTTP_0_9 = new HttpVersion(0, 9); + + /** HTTP protocol version 1.0 */ + public static final HttpVersion HTTP_1_0 = new HttpVersion(1, 0); + + /** HTTP protocol version 1.1 */ + public static final HttpVersion HTTP_1_1 = new HttpVersion(1, 1); + + /** + * Create an HTTP protocol version designator. + * + * @param major the major version number of the HTTP protocol + * @param minor the minor version number of the HTTP protocol + * + * @throws IllegalArgumentException if either major or minor version number is negative + */ + public HttpVersion(int major, int minor) { + if (major < 0) { + throw new IllegalArgumentException("HTTP major version number may not be negative"); + } + this.major = major; + if (minor < 0) { + throw new IllegalArgumentException("HTTP minor version number may not be negative"); + } + this.minor = minor; + } + + /** + * Returns the major version number of the HTTP protocol. + * + * @return the major version number. + */ + public int getMajor() { + return major; + } + + /** + * Returns the minor version number of the HTTP protocol. + * + * @return the minor version number. + */ + public int getMinor() { + return minor; + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return this.major * 100000 + this.minor; + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof HttpVersion)) { + return false; + } + return equals((HttpVersion)obj); + } + + /** + * Test if the HTTP protocol version is equal to the given number. + * + * @return true if HTTP protocol version is given to the given number, + * false otherwise. + */ + public boolean equals(HttpVersion version) { + if (version == null) { + throw new IllegalArgumentException("Version parameter may not be null"); + } + return (getMajor() == version.getMajor() && getMinor() == version.getMinor()); + } + + /** + * Test if the HTTP protocol version is greater or equal to the given number. + * + * @return true if HTTP protocol version is greater or equal given to the + * given number, false otherwise. + */ + public boolean greaterEquals(HttpVersion version) { + if (version == null) { + throw new IllegalArgumentException("Version parameter may not be null"); + } + int delta = getMajor() - version.getMajor(); + if (delta == 0) { + delta = getMinor() - version.getMinor(); + } + return delta >= 0; + } + + /** + * Test if the HTTP protocol version is less or equal to the given number. + * + * @return true if HTTP protocol version is less or equal to given to the + * given number, false otherwise. + */ + public boolean lessEquals(HttpVersion version) { + int delta = getMajor() - version.getMajor(); + if (delta == 0) { + delta = getMinor() - version.getMinor(); + } + return delta <= 0; + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("HTTP/"); + buffer.append(this.major); + buffer.append('.'); + buffer.append(this.minor); + return buffer.toString(); + } + + /** + * Parses the textual representation of the given HTTP protocol version. + * + * @return HTTP protocol version. + * + * @throws ProtocolException if the string is not a valid HTTP protocol version. + */ + public static HttpVersion parse(final String s) throws ProtocolException { + if (s == null) { + throw new IllegalArgumentException("String may not be null"); + } + if (!s.startsWith("HTTP/")) { + throw new ProtocolException("Invalid HTTP version string: " + s); + } + int major, minor; + + int i1 = "HTTP/".length(); + int i2 = s.indexOf(".", i1); + if (i2 == -1) { + throw new ProtocolException("Invalid HTTP version number: " + s); + } + try { + major = Integer.parseInt(s.substring(i1, i2)); + } catch (NumberFormatException e) { + throw new ProtocolException("Invalid HTTP major version number: " + s); + } + i1 = i2 + 1; + i2 = s.length(); + try { + minor = Integer.parseInt(s.substring(i1, i2)); + } catch (NumberFormatException e) { + throw new ProtocolException("Invalid HTTP minor version number: " + s); + } + return new HttpVersion(major, minor); + } +} Index: java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java,v retrieving revision 1.23 diff -u -r1.23 EntityEnclosingMethod.java --- java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java 17 Jul 2003 21:57:42 -0000 1.23 +++ java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java 25 Jul 2003 15:24:22 -0000 @@ -74,6 +74,7 @@ import org.apache.commons.httpclient.HttpConnection; import org.apache.commons.httpclient.HttpConstants; import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpVersion; import org.apache.commons.httpclient.ProtocolException; import org.apache.commons.httpclient.HttpState; import org.apache.commons.logging.Log; @@ -339,7 +340,8 @@ long len = getRequestContentLength(); if (len >= 0) { addRequestHeader("Content-Length", String.valueOf(len)); - } else if ((len == CONTENT_LENGTH_CHUNKED) && (isHttp11())) { + } else if ((len == CONTENT_LENGTH_CHUNKED) + && (getHttpVersion().greaterEquals(HttpVersion.HTTP_1_1))) { addRequestHeader("Transfer-Encoding", "chunked"); } } @@ -433,7 +435,8 @@ long contentLength = getRequestContentLength(); - if ((contentLength == CONTENT_LENGTH_CHUNKED) && !isHttp11()) { + if ((contentLength == CONTENT_LENGTH_CHUNKED) + && getHttpVersion().lessEquals(HttpVersion.HTTP_1_0)) { throw new ProtocolException( "Chunked transfer encoding not allowed for HTTP/1.0"); } Index: java/org/apache/commons/httpclient/methods/ExpectContinueMethod.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/ExpectContinueMethod.java,v retrieving revision 1.6 diff -u -r1.6 ExpectContinueMethod.java --- java/org/apache/commons/httpclient/methods/ExpectContinueMethod.java 5 Jul 2003 18:43:04 -0000 1.6 +++ java/org/apache/commons/httpclient/methods/ExpectContinueMethod.java 25 Jul 2003 15:24:22 -0000 @@ -68,6 +68,7 @@ import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpMethodBase; import org.apache.commons.httpclient.HttpState; +import org.apache.commons.httpclient.HttpVersion; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -178,7 +179,10 @@ // = HTTP/1.1 or higher // = request body present - if (getUseExpectHeader() && isHttp11() && hasRequestContent()) { + if (getUseExpectHeader() + && getHttpVersion().greaterEquals(HttpVersion.HTTP_1_1) + && hasRequestContent()) + { if (!headerPresent) { setRequestHeader("Expect", "100-continue"); } Index: test/org/apache/commons/httpclient/TestHttpVersion.java =================================================================== RCS file: test/org/apache/commons/httpclient/TestHttpVersion.java diff -N test/org/apache/commons/httpclient/TestHttpVersion.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ test/org/apache/commons/httpclient/TestHttpVersion.java 25 Jul 2003 15:24:22 -0000 @@ -0,0 +1,156 @@ +/* + * $Header$ + * $Revision$ + * $Date$ + * ==================================================================== + * + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999-2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + *