/**
   * Populate the properties of the specified <code>ActionForm</code> instance from the request
   * parameters included with this request. In addition, request attribute <code>Globals.CANCEL_KEY
   * </code> will be set if the request was submitted with a button created by <code>CancelTag
   * </code>.
   *
   * @param request The servlet request we are processing
   * @param response The servlet response we are creating
   * @param form The ActionForm instance we are populating
   * @param mapping The ActionMapping we are using
   * @throws ServletException if thrown by RequestUtils.populate()
   */
  protected void processPopulate(
      HttpServletRequest request,
      HttpServletResponse response,
      ActionForm form,
      ActionMapping mapping)
      throws ServletException {
    if (form == null) {
      return;
    }

    // Populate the bean properties of this ActionForm instance
    if (log.isDebugEnabled()) {
      log.debug(" Populating bean properties from this request");
    }

    form.setServlet(this.servlet);
    form.reset(mapping, request);

    if (mapping.getMultipartClass() != null) {
      request.setAttribute(Globals.MULTIPART_KEY, mapping.getMultipartClass());
    }

    RequestUtils.populate(form, mapping.getPrefix(), mapping.getSuffix(), request);

    // Set the cancellation request attribute if appropriate
    if ((request.getParameter(Globals.CANCEL_PROPERTY) != null)
        || (request.getParameter(Globals.CANCEL_PROPERTY_X) != null)) {
      request.setAttribute(Globals.CANCEL_KEY, Boolean.TRUE);
    }
  }
  /**
   * If this request was not cancelled, and the request's {@link ActionMapping} has not disabled
   * validation, call the <code>validate</code> method of the specified {@link ActionForm}, and
   * forward to the input path if there were any errors. Return <code>true</code> if we should
   * continue processing, or <code>false</code> if we have already forwarded control back to the
   * input form.
   *
   * @param request The servlet request we are processing
   * @param response The servlet response we are creating
   * @param form The ActionForm instance we are populating
   * @param mapping The ActionMapping we are using
   * @return <code>true</code> to continue normal processing; <code>false</code> if a response has
   *     been created.
   * @throws IOException if an input/output error occurs
   * @throws ServletException if a servlet exception occurs
   * @throws InvalidCancelException if a cancellation is attempted without the proper action
   *     configuration.
   */
  protected boolean processValidate(
      HttpServletRequest request,
      HttpServletResponse response,
      ActionForm form,
      ActionMapping mapping)
      throws IOException, ServletException, InvalidCancelException {
    if (form == null) {
      return (true);
    }

    // Has validation been turned off for this mapping?
    if (!mapping.getValidate()) {
      return (true);
    }

    // Was this request cancelled? If it has been, the mapping also
    // needs to state whether the cancellation is permissable; otherwise
    // the cancellation is considered to be a symptom of a programmer
    // error or a spoof.
    if (request.getAttribute(Globals.CANCEL_KEY) != null) {
      if (mapping.getCancellable()) {
        if (log.isDebugEnabled()) {
          log.debug(" Cancelled transaction, skipping validation");
        }
        return (true);
      } else {
        request.removeAttribute(Globals.CANCEL_KEY);
        throw new InvalidCancelException();
      }
    }

    // Call the form bean's validation method
    if (log.isDebugEnabled()) {
      log.debug(" Validating input form properties");
    }

    ActionMessages errors = form.validate(mapping, request);

    if ((errors == null) || errors.isEmpty()) {
      if (log.isTraceEnabled()) {
        log.trace("  No errors detected, accepting input");
      }

      return (true);
    }

    // Special handling for multipart request
    if (form.getMultipartRequestHandler() != null) {
      if (log.isTraceEnabled()) {
        log.trace("  Rolling back multipart request");
      }

      form.getMultipartRequestHandler().rollback();
    }

    // Was an input path (or forward) specified for this mapping?
    String input = mapping.getInput();

    if (input == null) {
      if (log.isTraceEnabled()) {
        log.trace("  Validation failed but no input form available");
      }

      response.sendError(
          HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
          getInternal().getMessage("noInput", mapping.getPath()));

      return (false);
    }

    // Save our error messages and return to the input form if possible
    if (log.isDebugEnabled()) {
      log.debug(" Validation failed, returning to '" + input + "'");
    }

    request.setAttribute(Globals.ERROR_KEY, errors);

    if (moduleConfig.getControllerConfig().getInputForward()) {
      ForwardConfig forward = mapping.findForward(input);

      processForwardConfig(request, response, forward);
    } else {
      internalModuleRelativeForward(input, request, response);
    }

    return (false);
  }