public Queue<AuthOption> select(
      Map<String, Header> challenges, HttpHost authhost, HttpResponse response, HttpContext context)
      throws MalformedChallengeException {
    Args.notNull(challenges, "Map of auth challenges");
    Args.notNull(authhost, "Host");
    Args.notNull(response, "HTTP response");
    Args.notNull(context, "HTTP context");
    HttpClientContext clientContext = HttpClientContext.adapt(context);

    Queue<AuthOption> options = new LinkedList();
    Lookup<AuthSchemeProvider> registry = clientContext.getAuthSchemeRegistry();
    if (registry == null) {
      this.log.debug("Auth scheme registry not set in the context");
      return options;
    }
    CredentialsProvider credsProvider = clientContext.getCredentialsProvider();
    if (credsProvider == null) {
      this.log.debug("Credentials provider not set in the context");
      return options;
    }
    RequestConfig config = clientContext.getRequestConfig();
    Collection<String> authPrefs = getPreferredAuthSchemes(config);
    if (authPrefs == null) {
      authPrefs = DEFAULT_SCHEME_PRIORITY;
    }
    if (this.log.isDebugEnabled()) {
      this.log.debug("Authentication schemes in the order of preference: " + authPrefs);
    }
    for (String id : authPrefs) {
      Header challenge = (Header) challenges.get(id.toLowerCase(Locale.US));
      if (challenge != null) {
        AuthSchemeProvider authSchemeProvider = (AuthSchemeProvider) registry.lookup(id);
        if (authSchemeProvider == null) {
          if (this.log.isWarnEnabled()) {
            this.log.warn("Authentication scheme " + id + " not supported");
          }
        } else {
          AuthScheme authScheme = authSchemeProvider.create(context);
          authScheme.processChallenge(challenge);

          AuthScope authScope =
              new AuthScope(
                  authhost.getHostName(),
                  authhost.getPort(),
                  authScheme.getRealm(),
                  authScheme.getSchemeName());

          Credentials credentials = credsProvider.getCredentials(authScope);
          if (credentials != null) {
            options.add(new AuthOption(authScheme, credentials));
          }
        }
      } else if (this.log.isDebugEnabled()) {
        this.log.debug("Challenge for " + id + " authentication scheme not available");
      }
    }
    return options;
  }
  public void authFailed(HttpHost authhost, AuthScheme authScheme, HttpContext context) {
    Args.notNull(authhost, "Host");
    Args.notNull(context, "HTTP context");

    HttpClientContext clientContext = HttpClientContext.adapt(context);

    AuthCache authCache = clientContext.getAuthCache();
    if (authCache != null) {
      if (this.log.isDebugEnabled()) {
        this.log.debug("Clearing cached auth scheme for " + authhost);
      }
      authCache.remove(authhost);
    }
  }
  public void authSucceeded(HttpHost authhost, AuthScheme authScheme, HttpContext context) {
    Args.notNull(authhost, "Host");
    Args.notNull(authScheme, "Auth scheme");
    Args.notNull(context, "HTTP context");

    HttpClientContext clientContext = HttpClientContext.adapt(context);
    if (isCachable(authScheme)) {
      AuthCache authCache = clientContext.getAuthCache();
      if (authCache == null) {
        authCache = new BasicAuthCache();
        clientContext.setAuthCache(authCache);
      }
      if (this.log.isDebugEnabled()) {
        this.log.debug("Caching '" + authScheme.getSchemeName() + "' auth scheme for " + authhost);
      }
      authCache.put(authhost, authScheme);
    }
  }