1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package org.apache.commons.httpclient;
31
32 import java.io.IOException;
33 import java.util.Collection;
34 import java.util.HashSet;
35 import java.util.Iterator;
36 import java.util.Map;
37 import java.util.Set;
38
39 import org.apache.commons.httpclient.auth.AuthChallengeException;
40 import org.apache.commons.httpclient.auth.AuthChallengeParser;
41 import org.apache.commons.httpclient.auth.AuthChallengeProcessor;
42 import org.apache.commons.httpclient.auth.AuthScheme;
43 import org.apache.commons.httpclient.auth.AuthState;
44 import org.apache.commons.httpclient.auth.AuthenticationException;
45 import org.apache.commons.httpclient.auth.CredentialsProvider;
46 import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;
47 import org.apache.commons.httpclient.auth.AuthScope;
48 import org.apache.commons.httpclient.auth.MalformedChallengeException;
49 import org.apache.commons.httpclient.params.HostParams;
50 import org.apache.commons.httpclient.params.HttpClientParams;
51 import org.apache.commons.httpclient.params.HttpConnectionParams;
52 import org.apache.commons.httpclient.params.HttpMethodParams;
53 import org.apache.commons.httpclient.params.HttpParams;
54 import org.apache.commons.logging.Log;
55 import org.apache.commons.logging.LogFactory;
56
57 /***
58 * Handles the process of executing a method including authentication, redirection and retries.
59 *
60 * @since 3.0
61 */
62 class HttpMethodDirector {
63
64 /*** The www authenticate challange header. */
65 public static final String WWW_AUTH_CHALLENGE = "WWW-Authenticate";
66
67 /*** The www authenticate response header. */
68 public static final String WWW_AUTH_RESP = "Authorization";
69
70 /*** The proxy authenticate challange header. */
71 public static final String PROXY_AUTH_CHALLENGE = "Proxy-Authenticate";
72
73 /*** The proxy authenticate response header. */
74 public static final String PROXY_AUTH_RESP = "Proxy-Authorization";
75
76 private static final Log LOG = LogFactory.getLog(HttpMethodDirector.class);
77
78 private ConnectMethod connectMethod;
79
80 private HttpState state;
81
82 private HostConfiguration hostConfiguration;
83
84 private HttpConnectionManager connectionManager;
85
86 private HttpClientParams params;
87
88 private HttpConnection conn;
89
90 /*** A flag to indicate if the connection should be released after the method is executed. */
91 private boolean releaseConnection = false;
92
93 /*** Authentication processor */
94 private AuthChallengeProcessor authProcessor = null;
95
96 private Set redirectLocations = null;
97
98 public HttpMethodDirector(
99 final HttpConnectionManager connectionManager,
100 final HostConfiguration hostConfiguration,
101 final HttpClientParams params,
102 final HttpState state
103 ) {
104 super();
105 this.connectionManager = connectionManager;
106 this.hostConfiguration = hostConfiguration;
107 this.params = params;
108 this.state = state;
109 this.authProcessor = new AuthChallengeProcessor(this.params);
110 }
111
112
113 /***
114 * Executes the method associated with this method director.
115 *
116 * @throws IOException
117 * @throws HttpException
118 */
119 public void executeMethod(final HttpMethod method) throws IOException, HttpException {
120 if (method == null) {
121 throw new IllegalArgumentException("Method may not be null");
122 }
123
124
125 this.hostConfiguration.getParams().setDefaults(this.params);
126 method.getParams().setDefaults(this.hostConfiguration.getParams());
127
128
129 Collection defaults = (Collection)this.hostConfiguration.getParams().
130 getParameter(HostParams.DEFAULT_HEADERS);
131 if (defaults != null) {
132 Iterator i = defaults.iterator();
133 while (i.hasNext()) {
134 method.addRequestHeader((Header)i.next());
135 }
136 }
137
138 try {
139 int maxRedirects = this.params.getIntParameter(HttpClientParams.MAX_REDIRECTS, 100);
140
141 for (int redirectCount = 0;;) {
142
143
144 if (this.conn != null && !hostConfiguration.hostEquals(this.conn)) {
145 this.conn.setLocked(false);
146 this.conn.releaseConnection();
147 this.conn = null;
148 }
149
150
151 if (this.conn == null) {
152 this.conn = connectionManager.getConnectionWithTimeout(
153 hostConfiguration,
154 this.params.getConnectionManagerTimeout()
155 );
156 this.conn.setLocked(true);
157 if (this.params.isAuthenticationPreemptive()
158 || this.state.isAuthenticationPreemptive())
159 {
160 LOG.debug("Preemptively sending default basic credentials");
161 method.getHostAuthState().setPreemptive();
162 method.getHostAuthState().setAuthAttempted(true);
163 if (this.conn.isProxied() && !this.conn.isSecure()) {
164 method.getProxyAuthState().setPreemptive();
165 method.getProxyAuthState().setAuthAttempted(true);
166 }
167 }
168 }
169 authenticate(method);
170 executeWithRetry(method);
171 if (this.connectMethod != null) {
172 fakeResponse(method);
173 break;
174 }
175
176 boolean retry = false;
177 if (isRedirectNeeded(method)) {
178 if (processRedirectResponse(method)) {
179 retry = true;
180 ++redirectCount;
181 if (redirectCount >= maxRedirects) {
182 LOG.error("Narrowly avoided an infinite loop in execute");
183 throw new RedirectException("Maximum redirects ("
184 + maxRedirects + ") exceeded");
185 }
186 if (LOG.isDebugEnabled()) {
187 LOG.debug("Execute redirect " + redirectCount + " of " + maxRedirects);
188 }
189 }
190 }
191 if (isAuthenticationNeeded(method)) {
192 if (processAuthenticationResponse(method)) {
193 LOG.debug("Retry authentication");
194 retry = true;
195 }
196 }
197 if (!retry) {
198 break;
199 }
200
201
202
203 if (method.getResponseBodyAsStream() != null) {
204 method.getResponseBodyAsStream().close();
205 }
206
207 }
208 } finally {
209 if (this.conn != null) {
210 this.conn.setLocked(false);
211 }
212
213
214
215
216
217 if (
218 (releaseConnection || method.getResponseBodyAsStream() == null)
219 && this.conn != null
220 ) {
221 this.conn.releaseConnection();
222 }
223 }
224
225 }
226
227
228 private void authenticate(final HttpMethod method) {
229 try {
230 if (this.conn.isProxied() && !this.conn.isSecure()) {
231 authenticateProxy(method);
232 }
233 authenticateHost(method);
234 } catch (AuthenticationException e) {
235 LOG.error(e.getMessage(), e);
236 }
237 }
238
239
240 private boolean cleanAuthHeaders(final HttpMethod method, final String name) {
241 Header[] authheaders = method.getRequestHeaders(name);
242 boolean clean = true;
243 for (int i = 0; i < authheaders.length; i++) {
244 Header authheader = authheaders[i];
245 if (authheader.isAutogenerated()) {
246 method.removeRequestHeader(authheader);
247 } else {
248 clean = false;
249 }
250 }
251 return clean;
252 }
253
254
255 private void authenticateHost(final HttpMethod method) throws AuthenticationException {
256
257 if (!cleanAuthHeaders(method, WWW_AUTH_RESP)) {
258
259 return;
260 }
261 AuthState authstate = method.getHostAuthState();
262 AuthScheme authscheme = authstate.getAuthScheme();
263 if (authscheme == null) {
264 return;
265 }
266 if (authstate.isAuthRequested() || !authscheme.isConnectionBased()) {
267 String host = method.getParams().getVirtualHost();
268 if (host == null) {
269 host = conn.getHost();
270 }
271 int port = conn.getPort();
272 AuthScope authscope = new AuthScope(
273 host, port,
274 authscheme.getRealm(),
275 authscheme.getSchemeName());
276 if (LOG.isDebugEnabled()) {
277 LOG.debug("Authenticating with " + authscope);
278 }
279 Credentials credentials = this.state.getCredentials(authscope);
280 if (credentials != null) {
281 String authstring = authscheme.authenticate(credentials, method);
282 if (authstring != null) {
283 method.addRequestHeader(new Header(WWW_AUTH_RESP, authstring, true));
284 }
285 } else {
286 if (LOG.isWarnEnabled()) {
287 LOG.warn("Required credentials not available for " + authscope);
288 if (method.getHostAuthState().isPreemptive()) {
289 LOG.warn("Preemptive authentication requested but no default " +
290 "credentials available");
291 }
292 }
293 }
294 }
295 }
296
297
298 private void authenticateProxy(final HttpMethod method) throws AuthenticationException {
299
300 if (!cleanAuthHeaders(method, PROXY_AUTH_RESP)) {
301
302 return;
303 }
304 AuthState authstate = method.getProxyAuthState();
305 AuthScheme authscheme = authstate.getAuthScheme();
306 if (authscheme == null) {
307 return;
308 }
309 if (authstate.isAuthRequested() || !authscheme.isConnectionBased()) {
310 AuthScope authscope = new AuthScope(
311 conn.getProxyHost(), conn.getProxyPort(),
312 authscheme.getRealm(),
313 authscheme.getSchemeName());
314 if (LOG.isDebugEnabled()) {
315 LOG.debug("Authenticating with " + authscope);
316 }
317 Credentials credentials = this.state.getProxyCredentials(authscope);
318 if (credentials != null) {
319 String authstring = authscheme.authenticate(credentials, method);
320 if (authstring != null) {
321 method.addRequestHeader(new Header(PROXY_AUTH_RESP, authstring, true));
322 }
323 } else {
324 if (LOG.isWarnEnabled()) {
325 LOG.warn("Required proxy credentials not available for " + authscope);
326 if (method.getProxyAuthState().isPreemptive()) {
327 LOG.warn("Preemptive authentication requested but no default " +
328 "proxy credentials available");
329 }
330 }
331 }
332 }
333 }
334
335
336 /***
337 * Applies connection parameters specified for a given method
338 *
339 * @param method HTTP method
340 *
341 * @throws IOException if an I/O occurs setting connection parameters
342 */
343 private void applyConnectionParams(final HttpMethod method) throws IOException {
344 int timeout = 0;
345
346 Object param = method.getParams().getParameter(HttpMethodParams.SO_TIMEOUT);
347 if (param == null) {
348
349 param = this.conn.getParams().getParameter(HttpConnectionParams.SO_TIMEOUT);
350 }
351 if (param != null) {
352 timeout = ((Integer)param).intValue();
353 }
354 this.conn.setSocketTimeout(timeout);
355 }
356
357 /***
358 * Executes a method with the current hostConfiguration.
359 *
360 * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
361 * can be recovered from.
362 * @throws HttpException if a protocol exception occurs. Usually protocol exceptions
363 * cannot be recovered from.
364 */
365 private void executeWithRetry(final HttpMethod method)
366 throws IOException, HttpException {
367
368 /*** How many times did this transparently handle a recoverable exception? */
369 int execCount = 0;
370
371
372 try {
373 while (true) {
374 execCount++;
375 try {
376
377 if (LOG.isTraceEnabled()) {
378 LOG.trace("Attempt number " + execCount + " to process request");
379 }
380 if (this.conn.getParams().isStaleCheckingEnabled()) {
381 this.conn.closeIfStale();
382 }
383 if (!this.conn.isOpen()) {
384
385
386 this.conn.open();
387 if (this.conn.isProxied() && this.conn.isSecure()
388 && !(method instanceof ConnectMethod)) {
389
390 if (!executeConnect()) {
391
392 return;
393 }
394 }
395 }
396 applyConnectionParams(method);
397 method.execute(state, this.conn);
398 break;
399 } catch (HttpException e) {
400
401 throw e;
402 } catch (IOException e) {
403 LOG.debug("Closing the connection.");
404 this.conn.close();
405
406
407
408
409 if (method instanceof HttpMethodBase) {
410 MethodRetryHandler handler =
411 ((HttpMethodBase)method).getMethodRetryHandler();
412 if (handler != null) {
413 if (!handler.retryMethod(
414 method,
415 this.conn,
416 new HttpRecoverableException(e.getMessage()),
417 execCount,
418 method.isRequestSent())) {
419 LOG.debug("Method retry handler returned false. "
420 + "Automatic recovery will not be attempted");
421 throw e;
422 }
423 }
424 }
425
426 HttpMethodRetryHandler handler =
427 (HttpMethodRetryHandler)method.getParams().getParameter(
428 HttpMethodParams.RETRY_HANDLER);
429 if (handler == null) {
430 handler = new DefaultHttpMethodRetryHandler();
431 }
432 if (!handler.retryMethod(method, e, execCount)) {
433 LOG.debug("Method retry handler returned false. "
434 + "Automatic recovery will not be attempted");
435 throw e;
436 }
437 if (LOG.isInfoEnabled()) {
438 LOG.info("I/O exception ("+ e.getClass().getName() +") caught when processing request: "
439 + e.getMessage());
440 }
441 if (LOG.isDebugEnabled()) {
442 LOG.debug(e.getMessage(), e);
443 }
444 LOG.info("Retrying request");
445 }
446 }
447 } catch (IOException e) {
448 if (this.conn.isOpen()) {
449 LOG.debug("Closing the connection.");
450 this.conn.close();
451 }
452 releaseConnection = true;
453 throw e;
454 } catch (RuntimeException e) {
455 if (this.conn.isOpen) {
456 LOG.debug("Closing the connection.");
457 this.conn.close();
458 }
459 releaseConnection = true;
460 throw e;
461 }
462 }
463
464 /***
465 * Executes a ConnectMethod to establish a tunneled connection.
466 *
467 * @return <code>true</code> if the connect was successful
468 *
469 * @throws IOException
470 * @throws HttpException
471 */
472 private boolean executeConnect()
473 throws IOException, HttpException {
474
475 this.connectMethod = new ConnectMethod();
476 this.connectMethod.getParams().setDefaults(this.hostConfiguration.getParams());
477
478 int code;
479 for (;;) {
480 if (!this.conn.isOpen()) {
481 this.conn.open();
482 }
483 if (this.params.isAuthenticationPreemptive()
484 || this.state.isAuthenticationPreemptive()) {
485 LOG.debug("Preemptively sending default basic credentials");
486 this.connectMethod.getProxyAuthState().setPreemptive();
487 this.connectMethod.getProxyAuthState().setAuthAttempted(true);
488 }
489 try {
490 authenticateProxy(this.connectMethod);
491 } catch (AuthenticationException e) {
492 LOG.error(e.getMessage(), e);
493 }
494 applyConnectionParams(this.connectMethod);
495 this.connectMethod.execute(state, this.conn);
496 code = this.connectMethod.getStatusCode();
497 boolean retry = false;
498 AuthState authstate = this.connectMethod.getProxyAuthState();
499 authstate.setAuthRequested(code == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED);
500 if (authstate.isAuthRequested()) {
501 if (processAuthenticationResponse(this.connectMethod)) {
502 retry = true;
503 }
504 }
505 if (!retry) {
506 break;
507 }
508 if (this.connectMethod.getResponseBodyAsStream() != null) {
509 this.connectMethod.getResponseBodyAsStream().close();
510 }
511 }
512 if ((code >= 200) && (code < 300)) {
513 this.conn.tunnelCreated();
514
515 this.connectMethod = null;
516 return true;
517 } else {
518 return false;
519 }
520 }
521
522 /***
523 * Fake response
524 * @param method
525 * @return
526 */
527
528 private void fakeResponse(final HttpMethod method)
529 throws IOException, HttpException {
530
531
532
533
534
535
536
537
538
539
540 LOG.debug("CONNECT failed, fake the response for the original method");
541
542
543
544
545
546
547
548 if (method instanceof HttpMethodBase) {
549 ((HttpMethodBase) method).fakeResponse(
550 this.connectMethod.getStatusLine(),
551 this.connectMethod.getResponseHeaderGroup(),
552 this.connectMethod.getResponseBodyAsStream()
553 );
554 method.getProxyAuthState().setAuthScheme(
555 this.connectMethod.getProxyAuthState().getAuthScheme());
556 this.connectMethod = null;
557 } else {
558 releaseConnection = true;
559 LOG.warn(
560 "Unable to fake response on method as it is not derived from HttpMethodBase.");
561 }
562 }
563
564 /***
565 * Process the redirect response.
566 *
567 * @return <code>true</code> if the redirect was successful
568 */
569 private boolean processRedirectResponse(final HttpMethod method)
570 throws RedirectException {
571
572 Header locationHeader = method.getResponseHeader("location");
573 if (locationHeader == null) {
574
575 LOG.error("Received redirect response " + method.getStatusCode()
576 + " but no location header");
577 return false;
578 }
579 String location = locationHeader.getValue();
580 if (LOG.isDebugEnabled()) {
581 LOG.debug("Redirect requested to location '" + location + "'");
582 }
583
584
585
586 URI redirectUri = null;
587 URI currentUri = null;
588
589 try {
590 currentUri = new URI(
591 this.conn.getProtocol().getScheme(),
592 null,
593 this.conn.getHost(),
594 this.conn.getPort(),
595 method.getPath()
596 );
597 redirectUri = new URI(location, true);
598 if (redirectUri.isRelativeURI()) {
599 if (this.params.isParameterTrue(HttpClientParams.REJECT_RELATIVE_REDIRECT)) {
600 LOG.warn("Relative redirect location '" + location + "' not allowed");
601 return false;
602 } else {
603
604 LOG.debug("Redirect URI is not absolute - parsing as relative");
605 redirectUri = new URI(currentUri, redirectUri);
606 }
607 }
608 method.setURI(redirectUri);
609 hostConfiguration.setHost(redirectUri);
610 } catch (URIException e) {
611 LOG.warn("Redirected location '" + location + "' is malformed");
612 return false;
613 }
614
615 if (this.params.isParameterFalse(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS)) {
616 if (this.redirectLocations == null) {
617 this.redirectLocations = new HashSet();
618 }
619 this.redirectLocations.add(currentUri);
620 try {
621 if(redirectUri.hasQuery()) {
622 redirectUri.setQuery(null);
623 }
624 } catch (URIException e) {
625
626 return false;
627 }
628
629 if (this.redirectLocations.contains(redirectUri)) {
630 throw new CircularRedirectException("Circular redirect to '" +
631 redirectUri + "'");
632 }
633 }
634
635 if (LOG.isDebugEnabled()) {
636 LOG.debug("Redirecting from '" + currentUri.getEscapedURI()
637 + "' to '" + redirectUri.getEscapedURI());
638 }
639
640 method.getHostAuthState().invalidate();
641 return true;
642 }
643
644 /***
645 * Processes a response that requires authentication
646 *
647 * @param method the current {@link HttpMethod HTTP method}
648 *
649 * @return <tt>true</tt> if the authentication challenge can be responsed to,
650 * (that is, at least one of the requested authentication scheme is supported,
651 * and matching credentials have been found), <tt>false</tt> otherwise.
652 */
653 private boolean processAuthenticationResponse(final HttpMethod method) {
654 LOG.trace("enter HttpMethodBase.processAuthenticationResponse("
655 + "HttpState, HttpConnection)");
656
657 try {
658 switch (method.getStatusCode()) {
659 case HttpStatus.SC_UNAUTHORIZED:
660 return processWWWAuthChallenge(method);
661 case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED:
662 return processProxyAuthChallenge(method);
663 default:
664 return false;
665 }
666 } catch (Exception e) {
667 if (LOG.isErrorEnabled()) {
668 LOG.error(e.getMessage(), e);
669 }
670 return false;
671 }
672 }
673
674 private boolean processWWWAuthChallenge(final HttpMethod method)
675 throws MalformedChallengeException, AuthenticationException
676 {
677 AuthState authstate = method.getHostAuthState();
678 Map challenges = AuthChallengeParser.parseChallenges(
679 method.getResponseHeaders(WWW_AUTH_CHALLENGE));
680 if (challenges.isEmpty()) {
681 LOG.debug("Authentication challenge(s) not found");
682 return false;
683 }
684 AuthScheme authscheme = null;
685 try {
686 authscheme = this.authProcessor.processChallenge(authstate, challenges);
687 } catch (AuthChallengeException e) {
688 if (LOG.isWarnEnabled()) {
689 LOG.warn(e.getMessage());
690 }
691 }
692 if (authscheme == null) {
693 return false;
694 }
695 String host = method.getParams().getVirtualHost();
696 if (host == null) {
697 host = conn.getHost();
698 }
699 int port = conn.getPort();
700 AuthScope authscope = new AuthScope(
701 host, port,
702 authscheme.getRealm(),
703 authscheme.getSchemeName());
704
705 if (LOG.isDebugEnabled()) {
706 LOG.debug("Authentication scope: " + authscope);
707 }
708 if (authstate.isAuthAttempted() && authscheme.isComplete()) {
709
710 Credentials credentials = promptForCredentials(
711 authscheme, method.getParams(), authscope);
712 if (credentials == null) {
713 if (LOG.isInfoEnabled()) {
714 LOG.info("Failure authenticating with " + authscope);
715 }
716 return false;
717 } else {
718 return true;
719 }
720 } else {
721 authstate.setAuthAttempted(true);
722 Credentials credentials = this.state.getCredentials(authscope);
723 if (credentials == null) {
724 credentials = promptForCredentials(
725 authscheme, method.getParams(), authscope);
726 }
727 if (credentials == null) {
728 if (LOG.isInfoEnabled()) {
729 LOG.info("No credentials available for " + authscope);
730 }
731 return false;
732 } else {
733 return true;
734 }
735 }
736 }
737
738 private boolean processProxyAuthChallenge(final HttpMethod method)
739 throws MalformedChallengeException, AuthenticationException
740 {
741 AuthState authstate = method.getProxyAuthState();
742 Map proxyChallenges = AuthChallengeParser.parseChallenges(
743 method.getResponseHeaders(PROXY_AUTH_CHALLENGE));
744 if (proxyChallenges.isEmpty()) {
745 LOG.debug("Proxy authentication challenge(s) not found");
746 return false;
747 }
748 AuthScheme authscheme = null;
749 try {
750 authscheme = this.authProcessor.processChallenge(authstate, proxyChallenges);
751 } catch (AuthChallengeException e) {
752 if (LOG.isWarnEnabled()) {
753 LOG.warn(e.getMessage());
754 }
755 }
756 if (authscheme == null) {
757 return false;
758 }
759 AuthScope authscope = new AuthScope(
760 conn.getProxyHost(), conn.getProxyPort(),
761 authscheme.getRealm(),
762 authscheme.getSchemeName());
763
764 if (LOG.isDebugEnabled()) {
765 LOG.debug("Proxy authentication scope: " + authscope);
766 }
767 if (authstate.isAuthAttempted() && authscheme.isComplete()) {
768
769 Credentials credentials = promptForProxyCredentials(
770 authscheme, method.getParams(), authscope);
771 if (credentials == null) {
772 if (LOG.isInfoEnabled()) {
773 LOG.info("Failure authenticating with " + authscope);
774 }
775 return false;
776 } else {
777 return true;
778 }
779 } else {
780 authstate.setAuthAttempted(true);
781 Credentials credentials = this.state.getProxyCredentials(authscope);
782 if (credentials == null) {
783 credentials = promptForProxyCredentials(
784 authscheme, method.getParams(), authscope);
785 }
786 if (credentials == null) {
787 if (LOG.isInfoEnabled()) {
788 LOG.info("No credentials available for " + authscope);
789 }
790 return false;
791 } else {
792 return true;
793 }
794 }
795 }
796
797 /***
798 * Tests if the {@link HttpMethod method} requires a redirect to another location.
799 *
800 * @param method HTTP method
801 *
802 * @return boolean <tt>true</tt> if a retry is needed, <tt>false</tt> otherwise.
803 */
804 private boolean isRedirectNeeded(final HttpMethod method) {
805 switch (method.getStatusCode()) {
806 case HttpStatus.SC_MOVED_TEMPORARILY:
807 case HttpStatus.SC_MOVED_PERMANENTLY:
808 case HttpStatus.SC_SEE_OTHER:
809 case HttpStatus.SC_TEMPORARY_REDIRECT:
810 LOG.debug("Redirect required");
811 if (method.getFollowRedirects()) {
812 return true;
813 } else {
814 LOG.info("Redirect requested but followRedirects is "
815 + "disabled");
816 return false;
817 }
818 default:
819 return false;
820 }
821 }
822
823 /***
824 * Tests if the {@link HttpMethod method} requires authentication.
825 *
826 * @param method HTTP method
827 *
828 * @return boolean <tt>true</tt> if a retry is needed, <tt>false</tt> otherwise.
829 */
830 private boolean isAuthenticationNeeded(final HttpMethod method) {
831 method.getHostAuthState().setAuthRequested(
832 method.getStatusCode() == HttpStatus.SC_UNAUTHORIZED);
833 method.getProxyAuthState().setAuthRequested(
834 method.getStatusCode() == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED);
835 if (method.getHostAuthState().isAuthRequested() ||
836 method.getProxyAuthState().isAuthRequested()) {
837 LOG.debug("Authorization required");
838 if (method.getDoAuthentication()) {
839 return true;
840 } else {
841 LOG.info("Authentication requested but doAuthentication is "
842 + "disabled");
843 return false;
844 }
845 } else {
846 return false;
847 }
848 }
849
850 private Credentials promptForCredentials(
851 final AuthScheme authScheme,
852 final HttpParams params,
853 final AuthScope authscope)
854 {
855 LOG.debug("Credentials required");
856 Credentials creds = null;
857 CredentialsProvider credProvider =
858 (CredentialsProvider)params.getParameter(CredentialsProvider.PROVIDER);
859 if (credProvider != null) {
860 try {
861 creds = credProvider.getCredentials(
862 authScheme, authscope.getHost(), authscope.getPort(), false);
863 } catch (CredentialsNotAvailableException e) {
864 LOG.warn(e.getMessage());
865 }
866 if (creds != null) {
867 this.state.setCredentials(authscope, creds);
868 if (LOG.isDebugEnabled()) {
869 LOG.debug(authscope + " new credentials given");
870 }
871 }
872 } else {
873 LOG.debug("Credentials provider not available");
874 }
875 return creds;
876 }
877
878 private Credentials promptForProxyCredentials(
879 final AuthScheme authScheme,
880 final HttpParams params,
881 final AuthScope authscope)
882 {
883 LOG.debug("Proxy credentials required");
884 Credentials creds = null;
885 CredentialsProvider credProvider =
886 (CredentialsProvider)params.getParameter(CredentialsProvider.PROVIDER);
887 if (credProvider != null) {
888 try {
889 creds = credProvider.getCredentials(
890 authScheme, authscope.getHost(), authscope.getPort(), true);
891 } catch (CredentialsNotAvailableException e) {
892 LOG.warn(e.getMessage());
893 }
894 if (creds != null) {
895 this.state.setProxyCredentials(authscope, creds);
896 if (LOG.isDebugEnabled()) {
897 LOG.debug(authscope + " new credentials given");
898 }
899 }
900 } else {
901 LOG.debug("Proxy credentials provider not available");
902 }
903 return creds;
904 }
905
906 /***
907 * @return
908 */
909 public HostConfiguration getHostConfiguration() {
910 return hostConfiguration;
911 }
912
913 /***
914 * @return
915 */
916 public HttpState getState() {
917 return state;
918 }
919
920 /***
921 * @return
922 */
923 public HttpConnectionManager getConnectionManager() {
924 return connectionManager;
925 }
926
927 /***
928 * @return
929 */
930 public HttpParams getParams() {
931 return this.params;
932 }
933 }