Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Copyright (C) 2014-2015 Philip Helger (www.helger.com) philip[at]helger[dot]com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
 
 package com.helger.webbasics.servlet;
 
 import java.io.File;
 import java.net.URL;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 
 
This class is intended to handle the initial application startup and the final shutdown. It is also responsible for creating the global and session scopes.

Author(s):
Philip Helger
 
 {
   static
   {
     VirtualMachineInitializer.runInitialization ();
 
     // Ensure that any AWT code runs headless (fonts etc.)
     SystemProperties.setPropertyValue ("java.awt.headless""true");
   }

  
Name of the initialization parameter to enable tracing.
 
   public static final String DEFAULT_INIT_PARAMETER_TRACE = "trace";

  
Name of the initialization parameter to enable debug.
 
   public static final String DEFAULT_INIT_PARAMETER_DEBUG = "debug";

  
Name of the initialization parameter to enable production mode.
 
   public static final String DEFAULT_INIT_PARAMETER_PRODUCTION = "production";

  
Name of the initialization parameter for the storagePath.
 
   public static final String INIT_PARAMETER_STORAGE_PATH = "storagePath";

  
Name of the initialization parameter to disable logging the startup info.
 
   public static final String INIT_PARAMETER_NO_STARTUP_INFO = "noStartupInfo";

  
Name of the initialization parameter that contains the server URL for non-production mode.
  public static final String INIT_PARAMETER_SERVER_URL = "serverUrl";

  
Name of the initialization parameter that contains the server URL for production mode.
  public static final String INIT_PARAMETER_SERVER_URL_PRODUCTION = "serverUrlProduction";

  
Name of the initialization parameter to disable the file access check on startup.
  public static final String INIT_PARAMETER_NO_CHECK_FILE_ACCESS = "noCheckFileAccess";

  
The default file name where the global unique IDs are stored.
  public static final String ID_FILENAME = "persistent_id.dat";

  
The logger to use.
  private static final Logger s_aLogger = LoggerFactory.getLogger (WebAppListener.class);
  private static final AtomicBoolean s_aInited = new AtomicBoolean (false);
  public WebAppListener ()
  {}
  protected final void logServerInfo (@Nonnull final ServletContext aSC)
  {
    // Print Java and Server (e.g. Tomcat) info
    .info ("Java " +
                    SystemProperties.getJavaVersion () +
                    " running '" +
                    aSC.getServletContextName () +
                    "' on " +
                    aSC.getServerInfo () +
                    " with " +
                    (Runtime.getRuntime ().maxMemory () / .) +
                    "MB max RAM and Servlet API " +
                    aSC.getMajorVersion () +
                    "." +
                    aSC.getMinorVersion ());
    // Tell them to use the server VM if possible:
    final EJVMVendor eJVMVendor = EJVMVendor.getCurrentVendor ();
    if (eJVMVendor.isSun () && eJVMVendor != .)
      .warn ("Consider using the Sun Server Runtime by specifiying '-server' on the commandline!");
    if (SystemProperties.getJavaVersion ().startsWith ("1.6.0_14"))
      .warn ("This Java version is bad for development - breakpoints don't work in the debugger!");
  }
  protected final void logClassPath ()
  {
    // List class path elements in trace mode
    if (GlobalDebug.isTraceMode ())
    {
      final List <StringaCP = ClassPathHelper.getAllClassPathEntries ();
      .info ("Class path [" + aCP.size () + " elements]:");
      for (final String sCP : ContainerHelper.getSortedInline (aCP))
        .info ("  " + sCP);
    }
  }
  protected final void logInitParameters (@Nonnull final ServletContext aSC)
  {
    .info ("Servlet context init-parameters:");
    // Put them in a sorted map
    final Map <StringStringaParams = new TreeMap <StringString> ();
    final Enumeration <?> aEnum = aSC.getInitParameterNames ();
    while (aEnum.hasMoreElements ())
    {
      final String sName = (StringaEnum.nextElement ();
      final String sValue = aSC.getInitParameter (sName);
      aParams.put (sNamesValue);
    }
    // Emit them
    for (final Map.Entry <StringStringaEntry : aParams.entrySet ())
      .info ("  " + aEntry.getKey () + "=" + aEntry.getValue ());
  }
  protected final void logThirdpartyModules ()
  {
    // List all third party modules for later evaluation
    final Set <IThirdPartyModuleaModules = ThirdPartyModuleRegistry.getInstance ()
                                                                     .getAllRegisteredThirdPartyModules ();
    if (!aModules.isEmpty ())
    {
      .info ("Using the following third party modules:");
      for (final IThirdPartyModule aModule : ContainerHelper.getSorted (aModules,
                                                                        new ComparatorHasDisplayName <IHasDisplayName> (null)))
        if (!aModule.isOptional ())
        {
          String sMsg = "  " + aModule.getDisplayName ();
          if (aModule.getVersion () != null)
            sMsg += ' ' + aModule.getVersion ().getAsString (true);
          sMsg += " licensed under " + aModule.getLicense ().getDisplayName ();
          if (aModule.getLicense ().getVersion () != null)
            sMsg += ' ' + aModule.getLicense ().getVersion ().getAsString ();
          .info (sMsg);
        }
    }
  }
  protected final void logJMX ()
  {
    if (SystemProperties.getPropertyValueOrNull ("com.sun.management.jmxremote") != null)
    {
      final String sPort = SystemProperties.getPropertyValueOrNull ("com.sun.management.jmxremote.port");
      final String sSSL = SystemProperties.getPropertyValueOrNull ("com.sun.management.jmxremote.ssl");
      final String sAuthenticate = SystemProperties.getPropertyValueOrNull ("com.sun.management.jmxremote.authenticate");
      final String sPasswordFile = SystemProperties.getPropertyValueOrNull ("com.sun.management.jmxremote.password.file");
      final String sAccessFile = SystemProperties.getPropertyValueOrNull ("com.sun.management.jmxremote.access.file");
      .info ("Remote JMX is enabled!");
      if (sPort != null)
        .info ("  Port=" + sPort);
      if (sSSL != null)
        .info ("  SSL enabled=" + sSSL);
      if (sAuthenticate != null)
        .info ("  Authenticate=" + sAuthenticate);
      if (sPasswordFile != null)
        .info ("  Password file=" + sPasswordFile);
      if (sAccessFile != null)
        .info ("  Access file=" + sAccessFile);
    }
  }
  protected void logStartupInfo (@Nonnull final ServletContext aSC)
  {
    logServerInfo (aSC);
    logClassPath ();
    logInitParameters (aSC);
    logJMX ();
  }

  
Callback before init. By default some relevant debug information is emitted

Parameters:
aSC ServletContext
  protected void beforeContextInitialized (@Nonnull final ServletContext aSC)
  {}

  
Callback after init

Parameters:
aSC ServletContext
  protected void afterContextInitialized (@Nonnull final ServletContext aSC)
  {}

  
Get the value of the servlet context init-parameter that represents the trace flag. This value is than converted to a boolean internally.

Parameters:
aSC The servlet context under investigation. Never null.
Returns:
The string value of the trace init-parameter. May be null if no such init-parameter is present.
  protected String getInitParameterTrace (@Nonnull final ServletContext aSC)
  {
  }

  
Get the value of the servlet context init-parameter that represents the debug flag. This value is than converted to a boolean internally.

Parameters:
aSC The servlet context under investigation. Never null.
Returns:
The string value of the debug init-parameter. May be null if no such init-parameter is present.
  protected String getInitParameterDebug (@Nonnull final ServletContext aSC)
  {
  }

  
Get the value of the servlet context init-parameter that represents the production flag. This value is than converted to a boolean internally.

Parameters:
aSC The servlet context under investigation. Never null.
Returns:
The string value of the production init-parameter. May be null if no such init-parameter is present.
  {
  }

  
Get the value of the servlet context init-parameter that represents the no-startup-info flag. This value is than converted to a boolean internally.

Parameters:
aSC The servlet context under investigation. Never null.
Returns:
The string value of the no-startup-info init-parameter. May be null if no such init-parameter is present.
  {
  }

  
Get the value of the servlet context init-parameter that represents the no-startup-info flag. This value is than converted to a boolean internally.

Parameters:
aSC The servlet context under investigation. Never null.
bProductionMode true if we're in production mode, false if not.
Returns:
The string value of the no-startup-info init-parameter. May be null if no such init-parameter is present.
  protected String getInitParameterServerURL (@Nonnull final ServletContext aSCfinal boolean bProductionMode)
  {
    final String sParameterName = bProductionMode ?  : ;
    return aSC.getInitParameter (sParameterName);
  }
  protected String getServletContextPath (@Nonnull final ServletContext aSC)
  {
    String sPath = aSC.getRealPath (".");
    if (sPath == null)
    {
      // Fallback for Undertow
      sPath = aSC.getRealPath ("");
    }
    if (StringHelper.hasNoText (sPath))
      throw new IllegalStateException ("Failed to determine real path of ServletContext " + aSC);
    return sPath;
  }

  
Get the data path to be used for this application. By default the servlet context init-parameter INIT_PARAMETER_STORAGE_PATH is evaluated. If non is present, the servlet context path is used.

Parameters:
aSC The servlet context. Never null.
Returns:
The data path to use. May neither be null nor empty.
  protected String getDataPath (@Nonnull final ServletContext aSC)
  {
    if (StringHelper.hasNoText (sDataPath))
    {
      // No storage path provided in web.xml
      sDataPath = getServletContextPath (aSC);
      if (GlobalDebug.isDebugMode () && .isInfoEnabled ())
        .info ("No servlet context init-parameter '" +
                         +
                        "' found! Defaulting to " +
                        sDataPath);
    }
    return sDataPath;
  }

  
Determine if the file access should be checked upon startup. By default this is done by evaluating the servlet context init-parameter INIT_PARAMETER_NO_CHECK_FILE_ACCESS.

Parameters:
aSC The servlet context. Never null.
Returns:
true if file access should be checked, false otherwise.
  protected boolean shouldCheckFileAccess (@Nonnull final ServletContext aSC)
  {
    return !StringParser.parseBool (aSC.getInitParameter ());
  }

  
This method is called to initialize the global ID factory. By default a file-based com.helger.appbasics.app.io.WebIOIntIDFactory with the filename ID_FILENAME is created.
  protected void initGlobalIDFactory ()
  {
    // Set persistent ID provider: file based
    GlobalIDFactory.setPersistentIntIDFactory (new WebIOIntIDFactory ());
  }
  public final void contextInitialized (@Nonnull final ServletContextEvent aSCE)
  {
    final ServletContext aSC = aSCE.getServletContext ();
    if (.getAndSet (true))
      throw new IllegalStateException ("WebAppListener was already instantiated!");
    final StopWatch aSW = new StopWatch (true);
    // set global debug/trace mode
    final boolean bTraceMode = StringParser.parseBool (getInitParameterTrace (aSC));
    final boolean bDebugMode = StringParser.parseBool (getInitParameterDebug (aSC));
    final boolean bProductionMode = StringParser.parseBool (getInitParameterProduction (aSC));
    GlobalDebug.setTraceModeDirect (bTraceMode);
    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 (aSCbProductionMode);
      if (StringHelper.hasText (sInitParameter))
      {
        final URL aURL = URLUtils.getAsURL (sInitParameter);
        if (aURL != null)
        {
          StaticServerInfo.init (aURL.getProtocol (), aURL.getHost (), aURL.getPort (), aSC.getContextPath ());
        }
        else
          .error ("The init-parameter for the server URL" +
                           (bProductionMode ? " (production mode)" : " (non-production mode)") +
                           "contains the non-URL value '" +
                           sInitParameter +
                           "'");
      }
    }
    // Call callback
    // begin global context
    WebScopeManager.onGlobalBegin (aSC);
    // Init IO
    {
      // Get the ServletContext base path
      final String sServletContextPath = getServletContextPath (aSC);
      // Get the data path
      final String sDataPath = getDataPath (aSC);
      if (StringHelper.hasNoText (sDataPath))
        throw new InitializationException ("No data path was provided!");
      final File aDataPath = new File (sDataPath);
      // Should the file access check be performed?
      final boolean bFileAccessCheck = shouldCheckFileAccess (aSC);
      // Init the IO layer
      WebFileIO.initPaths (aDataPathnew File (sServletContextPath), bFileAccessCheck);
    }
    // Set persistent ID provider - must be done after IO is setup
    // Callback
    // Remember end time
    // Finally
    if (.isInfoEnabled ())
      .info ("Servlet context '" +
                      aSC.getServletContextName () +
                      "' was initialized in " +
                      aSW.stopAndGetMillis () +
                      " milli seconds");
  }

  

Returns:
The date time when the initialization started. May be null if the context was never initialized.
  {
  }

  

Returns:
The date time when the initialization ended. May be null if the context was never initialized or is just in the middle of initialization.
  {
    return ;
  }

  
before destroy

Parameters:
aSC the servlet context in destruction
  protected void beforeContextDestroyed (@Nonnull final ServletContext aSC)
  {}

  
after destroy

Parameters:
aSC the servlet context in destruction
  protected void afterContextDestroyed (@Nonnull final ServletContext aSC)
  {}

  
Callback for handling statistics. This is mainly used for class WebAppListenerWithStatistics.
  protected void handleStatistics ()
  {}
  public final void contextDestroyed (@Nonnull final ServletContextEvent aSCE)
  {
    final ServletContext aSC = aSCE.getServletContext ();
    final StopWatch aSW = new StopWatch (true);
    if (.isInfoEnabled ())
      .info ("Servlet context '" + aSC.getServletContextName () + "' is being destroyed");
    // Callback before global scope end
    // Shutdown global scope and destroy all singletons
    WebScopeManager.onGlobalEnd ();
    // Callback after global scope end
    afterContextDestroyed (aSC);
    // Handle statistics
    handleStatistics ();
    // 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
    .set (false);
    if (.isInfoEnabled ())
      .info ("Servlet context '" +
                      aSC.getServletContextName () +
                      "' has been destroyed in " +
                      aSW.stopAndGetMillis () +
                      " milli seconds");
  }

  
Notification that a session was created.

Parameters:
aSessionEvent The notification event. Never null.
  public final void sessionCreated (@Nonnull final HttpSessionEvent aSessionEvent)
  {
    // Create the SessionScope
    final HttpSession aHttpSession = aSessionEvent.getSession ();
    WebScopeManager.onSessionBegin (aHttpSession);
  }

  
Notification that a session is about to be invalidated.

Parameters:
aSessionEvent The notification event. Never null.
  public final void sessionDestroyed (@Nonnull final HttpSessionEvent aSessionEvent)
  {
    // Destroy the SessionScope
    final HttpSession aHttpSession = aSessionEvent.getSession ();
    WebScopeManager.onSessionEnd (aHttpSession);
  }
New to GrepCode? Check out our FAQ X