2
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/HttpMethodDirector.java,v 1.34 2005/01/14 19:40:39 olegk Exp $
4
* $Date: 2006-12-13 15:05:50 +0100 (Wed, 13 Dec 2006) $
6
* ====================================================================
8
* Licensed to the Apache Software Foundation (ASF) under one or more
9
* contributor license agreements. See the NOTICE file distributed with
10
* this work for additional information regarding copyright ownership.
11
* The ASF licenses this file to You under the Apache License, Version 2.0
12
* (the "License"); you may not use this file except in compliance with
13
* the License. You may obtain a copy of the License at
15
* http://www.apache.org/licenses/LICENSE-2.0
17
* Unless required by applicable law or agreed to in writing, software
18
* distributed under the License is distributed on an "AS IS" BASIS,
19
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
* See the License for the specific language governing permissions and
21
* limitations under the License.
22
* ====================================================================
24
* This software consists of voluntary contributions made by many
25
* individuals on behalf of the Apache Software Foundation. For more
26
* information on the Apache Software Foundation, please see
27
* <http://www.apache.org/>.
31
package org.apache.commons.httpclient;
33
import java.io.IOException;
34
import java.util.Collection;
35
import java.util.HashSet;
36
import java.util.Iterator;
40
import org.apache.commons.httpclient.auth.AuthChallengeException;
41
import org.apache.commons.httpclient.auth.AuthChallengeParser;
42
import org.apache.commons.httpclient.auth.AuthChallengeProcessor;
43
import org.apache.commons.httpclient.auth.AuthScheme;
44
import org.apache.commons.httpclient.auth.AuthState;
45
import org.apache.commons.httpclient.auth.AuthenticationException;
46
import org.apache.commons.httpclient.auth.CredentialsProvider;
47
import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;
48
import org.apache.commons.httpclient.auth.AuthScope;
49
import org.apache.commons.httpclient.auth.MalformedChallengeException;
50
import org.apache.commons.httpclient.params.HostParams;
51
import org.apache.commons.httpclient.params.HttpClientParams;
52
import org.apache.commons.httpclient.params.HttpConnectionParams;
53
import org.apache.commons.httpclient.params.HttpMethodParams;
54
import org.apache.commons.httpclient.params.HttpParams;
55
import org.apache.commons.logging.Log;
56
import org.apache.commons.logging.LogFactory;
59
* Handles the process of executing a method including authentication, redirection and retries.
63
class HttpMethodDirector {
65
/** The www authenticate challange header. */
66
public static final String WWW_AUTH_CHALLENGE = "WWW-Authenticate";
68
/** The www authenticate response header. */
69
public static final String WWW_AUTH_RESP = "Authorization";
71
/** The proxy authenticate challange header. */
72
public static final String PROXY_AUTH_CHALLENGE = "Proxy-Authenticate";
74
/** The proxy authenticate response header. */
75
public static final String PROXY_AUTH_RESP = "Proxy-Authorization";
77
private static final Log LOG = LogFactory.getLog(HttpMethodDirector.class);
79
private ConnectMethod connectMethod;
81
private HttpState state;
83
private HostConfiguration hostConfiguration;
85
private HttpConnectionManager connectionManager;
87
private HttpClientParams params;
89
private HttpConnection conn;
91
/** A flag to indicate if the connection should be released after the method is executed. */
92
private boolean releaseConnection = false;
94
/** Authentication processor */
95
private AuthChallengeProcessor authProcessor = null;
97
private Set redirectLocations = null;
99
public HttpMethodDirector(
100
final HttpConnectionManager connectionManager,
101
final HostConfiguration hostConfiguration,
102
final HttpClientParams params,
103
final HttpState state
106
this.connectionManager = connectionManager;
107
this.hostConfiguration = hostConfiguration;
108
this.params = params;
110
this.authProcessor = new AuthChallengeProcessor(this.params);
115
* Executes the method associated with this method director.
117
* @throws IOException
118
* @throws HttpException
120
public void executeMethod(final HttpMethod method) throws IOException, HttpException {
121
if (method == null) {
122
throw new IllegalArgumentException("Method may not be null");
124
// Link all parameter collections to form the hierarchy:
125
// Global -> HttpClient -> HostConfiguration -> HttpMethod
126
this.hostConfiguration.getParams().setDefaults(this.params);
127
method.getParams().setDefaults(this.hostConfiguration.getParams());
129
// Generate default request headers
130
Collection defaults = (Collection)this.hostConfiguration.getParams().
131
getParameter(HostParams.DEFAULT_HEADERS);
132
if (defaults != null) {
133
Iterator i = defaults.iterator();
134
while (i.hasNext()) {
135
method.addRequestHeader((Header)i.next());
140
int maxRedirects = this.params.getIntParameter(HttpClientParams.MAX_REDIRECTS, 100);
142
for (int redirectCount = 0;;) {
144
// make sure the connection we have is appropriate
145
if (this.conn != null && !hostConfiguration.hostEquals(this.conn)) {
146
this.conn.setLocked(false);
147
this.conn.releaseConnection();
151
// get a connection, if we need one
152
if (this.conn == null) {
153
this.conn = connectionManager.getConnectionWithTimeout(
155
this.params.getConnectionManagerTimeout()
157
this.conn.setLocked(true);
158
if (this.params.isAuthenticationPreemptive()
159
|| this.state.isAuthenticationPreemptive())
161
LOG.debug("Preemptively sending default basic credentials");
162
method.getHostAuthState().setPreemptive();
163
method.getHostAuthState().setAuthAttempted(true);
164
if (this.conn.isProxied() && !this.conn.isSecure()) {
165
method.getProxyAuthState().setPreemptive();
166
method.getProxyAuthState().setAuthAttempted(true);
170
authenticate(method);
171
executeWithRetry(method);
172
if (this.connectMethod != null) {
173
fakeResponse(method);
177
boolean retry = false;
178
if (isRedirectNeeded(method)) {
179
if (processRedirectResponse(method)) {
182
if (redirectCount >= maxRedirects) {
183
LOG.error("Narrowly avoided an infinite loop in execute");
184
throw new RedirectException("Maximum redirects ("
185
+ maxRedirects + ") exceeded");
187
if (LOG.isDebugEnabled()) {
188
LOG.debug("Execute redirect " + redirectCount + " of " + maxRedirects);
192
if (isAuthenticationNeeded(method)) {
193
if (processAuthenticationResponse(method)) {
194
LOG.debug("Retry authentication");
201
// retry - close previous stream. Caution - this causes
202
// responseBodyConsumed to be called, which may also close the
204
if (method.getResponseBodyAsStream() != null) {
205
method.getResponseBodyAsStream().close();
208
} //end of retry loop
210
if (this.conn != null) {
211
this.conn.setLocked(false);
213
// If the response has been fully processed, return the connection
214
// to the pool. Use this flag, rather than other tests (like
215
// responseStream == null), as subclasses, might reset the stream,
216
// for example, reading the entire response into a file and then
217
// setting the file as the stream.
219
(releaseConnection || method.getResponseBodyAsStream() == null)
222
this.conn.releaseConnection();
229
private void authenticate(final HttpMethod method) {
231
if (this.conn.isProxied() && !this.conn.isSecure()) {
232
authenticateProxy(method);
234
authenticateHost(method);
235
} catch (AuthenticationException e) {
236
LOG.error(e.getMessage(), e);
241
private boolean cleanAuthHeaders(final HttpMethod method, final String name) {
242
Header[] authheaders = method.getRequestHeaders(name);
243
boolean clean = true;
244
for (int i = 0; i < authheaders.length; i++) {
245
Header authheader = authheaders[i];
246
if (authheader.isAutogenerated()) {
247
method.removeRequestHeader(authheader);
256
private void authenticateHost(final HttpMethod method) throws AuthenticationException {
257
// Clean up existing authentication headers
258
if (!cleanAuthHeaders(method, WWW_AUTH_RESP)) {
259
// User defined authentication header(s) present
262
AuthState authstate = method.getHostAuthState();
263
AuthScheme authscheme = authstate.getAuthScheme();
264
if (authscheme == null) {
267
if (authstate.isAuthRequested() || !authscheme.isConnectionBased()) {
268
String host = method.getParams().getVirtualHost();
270
host = conn.getHost();
272
int port = conn.getPort();
273
AuthScope authscope = new AuthScope(
275
authscheme.getRealm(),
276
authscheme.getSchemeName());
277
if (LOG.isDebugEnabled()) {
278
LOG.debug("Authenticating with " + authscope);
280
Credentials credentials = this.state.getCredentials(authscope);
281
if (credentials != null) {
282
String authstring = authscheme.authenticate(credentials, method);
283
if (authstring != null) {
284
method.addRequestHeader(new Header(WWW_AUTH_RESP, authstring, true));
287
if (LOG.isWarnEnabled()) {
288
LOG.warn("Required credentials not available for " + authscope);
289
if (method.getHostAuthState().isPreemptive()) {
290
LOG.warn("Preemptive authentication requested but no default " +
291
"credentials available");
299
private void authenticateProxy(final HttpMethod method) throws AuthenticationException {
300
// Clean up existing authentication headers
301
if (!cleanAuthHeaders(method, PROXY_AUTH_RESP)) {
302
// User defined authentication header(s) present
305
AuthState authstate = method.getProxyAuthState();
306
AuthScheme authscheme = authstate.getAuthScheme();
307
if (authscheme == null) {
310
if (authstate.isAuthRequested() || !authscheme.isConnectionBased()) {
311
AuthScope authscope = new AuthScope(
312
conn.getProxyHost(), conn.getProxyPort(),
313
authscheme.getRealm(),
314
authscheme.getSchemeName());
315
if (LOG.isDebugEnabled()) {
316
LOG.debug("Authenticating with " + authscope);
318
Credentials credentials = this.state.getProxyCredentials(authscope);
319
if (credentials != null) {
320
String authstring = authscheme.authenticate(credentials, method);
321
if (authstring != null) {
322
method.addRequestHeader(new Header(PROXY_AUTH_RESP, authstring, true));
325
if (LOG.isWarnEnabled()) {
326
LOG.warn("Required proxy credentials not available for " + authscope);
327
if (method.getProxyAuthState().isPreemptive()) {
328
LOG.warn("Preemptive authentication requested but no default " +
329
"proxy credentials available");
338
* Applies connection parameters specified for a given method
340
* @param method HTTP method
342
* @throws IOException if an I/O occurs setting connection parameters
344
private void applyConnectionParams(final HttpMethod method) throws IOException {
346
// see if a timeout is given for this method
347
Object param = method.getParams().getParameter(HttpMethodParams.SO_TIMEOUT);
349
// if not, use the default value
350
param = this.conn.getParams().getParameter(HttpConnectionParams.SO_TIMEOUT);
353
timeout = ((Integer)param).intValue();
355
this.conn.setSocketTimeout(timeout);
359
* Executes a method with the current hostConfiguration.
361
* @throws IOException if an I/O (transport) error occurs. Some transport exceptions
362
* can be recovered from.
363
* @throws HttpException if a protocol exception occurs. Usually protocol exceptions
364
* cannot be recovered from.
366
private void executeWithRetry(final HttpMethod method)
367
throws IOException, HttpException {
369
/** How many times did this transparently handle a recoverable exception? */
371
// loop until the method is successfully processed, the retryHandler
372
// returns false or a non-recoverable exception is thrown
378
if (LOG.isTraceEnabled()) {
379
LOG.trace("Attempt number " + execCount + " to process request");
381
if (this.conn.getParams().isStaleCheckingEnabled()) {
382
this.conn.closeIfStale();
384
if (!this.conn.isOpen()) {
385
// this connection must be opened before it can be used
386
// This has nothing to do with opening a secure tunnel
388
if (this.conn.isProxied() && this.conn.isSecure()
389
&& !(method instanceof ConnectMethod)) {
390
// we need to create a secure tunnel before we can execute the real method
391
if (!executeConnect()) {
392
// abort, the connect method failed
397
applyConnectionParams(method);
398
method.execute(state, this.conn);
400
} catch (HttpException e) {
401
// filter out protocol exceptions which cannot be recovered from
403
} catch (IOException e) {
404
LOG.debug("Closing the connection.");
406
// test if this method should be retried
407
// ========================================
408
// this code is provided for backward compatibility with 2.0
409
// will be removed in the next major release
410
if (method instanceof HttpMethodBase) {
411
MethodRetryHandler handler =
412
((HttpMethodBase)method).getMethodRetryHandler();
413
if (handler != null) {
414
if (!handler.retryMethod(
417
new HttpRecoverableException(e.getMessage()),
419
method.isRequestSent())) {
420
LOG.debug("Method retry handler returned false. "
421
+ "Automatic recovery will not be attempted");
426
// ========================================
427
HttpMethodRetryHandler handler =
428
(HttpMethodRetryHandler)method.getParams().getParameter(
429
HttpMethodParams.RETRY_HANDLER);
430
if (handler == null) {
431
handler = new DefaultHttpMethodRetryHandler();
433
if (!handler.retryMethod(method, e, execCount)) {
434
LOG.debug("Method retry handler returned false. "
435
+ "Automatic recovery will not be attempted");
438
if (LOG.isInfoEnabled()) {
439
LOG.info("I/O exception ("+ e.getClass().getName() +") caught when processing request: "
442
if (LOG.isDebugEnabled()) {
443
LOG.debug(e.getMessage(), e);
445
LOG.info("Retrying request");
448
} catch (IOException e) {
449
if (this.conn.isOpen()) {
450
LOG.debug("Closing the connection.");
453
releaseConnection = true;
455
} catch (RuntimeException e) {
456
if (this.conn.isOpen()) {
457
LOG.debug("Closing the connection.");
460
releaseConnection = true;
466
* Executes a ConnectMethod to establish a tunneled connection.
468
* @return <code>true</code> if the connect was successful
470
* @throws IOException
471
* @throws HttpException
473
private boolean executeConnect()
474
throws IOException, HttpException {
476
this.connectMethod = new ConnectMethod(this.hostConfiguration);
477
this.connectMethod.getParams().setDefaults(this.hostConfiguration.getParams());
481
if (!this.conn.isOpen()) {
484
if (this.params.isAuthenticationPreemptive()
485
|| this.state.isAuthenticationPreemptive()) {
486
LOG.debug("Preemptively sending default basic credentials");
487
this.connectMethod.getProxyAuthState().setPreemptive();
488
this.connectMethod.getProxyAuthState().setAuthAttempted(true);
491
authenticateProxy(this.connectMethod);
492
} catch (AuthenticationException e) {
493
LOG.error(e.getMessage(), e);
495
applyConnectionParams(this.connectMethod);
496
this.connectMethod.execute(state, this.conn);
497
code = this.connectMethod.getStatusCode();
498
boolean retry = false;
499
AuthState authstate = this.connectMethod.getProxyAuthState();
500
authstate.setAuthRequested(code == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED);
501
if (authstate.isAuthRequested()) {
502
if (processAuthenticationResponse(this.connectMethod)) {
509
if (this.connectMethod.getResponseBodyAsStream() != null) {
510
this.connectMethod.getResponseBodyAsStream().close();
513
if ((code >= 200) && (code < 300)) {
514
this.conn.tunnelCreated();
515
// Drop the connect method, as it is no longer needed
516
this.connectMethod = null;
530
private void fakeResponse(final HttpMethod method)
531
throws IOException, HttpException {
532
// What is to follow is an ugly hack.
533
// I REALLY hate having to resort to such
534
// an appalling trick
535
// The only feasible solution is to split monolithic
536
// HttpMethod into HttpRequest/HttpResponse pair.
537
// That would allow to execute CONNECT method
538
// behind the scene and return CONNECT HttpResponse
539
// object in response to the original request that
540
// contains the correct status line, headers &
542
LOG.debug("CONNECT failed, fake the response for the original method");
543
// Pass the status, headers and response stream to the wrapped
545
// To ensure that the connection is not released more than once
546
// this method is still responsible for releasing the connection.
547
// This will happen when the response body is consumed, or when
548
// the wrapped method closes the response connection in
549
// releaseConnection().
550
if (method instanceof HttpMethodBase) {
551
((HttpMethodBase) method).fakeResponse(
552
this.connectMethod.getStatusLine(),
553
this.connectMethod.getResponseHeaderGroup(),
554
this.connectMethod.getResponseBodyAsStream()
556
method.getProxyAuthState().setAuthScheme(
557
this.connectMethod.getProxyAuthState().getAuthScheme());
558
this.connectMethod = null;
560
releaseConnection = true;
562
"Unable to fake response on method as it is not derived from HttpMethodBase.");
567
* Process the redirect response.
569
* @return <code>true</code> if the redirect was successful
571
private boolean processRedirectResponse(final HttpMethod method)
572
throws RedirectException {
573
//get the location header to find out where to redirect to
574
Header locationHeader = method.getResponseHeader("location");
575
if (locationHeader == null) {
576
// got a redirect response, but no location header
577
LOG.error("Received redirect response " + method.getStatusCode()
578
+ " but no location header");
581
String location = locationHeader.getValue();
582
if (LOG.isDebugEnabled()) {
583
LOG.debug("Redirect requested to location '" + location + "'");
586
//rfc2616 demands the location value be a complete URI
587
//Location = "Location" ":" absoluteURI
588
URI redirectUri = null;
589
URI currentUri = null;
592
currentUri = new URI(
593
this.conn.getProtocol().getScheme(),
600
String charset = method.getParams().getUriCharset();
601
redirectUri = new URI(location, true, charset);
603
if (redirectUri.isRelativeURI()) {
604
if (this.params.isParameterTrue(HttpClientParams.REJECT_RELATIVE_REDIRECT)) {
605
LOG.warn("Relative redirect location '" + location + "' not allowed");
608
//location is incomplete, use current values for defaults
609
LOG.debug("Redirect URI is not absolute - parsing as relative");
610
redirectUri = new URI(currentUri, redirectUri);
613
// Reset the default params
614
method.getParams().setDefaults(this.params);
616
method.setURI(redirectUri);
617
hostConfiguration.setHost(redirectUri);
618
} catch (URIException ex) {
619
throw new InvalidRedirectLocationException(
620
"Invalid redirect location: " + location, location, ex);
623
if (this.params.isParameterFalse(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS)) {
624
if (this.redirectLocations == null) {
625
this.redirectLocations = new HashSet();
627
this.redirectLocations.add(currentUri);
629
if(redirectUri.hasQuery()) {
630
redirectUri.setQuery(null);
632
} catch (URIException e) {
633
// Should never happen
637
if (this.redirectLocations.contains(redirectUri)) {
638
throw new CircularRedirectException("Circular redirect to '" +
643
if (LOG.isDebugEnabled()) {
644
LOG.debug("Redirecting from '" + currentUri.getEscapedURI()
645
+ "' to '" + redirectUri.getEscapedURI());
647
//And finally invalidate the actual authentication scheme
648
method.getHostAuthState().invalidate();
653
* Processes a response that requires authentication
655
* @param method the current {@link HttpMethod HTTP method}
657
* @return <tt>true</tt> if the authentication challenge can be responsed to,
658
* (that is, at least one of the requested authentication scheme is supported,
659
* and matching credentials have been found), <tt>false</tt> otherwise.
661
private boolean processAuthenticationResponse(final HttpMethod method) {
662
LOG.trace("enter HttpMethodBase.processAuthenticationResponse("
663
+ "HttpState, HttpConnection)");
666
switch (method.getStatusCode()) {
667
case HttpStatus.SC_UNAUTHORIZED:
668
return processWWWAuthChallenge(method);
669
case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED:
670
return processProxyAuthChallenge(method);
674
} catch (Exception e) {
675
if (LOG.isErrorEnabled()) {
676
LOG.error(e.getMessage(), e);
682
private boolean processWWWAuthChallenge(final HttpMethod method)
683
throws MalformedChallengeException, AuthenticationException
685
AuthState authstate = method.getHostAuthState();
686
Map challenges = AuthChallengeParser.parseChallenges(
687
method.getResponseHeaders(WWW_AUTH_CHALLENGE));
688
if (challenges.isEmpty()) {
689
LOG.debug("Authentication challenge(s) not found");
692
AuthScheme authscheme = null;
694
authscheme = this.authProcessor.processChallenge(authstate, challenges);
695
} catch (AuthChallengeException e) {
696
if (LOG.isWarnEnabled()) {
697
LOG.warn(e.getMessage());
700
if (authscheme == null) {
703
String host = method.getParams().getVirtualHost();
705
host = conn.getHost();
707
int port = conn.getPort();
708
AuthScope authscope = new AuthScope(
710
authscheme.getRealm(),
711
authscheme.getSchemeName());
713
if (LOG.isDebugEnabled()) {
714
LOG.debug("Authentication scope: " + authscope);
716
if (authstate.isAuthAttempted() && authscheme.isComplete()) {
717
// Already tried and failed
718
Credentials credentials = promptForCredentials(
719
authscheme, method.getParams(), authscope);
720
if (credentials == null) {
721
if (LOG.isInfoEnabled()) {
722
LOG.info("Failure authenticating with " + authscope);
729
authstate.setAuthAttempted(true);
730
Credentials credentials = this.state.getCredentials(authscope);
731
if (credentials == null) {
732
credentials = promptForCredentials(
733
authscheme, method.getParams(), authscope);
735
if (credentials == null) {
736
if (LOG.isInfoEnabled()) {
737
LOG.info("No credentials available for " + authscope);
746
private boolean processProxyAuthChallenge(final HttpMethod method)
747
throws MalformedChallengeException, AuthenticationException
749
AuthState authstate = method.getProxyAuthState();
750
Map proxyChallenges = AuthChallengeParser.parseChallenges(
751
method.getResponseHeaders(PROXY_AUTH_CHALLENGE));
752
if (proxyChallenges.isEmpty()) {
753
LOG.debug("Proxy authentication challenge(s) not found");
756
AuthScheme authscheme = null;
758
authscheme = this.authProcessor.processChallenge(authstate, proxyChallenges);
759
} catch (AuthChallengeException e) {
760
if (LOG.isWarnEnabled()) {
761
LOG.warn(e.getMessage());
764
if (authscheme == null) {
767
AuthScope authscope = new AuthScope(
768
conn.getProxyHost(), conn.getProxyPort(),
769
authscheme.getRealm(),
770
authscheme.getSchemeName());
772
if (LOG.isDebugEnabled()) {
773
LOG.debug("Proxy authentication scope: " + authscope);
775
if (authstate.isAuthAttempted() && authscheme.isComplete()) {
776
// Already tried and failed
777
Credentials credentials = promptForProxyCredentials(
778
authscheme, method.getParams(), authscope);
779
if (credentials == null) {
780
if (LOG.isInfoEnabled()) {
781
LOG.info("Failure authenticating with " + authscope);
788
authstate.setAuthAttempted(true);
789
Credentials credentials = this.state.getProxyCredentials(authscope);
790
if (credentials == null) {
791
credentials = promptForProxyCredentials(
792
authscheme, method.getParams(), authscope);
794
if (credentials == null) {
795
if (LOG.isInfoEnabled()) {
796
LOG.info("No credentials available for " + authscope);
806
* Tests if the {@link HttpMethod method} requires a redirect to another location.
808
* @param method HTTP method
810
* @return boolean <tt>true</tt> if a retry is needed, <tt>false</tt> otherwise.
812
private boolean isRedirectNeeded(final HttpMethod method) {
813
switch (method.getStatusCode()) {
814
case HttpStatus.SC_MOVED_TEMPORARILY:
815
case HttpStatus.SC_MOVED_PERMANENTLY:
816
case HttpStatus.SC_SEE_OTHER:
817
case HttpStatus.SC_TEMPORARY_REDIRECT:
818
LOG.debug("Redirect required");
819
if (method.getFollowRedirects()) {
830
* Tests if the {@link HttpMethod method} requires authentication.
832
* @param method HTTP method
834
* @return boolean <tt>true</tt> if a retry is needed, <tt>false</tt> otherwise.
836
private boolean isAuthenticationNeeded(final HttpMethod method) {
837
method.getHostAuthState().setAuthRequested(
838
method.getStatusCode() == HttpStatus.SC_UNAUTHORIZED);
839
method.getProxyAuthState().setAuthRequested(
840
method.getStatusCode() == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED);
841
if (method.getHostAuthState().isAuthRequested() ||
842
method.getProxyAuthState().isAuthRequested()) {
843
LOG.debug("Authorization required");
844
if (method.getDoAuthentication()) { //process authentication response
846
} else { //let the client handle the authenticaiton
847
LOG.info("Authentication requested but doAuthentication is "
856
private Credentials promptForCredentials(
857
final AuthScheme authScheme,
858
final HttpParams params,
859
final AuthScope authscope)
861
LOG.debug("Credentials required");
862
Credentials creds = null;
863
CredentialsProvider credProvider =
864
(CredentialsProvider)params.getParameter(CredentialsProvider.PROVIDER);
865
if (credProvider != null) {
867
creds = credProvider.getCredentials(
868
authScheme, authscope.getHost(), authscope.getPort(), false);
869
} catch (CredentialsNotAvailableException e) {
870
LOG.warn(e.getMessage());
873
this.state.setCredentials(authscope, creds);
874
if (LOG.isDebugEnabled()) {
875
LOG.debug(authscope + " new credentials given");
879
LOG.debug("Credentials provider not available");
884
private Credentials promptForProxyCredentials(
885
final AuthScheme authScheme,
886
final HttpParams params,
887
final AuthScope authscope)
889
LOG.debug("Proxy credentials required");
890
Credentials creds = null;
891
CredentialsProvider credProvider =
892
(CredentialsProvider)params.getParameter(CredentialsProvider.PROVIDER);
893
if (credProvider != null) {
895
creds = credProvider.getCredentials(
896
authScheme, authscope.getHost(), authscope.getPort(), true);
897
} catch (CredentialsNotAvailableException e) {
898
LOG.warn(e.getMessage());
901
this.state.setProxyCredentials(authscope, creds);
902
if (LOG.isDebugEnabled()) {
903
LOG.debug(authscope + " new credentials given");
907
LOG.debug("Proxy credentials provider not available");
915
public HostConfiguration getHostConfiguration() {
916
return hostConfiguration;
922
public HttpState getState() {
929
public HttpConnectionManager getConnectionManager() {
930
return connectionManager;
936
public HttpParams getParams() {