/**
   * SystemException例外ハンドラのエントリポイント。
   *
   * @param ex 例外
   * @param eConfig 例外コンフィグ
   * @param mapping アクションマッピング
   * @param formInstance アクションフォーム
   * @param request HTTPリクエスト
   * @param response HTTPレスポンス
   * @return 遷移情報
   * @throws ServletException サーブレット例外
   * @see jp.terasoluna.fw.web.struts.action.DefaultExceptionHandler#execute( java.lang.Exception,
   *     org.apache.struts.config.ExceptionConfig, org.apache.struts.action.ActionMapping,
   *     org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest,
   *     javax.servlet.http.HttpServletResponse )
   */
  @Override
  public ActionForward execute(
      Exception ex,
      ExceptionConfig eConfig,
      ActionMapping mapping,
      ActionForm formInstance,
      HttpServletRequest request,
      HttpServletResponse response)
      throws ServletException {
    // 【フォワード先を設定する】
    // pathによるフォワード先が指定されない場合は、
    // アクションマッピングのinput属性をデフォルトとする。
    String path = null;
    if (eConfig.getPath() != null) {
      path = eConfig.getPath();
    } else {
      path = mapping.getInput();
    }
    ActionForward forward = new ActionForward(path);
    String logLevel = null;

    // 【遷移先を設定する】
    if (eConfig instanceof ExceptionConfigEx) {
      // 遷移先モジュールが設定されているとき、モジュール名を設定する
      forward.setModule(((ExceptionConfigEx) eConfig).getModule());
      // ログレベルを取得する
      logLevel = ((ExceptionConfigEx) eConfig).getLogLevel();
    }

    // 【SystemExceptionの場合、エラーキーとエラーメッセージの置換を行う】
    if (ex instanceof SystemException) {
      SystemException se = (SystemException) ex;

      // 【リクエストからメッセージリソースを取得する。】
      MessageResources resources = null;

      // スコープからメッセージリソースを取得する際のバンドルキーを取得する。
      String bundle = eConfig.getBundle();
      if (bundle == null) {
        // struts-config.xmlのmessage-resourcesで
        // bundle属性が指定されていない場合、
        // デフォルトのバンドルキーを設定する
        bundle = Globals.MESSAGES_KEY;
      }

      // リクエスト属性からの取得を試みる。
      resources = (MessageResources) request.getAttribute(bundle);
      if (resources == null) {
        // リクエスト属性になければアプリケーション属性からの取得を試みる。
        resources = (MessageResources) RequestUtil.getServletContext(request).getAttribute(bundle);
      }

      // 【エラーキーとエラーメッセージの置換を行う】
      // SystemExceptionのエラーキーをエラーメッセージに置換する。
      String message = null;
      if (resources == null) {
        // リソース取得できない場合はエラーキーをメッセージとする
        message = se.getErrorCode();
      } else {
        message = getErrorMessage(request, se, resources);
      }
      se.setMessage(message);

      // 【画面表示用にActionMessageを設定する】
      String key = eConfig.getKey();
      ActionMessage error = null;
      if (resources != null) {
        // エラーメッセージの置換文字列を取得する
        String[] options = se.getOptions();

        if (options != null && options.length > 0) {
          error = new ActionMessage(key, options);
        } else {
          error = new ActionMessage(key);
        }
      } else {
        // 画面であってもメッセージリソースが無い場合はエラーキーをメッセージにする
        error = new ActionMessage(key, false);
      }
      super.storeException(request, key, error, forward, eConfig.getScope());

      // 変換された例外メッセージ、スタックトレースと
      // セッションハッシュ値をログに出力
      String sessionHash = RequestUtil.getSessionHash(request);
      logException(logLevel, "sessionHash = " + sessionHash);
      logException(logLevel, ExceptionUtil.getStackTrace(se));

      // 【置換済のSystemExceptionを設定する】
      // システム例外をJSPエラーページで exception として
      // 取得できるように request に設定する
      request.setAttribute(PageContext.EXCEPTION, se);
    }

    // システムエラー時は、アクションマッピングの設定に沿って遷移する。
    return forward;
  }