public void executeMethod(HttpMethod method) throws IOException, HttpException {
if (method == null) {
throw new IllegalArgumentException("Method may not be null");
}
// Link all parameter collections to form the hierarchy:
// Global - > HttpClient - > HostConfiguration - > HttpMethod
this.hostConfiguration.getParams().setDefaults(this.params);
method.getParams().setDefaults(this.hostConfiguration.getParams());
// Generate default request headers
Collection defaults = (Collection)this.hostConfiguration.getParams().
getParameter(HostParams.DEFAULT_HEADERS);
if (defaults != null) {
Iterator i = defaults.iterator();
while (i.hasNext()) {
method.addRequestHeader((Header)i.next());
}
}
try {
int maxRedirects = this.params.getIntParameter(HttpClientParams.MAX_REDIRECTS, 100);
for (int redirectCount = 0;;) {
// make sure the connection we have is appropriate
if (this.conn != null && !hostConfiguration.hostEquals(this.conn)) {
this.conn.setLocked(false);
this.conn.releaseConnection();
this.conn = null;
}
// get a connection, if we need one
if (this.conn == null) {
this.conn = connectionManager.getConnectionWithTimeout(
hostConfiguration,
this.params.getConnectionManagerTimeout()
);
this.conn.setLocked(true);
if (this.params.isAuthenticationPreemptive()
|| this.state.isAuthenticationPreemptive())
{
LOG.debug("Preemptively sending default basic credentials");
method.getHostAuthState().setPreemptive();
method.getHostAuthState().setAuthAttempted(true);
if (this.conn.isProxied() && !this.conn.isSecure()) {
method.getProxyAuthState().setPreemptive();
method.getProxyAuthState().setAuthAttempted(true);
}
}
}
authenticate(method);
executeWithRetry(method);
if (this.connectMethod != null) {
fakeResponse(method);
break;
}
boolean retry = false;
if (isRedirectNeeded(method)) {
if (processRedirectResponse(method)) {
retry = true;
++redirectCount;
if (redirectCount >= maxRedirects) {
LOG.error("Narrowly avoided an infinite loop in execute");
throw new RedirectException("Maximum redirects ("
+ maxRedirects + ") exceeded");
}
if (LOG.isDebugEnabled()) {
LOG.debug("Execute redirect " + redirectCount + " of " + maxRedirects);
}
}
}
if (isAuthenticationNeeded(method)) {
if (processAuthenticationResponse(method)) {
LOG.debug("Retry authentication");
retry = true;
}
}
if (!retry) {
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
} finally {
if (this.conn != null) {
this.conn.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 (
(releaseConnection || method.getResponseBodyAsStream() == null)
&& this.conn != null
) {
this.conn.releaseConnection();
}
}
}
Executes the method associated with this method director. |