Index: java/org/apache/commons/httpclient/HttpClient.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpClient.java,v
retrieving revision 1.79
diff -u -r1.79 HttpClient.java
--- java/org/apache/commons/httpclient/HttpClient.java 16 Jul 2003 20:48:27 -0000 1.79
+++ java/org/apache/commons/httpclient/HttpClient.java 22 Jul 2003 12:32:52 -0000
@@ -98,6 +98,7 @@
private static final Log LOG = LogFactory.getLog(HttpClient.class);
static {
+
if (LOG.isDebugEnabled()) {
LOG.debug("Java version: " + System.getProperty("java.version"));
LOG.debug("Java vendor: " + System.getProperty("java.vendor"));
@@ -319,29 +320,32 @@
throw new IllegalArgumentException("HttpMethod parameter may not be null");
}
- int soTimeout = 0;
- boolean strictMode = false;
- int connectionTimeout = 0;
- long httpConnectionTimeout = 0;
+ if (hostConfiguration == null) {
+ hostConfiguration = (
+ method.getHostConfiguration() != null
+ ? method.getHostConfiguration()
+ : getHostConfiguration()
+ );
+ }
+
HostConfiguration defaultHostConfiguration = null;
+ HttpMethodSession methodSession = new HttpMethodSession();
/* access all synchronized data in a single block, this will keeps us
* from accessing data asynchronously as well having to regain the lock
* for each item.
*/
synchronized (this) {
- soTimeout = this.timeoutInMilliseconds;
- strictMode = this.strictMode;
- connectionTimeout = this.connectionTimeout;
- httpConnectionTimeout = this.httpConnectionTimeout;
- if (state == null) {
- state = getState();
- }
+ methodSession.setSoTimeout(this.timeoutInMilliseconds);
+ methodSession.setStrictMode(this.strictMode);
+ methodSession.setConnectionTimeout(this.connectionTimeout);
+ methodSession.setHttpConnectionFactoryTimeout(this.httpConnectionTimeout);
+ methodSession.setState(state == null ? getState() : state);
+ methodSession.setConnectionManager(this.httpConnectionManager);
defaultHostConfiguration = getHostConfiguration();
}
- HostConfiguration methodConfiguration
- = new HostConfiguration(hostConfiguration);
+ HostConfiguration methodConfiguration = new HostConfiguration(hostConfiguration);
if (hostConfiguration != defaultHostConfiguration) {
// we may need to apply some defaults
@@ -368,41 +372,15 @@
}
}
- HttpConnectionManager connmanager = this.httpConnectionManager;
-
- HttpConnection connection = connmanager.getConnectionWithTimeout(
- methodConfiguration,
- httpConnectionTimeout
- );
-
- try {
- // Catch all possible exceptions to make sure to release the
- // connection, as although the user may call
- // Method->releaseConnection(), the method doesn't know about the
- // connection until HttpMethod.execute() is called.
-
- method.setStrictMode(strictMode);
+ methodSession.setHostConfiguration(methodConfiguration);
+ methodSession.setMethod(method);
- if (!connection.isOpen()) {
- connection.setSoTimeout(soTimeout);
- connection.setConnectionTimeout(connectionTimeout);
- connection.open();
- if (connection.isProxied() && connection.isSecure()) {
- method = new ConnectMethod(method);
- }
- }
- } catch (IOException e) {
- connection.releaseConnection();
- throw e;
- } catch (RuntimeException e) {
- connection.releaseConnection();
- throw e;
- }
+ methodSession.executeMethod();
- return method.execute(state, connection);
+ return methodSession.getMethod().getStatusCode();
}
- /**
+ /**
* Return the host that the client is accessing.
*
* @return The host that the client is accessing, or null if
Index: java/org/apache/commons/httpclient/HttpConnection.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpConnection.java,v
retrieving revision 1.69
diff -u -r1.69 HttpConnection.java
--- java/org/apache/commons/httpclient/HttpConnection.java 16 Jul 2003 20:48:27 -0000 1.69
+++ java/org/apache/commons/httpclient/HttpConnection.java 22 Jul 2003 12:32:55 -0000
@@ -1020,11 +1020,30 @@
// we are assuming that the connection will only be released once used
used = true;
- if (httpConnectionManager != null) {
+
+ if (locked) {
+ LOG.debug("Connection is locked. Call to releaseConnection() ignored.");
+ } else if (httpConnectionManager != null) {
httpConnectionManager.releaseConnection(this);
+ } else {
+ LOG.warn("HttpConnectionManager is null. Connection cannot be released.");
}
}
+ /**
+ * @return
+ */
+ boolean isLocked() {
+ return locked;
+ }
+
+ /**
+ * @param locked
+ */
+ void setLocked(boolean locked) {
+ this.locked = locked;
+ }
+
// ------------------------------------------------------ Protected Methods
/**
@@ -1316,6 +1335,10 @@
/** TCP_NODELAY socket value */
private boolean soNodelay = true;
+
+ /** flag to indicate if this connection can be released, if locked the connection cannot be
+ * released */
+ private boolean locked = false;
/** Whether or not the _socket is a secure one. Note the difference to _ssl */
private boolean usingSecureSocket = false;
Index: java/org/apache/commons/httpclient/HttpMethod.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethod.java,v
retrieving revision 1.23
diff -u -r1.23 HttpMethod.java
--- java/org/apache/commons/httpclient/HttpMethod.java 28 Jan 2003 04:40:20 -0000 1.23
+++ java/org/apache/commons/httpclient/HttpMethod.java 22 Jul 2003 12:32:56 -0000
@@ -271,6 +271,14 @@
Header getResponseHeader(String headerName);
/**
+ * Returns the headers with the given name. Note that header-name matching is
+ * case insensitive.
+ * @param headerName the name of the headers to be returned.
+ * @return an array of zero or more headers
+ */
+ Header[] getResponseHeaders(String headerName);
+
+ /**
* Return an array of my response footers
* @return null if no footers are available
*/
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.170
diff -u -r1.170 HttpMethodBase.java
--- java/org/apache/commons/httpclient/HttpMethodBase.java 19 Jul 2003 09:41:37 -0000 1.170
+++ java/org/apache/commons/httpclient/HttpMethodBase.java 22 Jul 2003 12:33:00 -0000
@@ -68,13 +68,9 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
-import java.util.HashSet;
-import java.util.Set;
import org.apache.commons.httpclient.auth.AuthScheme;
-import org.apache.commons.httpclient.auth.AuthenticationException;
import org.apache.commons.httpclient.auth.HttpAuthenticator;
-import org.apache.commons.httpclient.auth.MalformedChallengeException;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.cookie.CookieSpec;
import org.apache.commons.httpclient.cookie.MalformedCookieException;
@@ -141,9 +137,6 @@
*/
public abstract class HttpMethodBase implements HttpMethod {
- /** Maximum number of redirects and authentications that will be followed */
- private static final int MAX_FORWARDS = 100;
-
// -------------------------------------------------------------- Constants
/** Log object for this class. */
@@ -173,15 +166,9 @@
/** My response trailer headers, if any. */
private HeaderGroup responseTrailerHeaders = new HeaderGroup();
- /** Realms that we tried to authenticate to */
- private Set realms = null;
-
/** Actual authentication realm */
private String realm = null;
- /** Proxy Realms that we tried to authenticate to */
- private Set proxyRealms = null;
-
/** Actual proxy authentication realm */
private String proxyRealm = null;
@@ -226,12 +213,6 @@
*/
private MethodRetryHandler methodRetryHandler;
- /** true if we are currently executing */
- private boolean inExecute = false;
-
- /** true if we are finished with the connection */
- private boolean doneWithConnection = false;
-
/** true if the connection must be closed when no longer needed */
private boolean connectionCloseForced = false;
@@ -578,6 +559,13 @@
}
/**
+ * @see org.apache.commons.httpclient.HttpMethod#getResponseHeaders(java.lang.String)
+ */
+ public Header[] getResponseHeaders(String headerName) {
+ return getResponseHeaderGroup().getHeaders(headerName);
+ }
+
+ /**
* Convenience method top provide access to the status code.
*
* @return the status code associated with the latest response.
@@ -903,48 +891,6 @@
}
/**
- * Return true if a retry is needed.
- * @param statusCode The status code
- * @param state The state.
- * @param conn The connection
- * @return boolean true if a retry is needed.
- */
- private boolean isRetryNeeded(int statusCode, HttpState state, HttpConnection conn) {
- switch (statusCode) {
- case HttpStatus.SC_UNAUTHORIZED:
- case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED:
- LOG.debug("Authorization required");
- if (doAuthentication) { //process authentication response
- //if the authentication is successful, return the statusCode
- //otherwise, drop through the switch and try again.
- if (processAuthenticationResponse(state, conn)) {
- return false;
- }
- } else { //let the client handle the authenticaiton
- return false;
- }
- break;
-
- case HttpStatus.SC_MOVED_TEMPORARILY:
- case HttpStatus.SC_MOVED_PERMANENTLY:
- case HttpStatus.SC_SEE_OTHER:
- case HttpStatus.SC_TEMPORARY_REDIRECT:
- LOG.debug("Redirect required");
-
- if (!processRedirectResponse(conn)) {
- return false;
- }
- break;
-
- default:
- // neither an unauthorized nor a redirect response
- return false;
- } //end of switch
-
- return true;
- }
-
- /**
* Check to see if the this method is ready to be executed.
*
* @param state The state.
@@ -960,15 +906,13 @@
if (conn == null) {
throw new IllegalArgumentException("HttpConnection parameter may not be null");
}
- if (hasBeenUsed()) {
- throw new IllegalStateException("Already used, but not recycled.");
- }
+ // TODO: do we care
+// if (hasBeenUsed()) {
+// throw new IllegalStateException("Already used, but not recycled.");
+// }
if (!validate()) {
throw new ProtocolException("HttpMethodBase object not valid");
}
- if (inExecute) {
- throw new IllegalStateException("Execute invoked recursively, or exited abnormally.");
- }
}
/**
@@ -1004,229 +948,22 @@
this.responseConnection = conn;
checkExecuteConditions(state, conn);
- inExecute = true;
-
- try {
- //pre-emptively add the authorization header, if required.
- if (state.isAuthenticationPreemptive()) {
+ this.statusLine = null;
- LOG.debug("Preemptively sending default basic credentials");
-
- try {
- if (HttpAuthenticator.authenticateDefault(this, conn, state)) {
- LOG.debug("Default basic credentials applied");
- }
- if (conn.isProxied()) {
- if (HttpAuthenticator.authenticateProxyDefault(this, conn, state)) {
- LOG.debug("Default basic proxy credentials applied");
- }
- }
- } catch (AuthenticationException e) {
- // Log error and move on
- LOG.error(e.getMessage(), e);
- }
- }
-
- realms = new HashSet();
- proxyRealms = new HashSet();
- int forwardCount = 0; //protect from an infinite loop
-
- while (forwardCount++ < MAX_FORWARDS) {
- // on every retry, reset this state information.
- conn.setLastResponseInputStream(null);
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("Execute loop try " + forwardCount);
- }
+ conn.setLastResponseInputStream(null);
- // Discard status line
- this.statusLine = null;
-
- //write the request and read the response, will retry
- processRequest(state, conn);
-
- if (!isRetryNeeded(statusLine.getStatusCode(), state, conn)) {
- // nope, no retry needed, exit loop.
- break;
- }
-
- // retry - close previous stream. Caution - this causes
- // responseBodyConsumed to be called, which may also close the
- // connection.
- if (responseStream != null) {
- responseStream.close();
- }
-
- } //end of retry loop
-
- if (forwardCount >= MAX_FORWARDS) {
- LOG.error("Narrowly avoided an infinite loop in execute");
- throw new ProtocolException("Maximum redirects ("
- + MAX_FORWARDS + ") exceeded");
- }
-
- } finally {
- inExecute = false;
- // If the response has been fully processed, return the connection
- // to the pool. Use this flag, rather than other tests (like
- // responseStream == null), as subclasses, might reset the stream,
- // for example, reading the entire response into a file and then
- // setting the file as the stream.
- if (doneWithConnection) {
- ensureConnectionRelease();
- }
- }
+ // TODO: this needs to be exposed
+ boolean requestSent = false;
+ writeRequest(state, conn);
+ requestSent = true;
+ readResponse(state, conn);
+ // the method has successfully executed
+ used = true;
return statusLine.getStatusCode();
}
/**
- * Process the redirect response.
- * @param conn The connection to use.
- * @return boolean true if the redirect was successful.
- */
- private boolean processRedirectResponse(HttpConnection conn) {
-
- if (!getFollowRedirects()) {
- LOG.info("Redirect requested but followRedirects is "
- + "disabled");
- return false;
- }
-
- //get the location header to find out where to redirect to
- Header locationHeader = getResponseHeader("location");
- if (locationHeader == null) {
- // got a redirect response, but no location header
- LOG.error("Received redirect response " + getStatusCode()
- + " but no location header");
- return false;
- }
- String location = locationHeader.getValue();
- if (LOG.isDebugEnabled()) {
- LOG.debug("Redirect requested to location '" + location
- + "'");
- }
-
- //rfc2616 demands the location value be a complete URI
- //Location = "Location" ":" absoluteURI
- URI redirectUri = null;
- URI currentUri = null;
-
- try {
- currentUri = new URI(
- conn.getProtocol().getScheme(),
- null,
- conn.getHost(),
- conn.getPort(),
- this.getPath()
- );
- redirectUri = new URI(location, true);
- if (redirectUri.isRelativeURI()) {
- if (isStrictMode()) {
- LOG.warn("Redirected location '" + location
- + "' is not acceptable in strict mode");
- return false;
- } else {
- //location is incomplete, use current values for defaults
- LOG.debug("Redirect URI is not absolute - parsing as relative");
- redirectUri = new URI(currentUri, redirectUri);
- }
- }
- } catch (URIException e) {
- LOG.warn("Redirected location '" + location + "' is malformed");
- return false;
- }
-
- //check for redirect to a different protocol, host or port
- try {
- checkValidRedirect(currentUri, redirectUri);
- } catch (HttpException ex) {
- //LOG the error and let the client handle the redirect
- LOG.warn(ex.getMessage());
- return false;
- }
-
- //invalidate the list of authentication attempts
- this.realms.clear();
- //remove exisitng authentication headers
- removeRequestHeader(HttpAuthenticator.WWW_AUTH_RESP);
- //update the current location with the redirect location.
- //avoiding use of URL.getPath() and URL.getQuery() to keep
- //jdk1.2 comliance.
- setPath(redirectUri.getEscapedPath());
- setQueryString(redirectUri.getEscapedQuery());
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("Redirecting from '" + currentUri.getEscapedURI()
- + "' to '" + redirectUri.getEscapedURI());
- }
-
- return true;
- }
-
- /**
- * Check for a valid redirect given the current conn and new URI.
- * Redirect to a different protocol, host or port are checked for validity.
- *
- * @param currentUri The current URI (redirecting from)
- * @param redirectUri The new URI to redirect to
- * @throws HttpException if the redirect is invalid
- * @since 2.0
- */
- private static void checkValidRedirect(URI currentUri, URI redirectUri)
- throws HttpException {
- LOG.trace("enter HttpMethodBase.checkValidRedirect(HttpConnection, URL)");
-
- String oldProtocol = currentUri.getScheme();
- String newProtocol = redirectUri.getScheme();
- if (!oldProtocol.equals(newProtocol)) {
- throw new ProtocolException("Redirect from protocol " + oldProtocol
- + " to " + newProtocol + " is not supported");
- }
-
- String oldHost = currentUri.getHost();
- String newHost = redirectUri.getHost();
- if (!oldHost.equalsIgnoreCase(newHost)) {
- // TODO: Add an HttpNotImplementedException or some such?
- throw new ProtocolException("Redirect from host " + oldHost
- + " to " + newHost + " is not supported");
- }
-
- int oldPort = currentUri.getPort();
- if (oldPort < 0) {
- oldPort = getDefaultPort(oldProtocol);
- }
- int newPort = redirectUri.getPort();
- if (newPort < 0) {
- newPort = getDefaultPort(newProtocol);
- }
- if (oldPort != newPort) {
- throw new ProtocolException("Redirect from port " + oldPort
- + " to " + newPort + " is not supported");
- }
- }
-
- /**
- * Returns the default port for the given protocol.
- *
- * @param protocol currently only http and https are recognized
- * @return the default port of the given protocol or -1 if the
- * protocol is not recognized.
- *
- * @since 2.0
- *
- */
- private static int getDefaultPort(String protocol) {
- String proto = protocol.toLowerCase().trim();
- if (proto.equals("http")) {
- return 80;
- } else if (proto.equals("https")) {
- return 443;
- }
- return -1;
- }
-
- /**
* Whether the object has been used and not recycled.
*
* @return true if I have been {@link #execute executed} but not
@@ -1259,8 +996,6 @@
http11 = true;
responseBody = null;
recoverableExceptionCount = 0;
- inExecute = false;
- doneWithConnection = false;
connectionCloseForced = false;
}
@@ -1911,7 +1646,6 @@
"enter HttpMethodBase.readResponseBody(HttpState, HttpConnection)");
// assume we are not done with the connection if we get a stream
- doneWithConnection = false;
InputStream stream = readResponseBody(conn);
if (stream == null) {
// done using the connection!
@@ -2356,109 +2090,8 @@
}
/**
- * process a response that requires authentication
- *
- * @param state the current state
- * @param conn The connection
- *
- * @return true if the request has completed process, false if more
- * attempts are needed
- */
- private boolean processAuthenticationResponse(HttpState state, HttpConnection conn) {
- LOG.trace("enter HttpMethodBase.processAuthenticationResponse("
- + "HttpState, HttpConnection)");
-
- int statusCode = statusLine.getStatusCode();
- // handle authentication required
- Header[] challenges = null;
- Set realmsUsed = null;
- switch (statusCode) {
- case HttpStatus.SC_UNAUTHORIZED:
- challenges = getResponseHeaderGroup().getHeaders(HttpAuthenticator.WWW_AUTH);
- realmsUsed = realms;
- break;
- case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED:
- challenges = getResponseHeaderGroup().getHeaders(HttpAuthenticator.PROXY_AUTH);
- realmsUsed = proxyRealms;
- break;
- }
- boolean authenticated = false;
- // if there was a header requesting authentication
- if (challenges.length > 0) {
- AuthScheme authscheme = null;
- try {
- authscheme = HttpAuthenticator.selectAuthScheme(challenges);
- } catch (MalformedChallengeException e) {
- if (LOG.isErrorEnabled()) {
- LOG.error(e.getMessage(), e);
- }
- return true;
- } catch (UnsupportedOperationException e) {
- if (LOG.isErrorEnabled()) {
- LOG.error(e.getMessage(), e);
- }
- return true;
- }
-
- StringBuffer buffer = new StringBuffer();
- buffer.append(conn.getHost());
- int port = conn.getPort();
- if (conn.getProtocol().getDefaultPort() != port) {
- buffer.append(':');
- buffer.append(port);
- }
- buffer.append('#');
- buffer.append(authscheme.getID());
- String realm = buffer.toString();
-
- if (realmsUsed.contains(realm)) {
- if (LOG.isInfoEnabled()) {
- LOG.info("Already tried to authenticate to \""
- + realm + "\" but still receiving "
- + statusCode + ".");
- }
- return true;
- } else {
- realmsUsed.add(realm);
- }
-
- try {
- //remove preemptive header and reauthenticate
- switch (statusCode) {
- case HttpStatus.SC_UNAUTHORIZED:
- removeRequestHeader(HttpAuthenticator.WWW_AUTH_RESP);
- authenticated = HttpAuthenticator.authenticate(
- authscheme, this, conn, state);
- this.realm = authscheme.getRealm();
- break;
- case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED:
- removeRequestHeader(HttpAuthenticator.PROXY_AUTH_RESP);
- authenticated = HttpAuthenticator.authenticateProxy(
- authscheme, this, conn, state);
- this.proxyRealm = authscheme.getRealm();
- break;
- }
- } catch (AuthenticationException e) {
- LOG.warn(e.getMessage());
- return true; // finished request
- }
- if (!authenticated) {
- // won't be able to authenticate to this challenge
- // without additional information
- LOG.debug("HttpMethodBase.execute(): Server demands "
- + "authentication credentials, but none are "
- + "available, so aborting.");
- } else {
- LOG.debug("HttpMethodBase.execute(): Server demanded "
- + "authentication credentials, will try again.");
- // let's try it again, using the credentials
- }
- }
-
- return !authenticated; // finished processing if we aren't authenticated
- }
-
- /**
+ * @deprecated no longer used
+ *
* Returns proxy authentication realm, if it has been used during authentication process.
* Otherwise returns null.
*
@@ -2469,6 +2102,8 @@
}
/**
+ * @deprecated no longer used
+ *
* Returns authentication realm, if it has been used during authentication process.
* Otherwise returns null.
*
@@ -2479,81 +2114,6 @@
}
/**
- * Write a request and read the response. Both the write to the server will
- * be retried {@link #maxRetries} times if the operation fails with a
- * HttpRecoverableException. The write will only be attempted if the read
- * has succeeded.
- *
- *
- * The used is set to true if the write succeeds.
- *
- *
- * @param state the current state
- * @param connection the connection for communication
- *
- * @throws HttpException when errors occur as part of the HTTP protocol
- * conversation
- * @throws IOException when an I/O error occurs communicating with the
- * server
- *
- * @see #writeRequest(HttpState,HttpConnection)
- * @see #readResponse(HttpState,HttpConnection)
- */
- private void processRequest(HttpState state, HttpConnection connection)
- throws HttpException, IOException {
- LOG.trace("enter HttpMethodBase.processRequest(HttpState, HttpConnection)");
-
- int execCount = 0;
- boolean requestSent = false;
-
- // loop until the method is successfully processed, the retryHandler
- // returns false or a non-recoverable exception is thrown
- while (true) {
- execCount++;
- requestSent = false;
-
- if (LOG.isTraceEnabled()) {
- LOG.trace("Attempt number " + execCount + " to process request");
- }
- try {
- if (!connection.isOpen()) {
- LOG.debug("Opening the connection.");
- connection.open();
- }
- writeRequest(state, connection);
- requestSent = true;
- readResponse(state, connection);
- // the method has successfully executed
- used = true;
- break;
- } catch (HttpRecoverableException httpre) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Closing the connection.");
- }
- connection.close();
- LOG.info("Recoverable exception caught when processing request");
- // update the recoverable exception count.
- recoverableExceptionCount++;
-
- // test if this method should be retried
- if (!getMethodRetryHandler().retryMethod(
- this,
- connection,
- httpre,
- execCount,
- requestSent)
- ) {
- LOG.warn(
- "Recoverable exception caught but MethodRetryHandler.retryMethod() "
- + "returned false, rethrowing exception"
- );
- throw httpre;
- }
- }
- }
- }
-
- /**
* Return the character set from the header.
* @param contentheader The content header.
* @return String The character set.
@@ -2604,6 +2164,8 @@
}
/**
+ * @deprecated no longer used
+ *
* Returns the number of "recoverable" exceptions thrown and handled, to
* allow for monitoring the quality of the connection.
*
@@ -2633,10 +2195,7 @@
responseConnection.close();
}
- doneWithConnection = true;
- if (!inExecute) {
- ensureConnectionRelease();
- }
+ ensureConnectionRelease();
}
/**
Index: java/org/apache/commons/httpclient/HttpMethodSession.java
===================================================================
RCS file: java/org/apache/commons/httpclient/HttpMethodSession.java
diff -N java/org/apache/commons/httpclient/HttpMethodSession.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ java/org/apache/commons/httpclient/HttpMethodSession.java 22 Jul 2003 12:33:02 -0000
@@ -0,0 +1,637 @@
+/*
+ * $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
+ * .
+ *
+ * [Additional notices, if required by prior licensing conditions]
+ *
+ */
+
+package org.apache.commons.httpclient;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.httpclient.auth.AuthScheme;
+import org.apache.commons.httpclient.auth.AuthenticationException;
+import org.apache.commons.httpclient.auth.HttpAuthenticator;
+import org.apache.commons.httpclient.auth.MalformedChallengeException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * @author Michael Becke
+ */
+class HttpMethodSession {
+
+ /** Maximum number of redirects and authentications that will be followed */
+ private static final int MAX_FORWARDS = 100;
+
+ private static final Log LOG = LogFactory.getLog(HttpMethodSession.class);
+
+ private HttpMethod method;
+
+ private HttpState state;
+
+ private HostConfiguration hostConfiguration;
+
+ private HttpConnectionManager connectionManager;
+
+ private HttpConnection connection;
+
+ private int soTimeout;
+
+ private int connectionTimeout;
+
+ private boolean strictMode;
+
+ private long httpConnectionFactoryTimeout;
+
+ /** How many times did this transparently handle a recoverable exception? */
+ private int recoverableExceptionCount = 0;
+
+ /** Realms that we tried to authenticate to */
+ private Set realms = null;
+
+ /** Proxy Realms that we tried to authenticate to */
+ private Set proxyRealms = null;
+
+ /** Actual authentication realm */
+ private String realm = null;
+
+ /** Actual proxy authentication realm */
+ private String proxyRealm = null;
+
+ public void executeMethod() throws IOException, HttpException {
+
+ method.setStrictMode(strictMode);
+
+ try {
+ int forwardCount = 0; //protect from an infinite loop
+
+ while (forwardCount++ < MAX_FORWARDS) {
+ // on every retry, reset this state information.
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Execute loop try " + forwardCount);
+ }
+
+ executeMethodForHost();
+
+ if (!isRetryNeeded()) {
+ // nope, no retry needed, exit loop.
+ break;
+ }
+
+ // retry - close previous stream. Caution - this causes
+ // responseBodyConsumed to be called, which may also close the
+ // connection.
+ if (method.getResponseBodyAsStream() != null) {
+ method.getResponseBodyAsStream().close();
+ }
+
+ } //end of retry loop
+
+ if (forwardCount >= MAX_FORWARDS) {
+ LOG.error("Narrowly avoided an infinite loop in execute");
+ throw new ProtocolException("Maximum redirects ("
+ + MAX_FORWARDS + ") exceeded");
+ }
+
+ } finally {
+ if (connection != null) {
+ connection.setLocked(false);
+ }
+ // If the response has been fully processed, return the connection
+ // to the pool. Use this flag, rather than other tests (like
+ // responseStream == null), as subclasses, might reset the stream,
+ // for example, reading the entire response into a file and then
+ // setting the file as the stream.
+ if (method.getResponseBodyAsStream() == null) {
+ method.releaseConnection();
+ }
+ }
+
+ }
+
+ /**
+ * Executes a method with the current hostConfiguration.
+ *
+ * @throws IOException
+ * @throws HttpException
+ */
+ private void executeMethodForHost() throws IOException, HttpException {
+
+ if (connection != null && !hostConfiguration.hostEquals(connection)) {
+ connection.setLocked(false);
+ connection.releaseConnection();
+ connection = null;
+ }
+ if (connection == null) {
+ connection = connectionManager.getConnectionWithTimeout(
+ hostConfiguration,
+ httpConnectionFactoryTimeout
+ );
+ connection.setLocked(true);
+
+ realms = new HashSet();
+ proxyRealms = new HashSet();
+
+ //pre-emptively add the authorization header, if required.
+ if (state.isAuthenticationPreemptive()) {
+
+ LOG.debug("Preemptively sending default basic credentials");
+
+ try {
+ if (HttpAuthenticator.authenticateDefault(method, connection, state)) {
+ LOG.debug("Default basic credentials applied");
+ }
+ if (connection.isProxied()) {
+ if (HttpAuthenticator.authenticateProxyDefault(method, connection, state)) {
+ LOG.debug("Default basic proxy credentials applied");
+ }
+ }
+ } catch (AuthenticationException e) {
+ // Log error and move on
+ LOG.error(e.getMessage(), e);
+ }
+ }
+
+ }
+
+ try {
+ // Catch all possible exceptions to make sure to release the
+ // connection, as although the user may call
+ // Method->releaseConnection(), the method doesn't know about the
+ // connection until HttpMethod.execute() is called.
+
+ if (!connection.isOpen()) {
+ connection.setSoTimeout(soTimeout);
+ connection.setConnectionTimeout(connectionTimeout);
+ connection.open();
+ if (connection.isProxied() && connection.isSecure()) {
+ executeConnect();
+ }
+ }
+ } catch (IOException e) {
+ connection.releaseConnection();
+ throw e;
+ } catch (RuntimeException e) {
+ connection.releaseConnection();
+ throw e;
+ }
+
+ connection.setLastResponseInputStream(null);
+ executeMethodWithRetry();
+ }
+
+ private void executeMethodWithRetry() throws HttpException, IOException {
+
+ int execCount = 0;
+ // TODO: how do we get requestSent?
+ boolean requestSent = false;
+
+ // loop until the method is successfully processed, the retryHandler
+ // returns false or a non-recoverable exception is thrown
+ while (true) {
+ execCount++;
+ requestSent = false;
+
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Attempt number " + execCount + " to process request");
+ }
+ try {
+ if (!connection.isOpen()) {
+ LOG.debug("Opening the connection.");
+ connection.open();
+ }
+ method.execute(state, connection);
+ break;
+ } catch (HttpRecoverableException httpre) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Closing the connection.");
+ }
+ connection.close();
+ LOG.info("Recoverable exception caught when processing request");
+ // update the recoverable exception count.
+ recoverableExceptionCount++;
+
+ // test if this method should be retried
+ if (!getMethodRetryHandler().retryMethod(
+ method,
+ connection,
+ httpre,
+ execCount,
+ requestSent)
+ ) {
+ LOG.warn(
+ "Recoverable exception caught but MethodRetryHandler.retryMethod() "
+ + "returned false, rethrowing exception"
+ );
+ throw httpre;
+ }
+ }
+ }
+
+ }
+
+ private MethodRetryHandler getMethodRetryHandler() {
+
+ if (method instanceof HttpMethodBase) {
+ return ((HttpMethodBase) method).getMethodRetryHandler();
+ } else {
+ return new DefaultMethodRetryHandler();
+ }
+ }
+
+ private void executeConnect() throws IOException, HttpException {
+ // TODO: implement me
+ }
+
+ /**
+ * Process the redirect response.
+ * @return boolean true if the redirect was successful.
+ */
+ private boolean processRedirectResponse() {
+
+ if (!method.getFollowRedirects()) {
+ LOG.info("Redirect requested but followRedirects is "
+ + "disabled");
+ return false;
+ }
+
+ //get the location header to find out where to redirect to
+ Header locationHeader = method.getResponseHeader("location");
+ if (locationHeader == null) {
+ // got a redirect response, but no location header
+ LOG.error("Received redirect response " + method.getStatusCode()
+ + " but no location header");
+ return false;
+ }
+ String location = locationHeader.getValue();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Redirect requested to location '" + location
+ + "'");
+ }
+
+ //rfc2616 demands the location value be a complete URI
+ //Location = "Location" ":" absoluteURI
+ URI redirectUri = null;
+ URI currentUri = null;
+
+ try {
+ currentUri = new URI(
+ connection.getProtocol().getScheme(),
+ null,
+ connection.getHost(),
+ connection.getPort(),
+ method.getPath()
+ );
+ redirectUri = new URI(location, true);
+ if (redirectUri.isRelativeURI()) {
+ if (method.isStrictMode()) {
+ LOG.warn("Redirected location '" + location
+ + "' is not acceptable in strict mode");
+ return false;
+ } else {
+ //location is incomplete, use current values for defaults
+ LOG.debug("Redirect URI is not absolute - parsing as relative");
+ redirectUri = new URI(currentUri, redirectUri);
+ }
+ }
+ } catch (URIException e) {
+ LOG.warn("Redirected location '" + location + "' is malformed");
+ return false;
+ }
+
+ //invalidate the list of authentication attempts
+ this.realms.clear();
+ //remove exisitng authentication headers
+ method.removeRequestHeader(HttpAuthenticator.WWW_AUTH_RESP);
+ //update the current location with the redirect location.
+ //avoiding use of URL.getPath() and URL.getQuery() to keep
+ //jdk1.2 comliance.
+ method.setPath(redirectUri.getEscapedPath());
+ method.setQueryString(redirectUri.getEscapedQuery());
+ hostConfiguration.setHost(redirectUri);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Redirecting from '" + currentUri.getEscapedURI()
+ + "' to '" + redirectUri.getEscapedURI());
+ }
+
+ return true;
+ }
+
+ /**
+ * process a response that requires authentication
+ *
+ * @param state the current state
+ * @param conn The connection
+ *
+ * @return true if the request has completed process, false if more
+ * attempts are needed
+ */
+ private boolean processAuthenticationResponse(HttpState state, HttpConnection conn) {
+ LOG.trace("enter HttpMethodBase.processAuthenticationResponse("
+ + "HttpState, HttpConnection)");
+
+ int statusCode = method.getStatusCode();
+ // handle authentication required
+ Header[] challenges = null;
+ Set realmsUsed = null;
+ switch (statusCode) {
+ case HttpStatus.SC_UNAUTHORIZED:
+ challenges = method.getResponseHeaders(HttpAuthenticator.WWW_AUTH);
+ realmsUsed = realms;
+ break;
+ case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED:
+ challenges = method.getResponseHeaders(HttpAuthenticator.PROXY_AUTH);
+ realmsUsed = proxyRealms;
+ break;
+ }
+ boolean authenticated = false;
+ // if there was a header requesting authentication
+ if (challenges.length > 0) {
+ AuthScheme authscheme = null;
+ try {
+ authscheme = HttpAuthenticator.selectAuthScheme(challenges);
+ } catch (MalformedChallengeException e) {
+ if (LOG.isErrorEnabled()) {
+ LOG.error(e.getMessage(), e);
+ }
+ return true;
+ } catch (UnsupportedOperationException e) {
+ if (LOG.isErrorEnabled()) {
+ LOG.error(e.getMessage(), e);
+ }
+ return true;
+ }
+
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(conn.getHost());
+ int port = conn.getPort();
+ if (conn.getProtocol().getDefaultPort() != port) {
+ buffer.append(':');
+ buffer.append(port);
+ }
+ buffer.append('#');
+ buffer.append(authscheme.getID());
+ String realm = buffer.toString();
+
+ if (realmsUsed.contains(realm)) {
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Already tried to authenticate to \""
+ + realm + "\" but still receiving "
+ + statusCode + ".");
+ }
+ return true;
+ } else {
+ realmsUsed.add(realm);
+ }
+
+ try {
+ //remove preemptive header and reauthenticate
+ switch (statusCode) {
+ case HttpStatus.SC_UNAUTHORIZED:
+ method.removeRequestHeader(HttpAuthenticator.WWW_AUTH_RESP);
+ authenticated = HttpAuthenticator.authenticate(
+ authscheme, method, conn, state);
+ this.realm = authscheme.getRealm();
+ break;
+ case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED:
+ method.removeRequestHeader(HttpAuthenticator.PROXY_AUTH_RESP);
+ authenticated = HttpAuthenticator.authenticateProxy(
+ authscheme, method, conn, state);
+ this.proxyRealm = authscheme.getRealm();
+ break;
+ }
+ } catch (AuthenticationException e) {
+ LOG.warn(e.getMessage());
+ return true; // finished request
+ }
+ if (!authenticated) {
+ // won't be able to authenticate to this challenge
+ // without additional information
+ LOG.debug("HttpMethodBase.execute(): Server demands "
+ + "authentication credentials, but none are "
+ + "available, so aborting.");
+ } else {
+ LOG.debug("HttpMethodBase.execute(): Server demanded "
+ + "authentication credentials, will try again.");
+ // let's try it again, using the credentials
+ }
+ }
+
+ return !authenticated; // finished processing if we aren't authenticated
+ }
+
+ /**
+ * Return true if a retry is needed.
+ * @param statusCode The status code
+ * @param state The state.
+ * @param conn The connection
+ * @return boolean true if a retry is needed.
+ */
+ private boolean isRetryNeeded() {
+ switch (method.getStatusCode()) {
+ case HttpStatus.SC_UNAUTHORIZED:
+ case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED:
+ LOG.debug("Authorization required");
+ if (method.getDoAuthentication()) { //process authentication response
+ //if the authentication is successful, return the statusCode
+ //otherwise, drop through the switch and try again.
+ if (processAuthenticationResponse(state, connection)) {
+ return false;
+ }
+ } else { //let the client handle the authenticaiton
+ return false;
+ }
+ break;
+
+ case HttpStatus.SC_MOVED_TEMPORARILY:
+ case HttpStatus.SC_MOVED_PERMANENTLY:
+ case HttpStatus.SC_SEE_OTHER:
+ case HttpStatus.SC_TEMPORARY_REDIRECT:
+ LOG.debug("Redirect required");
+
+ if (!processRedirectResponse()) {
+ return false;
+ }
+ break;
+
+ default:
+ // neither an unauthorized nor a redirect response
+ return false;
+ } //end of switch
+
+ return true;
+ }
+
+ /**
+ * @return
+ */
+ public HostConfiguration getHostConfiguration() {
+ return hostConfiguration;
+ }
+
+ /**
+ * @param hostConfiguration
+ */
+ public void setHostConfiguration(HostConfiguration hostConfiguration) {
+ this.hostConfiguration = hostConfiguration;
+ }
+
+ /**
+ * @return
+ */
+ public HttpMethod getMethod() {
+ return method;
+ }
+
+ /**
+ * @param method
+ */
+ public void setMethod(HttpMethod method) {
+ this.method = method;
+ }
+
+ /**
+ * @return
+ */
+ public HttpState getState() {
+ return state;
+ }
+
+ /**
+ * @param state
+ */
+ public void setState(HttpState state) {
+ this.state = state;
+ }
+
+ /**
+ * @return
+ */
+ public HttpConnectionManager getConnectionManager() {
+ return connectionManager;
+ }
+
+ /**
+ * @param connectionManager
+ */
+ public void setConnectionManager(HttpConnectionManager connectionManager) {
+ this.connectionManager = connectionManager;
+ }
+
+ /**
+ * @return
+ */
+ public int getConnectionTimeout() {
+ return connectionTimeout;
+ }
+
+ /**
+ * @param connectionTimeout
+ */
+ public void setConnectionTimeout(int connectionTimeout) {
+ this.connectionTimeout = connectionTimeout;
+ }
+
+ /**
+ * @return
+ */
+ public long getHttpConnectionFactoryTimeout() {
+ return httpConnectionFactoryTimeout;
+ }
+
+ /**
+ * @param httpConnectionFactoryTimeout
+ */
+ public void setHttpConnectionFactoryTimeout(long httpConnectionTimeout) {
+ this.httpConnectionFactoryTimeout = httpConnectionTimeout;
+ }
+
+ /**
+ * @return
+ */
+ public int getSoTimeout() {
+ return soTimeout;
+ }
+
+ /**
+ * @param soTimeout
+ */
+ public void setSoTimeout(int soTimeout) {
+ this.soTimeout = soTimeout;
+ }
+
+ /**
+ * @return
+ */
+ public boolean isStrictMode() {
+ return strictMode;
+ }
+
+ /**
+ * @param strictMode
+ */
+ public void setStrictMode(boolean strictMode) {
+ this.strictMode = strictMode;
+ }
+
+}
Index: test/org/apache/commons/httpclient/NoHostHttpConnectionManager.java
===================================================================
RCS file: test/org/apache/commons/httpclient/NoHostHttpConnectionManager.java
diff -N test/org/apache/commons/httpclient/NoHostHttpConnectionManager.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ test/org/apache/commons/httpclient/NoHostHttpConnectionManager.java 22 Jul 2003 12:33:04 -0000
@@ -0,0 +1,77 @@
+/*
+ * Created on Jul 21, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+package org.apache.commons.httpclient;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @author mbecke
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class NoHostHttpConnectionManager implements HttpConnectionManager {
+
+ private HttpConnection connection;
+
+ public NoHostHttpConnectionManager() {
+ this.connection = new SimpleHttpConnection();
+ }
+
+ /**
+ * @param connection
+ */
+ public void setConnection(HttpConnection connection) {
+ this.connection = connection;
+ }
+
+ public HttpConnection getConnection(HostConfiguration hostConfiguration) {
+ return connection;
+ }
+
+ public HttpConnection getConnection(HostConfiguration hostConfiguration, long timeout)
+ throws HttpException {
+ return connection;
+ }
+
+ public HttpConnection getConnectionWithTimeout(
+ HostConfiguration hostConfiguration,
+ long timeout)
+ throws ConnectTimeoutException {
+ return connection;
+ }
+
+ public void releaseConnection(HttpConnection conn) {
+ if (conn != connection) {
+ throw new IllegalStateException("Unexpected close on a different connection.");
+ }
+
+ finishLastResponse(connection);
+ }
+
+ /**
+ * Since the same connection is about to be reused, make sure the
+ * previous request was completely processed, and if not
+ * consume it now.
+ * @param conn The connection
+ */
+ static void finishLastResponse(HttpConnection conn) {
+ InputStream lastResponse = conn.getLastResponseInputStream();
+ if (lastResponse != null) {
+ conn.setLastResponseInputStream(null);
+ try {
+ lastResponse.close();
+ } catch (IOException ioe) {
+ //FIXME: badness - close to force reconnect.
+ conn.close();
+ }
+ }
+ }
+
+
+}
Index: test/org/apache/commons/httpclient/TestAuthenticator.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestAuthenticator.java,v
retrieving revision 1.26
diff -u -r1.26 TestAuthenticator.java
--- test/org/apache/commons/httpclient/TestAuthenticator.java 5 Jul 2003 22:31:21 -0000 1.26
+++ test/org/apache/commons/httpclient/TestAuthenticator.java 22 Jul 2003 12:33:07 -0000
@@ -78,7 +78,7 @@
* @author Jeff Dever
* @version $Id: TestAuthenticator.java,v 1.26 2003/07/05 22:31:21 olegk Exp $
*/
-public class TestAuthenticator extends TestCase {
+public class TestAuthenticator extends TestNoHostBase {
// ------------------------------------------------------------ Constructor
public TestAuthenticator(String testName) {
@@ -487,10 +487,8 @@
public void testNTLMAuthenticationRetry() throws Exception {
NTCredentials cred = new NTCredentials("username", "password", "host", "domain");
- HttpState state = new HttpState();
- state.setCredentials(null, null, cred);
+ client.getState().setCredentials(null, null, cred);
HttpMethod method = new SimpleHttpMethod();
- SimpleHttpConnection conn = new SimpleHttpConnection();
conn.addResponse(
"HTTP/1.1 401 Unauthorized\r\n" +
"WWW-Authenticate: NTLM\r\n" +
@@ -506,7 +504,7 @@
"Connection: close\r\n" +
"Server: HttpClient Test/2.0\r\n\r\n" +
"stuff\r\n");
- method.execute(state, conn);
+ client.executeMethod(method);
assertNull(method.getResponseHeader("WWW-Authenticate"));
assertEquals(200, method.getStatusCode());
}
@@ -515,12 +513,10 @@
* Test that the Unauthorized response is returned when doAuthentication is false.
*/
public void testDoAuthenticateFalse() throws Exception {
- HttpState state = new HttpState();
- state.setCredentials(null, "Protected",
+ client.getState().setCredentials(null, "Protected",
new UsernamePasswordCredentials("name", "pass"));
HttpMethod method = new SimpleHttpMethod();
method.setDoAuthentication(false);
- SimpleHttpConnection conn = new SimpleHttpConnection();
conn.addResponse(
"HTTP/1.1 401 Unauthorized\r\n" +
"WWW-Authenticate: Basic realm=\"Protected\"\r\n" +
@@ -530,7 +526,7 @@
"HTTP/1.1 200 OK\r\n" +
"Connection: close\r\n" +
"Server: HttpClient Test/2.0\r\n");
- method.execute(state, conn);
+ client.executeMethod(method);
assertNotNull(method.getResponseHeader("WWW-Authenticate"));
assertNull(method.getRequestHeader("Authorization"));
assertEquals(401, method.getStatusCode());
@@ -541,18 +537,16 @@
/**
*/
public void testInvalidCredentials() throws Exception {
- HttpState state = new HttpState();
- state.setCredentials(null, "Protected", new UsernamePasswordCredentials("name", "pass"));
+ client.getState().setCredentials(null, "Protected", new UsernamePasswordCredentials("name", "pass"));
HttpMethod method = new SimpleHttpMethod();
method.setDoAuthentication(false);
- SimpleHttpConnection conn = new SimpleHttpConnection();
conn.addResponse(
"HTTP/1.1 401 Unauthorized\r\n" +
"WWW-Authenticate: Basic realm=\"Protected\"\r\n" +
"Connection: close\r\n" +
"Server: HttpClient Test/2.0\r\n"
);
- method.execute(state, conn);
+ client.executeMethod(method);
assertEquals(401, method.getStatusCode());
}
@@ -560,10 +554,8 @@
// --------------------------------- Test Methods for Multiple Authentication
public void testMultipleChallengeBasic() throws Exception {
- HttpState state = new HttpState();
- state.setCredentials("Protected", null, new UsernamePasswordCredentials("name", "pass"));
+ client.getState().setCredentials("Protected", null, new UsernamePasswordCredentials("name", "pass"));
HttpMethod method = new SimpleHttpMethod();
- SimpleHttpConnection conn = new SimpleHttpConnection();
conn.addResponse(
"HTTP/1.1 401 Unauthorized\r\n" +
"WWW-Authenticate: Unsupported\r\n" +
@@ -575,8 +567,8 @@
"HTTP/1.1 200 OK\r\n" +
"Connection: close\r\n" +
"Server: HttpClient Test/2.0\r\n"
- );
- method.execute(state, conn);
+ );
+ client.executeMethod(method);
Header authHeader = method.getRequestHeader("Authorization");
assertNotNull(authHeader);
@@ -585,10 +577,8 @@
}
public void testMultipleChallengeBasicLongRealm() throws Exception {
- HttpState state = new HttpState();
- state.setCredentials(null, null, new UsernamePasswordCredentials("name", "pass"));
+ client.getState().setCredentials(null, null, new UsernamePasswordCredentials("name", "pass"));
HttpMethod method = new SimpleHttpMethod();
- SimpleHttpConnection conn = new SimpleHttpConnection();
conn.addResponse(
"HTTP/1.1 401 Unauthorized\r\n" +
"WWW-Authenticate: Unsupported\r\n" +
@@ -601,7 +591,7 @@
"Connection: close\r\n" +
"Server: HttpClient Test/2.0\r\n"
);
- method.execute(state, conn);
+ client.executeMethod(method);
Header authHeader = method.getRequestHeader("Authorization");
assertNotNull(authHeader);
@@ -613,10 +603,8 @@
public void testMultipleChallengeDigest() throws Exception {
- HttpState state = new HttpState();
- state.setCredentials("Protected", null, new UsernamePasswordCredentials("name", "pass"));
+ client.getState().setCredentials("Protected", null, new UsernamePasswordCredentials("name", "pass"));
HttpMethod method = new SimpleHttpMethod();
- SimpleHttpConnection conn = new SimpleHttpConnection();
conn.addResponse(
"HTTP/1.1 401 Unauthorized\r\n" +
"WWW-Authenticate: Unsupported\r\n" +
@@ -630,7 +618,7 @@
"Connection: close\r\n" +
"Server: HttpClient Test/2.0\r\n"
);
- method.execute(state, conn);
+ client.executeMethod(method);
Header authHeader = method.getRequestHeader("Authorization");
assertNotNull(authHeader);
@@ -640,10 +628,8 @@
public void testMultipleProxyChallengeBasic() throws Exception {
- HttpState state = new HttpState();
- state.setProxyCredentials("Protected", null, new UsernamePasswordCredentials("name", "pass"));
+ client.getState().setProxyCredentials("Protected", null, new UsernamePasswordCredentials("name", "pass"));
HttpMethod method = new SimpleHttpMethod();
- SimpleHttpConnection conn = new SimpleHttpConnection();
conn.addResponse(
"HTTP/1.1 407 Proxy Authentication Required\r\n" +
"Proxy-Authenticate: Basic realm=\"Protected\"\r\n" +
@@ -656,7 +642,7 @@
"Connection: close\r\n" +
"Server: HttpClient Test/2.0\r\n"
);
- method.execute(state, conn);
+ client.executeMethod(method);
Header authHeader = method.getRequestHeader("Proxy-Authorization");
assertNotNull(authHeader);
@@ -666,10 +652,8 @@
public void testMultipleProxyChallengeDigest() throws Exception {
- HttpState state = new HttpState();
- state.setProxyCredentials("Protected", null, new UsernamePasswordCredentials("name", "pass"));
+ client.getState().setProxyCredentials("Protected", null, new UsernamePasswordCredentials("name", "pass"));
HttpMethod method = new SimpleHttpMethod();
- SimpleHttpConnection conn = new SimpleHttpConnection();
conn.addResponse(
"HTTP/1.1 407 Proxy Authentication Required\r\n" +
"Proxy-Authenticate: Basic realm=\"Protected\"\r\n" +
@@ -683,7 +667,7 @@
"Connection: close\r\n" +
"Server: HttpClient Test/2.0\r\n"
);
- method.execute(state, conn);
+ client.executeMethod(method);
Header authHeader = method.getRequestHeader("Proxy-Authorization");
assertNotNull(authHeader);
Index: test/org/apache/commons/httpclient/TestHttpConnectionManager.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestHttpConnectionManager.java,v
retrieving revision 1.9
diff -u -r1.9 TestHttpConnectionManager.java
--- test/org/apache/commons/httpclient/TestHttpConnectionManager.java 16 Jul 2003 20:48:28 -0000 1.9
+++ test/org/apache/commons/httpclient/TestHttpConnectionManager.java 22 Jul 2003 12:33:08 -0000
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestHttpConnectionManager.java,v 1.9 2003/07/16 20:48:28 olegk Exp $
- * $Revision: 1.9 $
- * $Date: 2003/07/16 20:48:28 $
+ * $Header: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestHttpConnectionManager.java,v 1.8 2003/04/28 23:19:58 mbecke Exp $
+ * $Revision: 1.8 $
+ * $Date: 2003/04/28 23:19:58 $
* ====================================================================
*
* The Apache Software License, Version 1.1
@@ -73,7 +73,7 @@
* Unit tests for {@link HttpConnectionManager}.
*
* @author Marc A. Saegesser
- * @version $Id: TestHttpConnectionManager.java,v 1.9 2003/07/16 20:48:28 olegk Exp $
+ * @version $Id: TestHttpConnectionManager.java,v 1.8 2003/04/28 23:19:58 mbecke Exp $
*/
public class TestHttpConnectionManager extends TestLocalHostBase {
@@ -128,7 +128,7 @@
HttpConnection connection = mgr.getConnection(hostConfiguration);
ConnectMethod connect = new ConnectMethod(get);
assertTrue(connect.execute(new HttpState(), connection) != 200);
- } catch (Exception e) {
+ } catch (IOException e) {
e.printStackTrace();
fail("Error executing connect: " + e);
}
@@ -137,7 +137,7 @@
try {
get.releaseConnection();
mgr.getConnectionWithTimeout(hostConfiguration, 1).releaseConnection();
- } catch (Exception e1) {
+ } catch (ConnectTimeoutException e1) {
fail("Connection should have been available.");
}
@@ -147,7 +147,7 @@
HttpConnection connection = mgr.getConnection(hostConfiguration);
ConnectMethod connect = new ConnectMethod(get);
assertTrue(connect.execute(new HttpState(), connection) != 200);
- } catch (Exception e) {
+ } catch (IOException e) {
e.printStackTrace();
fail("Error executing connect: " + e);
}
@@ -166,7 +166,7 @@
HttpConnection connection = mgr.getConnection(hostConfiguration);
ConnectMethod connect = new ConnectMethod(get);
assertTrue(connect.execute(new HttpState(), connection) != 200);
- } catch (Exception e) {
+ } catch (IOException e) {
e.printStackTrace();
fail("Error executing connect: " + e);
}
@@ -224,7 +224,7 @@
HttpClient client = createHttpClient(connectionManager);
// we shouldn't have to wait if a connection is available
- client.setHttpConnectionFactoryTimeout( 1 );
+ client.setHttpConnectionFactoryTimeout(1);
GetMethod getMethod = new GetMethod("/");
@@ -242,6 +242,7 @@
} catch (HttpException e) {
fail("error reading from server; " + e);
} catch (IOException e) {
+ e.printStackTrace();
fail("error reading from server; " + e);
}
Index: test/org/apache/commons/httpclient/TestMethodsNoHost.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestMethodsNoHost.java,v
retrieving revision 1.19
diff -u -r1.19 TestMethodsNoHost.java
--- test/org/apache/commons/httpclient/TestMethodsNoHost.java 19 Jun 2003 20:52:07 -0000 1.19
+++ test/org/apache/commons/httpclient/TestMethodsNoHost.java 22 Jul 2003 12:33:10 -0000
@@ -67,11 +67,11 @@
import java.io.Reader;
import junit.framework.Test;
-import junit.framework.TestCase;
import junit.framework.TestSuite;
+
import org.apache.commons.httpclient.methods.GetMethod;
-import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.HeadMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
/**
* @author Rodney Waldhoff
@@ -80,7 +80,7 @@
* @author Oleg Kalnichevski
* @version $Revision: 1.19 $ $Date: 2003/06/19 20:52:07 $
*/
-public class TestMethodsNoHost extends TestCase {
+public class TestMethodsNoHost extends TestNoHostBase {
static final String NAME = "name", VALUE = "value";
static final String NAME0 = "name0", VALUE0 = "value0";
@@ -186,7 +186,6 @@
}
public void testConnectionAutoClose() throws Exception {
- SimpleHttpConnection conn = new SimpleHttpConnection();
String headers = "HTTP/1.1 200 OK\r\n"
+"Date: Wed, 28 Mar 2001 05:05:04 GMT\r\n"
+"Connection: close\r\n";
@@ -199,7 +198,7 @@
conn.addResponse(headers, body);
conn.open();
HttpMethodBase method = new GetMethod("/");
- method.execute(new HttpState(), conn);
+ client.executeMethod(method);
Reader response = new InputStreamReader(method.getResponseBodyAsStream());
int c;
while ((c = response.read()) != -1) {
@@ -214,7 +213,7 @@
conn.addResponse(headers, "");
try {
- headMethod.execute(new HttpState(), conn);
+ client.executeMethod(headMethod);
conn.assertNotOpen();
} catch (Throwable t) {
@@ -250,7 +249,6 @@
* Make sure that its OK to call releaseConnection if the connection has not been.
*/
public void testReleaseConnection() {
- HttpClient client = new HttpClient();
HttpMethod method = new GetMethod("http://bogus.url/path/");
method.releaseConnection();
}
Index: test/org/apache/commons/httpclient/TestMethodsRedirectNoHost.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestMethodsRedirectNoHost.java,v
retrieving revision 1.6
diff -u -r1.6 TestMethodsRedirectNoHost.java
--- test/org/apache/commons/httpclient/TestMethodsRedirectNoHost.java 20 Apr 2003 23:26:23 -0000 1.6
+++ test/org/apache/commons/httpclient/TestMethodsRedirectNoHost.java 22 Jul 2003 12:33:11 -0000
@@ -63,21 +63,17 @@
package org.apache.commons.httpclient;
import junit.framework.Test;
-import junit.framework.TestCase;
import junit.framework.TestSuite;
-import org.apache.commons.httpclient.methods.*;
+import org.apache.commons.httpclient.methods.PostMethod;
/**
* @author Jeff Dever
* @version $Revision: 1.6 $
*/
-public class TestMethodsRedirectNoHost extends TestCase {
+public class TestMethodsRedirectNoHost extends TestNoHostBase {
- SimpleHttpConnection conn;
-
-
// ------------------------------------------------------------ Constructor
public TestMethodsRedirectNoHost(String testName) {
@@ -90,11 +86,6 @@
return new TestSuite(TestMethodsRedirectNoHost.class);
}
- public void setUp() throws Exception{
- conn = new SimpleHttpConnection();
- }
-
-
private void addRedirectResponse(String location) {
String headers = "HTTP/1.1 302 Redirect\r\n"
+"Date: Wed, 28 Mar 2002 05:05:04 GMT\r\n"
@@ -118,9 +109,9 @@
addOkResponse();
conn.open();
- HttpMethod method = new SimpleHttpMethod("/oldfile");
+ HttpMethod method = new SimpleHttpMethod("http://localhost/oldfile");
method.setFollowRedirects(true);
- method.execute(new HttpState(), conn);
+ client.executeMethod(method);
Header locationHeader = method.getResponseHeader("Location");
assertEquals(200, method.getStatusCode());
assertEquals("/newfile", method.getPath());
@@ -135,7 +126,7 @@
HttpMethod method = new SimpleHttpMethod("/oldfile");
method.setFollowRedirects(true);
- method.execute(new HttpState(), conn);
+ client.executeMethod(method);
Header locationHeader = method.getResponseHeader("Location");
assertEquals(200, method.getStatusCode());
assertEquals("/newfile", method.getPath());
@@ -150,7 +141,7 @@
PostMethod method = new PostMethod("/oldfile");
method.setRequestBody(new NameValuePair[] { new NameValuePair("name", "value") } );
- method.execute(new HttpState(), conn);
+ client.executeMethod(method);
Header locationHeader = method.getResponseHeader("Location");
assertEquals(302, method.getStatusCode());
assertEquals("/oldfile", method.getPath());
@@ -182,7 +173,7 @@
HttpMethod method = new SimpleHttpMethod("/oldfile");
method.setFollowRedirects(true);
method.setStrictMode(false);
- method.execute(new HttpState(), conn);
+ client.executeMethod(method);
Header locationHeader = method.getResponseHeader("Location");
assertEquals(200, method.getStatusCode());
assertEquals("/newfile", method.getPath());
@@ -266,13 +257,11 @@
addOkResponse();
conn.open();
- HttpState state = new HttpState();
- state.addCookie(
- new Cookie("localhost", "name", "value", "/", -1, false));
+ client.getState().addCookie(new Cookie("localhost", "name", "value", "/", -1, false));
HttpMethod method = new SimpleHttpMethod("/oldfile");
method.setFollowRedirects(true);
- method.execute(state, conn);
+ client.executeMethod(method);
Header locationHeader = method.getResponseHeader("Location");
assertEquals(200, method.getStatusCode());
Index: test/org/apache/commons/httpclient/TestNoHostBase.java
===================================================================
RCS file: test/org/apache/commons/httpclient/TestNoHostBase.java
diff -N test/org/apache/commons/httpclient/TestNoHostBase.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ test/org/apache/commons/httpclient/TestNoHostBase.java 22 Jul 2003 12:33:11 -0000
@@ -0,0 +1,37 @@
+package org.apache.commons.httpclient;
+
+import junit.framework.TestCase;
+
+/**
+ */
+public abstract class TestNoHostBase extends TestCase {
+
+ protected SimpleHttpConnection conn;
+
+ protected HttpClient client;
+
+ protected NoHostHttpConnectionManager connectionManager;
+
+ /**
+ *
+ */
+ public TestNoHostBase() {
+ super();
+ }
+
+ /**
+ * @param arg0
+ */
+ public TestNoHostBase(String arg0) {
+ super(arg0);
+ }
+
+ public void setUp() throws Exception{
+ conn = new SimpleHttpConnection();
+ connectionManager = new NoHostHttpConnectionManager();
+ connectionManager.setConnection(conn);
+ client = new HttpClient(connectionManager);
+ client.getHostConfiguration().setHost("localhost", 80, "http");
+ }
+
+}
Index: test/org/apache/commons/httpclient/TestResponseHeaders.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestResponseHeaders.java,v
retrieving revision 1.8
diff -u -r1.8 TestResponseHeaders.java
--- test/org/apache/commons/httpclient/TestResponseHeaders.java 20 Jun 2003 13:33:09 -0000 1.8
+++ test/org/apache/commons/httpclient/TestResponseHeaders.java 22 Jul 2003 12:33:12 -0000
@@ -76,7 +76,7 @@
* @author Adrian Sutton
* @version $Id: TestResponseHeaders.java,v 1.8 2003/06/20 13:33:09 adrian Exp $
*/
-public class TestResponseHeaders extends TestCase {
+public class TestResponseHeaders extends TestNoHostBase {
// ------------------------------------------------------------ Constructor
public TestResponseHeaders(String testName) {
@@ -94,20 +94,6 @@
return new TestSuite(TestResponseHeaders.class);
}
-
-
- /**
- * Simple extension of HttpMethodBase.
- */
- private class SimpleHttpMethod extends HttpMethodBase {
- public SimpleHttpMethod() {
- super("");
- }
- public String getName() {
- return "simple";
- }
- }
-
// ----------------------------------------------------------- Test Methods
public void testHeaders() throws Exception {
String body = "XXX\r\nYYY\r\nZZZ";
@@ -118,10 +104,9 @@
"Content-Type: text/xml; charset=utf-8\r\n" +
"Date: Wed, 28 Mar 2001 05:05:04 GMT\r\n" +
"Server: UserLand Frontier/7.0-WinNT\r\n";
- HttpState state = new HttpState();
HttpMethod method = new SimpleHttpMethod();
- SimpleHttpConnection conn = new SimpleHttpConnection(headers, body);
- method.execute(state, conn);
+ conn.addResponse(headers, body);
+ client.executeMethod(method);
assertEquals("close", method.getResponseHeader("Connection").getValue());
assertEquals(body.length(), Integer.parseInt(method.getResponseHeader("Content-Length").getValue()));
assertEquals("text/xml; charset=utf-8", method.getResponseHeader("Content-Type").getValue());
@@ -139,17 +124,15 @@
"HTTP/1.1 200 OK\r\n" +
"Content-Length: " + body.length() + "\r\n" +
"Content-Length: " + body.length() + "\r\n";
- HttpState state = new HttpState();
HttpMethod method = new SimpleHttpMethod();
- SimpleHttpConnection conn = new SimpleHttpConnection(headers, body);
- method.execute(state, conn);
+ conn.addResponse(headers, body);
+ client.executeMethod(method);
assertNotNull( "Response body is null.", method.getResponseBodyAsStream() );
}
public void testDuplicateProxyConnection() throws Exception {
- SimpleHttpConnection conn = new SimpleHttpConnection();
String headers =
"HTTP/1.1 200 OK\r\n"
+ "proxy-connection: close\r\n"
@@ -161,12 +144,11 @@
conn.setProxyHost("proxy");
conn.setProxyPort(1);
GetMethod method = new GetMethod("/");
- method.execute(new HttpState(), conn);
+ client.executeMethod(method);
method.getResponseBodyAsString();
assertFalse(conn.isOpen());
- conn = new SimpleHttpConnection();
headers =
"HTTP/1.0 200 OK\r\n"
+ "proxy-connection: keep-alive\r\n"
@@ -178,7 +160,7 @@
conn.setProxyHost("proxy");
conn.setProxyPort(1);
method = new GetMethod("/");
- method.execute(new HttpState(), conn);
+ client.executeMethod(method);
method.getResponseBodyAsString();
assertTrue(conn.isOpen());
@@ -186,21 +168,19 @@
public void testDuplicateConnection() throws Exception {
- SimpleHttpConnection conn = new SimpleHttpConnection();
String headers =
"HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Connection: close\r\n"
+ "\r\n";
- conn.addResponse(headers, "");
GetMethod method = new GetMethod("/");
- method.execute(new HttpState(), conn);
+ conn.addResponse(headers, "");
+ client.executeMethod(method);
method.getResponseBodyAsString();
assertFalse(conn.isOpen());
- conn = new SimpleHttpConnection();
headers =
"HTTP/1.0 200 OK\r\n"
+"Connection: keep-alive\r\n"
@@ -208,9 +188,9 @@
+ "Content-Length: 0\r\n"
+"\r\n";
- conn.addResponse(headers, "");
method = new GetMethod("/");
- method.execute(new HttpState(), conn);
+ conn.addResponse(headers, "");
+ client.executeMethod(method);
method.getResponseBodyAsString();
assertTrue(conn.isOpen());
@@ -218,27 +198,25 @@
public void testNoContentLength() throws Exception {
// test with connection header
- SimpleHttpConnection conn = new SimpleHttpConnection();
String headers =
"HTTP/1.1 200 OK\r\n"
+ "Connection: keep-alive\r\n"
+ "\r\n";
- conn.addResponse(headers, "12345");
GetMethod method = new GetMethod("/");
- method.execute(new HttpState(), conn);
+ conn.addResponse(headers, "12345");
+ client.executeMethod(method);
method.getResponseBodyAsString();
assertFalse(conn.isOpen());
// test without connection header
- conn = new SimpleHttpConnection();
headers = "HTTP/1.1 200 OK\r\n\r\n";
// test with connection header
- conn.addResponse(headers, "12345");
method = new GetMethod("/");
- method.execute(new HttpState(), conn);
+ conn.addResponse(headers, "12345");
+ client.executeMethod(method);
method.getResponseBodyAsString();
assertFalse(conn.isOpen());
@@ -246,30 +224,28 @@
public void testProxyNoContentLength() throws Exception {
// test with proxy-connection header
- SimpleHttpConnection conn = new SimpleHttpConnection();
String headers =
"HTTP/1.1 200 OK\r\n"
+ "proxy-connection: keep-alive\r\n"
+ "\r\n";
- conn.addResponse(headers, "12345");
conn.setProxyHost("proxy");
conn.setProxyPort(1);
GetMethod method = new GetMethod("/");
- method.execute(new HttpState(), conn);
+ conn.addResponse(headers, "12345");
+ client.executeMethod(method);
method.getResponseBodyAsString();
assertFalse(conn.isOpen());
// test without proxy-connection header
- conn = new SimpleHttpConnection();
headers = "HTTP/1.1 200 OK\r\n\r\n";
- conn.addResponse(headers, "12345");
conn.setProxyHost("proxy");
conn.setProxyPort(1);
method = new GetMethod("/");
- method.execute(new HttpState(), conn);
+ conn.addResponse(headers, "12345");
+ client.executeMethod(method);
method.getResponseBodyAsString();
assertFalse(conn.isOpen());
@@ -280,10 +256,9 @@
String headers =
"HTTP/1.1 200 OK\r\n" +
"Content-Length: " + body.length() + "\r\n";
- HttpState state = new HttpState();
HttpMethod method = new SimpleHttpMethod();
- SimpleHttpConnection conn = new SimpleHttpConnection(headers, body);
- method.execute(state, conn);
+ conn.addResponse(headers, body);
+ client.executeMethod(method);
assertEquals(null, method.getResponseHeader(null));
assertEquals(null, method.getResponseHeader("bogus"));
}
@@ -299,10 +274,9 @@
"Date: Wed, 28 Mar 2001\r\n" +
" 05:05:04 GMT\r\n" +
"Server: UserLand Frontier/7.0-WinNT\r\n";
- HttpState state = new HttpState();
HttpMethod method = new SimpleHttpMethod();
- SimpleHttpConnection conn = new SimpleHttpConnection(headers, body);
- method.execute(state, conn);
+ conn.addResponse(headers, body);
+ client.executeMethod(method);
assertEquals("close", method.getResponseHeader("Connection").getValue());
assertEquals(body.length(), Integer.parseInt(method.getResponseHeader("Content-Length").getValue()));
assertEquals("text/xml; charset=utf-8 boundary=XXXX", method.getResponseHeader("Content-Type").getValue());