@Override
  public SecurityChallenge getUserSecurityChallenge(String username) {

    for (LdapServer server : ldapServers) {
      try {
        SecurityChallenge challenge = server.getUserSecurityChallenge(username);
        if (logger.isDebugEnabled()) {
          if (challenge != null) {
            logger.debug(
                "Successfully got security challenge for "
                    + username
                    + " at "
                    + server.getDescription());
          } else {
            logger.debug(
                "Got null security challenge for " + username + " at " + server.getDescription());
          }
        }
        return challenge;
      } catch (NameNotFoundException ex) {
        logger.debug("Didn't find " + username + " in " + server.getDescription());
        // ignore it... try the next server
      } catch (ObjectRetrievalException ex) {
        logger.debug("Multiple results found for " + username);
        // ignore it... try the next server
      }
    }

    throw new NameNotFoundException(
        "Couldn't find username " + username + " in any of provided servers.");
  }
  @Override
  public void setUserPassword(String username, String password) {
    for (LdapServer ldapServer : ldapServers) {
      try {
        ldapServer.setPassword(username, password);
        logger.debug(
            "Successfully set password for " + username + " at " + ldapServer.getDescription());
        return;
      } catch (NameNotFoundException ex) {
        logger.debug("Didn't find " + username + " in " + ldapServer.getDescription());
        // ignore... we'll try another server
      } catch (ObjectRetrievalException ex) {
        logger.debug("Multiple results found for " + username);
        // ignore it... try the next server
      }
    }

    logger.debug("Couldn't find server for " + username);
    throw new NameNotFoundException(
        "Couldn't find username " + username + " in any of provided servers.");
  }
  @Override
  public void setUserSecurityChallenge(String username, SecurityChallenge securityChallenge) {

    for (LdapServer server : ldapServers) {
      try {
        server.setUserSecurityChallenge(username, securityChallenge);
        logger.debug(
            "Successfully set user security challenge for "
                + username
                + " at "
                + server.getDescription());
        return;
      } catch (NameNotFoundException ex) {
        logger.debug("Didn't find " + username + " in " + server.getDescription());
        // ignore it... try the next server
      } catch (ObjectRetrievalException ex) {
        logger.debug("Multiple results found for " + username);
        // ignore it... try the next server
      }
    }

    throw new NameNotFoundException(
        "Couldn't find username " + username + " in any of provided servers.");
  }
  @Override
  public PasswordWarningInfo getPasswordWarningInfo(String username) {

    logger.debug("Getting password warning info for " + username);

    for (LdapServer server : ldapServers) {
      try {
        PasswordWarningInfo passwordWarningInfo = server.getPasswordWarningInfo(username);
        if (logger.isDebugEnabled()) {
          if (passwordWarningInfo != null) {
            logger.debug(
                "Successfully got password warning info for "
                    + username
                    + " at "
                    + server.getDescription());
          } else {
            logger.debug(
                "Got null password warning info for "
                    + username
                    + " at "
                    + server.getDescription());
          }
        }
        return passwordWarningInfo;
      } catch (NameNotFoundException ex) {
        logger.debug("Didn't find " + username + " in " + server.getDescription());
        // ignore it... try the next server
      } catch (ObjectRetrievalException ex) {
        logger.debug("Multiple results found for " + username);
        // ignore it... try the next server
      }
    }

    throw new NameNotFoundException(
        "Couldn't find username " + username + " in any of provided servers.");
  }
  @Override
  public void changeUserPassword(String username, String oldPassword, String newPassword)
      throws UserLockedOutException {

    // throws UserLockedOutException if this isn't allowed
    lockoutService.allowAttempt(username);

    for (LdapServer ldapServer : ldapServers) {
      try {
        if (ldapServer.verifyPassword(username, oldPassword)) {
          ldapServer.setPassword(username, newPassword);
          logger.debug(
              "Successfully changed password for "
                  + username
                  + " at "
                  + ldapServer.getDescription());
          lockoutService.clearIncorrectAttempts(username);
          return;
        }
      } catch (AuthenticationException ex) {
        logger.debug("Didn't find " + username + " in " + ldapServer.getDescription());
        // ignore... we'll try another server
      } catch (NameNotFoundException ex) {
        logger.debug("Didn't find " + username + " in " + ldapServer.getDescription());
        // ignore... we'll try another server
      } catch (ObjectRetrievalException ex) {
        logger.debug("Multiple results found for " + username);
        // ignore it... try the next server
      }
    }

    lockoutService.registerIncorrectAttempt(username);
    logger.debug("Couldn't find server for " + username + " or bad password.");
    throw new NameNotFoundException(
        "Couldn't find username " + username + " in any of provided servers or bad password.");
  }