AppInit.java

  1. /*
  2.  * Copyright (c) 2002-2022, City of Paris
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  *  1. Redistributions of source code must retain the above copyright notice
  10.  *     and the following disclaimer.
  11.  *
  12.  *  2. Redistributions in binary form must reproduce the above copyright notice
  13.  *     and the following disclaimer in the documentation and/or other materials
  14.  *     provided with the distribution.
  15.  *
  16.  *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
  17.  *     contributors may be used to endorse or promote products derived from
  18.  *     this software without specific prior written permission.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  24.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  25.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  26.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30.  * POSSIBILITY OF SUCH DAMAGE.
  31.  *
  32.  * License 1.0
  33.  */
  34. package fr.paris.lutece.portal.service.init;

  35. import java.io.FileInputStream;
  36. import java.io.FileWriter;
  37. import java.text.DateFormat;
  38. import java.util.Date;
  39. import java.util.HashMap;
  40. import java.util.Locale;
  41. import java.util.Map;
  42. import java.util.Properties;

  43. import javax.servlet.ServletContext;

  44. import fr.paris.lutece.portal.service.admin.AdminAuthenticationService;
  45. import fr.paris.lutece.portal.service.admin.AdminUserService;
  46. import fr.paris.lutece.portal.service.content.ContentPostProcessorService;
  47. import fr.paris.lutece.portal.service.content.ContentService;
  48. import fr.paris.lutece.portal.service.daemon.AppDaemonService;
  49. import fr.paris.lutece.portal.service.database.AppConnectionService;
  50. import fr.paris.lutece.portal.service.datastore.CoreDataKeys;
  51. import fr.paris.lutece.portal.service.datastore.DatastoreService;
  52. import fr.paris.lutece.portal.service.fileimage.FileImageService;
  53. import fr.paris.lutece.portal.service.filter.FilterService;
  54. import fr.paris.lutece.portal.service.html.XmlTransformerCacheService;
  55. import fr.paris.lutece.portal.service.i18n.I18nService;
  56. import fr.paris.lutece.portal.service.mailinglist.AdminMailingListService;
  57. import fr.paris.lutece.portal.service.plugin.PluginService;
  58. import fr.paris.lutece.portal.service.portal.PortalService;
  59. import fr.paris.lutece.portal.service.search.IndexationService;
  60. import fr.paris.lutece.portal.service.security.SecurityService;
  61. import fr.paris.lutece.portal.service.servlet.ServletService;
  62. import fr.paris.lutece.portal.service.spring.SpringContextService;
  63. import fr.paris.lutece.portal.service.template.AppTemplateService;
  64. import fr.paris.lutece.portal.service.util.AppLogService;
  65. import fr.paris.lutece.portal.service.util.AppPathService;
  66. import fr.paris.lutece.portal.service.util.AppPropertiesService;
  67. import fr.paris.lutece.util.bean.BeanUtil;
  68. import fr.paris.lutece.util.html.HtmlTemplate;

  69. /**
  70.  * This class initializes all the application services
  71.  *
  72.  * @since 1.1
  73.  */
  74. public final class AppInit
  75. {
  76.     private static final String PROPERTY_AUTOINIT = "autoInit";
  77.     private static final String PROPERTY_INIT_WEBAPP_PROD_URL = "init.webapp.prod.url";
  78.     private static final String PROPERTY_SENDMAIL_SUBJECT = "portal.system.log4j.sendmail.subject";
  79.     private static final String PROPERTY_SITE_NAME = "lutece.name";
  80.     private static final String MARK_WEBAPP_HOME = "webapp_home";
  81.     private static final String MARK_PROD_URL = "lutece_prod_url";
  82.     private static final String MARK_SENDMAIL_SUBJECT = "sendmail_subject";
  83.     private static final String MARK_AUTOINIT = "autoinit";
  84.     private static final String PATH_CONFIG = "/WEB-INF/conf/";
  85.     private static final String FILE_PROPERTIES_CONFIG = "config.properties";
  86.     private static final String FILE_PROPERTIES_DATABASE = "db.properties";
  87.     private static final String PATH_TEMPLATES = "/WEB-INF/templates/";
  88.     private static final String CONFIG_PROPERTIES_TEMPLATE = "admin/system/config_properties.html";
  89.     private static boolean _bInitSuccessfull;
  90.     private static String _strLoadingFailureCause;
  91.     private static String _strLoadingFailureDetails;

  92.     /**
  93.      * Constructor
  94.      */
  95.     private AppInit( )
  96.     {
  97.     }

  98.     /**
  99.      * Initializes all the application services (used for junit tests)
  100.      *
  101.      * @param strConfPath
  102.      *            The relative path to the config files
  103.      */
  104.     public static void initServices( String strConfPath )
  105.     {
  106.         initServices( null, strConfPath, null );
  107.     }

  108.     /**
  109.      * Initializes all the application services
  110.      *
  111.      * @param context
  112.      *            The servlet context
  113.      * @param strConfPath
  114.      *            The relative path to the config files
  115.      * @param strRealPath
  116.      *            The real path to the config files
  117.      */
  118.     public static void initServices( ServletContext context, String strConfPath, String strRealPath )
  119.     {
  120.         try
  121.         {
  122.             long lStart = System.currentTimeMillis( );

  123.             Thread.currentThread( ).setName( "Lutece-MainThread" );
  124.             // Initializes the properties download files containing the variables used by
  125.             // the application
  126.             AppPropertiesService.init( strConfPath );

  127.             // Initializes the template services from the servlet context information
  128.             AppTemplateService.init( PATH_TEMPLATES );

  129.             // Initializes the Datastore Service
  130.             DatastoreService.init( );

  131.             if ( strRealPath != null )
  132.             {
  133.                 // Initializes the properties download files containing the
  134.                 // variables used by the application
  135.                 initProperties( strRealPath );
  136.             }

  137.             AppLogService.info( " {} {} {} ...\n", AppInfo.LUTECE_BANNER_VERSION, "Starting  version", AppInfo.getVersion( ) );

  138.             // BeanUtil initialization, considering Lutèce availables locales and date
  139.             // format properties
  140.             BeanUtil.init( );

  141.             // Initializes the connection pools
  142.             AppConnectionService.init( strConfPath, FILE_PROPERTIES_DATABASE, "portal" );
  143.             AppLogService.info( "Creating connexions pool 'portal'." );
  144.            
  145.             //Initializes early initialization services.
  146.             StartUpServiceManager.initializeEarlyInitializationServices( );
  147.             // Spring ApplicationContext initialization
  148.             AppLogService.info( "Loading context files ..." );
  149.             SpringContextService.init( context );

  150.             // Initialize and run StartUp services
  151.             AppLogService.info( "Running extra startup services ..." );
  152.             StartUpServiceManager.init( );

  153.             // XmlTransformer service cache manager
  154.             XmlTransformerCacheService.init( );

  155.             AdminMailingListService.init( );

  156.             // Initializes Search Engine Indexation Service
  157.             IndexationService.init( );

  158.             // Initializes PluginService
  159.             AppLogService.info( "Initializing plugins ..." );
  160.             PluginService.init( );

  161.             // Initializes FilterService and ServletService
  162.             AppLogService.info( "Initializing plugins filters ..." );
  163.             FilterService.init( context );
  164.             AppLogService.info( "Initializing plugins servlets ..." );
  165.             ServletService.init( context );

  166.             // Trace Contents services loading
  167.             traceContentServicesLoading( );

  168.             // Initializes the SecurityService
  169.             SecurityService.init( );

  170.             // Initializes plugins autoincludes - needs to be launched before the daemons
  171.             // (indexer could fail)
  172.             AppTemplateService.initAutoIncludes( );

  173.             // Initializes the daemons service
  174.             AppDaemonService.init( );

  175.             // Initializes the admin authentication module
  176.             AdminAuthenticationService.init( );

  177.             // Initialize FileImageService
  178.             FileImageService.init( );

  179.             // Initialize AdminUserService
  180.             AdminUserService.init( );

  181.             // Process post startup services
  182.             AppLogService.info( "Running post startup services ..." );
  183.             PostStartUpServiceManager.init( );

  184.             // Initialize Content Post Processor Service
  185.             ContentPostProcessorService.init( );

  186.             _bInitSuccessfull = true;

  187.             logStartupTime( );

  188.             // Start datastore's cache after all processes that may use Datastore
  189.             DatastoreService.startCache( );

  190.             long lEnd = System.currentTimeMillis( );
  191.             long lTime = 1 + ( lEnd - lStart ) / 1000;

  192.             String strBaseUrl = getBaseUrl( context );
  193.             StringBuilder sbBanner = new StringBuilder( );
  194.             sbBanner.append( AppInfo.LUTECE_BANNER_SERVER ).append( "  started successfully in " ).append( lTime ).append( "s !!!\n" )
  195.                     .append( "\n   Front office " ).append( strBaseUrl ).append( AppPathService.getPortalUrl( ) ).append( "\n   Back office  " )
  196.                     .append( strBaseUrl ).append( AppPathService.getAdminMenuUrl( ) ).append( "\n" );
  197.             AppLogService.info( sbBanner.toString( ) );
  198.         }
  199.         catch( LuteceInitException e )
  200.         {
  201.             _strLoadingFailureCause = e.getMessage( );

  202.             Throwable cause = e.getCause( );

  203.             while ( cause != null )
  204.             {
  205.                 _strLoadingFailureDetails = cause.getMessage( );
  206.                 cause = cause.getCause( );
  207.             }
  208.         }
  209.     }

  210.     /**
  211.      * Get a base url to display in start logs
  212.      *
  213.      * @param context
  214.      *            the servlet context
  215.      * @return the base url
  216.      */
  217.     private static String getBaseUrl( ServletContext context )
  218.     {
  219.         StringBuilder sbBaseUrl = new StringBuilder( "http(s)://server:port" );
  220.         if ( context != null )
  221.         {
  222.             sbBaseUrl.append( context.getContextPath( ) );
  223.         }
  224.         return sbBaseUrl.append( '/' ).toString( );
  225.     }

  226.     /**
  227.      * Tells if Lutece Startup was successful
  228.      *
  229.      * @return True, if no error, otherwise false
  230.      */
  231.     public static boolean isWebappSuccessfullyLoaded( )
  232.     {
  233.         return _bInitSuccessfull;
  234.     }

  235.     /**
  236.      * Returns the cause of the startup failure
  237.      *
  238.      * @return the cause of the startup failure
  239.      */
  240.     public static String getLoadingFailureCause( )
  241.     {
  242.         return _strLoadingFailureCause;
  243.     }

  244.     /**
  245.      * Returns details of the startup failure
  246.      *
  247.      * @return details of the startup failure
  248.      */
  249.     public static String getLoadingFailureDetails( )
  250.     {
  251.         return _strLoadingFailureDetails;
  252.     }

  253.     /**
  254.      * Traces Content Services loading
  255.      */
  256.     private static void traceContentServicesLoading( )
  257.     {
  258.         for ( ContentService cs : PortalService.getContentServicesList( ) )
  259.         {
  260.             AppLogService.info( "Content Service '{}' is loaded {} ", cs.getName( ), ( cs.isCacheEnable( ) ? " [ cache enable ] " : " [ cache disable ] " ) );
  261.         }
  262.     }

  263.     /**
  264.      * Initializes the config.properties file after first installation
  265.      *
  266.      * @param strRealPath
  267.      *            The real path to the configuration file
  268.      */
  269.     private static void initProperties( String strRealPath )
  270.     {
  271.         Map<String, Object> model = new HashMap<>( );
  272.         Properties p = new Properties( );

  273.         try ( FileInputStream fis = new FileInputStream( strRealPath + PATH_CONFIG + FILE_PROPERTIES_CONFIG ) )
  274.         {
  275.             p.load( fis );
  276.         }
  277.         catch( Exception e )
  278.         {
  279.             AppLogService.error( e.getMessage( ), e );
  280.         }

  281.         if ( Boolean.parseBoolean( p.getProperty( PROPERTY_AUTOINIT ) ) )
  282.         {
  283.             Object [ ] params = {
  284.                     AppPropertiesService.getProperty( PROPERTY_SITE_NAME )
  285.             };
  286.             String strSendMailSubject = I18nService.getLocalizedString( PROPERTY_SENDMAIL_SUBJECT, params, I18nService.getDefaultLocale( ) );
  287.             model.put( MARK_SENDMAIL_SUBJECT, strSendMailSubject );
  288.             model.put( MARK_WEBAPP_HOME, AppPathService.getWebAppPath( ) );
  289.             model.put( MARK_PROD_URL, p.getProperty( PROPERTY_INIT_WEBAPP_PROD_URL ) );
  290.             model.put( MARK_AUTOINIT, Boolean.FALSE.toString( ) );

  291.             HtmlTemplate configTemplate = AppTemplateService.getTemplate( CONFIG_PROPERTIES_TEMPLATE, Locale.getDefault( ), model );
  292.             // reset configuration cache to avoid configuration caching before macros are
  293.             // set. See LUTECE-1460
  294.             AppTemplateService.resetConfiguration( );

  295.             try ( FileWriter fw = new FileWriter( strRealPath + PATH_CONFIG + FILE_PROPERTIES_CONFIG ) )
  296.             {
  297.                 fw.write( configTemplate.getHtml( ) );
  298.             }
  299.             catch( Exception io )
  300.             {
  301.                 AppLogService.error( "Error reading file", io );
  302.             }
  303.         }
  304.     }

  305.     /**
  306.      * Log startup time.
  307.      */
  308.     private static void logStartupTime( )
  309.     {
  310.         String strStartupTime = DateFormat.getDateTimeInstance( ).format( new Date( ) );
  311.         DatastoreService.setDataValue( CoreDataKeys.KEY_STARTUP_TIME, strStartupTime );
  312.     }
  313. }