public final void contextDestroyed(@Nonnull final ServletContextEvent aSCE) {
    final ServletContext aSC = aSCE.getServletContext();

    final StopWatch aSW = StopWatch.createdStarted();
    if (s_aLogger.isInfoEnabled())
      s_aLogger.info("Servlet context '" + aSC.getServletContextName() + "' is being destroyed");

    // Callback before global scope end
    beforeContextDestroyed(aSC);

    // Shutdown global scope and destroy all singletons
    WebScopeManager.onGlobalEnd();

    // Callback after global scope end
    afterContextDestroyed(aSC);

    // Handle statistics
    if (isHandleStatisticsOnEnd()) handleStatisticsOnEnd();

    // Reset base path - mainly for testing
    WebFileIO.resetPaths();

    // Clear commons cache also manually - but after destroy because it
    // is used in equals and hashCode implementations
    CommonsCleanup.cleanup();

    // De-init
    s_aInited.set(false);

    if (s_aLogger.isInfoEnabled())
      s_aLogger.info(
          "Servlet context '"
              + aSC.getServletContextName()
              + "' was destroyed in "
              + aSW.stopAndGetMillis()
              + " milli seconds");
  }
  public final void contextInitialized(@Nonnull final ServletContextEvent aSCE) {
    final ServletContext aSC = aSCE.getServletContext();

    if (s_aInited.getAndSet(true))
      throw new IllegalStateException("WebAppListener was already instantiated!");

    final StopWatch aSW = StopWatch.createdStarted();
    m_aInitializationStartDT = PDTFactory.getCurrentLocalDateTime();

    // set global debug/trace mode
    final boolean bDebugMode = StringParser.parseBool(getInitParameterDebug(aSC));
    final boolean bProductionMode = StringParser.parseBool(getInitParameterProduction(aSC));
    GlobalDebug.setDebugModeDirect(bDebugMode);
    GlobalDebug.setProductionModeDirect(bProductionMode);

    final boolean bNoStartupInfo = StringParser.parseBool(getInitParameterNoStartupInfo(aSC));
    if (!bNoStartupInfo) {
      // Requires the global debug things to be present
      logStartupInfo(aSC);
    }

    // StaticServerInfo
    {
      final String sInitParameter = getInitParameterServerURL(aSC, bProductionMode);
      if (StringHelper.hasText(sInitParameter)) {
        final URL aURL = URLHelper.getAsURL(sInitParameter);
        if (aURL != null) {
          StaticServerInfo.init(
              aURL.getProtocol(), aURL.getHost(), aURL.getPort(), aSC.getContextPath());
        } else
          s_aLogger.error(
              "The init-parameter for the server URL"
                  + (bProductionMode ? " (production mode)" : " (non-production mode)")
                  + "contains the non-URL value '"
                  + sInitParameter
                  + "'");
      }
    }

    // Call callback
    beforeContextInitialized(aSC);

    // begin global context
    WebScopeManager.onGlobalBegin(aSC);

    // Init IO
    initPaths(aSC);

    // Set persistent ID provider - must be done after IO is setup
    initGlobalIDFactory();

    // Callback
    afterContextInitialized(aSC);

    // Remember end time
    m_aInitializationEndDT = PDTFactory.getCurrentLocalDateTime();

    // Finally
    if (s_aLogger.isInfoEnabled())
      s_aLogger.info(
          "Servlet context '"
              + aSC.getServletContextName()
              + "' was initialized in "
              + aSW.stopAndGetMillis()
              + " milli seconds");
  }