InitListener.java
/*
* GovWay - A customizable API Gateway
* https://govway.org
*
* Copyright (c) 2005-2024 Link.it srl (https://link.it).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3, as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openspcoop2.web.ctrlstat.core;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Properties;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.commons.lang.StringUtils;
import org.openspcoop2.core.config.driver.ExtendedInfoManager;
import org.openspcoop2.core.constants.CostantiDB;
import org.openspcoop2.message.OpenSPCoop2MessageFactory;
import org.openspcoop2.message.xml.XMLDiff;
import org.openspcoop2.monitor.engine.alarm.AlarmConfigProperties;
import org.openspcoop2.monitor.engine.alarm.AlarmEngineConfig;
import org.openspcoop2.monitor.engine.alarm.AlarmManager;
import org.openspcoop2.monitor.engine.dynamic.CorePluginLoader;
import org.openspcoop2.monitor.engine.dynamic.PluginLoader;
import org.openspcoop2.pdd.config.ConfigurazioneNodiRuntime;
import org.openspcoop2.pdd.config.ConfigurazioneNodiRuntimeProperties;
import org.openspcoop2.pdd.logger.filetrace.FileTraceGovWayState;
import org.openspcoop2.protocol.basic.archive.BasicArchive;
import org.openspcoop2.utils.LoggerWrapperFactory;
import org.openspcoop2.utils.Semaphore;
import org.openspcoop2.utils.Utilities;
import org.openspcoop2.utils.UtilsException;
import org.openspcoop2.utils.UtilsRuntimeException;
import org.openspcoop2.utils.certificate.hsm.HSMManager;
import org.openspcoop2.utils.certificate.hsm.HSMUtils;
import org.openspcoop2.utils.certificate.ocsp.OCSPManager;
import org.openspcoop2.utils.json.YamlSnakeLimits;
import org.openspcoop2.utils.resources.Loader;
import org.openspcoop2.utils.xml.XMLDiffImplType;
import org.openspcoop2.utils.xml.XMLDiffOptions;
import org.openspcoop2.web.ctrlstat.config.ConsoleProperties;
import org.openspcoop2.web.ctrlstat.config.DatasourceProperties;
import org.openspcoop2.web.ctrlstat.config.RegistroServiziRemotoProperties;
import org.openspcoop2.web.ctrlstat.driver.DriverControlStationDB_LIB;
import org.openspcoop2.web.ctrlstat.gestori.GestoreConsistenzaDati;
import org.openspcoop2.web.ctrlstat.gestori.GestoriStartupThread;
import org.openspcoop2.web.ctrlstat.servlet.config.ConfigurazioneRegistroPluginsReader;
import org.openspcoop2.web.lib.mvc.DataElement;
import org.openspcoop2.web.lib.mvc.DataElementParameter;
import org.openspcoop2.web.lib.queue.config.QueueProperties;
import org.slf4j.Logger;
/**
* Questa classe si occupa di inizializzare tutte le risorse necessarie alla
* govwayConsole.
*
*
* @author Andrea Poli (apoli@link.it)
* @author Stefano Corallo (corallo@link.it)
* @author Sandra Giangrandi (sandra@link.it)
* @author $Author$
* @version $Rev$, $Date$
*
*/
public class InitListener implements ServletContextListener {
protected static Logger log = null;
public static void setLog(Logger log) {
InitListener.log = log;
}
static void logDebug(String msg) {
if(InitListener.log!=null) {
InitListener.log.debug(msg);
}
}
static void logDebug(String msg, Throwable e) {
if(InitListener.log!=null) {
InitListener.log.debug(msg, e);
}
}
static void logError(String msg) {
if(InitListener.log!=null) {
InitListener.log.error(msg);
}
}
static void logError(String msg, Throwable e) {
if(InitListener.log!=null) {
InitListener.log.error(msg,e);
}
}
private static final Semaphore semaphoreInitListener = new Semaphore("InitListener");
private static boolean initialized = false;
static {
InitListener.log = LoggerWrapperFactory.getLogger(InitListener.class);
}
public static boolean isInitialized() {
return InitListener.initialized;
}
public static void setInitialized(boolean initialized) {
InitListener.initialized = initialized;
}
private static FileTraceGovWayState fileTraceGovWayState;
static void setFileTraceGovWayState(FileTraceGovWayState fileTraceGovWayState) {
InitListener.fileTraceGovWayState = fileTraceGovWayState;
}
public static FileTraceGovWayState getFileTraceGovWayState() {
return fileTraceGovWayState;
}
private GestoriStartupThread gestoriStartupThread;
private GestoreConsistenzaDati gestoreConsistenzaDati;
private InitRuntimeConfigReader initRuntimeConfigReader;
@Override
public void contextDestroyed(ServletContextEvent sce) {
InitListener.log.info("Undeploy govwayConsole in corso...");
InitListener.setInitialized(false);
// Fermo i Gestori
if(this.gestoriStartupThread!=null){
this.gestoriStartupThread.stopGestori();
}
if(this.gestoreConsistenzaDati!=null){
this.gestoreConsistenzaDati.setStop(true);
int limite = 60;
int index = 0;
while(GestoreConsistenzaDati.gestoreConsistenzaDatiInEsecuzione && index<limite){
Utilities.sleep(1000);
index++;
}
}
if(this.initRuntimeConfigReader!=null) {
this.initRuntimeConfigReader.setStop(true);
}
// chiusura repository dei plugin
try {
CorePluginLoader.close(InitListener.log);
} catch (Exception e) {
String msgErrore = "Errore durante la chiusura del loader dei plugins: " + e.getMessage();
InitListener.logError(msgErrore,e);
}
InitListener.log.info("Undeploy govwayConsole effettuato.");
}
@Override
public void contextInitialized(ServletContextEvent sce) {
semaphoreInitListener.acquireThrowRuntime("contextInitialized");
try {
if(InitListener.initialized) {
return;
}
String confDir = null;
String confPropertyName = null;
String confLocalPathPrefix = null;
boolean appendActualConfiguration = false;
try{
try (InputStream is = InitListener.class.getResourceAsStream("/console.properties");){
if(is!=null){
Properties p = new Properties();
p.load(is);
confDir = p.getProperty("confDirectory");
if(confDir!=null){
confDir = confDir.trim();
}
confPropertyName = p.getProperty("confPropertyName");
if(confPropertyName!=null){
confPropertyName = confPropertyName.trim();
}
confLocalPathPrefix = p.getProperty("confLocalPathPrefix");
if(confLocalPathPrefix!=null){
confLocalPathPrefix = confLocalPathPrefix.trim();
}
String tmpAppendActualConfiguration = p.getProperty("appendLog4j");
if(tmpAppendActualConfiguration!=null){
appendActualConfiguration = "true".equalsIgnoreCase(tmpAppendActualConfiguration.trim());
}
}
}
}catch(Exception e){
// ignore
}
try{
ControlStationLogger.initialize(InitListener.log, confDir, confPropertyName, confLocalPathPrefix, null, appendActualConfiguration);
InitListener.setLog(ControlStationLogger.getPddConsoleCoreLogger());
}catch(Exception e){
throw new UtilsRuntimeException(e.getMessage(),e);
}
InitListener.log.info("Inizializzazione resources (properties) govwayConsole in corso...");
ConsoleProperties consoleProperties = null;
try{
if(!ConsoleProperties.initialize(confDir, confPropertyName, confLocalPathPrefix,InitListener.log)){
throw new UtilsException("ConsoleProperties not initialized");
}
consoleProperties = ConsoleProperties.getInstance();
if(!DatasourceProperties.initialize(confDir, confPropertyName, confLocalPathPrefix,InitListener.log)){
throw new UtilsException("DatasourceProperties not initialized");
}
if(
(consoleProperties.isSinglePddRegistroServiziLocale()==null || (!consoleProperties.isSinglePddRegistroServiziLocale().booleanValue()))
&&
(!RegistroServiziRemotoProperties.initialize(confDir, confPropertyName, confLocalPathPrefix,InitListener.log))
){
throw new UtilsException("RegistroServiziRemotoProperties not initialized");
}
if(
(consoleProperties.isSinglePdD() == null || (!consoleProperties.isSinglePdD().booleanValue()))
&&
(!QueueProperties.initialize(confDir,InitListener.log))
){
throw new UtilsException("QueueProperties not initialized");
}
}catch(Exception e){
throw new UtilsRuntimeException(e.getMessage(),e);
}
InitListener.log.info("Inizializzazione resources (properties) govwayConsole effettuata con successo.");
InitListener.log.info("Inizializzazione ExtendedInfoManager in corso...");
try{
ExtendedInfoManager.initialize(new Loader(),
consoleProperties.getExtendedInfoDriverConfigurazione(),
consoleProperties.getExtendedInfoDriverPortaDelegata(),
consoleProperties.getExtendedInfoDriverPortaApplicativa());
}catch(Exception e){
throw new UtilsRuntimeException(e.getMessage(),e);
}
InitListener.log.info("Inizializzazione ExtendedInfoManager effettuata con successo");
InitListener.log.info("Inizializzazione resources govwayConsole in corso...");
try{
Connettori.initialize(InitListener.log);
DriverControlStationDB_LIB.initialize(InitListener.log);
}catch(Exception e){
throw new UtilsRuntimeException(e.getMessage(),e);
}
InitListener.log.info("Inizializzazione resources govwayConsole effettuata con successo.");
InitListener.log.info("Inizializzazione YAML Limits in corso...");
try{
Properties yamlSnakeLimits = consoleProperties.getApiYamlSnakeLimits();
if(yamlSnakeLimits!=null && !yamlSnakeLimits.isEmpty()) {
YamlSnakeLimits.initialize(InitListener.log, yamlSnakeLimits);
}
}catch(Exception e){
throw new UtilsRuntimeException(e.getMessage(),e);
}
InitListener.log.info("Inizializzazione YAML Limits con successo");
InitListener.log.info("Inizializzazione XMLDiff in corso...");
try{
XMLDiff diff = new XMLDiff(OpenSPCoop2MessageFactory.getDefaultMessageFactory());
diff.initialize(XMLDiffImplType.XML_UNIT, new XMLDiffOptions());
}catch(Exception e){
throw new UtilsRuntimeException(e.getMessage(),e);
}
InitListener.log.info("Inizializzazione XMLDiff effettuata con successo");
try{
if(consoleProperties.isSinglePdD()==null || (!consoleProperties.isSinglePdD())){
InitListener.log.info("Inizializzazione Gestori, della govwayConsole Centralizzata, in corso...");
this.gestoriStartupThread = new GestoriStartupThread();
new Thread(this.gestoriStartupThread).start();
InitListener.log.info("Inizializzazione Gestori, della govwayConsole Centralizzata, effettuata con successo.");
}
}catch(Exception e){
throw new UtilsRuntimeException(e.getMessage(),e);
}
try{
// Notes on Apache Commons FileUpload 1.3.3
// Regarding potential security problems with the class called DiskFileItem, it is true, that this class exists,
// and can be serialized/deserialized in FileUpload versions, up to, and including 1.3.2.
// ...
// Beginning with 1.3.3, the class DiskFileItem is still implementing the interface java.io.Serializable.
// In other words, it still declares itself as serializable, and deserializable to the JVM.
// In practice, however, an attempt to deserialize an instance of DiskFileItem will trigger an Exception.
// In the unlikely case, that your application depends on the deserialization of DiskFileItems,
// you can revert to the previous behaviour by setting the system property "org.apache.commons.fileupload.disk.DiskFileItem.serializable" to "true".
//
// Purtroppo la classe 'org.apache.struts.upload.FormFile', all'interna utilizza DiskFileItem per serializzare le informazioni.
// Tale classe viene usata nel meccanismo di import/export nei metodi writeFormFile e readFormFile della classe org.openspcoop2.web.ctrlstat.servlet.archivi.ImporterUtils
// Per questo motivo si riabilita' l'opzione!
InitListener.log.info("Inizializzazione DiskFileItem (opzione serializable), in corso...");
System.setProperty("org.apache.commons.fileupload.disk.DiskFileItem.serializable", "true");
InitListener.log.info("Inizializzazione DiskFileItem (opzione serializable), effettuata.");
}catch(Exception e){
throw new UtilsRuntimeException(e.getMessage(),e);
}
try{
if(consoleProperties.isGestoreConsistenzaDatiEnabled()){
this.gestoreConsistenzaDati = new GestoreConsistenzaDati(consoleProperties.isGestoreConsistenzaDatiForceCheckMapping());
new Thread(this.gestoreConsistenzaDati).start();
InitListener.log.info("Gestore Controllo Consistenza Dati avviato con successo.");
}
else{
InitListener.log.info("Gestore Controllo Consistenza Dati disabilitato.");
}
}catch(Exception e){
throw new UtilsRuntimeException(e.getMessage(),e);
}
InitListener.log.info("Inizializzazione DataElement in corso...");
try{
int consoleLunghezzaLabel = consoleProperties.getConsoleLunghezzaLabel();
int numeroColonneTextArea = consoleProperties.getConsoleNumeroColonneDefaultTextArea();
DataElementParameter dep = new DataElementParameter();
dep.setSize(consoleLunghezzaLabel);
dep.setCols(numeroColonneTextArea);
DataElement.initialize(dep);
}catch(Exception e){
throw new UtilsRuntimeException(e.getMessage(),e);
}
InitListener.log.info("Inizializzazione DataElement effettuata con successo");
ServletContext servletContext = sce.getServletContext();
InputStream isFont = null;
try{
String fontFileName = ConsoleProperties.getInstance().getConsoleFont();
InitListener.logDebug("Caricato Font dal file: ["+fontFileName+"] in corso... ");
isFont = servletContext.getResourceAsStream("/fonts/"+ fontFileName);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
Font fontCaricato = Font.createFont(Font.PLAIN, isFont);
InitListener.logDebug("Caricato Font: ["+fontCaricato.getName()+"] FontName: ["+fontCaricato.getFontName()+"] FontFamily: ["+fontCaricato.getFamily()+"] FontStyle: ["+fontCaricato.getStyle()+"]");
ge.registerFont(fontCaricato);
InitListener.logDebug("Check Graphics Environment: is HeadeLess ["+java.awt.GraphicsEnvironment.isHeadless()+"]");
InitListener.logDebug("Elenco Nomi Font disponibili: " + Arrays.asList(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames()));
ConsoleProperties.getInstance().setConsoleFontName(fontCaricato.getName());
ConsoleProperties.getInstance().setConsoleFontFamilyName(fontCaricato.getFamily());
ConsoleProperties.getInstance().setConsoleFontStyle(fontCaricato.getStyle());
InitListener.logDebug("Caricato Font dal file: ["+fontFileName+"] completato.");
}catch (Exception e) {
InitListener.logError(e.getMessage(),e);
} finally {
if(isFont != null){
try { isFont.close(); } catch (IOException e) {
// ignore
}
}
}
// inizializza nodi runtime
try {
ConfigurazioneNodiRuntimeProperties backwardCompatibility = new ConfigurazioneNodiRuntimeProperties(consoleProperties.getJmxPdDBackwardCompatibilityPrefix(),
consoleProperties.getJmxPdDBackwardCompatibilityProperties());
ConfigurazioneNodiRuntime.initialize(consoleProperties.getJmxPdDExternalConfiguration(), backwardCompatibility);
} catch (Exception e) {
String msgErrore = "Errore durante l'inizializzazione del gestore dei nodi run: " + e.getMessage();
InitListener.logError(
// throw new ServletException(
msgErrore,e);
throw new UtilsRuntimeException(msgErrore,e);
}
// inizializza il repository dei plugin
try {
if(consoleProperties.isConfigurazionePluginsEnabled()!=null && consoleProperties.isConfigurazionePluginsEnabled().booleanValue()) {
CorePluginLoader.initialize(new Loader(), InitListener.log,
PluginLoader.class,
new ConfigurazioneRegistroPluginsReader(new ControlStationCore()),
consoleProperties.getPluginsSeconds());
}
if(consoleProperties.isConfigurazioneAllarmiEnabled()!=null && consoleProperties.isConfigurazioneAllarmiEnabled().booleanValue()) {
AlarmEngineConfig alarmEngineConfig = AlarmConfigProperties.getAlarmConfiguration(InitListener.log, consoleProperties.getAllarmiConfigurazione(), consoleProperties.getConfDirectory());
AlarmManager.setAlarmEngineConfig(alarmEngineConfig);
CostantiDB.setAllarmiEnabled(true);
}
} catch (Exception e) {
String msgErrore = "Errore durante l'inizializzazione del loader dei plugins: " + e.getMessage();
InitListener.logError(
// throw new ServletException(
msgErrore,e);
throw new UtilsRuntimeException(msgErrore,e);
}
// inizializzo HSM Manager
try {
String hsmConfig = consoleProperties.getHSMConfigurazione();
if(StringUtils.isNotEmpty(hsmConfig)) {
File f = new File(hsmConfig);
HSMManager.init(f, consoleProperties.isHSMRequired(), log, false);
HSMUtils.setHsmConfigurableKeyPassword(consoleProperties.isHSMKeyPasswordConfigurable());
}
} catch (Exception e) {
String msgErrore = "Errore durante l'inizializzazione del manager HSM: " + e.getMessage();
InitListener.logError(
// throw new ServletException(
msgErrore,e);
throw new UtilsRuntimeException(msgErrore,e);
}
// inizializzo OCSP Manager
try {
String ocspConfig = consoleProperties.getOCSPConfigurazione();
if(StringUtils.isNotEmpty(ocspConfig)) {
File f = new File(ocspConfig);
OCSPManager.init(f, consoleProperties.isOCSPRequired(), consoleProperties.isOCSPLoadDefault(), log);
}
} catch (Exception e) {
String msgErrore = "Errore durante l'inizializzazione del manager OCSP: " + e.getMessage();
InitListener.logError(
// throw new ServletException(
msgErrore,e);
throw new UtilsRuntimeException(msgErrore,e);
}
// inizializzo OpenAPIValidator
try {
org.openapi4j.parser.validation.v3.OpenApi3Validator.VALIDATE_URI_REFERENCE_AS_URL = consoleProperties.isApiOpenAPIValidateUriReferenceAsUrl();
} catch (Exception e) {
String msgErrore = "Errore durante l'inizializzazione del validatore OpenAPI: " + e.getMessage();
InitListener.logError(
// throw new ServletException(
msgErrore,e);
throw new UtilsRuntimeException(msgErrore,e);
}
// Basic Archive
try {
BasicArchive.setNormalizeDescription255(consoleProperties.isApiDescriptionTruncate255());
BasicArchive.setNormalizeDescription4000(consoleProperties.isApiDescriptionTruncate4000());
} catch (Exception e) {
String msgErrore = "Errore durante l'inizializzazione del BasicArchive: " + e.getMessage();
InitListener.logError(
// throw new ServletException(
msgErrore,e);
throw new UtilsRuntimeException(msgErrore,e);
}
// fileTraceGovWayState
try{
this.initRuntimeConfigReader = new InitRuntimeConfigReader(consoleProperties);
this.initRuntimeConfigReader.start();
InitListener.log.info("RuntimeConfigReader avviato con successo.");
} catch (Exception e) {
String msgErrore = "Errore durante l'inizializzazione del RuntimeConfigReader: " + e.getMessage();
InitListener.logError(
msgErrore,e);
//throw new UtilsRuntimeException(msgErrore,e); non sollevo l'eccezione, e' solo una informazione informativa, non voglio mettere un vincolo che serve per forza un nodo acceso
}
InitListener.setInitialized(true);
}finally {
semaphoreInitListener.release("contextInitialized");
}
}
}