/**
   * Perform access control based on the specified authorization constraint. Return <code>true
   * </code> if this constraint is satisfied and processing should continue, or <code>false</code>
   * otherwise.
   *
   * @param request Request we are processing
   * @param response Response we are creating
   * @param constraint Security constraint we are enforcing
   * @exception IOException if an input/output error occurs
   */
  protected boolean accessControl(
      HttpRequest request, HttpResponse response, SecurityConstraint constraint)
      throws IOException {

    if (constraint == null) return (true);

    // Specifically allow access to the form login and form error pages
    // and the "j_security_check" action
    LoginConfig config = context.getLoginConfig();
    if ((config != null) && (Constants.FORM_METHOD.equals(config.getAuthMethod()))) {
      String requestURI = request.getDecodedRequestURI();
      String loginPage = context.getPath() + config.getLoginPage();
      if (loginPage.equals(requestURI)) {
        if (debug >= 1) log(" Allow access to login page " + loginPage);
        return (true);
      }
      String errorPage = context.getPath() + config.getErrorPage();
      if (errorPage.equals(requestURI)) {
        if (debug >= 1) log(" Allow access to error page " + errorPage);
        return (true);
      }
      if (requestURI.endsWith(Constants.FORM_ACTION)) {
        if (debug >= 1) log(" Allow access to username/password submission");
        return (true);
      }
    }

    // Which user principal have we already authenticated?
    Principal principal = ((HttpServletRequest) request.getRequest()).getUserPrincipal();
    if (principal == null) {
      if (debug >= 2) log("  No user authenticated, cannot grant access");
      ((HttpServletResponse) response.getResponse())
          .sendError(
              HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
              sm.getString("authenticator.notAuthenticated"));
      return (false);
    }

    // Check each role included in this constraint
    Realm realm = context.getRealm();
    String roles[] = constraint.findAuthRoles();
    if (roles == null) roles = new String[0];

    if (constraint.getAllRoles()) return (true);
    if ((roles.length == 0) && (constraint.getAuthConstraint())) {
      ((HttpServletResponse) response.getResponse())
          .sendError(HttpServletResponse.SC_FORBIDDEN, sm.getString("authenticator.forbidden"));
      return (false); // No listed roles means no access at all
    }
    for (int i = 0; i < roles.length; i++) {
      if (realm.hasRole(principal, roles[i])) return (true);
    }

    // Return a "Forbidden" message denying access to this resource
    ((HttpServletResponse) response.getResponse())
        .sendError(HttpServletResponse.SC_FORBIDDEN, sm.getString("authenticator.forbidden"));
    return (false);
  }
  /**
   * Perform access control based on the specified authorization constraint. Return <code>true
   * </code> if this constraint is satisfied and processing should continue, or <code>false</code>
   * otherwise.
   *
   * @param request Request we are processing
   * @param response Response we are creating
   * @param constraints Security constraint we are enforcing
   * @param context The Context to which client of this class is attached.
   * @exception IOException if an input/output error occurs
   */
  @Override
  public boolean hasResourcePermission(
      Request request, Response response, SecurityConstraint[] constraints, Context context)
      throws IOException {

    if (constraints == null || constraints.length == 0) return (true);

    // Specifically allow access to the form login and form error pages
    // and the "j_security_check" action
    LoginConfig config = context.getLoginConfig();
    if ((config != null) && (Constants.FORM_METHOD.equals(config.getAuthMethod()))) {
      String requestURI = request.getRequestPathMB().toString();
      String loginPage = config.getLoginPage();
      if (loginPage.equals(requestURI)) {
        if (log.isDebugEnabled()) log.debug(" Allow access to login page " + loginPage);
        return (true);
      }
      String errorPage = config.getErrorPage();
      if (errorPage.equals(requestURI)) {
        if (log.isDebugEnabled()) log.debug(" Allow access to error page " + errorPage);
        return (true);
      }
      if (requestURI.endsWith(Constants.FORM_ACTION)) {
        if (log.isDebugEnabled()) log.debug(" Allow access to username/password submission");
        return (true);
      }
    }

    // Which user principal have we already authenticated?
    Principal principal = request.getPrincipal();
    boolean status = false;
    boolean denyfromall = false;
    for (int i = 0; i < constraints.length; i++) {
      SecurityConstraint constraint = constraints[i];

      String roles[];
      if (constraint.getAllRoles()) {
        // * means all roles defined in web.xml
        roles = request.getContext().findSecurityRoles();
      } else {
        roles = constraint.findAuthRoles();
      }

      if (roles == null) roles = new String[0];

      if (log.isDebugEnabled()) log.debug("  Checking roles " + principal);

      if (roles.length == 0 && !constraint.getAllRoles()) {
        if (constraint.getAuthConstraint()) {
          if (log.isDebugEnabled()) log.debug("No roles");
          status = false; // No listed roles means no access at all
          denyfromall = true;
          break;
        }

        if (log.isDebugEnabled()) log.debug("Passing all access");
        status = true;
      } else if (principal == null) {
        if (log.isDebugEnabled()) log.debug("  No user authenticated, cannot grant access");
      } else {
        for (int j = 0; j < roles.length; j++) {
          if (hasRole(null, principal, roles[j])) {
            status = true;
            if (log.isDebugEnabled()) log.debug("Role found:  " + roles[j]);
          } else if (log.isDebugEnabled()) log.debug("No role found:  " + roles[j]);
        }
      }
    }

    if (!denyfromall && allRolesMode != AllRolesMode.STRICT_MODE && !status && principal != null) {
      if (log.isDebugEnabled()) {
        log.debug("Checking for all roles mode: " + allRolesMode);
      }
      // Check for an all roles(role-name="*")
      for (int i = 0; i < constraints.length; i++) {
        SecurityConstraint constraint = constraints[i];
        String roles[];
        // If the all roles mode exists, sets
        if (constraint.getAllRoles()) {
          if (allRolesMode == AllRolesMode.AUTH_ONLY_MODE) {
            if (log.isDebugEnabled()) {
              log.debug("Granting access for role-name=*, auth-only");
            }
            status = true;
            break;
          }

          // For AllRolesMode.STRICT_AUTH_ONLY_MODE there must be zero roles
          roles = request.getContext().findSecurityRoles();
          if (roles.length == 0 && allRolesMode == AllRolesMode.STRICT_AUTH_ONLY_MODE) {
            if (log.isDebugEnabled()) {
              log.debug("Granting access for role-name=*, strict auth-only");
            }
            status = true;
            break;
          }
        }
      }
    }

    // Return a "Forbidden" message denying access to this resource
    if (!status) {
      response.sendError(HttpServletResponse.SC_FORBIDDEN, sm.getString("realmBase.forbidden"));
    }
    return status;
  }