public final ActionForward perform(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { HttpSession session = request.getSession(); ActionForward forward = null; if (isTokenValid(request)) { // Reset token and session attributes reset(request); try { // Perform the action and store the results forward = performSynchro(mapping, form, request, response); session.setAttribute(FORM_KEY, form); session.setAttribute(FORWARD_KEY, forward); ActionErrors errors = (ActionErrors) request.getAttribute(Action.ERROR_KEY); if (errors != null && !errors.empty()) { saveToken(request); } session.setAttribute(ERRORS_KEY, errors); session.setAttribute(COMPLETE_KEY, "true"); } catch (IOException e) { // Store and rethrow the exception session.setAttribute(EXCEPTION_KEY, e); session.setAttribute(COMPLETE_KEY, "true"); throw e; } catch (ServletException e) { // Store and rethrow the exception session.setAttribute(EXCEPTION_KEY, e); session.setAttribute(COMPLETE_KEY, "true"); throw e; } } else { // If the action is complete if ("true".equals(session.getAttribute(COMPLETE_KEY))) { // Obtain the exception from the session Exception e = (Exception) session.getAttribute(EXCEPTION_KEY); // If it is not null, throw it if (e != null) { if (e instanceof IOException) { throw (IOException) e; } else if (e instanceof ServletException) { throw (ServletException) e; } } // Obtain the form from the session ActionForm f = (ActionForm) session.getAttribute(FORM_KEY); // Set it in the appropriate context if ("request".equals(mapping.getScope())) { request.setAttribute(mapping.getAttribute(), f); } else { session.setAttribute(mapping.getAttribute(), f); } // Obtain and save the errors from the session saveErrors(request, (ActionErrors) session.getAttribute(ERRORS_KEY)); // Obtain the forward from the session forward = (ActionForward) session.getAttribute(FORWARD_KEY); } else { // Perform the appropriate action in case of token error forward = performInvalidToken(mapping, form, request, response); } } return forward; }