docs: public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
          List<Callback> toRespondTo = new LinkedList<Callback>();
  
          String userName = null;
          boolean userFound = false;
  
          Properties users = getProperties();
  
          // A single pass may be sufficient but by using a two pass approach the Callbackhandler will not
          // fail if an unexpected order is encountered.
  
          // First Pass - is to double check no unsupported callbacks and to retrieve
          // information from the callbacks passing in information.
          for (Callback current : callbacks) {
  
              if (current instanceof AuthorizeCallback) {
                  toRespondTo.add(current);
              } else if (current instanceof NameCallback) {
                  NameCallback nameCallback = (NameCallback) current;
                  userName = nameCallback.getDefaultName();
                  userFound = users.containsKey(userName);
              } else if (current instanceof PasswordCallback && plainText) {
                  toRespondTo.add(current);
              } else if (current instanceof CredentialCallback) {
                  toRespondTo.add(current);
              } else if (current instanceof EvidenceVerifyCallback && ((EvidenceVerifyCallback)current).getEvidence() instanceof PasswordGuessEvidence) {
                  toRespondTo.add(current);
              } else if (current instanceof RealmCallback) {
                  String realm = ((RealmCallback) current).getDefaultText();
                  if (this.realm.equals(realm) == false) {
                      throw DomainManagementLogger.ROOT_LOGGER.invalidRealm(realm, this.realm);
                  }
              } else {
                  throw new UnsupportedCallbackException(current);
              }
          }
  
          // Second Pass - Now iterate the Callback(s) requiring a response.
          for (Callback current : toRespondTo) {
              if (current instanceof AuthorizeCallback) {
                  AuthorizeCallback acb = (AuthorizeCallback) current;
                  boolean authorized = acb.getAuthenticationID().equals(acb.getAuthorizationID());
                  if (authorized == false) {
                      SECURITY_LOGGER.tracef(
                              "Checking 'AuthorizeCallback', authorized=false, authenticationID=%s, authorizationID=%s.",
                              acb.getAuthenticationID(), acb.getAuthorizationID());
                  }
                  acb.setAuthorized(authorized);
              } else if (current instanceof PasswordCallback) {
                  if (userFound == false) {
                      SECURITY_LOGGER.tracef("User '%s' not found in properties file.", userName);
                      throw new UserNotFoundException(userName);
                  }
                  String password = users.get(userName).toString();
                  ((PasswordCallback) current).setPassword(password.toCharArray());
              } else if (current instanceof CredentialCallback) {
                  if (userFound == false) {
                      SECURITY_LOGGER.tracef("User '%s' not found in properties file.", userName);
                      throw new UserNotFoundException(userName);
                  }
  
                  CredentialCallback cc = (CredentialCallback) current;
                  if (PasswordCredential.class.isAssignableFrom(cc.getCredentialType())) {
                      String algorithmName = cc.getAlgorithm();
                      final Password password;
                      if ((algorithmName == null || ALGORITHM_CLEAR.equals(algorithmName)) && plainText) {
                          password = ClearPassword.createRaw(ALGORITHM_CLEAR, ((String) users.get(userName)).toCharArray());
                      } else if ((algorithmName == null || ALGORITHM_DIGEST_MD5.equals(algorithmName)) && plainText == false) {
                          byte[] hashed = ByteIterator.ofBytes(((String) users.get(userName)).getBytes(StandardCharsets.UTF_8)).asUtf8String().hexDecode().drain();
                          password = DigestPassword.createRaw(ALGORITHM_DIGEST_MD5, userName, realm, hashed);
                      } else {
                          continue;
                      }
                      cc.setCredential(cc.getCredentialType().cast(new PasswordCredential(password)));
                  }
              } else if (current instanceof EvidenceVerifyCallback) {
                  if (userFound == false) {
                      SECURITY_LOGGER.tracef("User '%s' not found in properties file.", userName);
                      throw new UserNotFoundException(userName);
                  }
                  EvidenceVerifyCallback evc = (EvidenceVerifyCallback) current;
                  PasswordGuessEvidence evidence = (PasswordGuessEvidence) evc.getEvidence();
                  char[] guess = evidence.getGuess();
                  if (plainText) {
                      String password = users.get(userName).toString();
                      boolean verified = password.equals(new String(guess));
                      if (verified == false) {
                          SECURITY_LOGGER.tracef("Password verification failed for user '%s'", userName);
                      }
                      evc.setVerified(verified);
                  } else {
                      UsernamePasswordHashUtil hashUtil = getHashUtil();
                      String hash;
                      synchronized (hashUtil) {
                          hash = hashUtil.generateHashedHexURP(userName, realm, guess);
                      }
                      String expected = users.get(userName).toString();
                      boolean verified = expected.equals(hash);
                      if (verified == false) {
                          SECURITY_LOGGER.tracef("Digest verification failed for user '%s'", userName);
                      }
                      evc.setVerified(verified);
                  }
              }
          }
      }