/* * oxTrust is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. * * Copyright (c) 2014, Gluu */ package org.gluu.oxtrust.service; import java.lang.annotation.Annotation; import java.net.URISyntaxException; import java.util.Arrays; import java.util.List; import java.util.Properties; import javax.annotation.PostConstruct; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.context.BeforeDestroyed; import javax.enterprise.context.Initialized; import javax.enterprise.event.Event; import javax.enterprise.event.Observes; import javax.enterprise.inject.Instance; import javax.enterprise.inject.Produces; import javax.enterprise.inject.spi.BeanManager; import javax.inject.Inject; import javax.inject.Named; import javax.servlet.ServletContext; import org.gluu.exception.OxIntializationException; import org.gluu.model.custom.script.CustomScriptType; import org.gluu.oxauth.client.OpenIdConfigurationClient; import org.gluu.oxauth.client.OpenIdConfigurationResponse; import org.gluu.oxauth.client.OpenIdConnectDiscoveryClient; import org.gluu.oxauth.client.OpenIdConnectDiscoveryResponse; import org.gluu.oxauth.model.util.SecurityProviderUtility; import org.gluu.oxtrust.ldap.cache.service.CacheRefreshTimer; import org.gluu.oxtrust.service.cdi.event.CentralLdap; import org.gluu.oxtrust.service.config.ConfigurationFactory; import org.gluu.oxtrust.service.logger.LoggerService; import org.gluu.oxtrust.service.status.ldap.PersistanceStatusTimer; import org.gluu.oxtrust.util.BuildVersionService; import org.gluu.persist.PersistenceEntryManager; import org.gluu.persist.model.PersistenceConfiguration; import org.gluu.service.PythonService; import org.gluu.service.cdi.event.ApplicationInitialized; import org.gluu.service.cdi.event.ApplicationInitializedEvent; import org.gluu.service.cdi.event.LdapConfigurationReload; import org.gluu.service.cdi.util.CdiUtil; import org.gluu.service.custom.lib.CustomLibrariesLoader; import org.gluu.service.custom.script.CustomScriptManager; import org.gluu.service.external.ExternalPersistenceExtensionService; import org.gluu.service.external.context.PersistenceExternalContext; import org.gluu.service.metric.inject.ReportMetric; import org.gluu.service.timer.QuartzSchedulerManager; import org.gluu.util.StringHelper; import org.gluu.util.properties.FileConfiguration; import org.gluu.util.security.StringEncrypter; import org.gluu.util.security.StringEncrypter.EncryptionException; import org.slf4j.Logger; import org.slf4j.bridge.SLF4JBridgeHandler; /** * Perform startup time initialization * * @author Yuriy Movchan */ @ApplicationScoped @Named public class AppInitializer { @Inject private Logger log; @Inject private BeanManager beanManager; @Inject @Named(ApplicationFactory.PERSISTENCE_ENTRY_MANAGER_NAME) private Instance<PersistenceEntryManager> persistenceEntryManagerInstance; @Inject @Named(ApplicationFactory.PERSISTENCE_METRIC_ENTRY_MANAGER_NAME) @ReportMetric private Instance<PersistenceEntryManager> persistenceMetricEntryManagerInstance; @Inject @Named(ApplicationFactory.PERSISTENCE_CENTRAL_ENTRY_MANAGER_NAME) @CentralLdap private Instance<PersistenceEntryManager> persistenceCentralEntryManagerInstance; @Inject private Instance<EncryptionService> encryptionServiceInstance; @Inject private ApplicationFactory applicationFactory; @Inject private MetadataValidationTimer metadataValidationTimer; @Inject private EntityIDMonitoringService entityIDMonitoringService; @Inject private LogFileSizeChecker logFileSizeChecker; @Inject private ConfigurationFactory configurationFactory; @Inject private CacheRefreshTimer cacheRefreshTimer; @Inject private StatusCheckerDaily statusCheckerDaily; @Inject private StatusCheckerTimer statusCheckerTimer; @Inject private UpdateChecker updateChecker; @Inject private PythonService pythonService; @Inject private MetricService metricService; @Inject private CustomScriptManager customScriptManager; @Inject private ExternalPersistenceExtensionService externalPersistenceExtensionService; @Inject private PersistanceStatusTimer ldapStatusTimer; @Inject private ShibbolethInitializer shibbolethInitializer; @Inject private TemplateService templateService; @Inject private CustomLibrariesLoader customLibrariesLoader; @Inject private QuartzSchedulerManager quartzSchedulerManager; @Inject private LdifArchiver ldifArchiver; @Inject private BuildVersionService buildVersionService; @Inject private LoggerService loggerService; @Inject private CleanerTimer cleanerTimer; @Inject private Event<ApplicationInitializedEvent> eventApplicationInitialized; @PostConstruct public void createApplicationComponents() { SecurityProviderUtility.installBCProvider(); // Remove JUL console logger SLF4JBridgeHandler.removeHandlersForRootLogger(); // Add SLF4JBridgeHandler to JUL root logger SLF4JBridgeHandler.install(); } /** * Initialize components and schedule DS connection time checker */ public void applicationInitialized(@Observes @Initialized(ApplicationScoped.class) Object init) { log.debug("Initializing application services"); showBuildInfo(); configurationFactory.create(); PersistenceEntryManager localLdapEntryManager = persistenceEntryManagerInstance.get(); initializeLdifArchiver(localLdapEntryManager); // Initialize template engine templateService.initTemplateEngine(); // Initialize python interpreter pythonService.initPythonInterpreter(configurationFactory.getBaseConfiguration() .getString("pythonModulesDir", null)); // Initialize Shibboleth shibbolethInitializer.createShibbolethConfiguration(); // Initialize script manager List<CustomScriptType> supportedCustomScriptTypes = Arrays.asList(CustomScriptType.CACHE_REFRESH, CustomScriptType.UPDATE_USER, CustomScriptType.USER_REGISTRATION, CustomScriptType.ID_GENERATOR, CustomScriptType.PERSISTENCE_EXTENSION); // Start timer initSchedulerService(); // Schedule timer tasks metricService.initTimer(); configurationFactory.initTimer(); loggerService.initTimer(); ldapStatusTimer.initTimer(); metadataValidationTimer.initTimer(); entityIDMonitoringService.initTimer(); cacheRefreshTimer.initTimer(); customScriptManager.initTimer(supportedCustomScriptTypes); cleanerTimer.initTimer(); statusCheckerDaily.initTimer(); statusCheckerTimer.initTimer(); logFileSizeChecker.initTimer(); updateChecker.initTimer(); // Notify other components/plugins about finish application initialization eventApplicationInitialized.select(ApplicationInitialized.Literal.APPLICATION) .fire(new ApplicationInitializedEvent()); } protected void initSchedulerService() { quartzSchedulerManager.start(); String disableScheduler = System.getProperties().getProperty("gluu.disable.scheduler"); if ((disableScheduler != null) && Boolean.valueOf(disableScheduler)) { this.log.warn("Suspending Quartz Scheduler Service..."); quartzSchedulerManager.standby(); return; } } @Produces @ApplicationScoped public StringEncrypter getStringEncrypter() throws OxIntializationException { String encodeSalt = configurationFactory.getCryptoConfigurationSalt(); if (StringHelper.isEmpty(encodeSalt)) { throw new OxIntializationException("Encode salt isn't defined"); } try { StringEncrypter stringEncrypter = StringEncrypter.instance(encodeSalt); return stringEncrypter; } catch (EncryptionException ex) { throw new OxIntializationException("Failed to create StringEncrypter instance"); } } private void showBuildInfo() { log.info("Build date {}. Code revision {} on {}. Build {}", getGluuBuildDate(), getGluuRevisionVersion(), getGluuRevisionDate(), getGluuBuildNumber()); } protected Properties preparePersistanceProperties() { PersistenceConfiguration persistenceConfiguration = this.configurationFactory.getPersistenceConfiguration(); FileConfiguration persistenceConfig = persistenceConfiguration.getConfiguration(); Properties connectionProperties = (Properties) persistenceConfig.getProperties(); EncryptionService securityService = encryptionServiceInstance.get(); Properties decryptedConnectionProperties = securityService.decryptAllProperties(connectionProperties); return decryptedConnectionProperties; } protected Properties prepareCustomPersistanceProperties(String configId) { Properties connectionProperties = preparePersistanceProperties(); if (StringHelper.isNotEmpty(configId)) { // Replace properties names 'configId.xyz' to 'configId.xyz' in order to // override default values connectionProperties = (Properties) connectionProperties.clone(); String baseGroup = configId + "."; for (Object key : connectionProperties.keySet()) { String propertyName = (String) key; if (propertyName.startsWith(baseGroup)) { propertyName = propertyName.substring(baseGroup.length()); Object value = connectionProperties.get(key); connectionProperties.put(propertyName, value); } } } return connectionProperties; } @Produces @ApplicationScoped @Named(ApplicationFactory.PERSISTENCE_ENTRY_MANAGER_NAME) public PersistenceEntryManager createPersistenceEntryManager() { Properties connectionProperties = preparePersistanceProperties(); PersistenceEntryManager persistenceEntryManager = applicationFactory.getPersistenceEntryManagerFactory() .createEntryManager(connectionProperties); log.info("Created {}: {} with operation service: {}", new Object[] { ApplicationFactory.PERSISTENCE_ENTRY_MANAGER_NAME, persistenceEntryManager, persistenceEntryManager.getOperationService() }); externalPersistenceExtensionService.executePersistenceExtensionAfterCreate(connectionProperties, persistenceEntryManager); return persistenceEntryManager; } @Produces @ApplicationScoped @Named(ApplicationFactory.PERSISTENCE_METRIC_ENTRY_MANAGER_NAME) @ReportMetric public PersistenceEntryManager createMetricPersistenceEntryManager() { Properties connectionProperties = prepareCustomPersistanceProperties( ApplicationFactory.PERSISTENCE_METRIC_CONFIG_GROUP_NAME); PersistenceEntryManager persistenceEntryManager = applicationFactory.getPersistenceEntryManagerFactory() .createEntryManager(connectionProperties); log.info("Created {}: {} with operation service: {}", new Object[] { ApplicationFactory.PERSISTENCE_METRIC_ENTRY_MANAGER_NAME, persistenceEntryManager, persistenceEntryManager.getOperationService() }); externalPersistenceExtensionService.executePersistenceExtensionAfterCreate(connectionProperties, persistenceEntryManager); return persistenceEntryManager; } public void recreatePersistanceEntryManager(@Observes @LdapConfigurationReload String event) { recreatePersistanceEntryManagerImpl(persistenceEntryManagerInstance, ApplicationFactory.PERSISTENCE_ENTRY_MANAGER_NAME); recreatePersistanceEntryManagerImpl(persistenceEntryManagerInstance, ApplicationFactory.PERSISTENCE_METRIC_ENTRY_MANAGER_NAME, ReportMetric.Literal.INSTANCE); } protected void recreatePersistanceEntryManagerImpl(Instance<PersistenceEntryManager> instance, String persistenceEntryManagerName, Annotation... qualifiers) { // Get existing application scoped instance PersistenceEntryManager oldLdapEntryManager = CdiUtil.getContextBean(beanManager, PersistenceEntryManager.class, persistenceEntryManagerName, qualifiers); // Close existing connections closePersistenceEntryManager(oldLdapEntryManager, persistenceEntryManagerName); // Force to create new bean PersistenceEntryManager ldapEntryManager = instance.get(); instance.destroy(ldapEntryManager); log.info("Recreated instance {}: {} with operation service: {}", persistenceEntryManagerName, ldapEntryManager, ldapEntryManager.getOperationService()); } private void closePersistenceEntryManager(PersistenceEntryManager oldPersistenceEntryManager, String persistenceEntryManagerName) { // Close existing connections if ((oldPersistenceEntryManager != null) && (oldPersistenceEntryManager.getOperationService() != null)) { log.debug("Attempting to destroy {}:{} with operation service: {}", persistenceEntryManagerName, oldPersistenceEntryManager, oldPersistenceEntryManager.getOperationService()); oldPersistenceEntryManager.destroy(); log.debug("Destroyed {}:{} with operation service: {}", persistenceEntryManagerName, oldPersistenceEntryManager, oldPersistenceEntryManager.getOperationService()); externalPersistenceExtensionService.executePersistenceExtensionAfterDestroy(oldPersistenceEntryManager); } } private void initializeLdifArchiver(PersistenceEntryManager ldapEntryManager) { ldifArchiver.init(); ldapEntryManager.addDeleteSubscriber(ldifArchiver); } @Produces @ApplicationScoped @Named("openIdConfiguration") public OpenIdConfigurationResponse initOpenIdConfiguration() throws OxIntializationException { String oxAuthIssuer = this.configurationFactory.getAppConfiguration().getOxAuthIssuer(); if (StringHelper.isEmpty(oxAuthIssuer)) { log.info("oxAuth issuer isn't specified"); return null; } log.debug("Attempting to determine configuration endpoint URL"); OpenIdConnectDiscoveryClient openIdConnectDiscoveryClient; try { openIdConnectDiscoveryClient = new OpenIdConnectDiscoveryClient(oxAuthIssuer); } catch (URISyntaxException ex) { throw new OxIntializationException("OpenId discovery response is invalid!", ex); } OpenIdConnectDiscoveryResponse openIdConnectDiscoveryResponse = openIdConnectDiscoveryClient.exec(); if ((openIdConnectDiscoveryResponse.getStatus() != 200) || (openIdConnectDiscoveryResponse.getSubject() == null) || (openIdConnectDiscoveryResponse.getLinks().size() == 0)) { throw new OxIntializationException("OpenId discovery response is invalid!"); } log.debug("Attempting to load OpenID configuration"); String configurationEndpoint = openIdConnectDiscoveryResponse.getLinks().get(0).getHref() + "/.well-known/openid-configuration"; OpenIdConfigurationClient client = new OpenIdConfigurationClient(configurationEndpoint); OpenIdConfigurationResponse openIdConfiguration; try { openIdConfiguration = client.execOpenIdConfiguration(); } catch (Exception e) { log.error("Failed to load OpenId configuration!", e); throw new OxIntializationException("Failed to load OpenId configuration!"); } if (openIdConfiguration.getStatus() != 200) { throw new OxIntializationException("OpenId configuration response is invalid!"); } return openIdConfiguration; } public void destroy(@Observes @BeforeDestroyed(ApplicationScoped.class) ServletContext init) { log.info("Stopping services and closing DB connections at server shutdown..."); log.debug("Checking who intiated destory", new Throwable()); metricService.close(); PersistenceEntryManager persistanceEntryManager = persistenceEntryManagerInstance.get(); closePersistenceEntryManager(persistanceEntryManager, ApplicationFactory.PERSISTENCE_ENTRY_MANAGER_NAME); PersistenceEntryManager persistanceMetricEntryManager = persistenceMetricEntryManagerInstance.get(); closePersistenceEntryManager(persistanceMetricEntryManager, ApplicationFactory.PERSISTENCE_METRIC_ENTRY_MANAGER_NAME); PersistenceEntryManager persistanceCentralEntryManager = persistenceCentralEntryManagerInstance.get(); if (persistanceCentralEntryManager != null) { closePersistenceEntryManager(persistanceCentralEntryManager, ApplicationFactory.PERSISTENCE_CENTRAL_ENTRY_MANAGER_NAME); } } public String getGluuRevisionVersion() { return buildVersionService.getRevisionVersion(); } public String getGluuRevisionDate() { return buildVersionService.getRevisionDate(); } public String getGluuBuildDate() { return buildVersionService.getBuildDate(); } public String getGluuBuildNumber() { return buildVersionService.getBuildNumber(); } }