public static void onApplicationEnd(cfApplicationData appData) {
    String applicationCfcPath = appData.getApplicationCfcPath();
    if (applicationCfcPath == null) return;

    cfSession session =
        new cfSession(
            new dummyServletRequest(appData.getWebroot()),
            new dummyServletResponse(),
            cfEngine.thisServletContext);
    cfComponentData applicationCfc = null;

    try {
      cfFile applicationFile = session.getRealFile(applicationCfcPath);
      applicationFile.setComponentName("Application");

      applicationCfc =
          new cfComponentData(session, applicationFile, false); // false = don't allow abstract

      List<cfApplicationData> args = new ArrayList<cfApplicationData>();
      args.add(appData); // ApplicationScope

      cfcMethodData methodData = new cfcMethodData(session, ON_APPLICATION_END, args);
      applicationCfc.invokeApplicationFunction(session, methodData);

    } catch (cfmAbortException ignore) {
      // do nothing, we're finished anyway (catch here so it's not caught as Throwable below)
    } catch (cfmRunTimeException e) {
      try {
        session.invokeOnError(applicationCfc, e, ON_APPLICATION_END);
      } catch (cfmRunTimeException ie) {
        cfEngine.log("RunTimeError in onApplicationEnd: " + applicationCfcPath);
        ie.handleException(session);
      }
    } catch (Throwable t) {
      com.nary.Debug.printStackTrace(t);
      new cfmRunTimeException(session, t).handleException(session);
    } finally {
      // Make sure per request connections are closed (bug #3174)
      session.sessionEnd();
    }
  }
  public void loadApplication(cfComponentData applicationCfc, cfSession session)
      throws cfmRunTimeException {
    cfData appName = applicationCfc.getData("NAME");
    cfApplicationData appData =
        getAppData(session, appName == null ? cfAPPLICATION.UNNAMED_APPNAME : appName.toString());

    String scriptProtect = null;
    if (applicationCfc.containsKey(cfAPPLICATION.SCRIPTPROTECT)) {
      scriptProtect = applicationCfc.getData(cfAPPLICATION.SCRIPTPROTECT).getString();
    }

    // Set up the specific application mappings
    if (applicationCfc.containsKey(cfAPPLICATION.MAPPINGS)) {
      cfData mappingsData = (cfData) applicationCfc.getData(cfAPPLICATION.MAPPINGS);
      if (mappingsData.getDataType() == cfData.CFSTRUCTDATA) {
        session.setDataBin(cfAPPLICATION.MAPPINGS, mappingsData);
      }
    }

    // Set up the specific application customtagpaths
    if (applicationCfc.containsKey(cfAPPLICATION.CUSTOMTAGPATHS)) {
      cfData mappingsData = (cfData) applicationCfc.getData(cfAPPLICATION.CUSTOMTAGPATHS);
      if (mappingsData.getDataType() == cfData.CFSTRINGDATA) {
        session.setDataBin(cfAPPLICATION.CUSTOMTAGPATHS, mappingsData.getString());
      }
    }

    String datasource = null;
    if (applicationCfc.containsKey(cfAPPLICATION.DATASOURCE))
      datasource = applicationCfc.getData(cfAPPLICATION.DATASOURCE).getString();

    String sessionstorage = null;
    if (applicationCfc.containsKey(cfAPPLICATION.SESSIONSTORAGE))
      sessionstorage = applicationCfc.getData(cfAPPLICATION.SESSIONSTORAGE).getString();

    appData.onRequestStart(
        session,
        bJ2EESessionManagement,
        (long)
            (applicationCfc.getData(cfAPPLICATION.APPLICATIONTIMEOUT).getDouble()
                * DateUtils.MILLIS_PER_DAY),
        (long)
            (applicationCfc.getData(cfAPPLICATION.SESSIONTIMEOUT).getDouble()
                * DateUtils.MILLIS_PER_DAY),
        applicationCfc.getData(cfAPPLICATION.SETCLIENTCOOKIES).getBoolean(),
        applicationCfc.getData(cfAPPLICATION.SETDOMAINCOOKIES).getBoolean(),
        applicationCfc.getData(cfAPPLICATION.SESSIONMANAGEMENT).getBoolean(),
        applicationCfc.getData(cfAPPLICATION.CLIENTMANAGEMENT).getBoolean(),
        applicationCfc.getData(cfAPPLICATION.CLIENTSTORAGE).getString(),
        applicationCfc.getData(cfAPPLICATION.LOGINSTORAGE).getString(),
        applicationCfc.getComponentPath(),
        scriptProtect,
        applicationCfc.getData(cfAPPLICATION.SECUREJSON).getBoolean(),
        applicationCfc.getData(cfAPPLICATION.SECUREJSONPREFIX).getString(),
        datasource,
        sessionstorage,
        applicationCfc);
  }