package io.cattle.platform.archaius.startup; import io.cattle.platform.archaius.polling.RefreshableFixedDelayPollingScheduler; import io.cattle.platform.archaius.sources.LazyJDBCSource; import io.cattle.platform.archaius.util.ArchaiusUtil; import io.cattle.platform.datasource.DataSourceFactory; import io.cattle.platform.extension.impl.ExtensionManagerImpl; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import javax.annotation.PostConstruct; import javax.inject.Inject; import javax.sql.DataSource; import org.apache.commons.configuration.AbstractConfiguration; import org.apache.commons.configuration.MapConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.netflix.config.ConcurrentCompositeConfiguration; import com.netflix.config.DynamicConfiguration; import com.netflix.config.DynamicPropertyFactory; import com.netflix.config.sources.JDBCConfigurationSource; public class ArchaiusStartup { public static final String CONFIG_KEY = "config"; public static final String DB_CONFIG = "DatabaseConfig"; private static Properties GLOBAL_DEFAULT = null; private static final Logger log = LoggerFactory.getLogger("ConsoleStatus"); ExtensionManagerImpl extensionManager; ConcurrentCompositeConfiguration baseConfig; DataSource configDataSource; DataSourceFactory dataSourceFactory; String dataSourceName = "config"; String query = "SELECT distinct name, value FROM setting"; String keyColumnName = "name"; String valueColumnName = "value"; List<RefreshableFixedDelayPollingScheduler> schedulers; boolean init = false; @PostConstruct public void init() { if (init) { return; } if (GLOBAL_DEFAULT == null) { throw new IllegalStateException("setGlobalDefaults() must be set before init() is called"); } baseConfig = new ConcurrentCompositeConfiguration(); baseConfig.addConfiguration(new MapConfiguration(getOverride())); baseConfig.addConfiguration(new MapConfiguration(GLOBAL_DEFAULT)); DynamicPropertyFactory.initWithConfigurationSource(baseConfig); init = true; } protected Map<String, Object> getOverride() { Map<String, Object> override = new HashMap<String, Object>(); override.put(CONFIG_KEY + ".exclude", DB_CONFIG); return override; } public void start() { log.info("Loading configuration"); load(false); extensionManager.reset(); load(true); } protected void load(boolean refresh) { List<AbstractConfiguration> configs = extensionManager.getExtensionList(CONFIG_KEY, AbstractConfiguration.class); for (AbstractConfiguration config : configs) { config.setDelimiterParsingDisabled(true); } if (refresh) { for (AbstractConfiguration config : configs) { refresh(config); } } baseConfig.clear(); for (AbstractConfiguration config : configs) { baseConfig.addConfiguration(config); } if (refresh) { for (RefreshableFixedDelayPollingScheduler scheduler : schedulers) { scheduler.refresh(); } ArchaiusUtil.addSchedulers(schedulers); } } protected void refresh(AbstractConfiguration config) { if (config instanceof DynamicConfiguration && ((DynamicConfiguration) config).getSource() instanceof LazyJDBCSource) { LazyJDBCSource source = (LazyJDBCSource) ((DynamicConfiguration) config).getSource(); if (configDataSource == null) { configDataSource = dataSourceFactory.createDataSource(dataSourceName); } source.setSource(new JDBCConfigurationSource(configDataSource, query, keyColumnName, valueColumnName)); } } public ExtensionManagerImpl getExtensionManager() { return extensionManager; } @Inject public void setExtensionManager(ExtensionManagerImpl extensionManager) { this.extensionManager = extensionManager; } public static Properties setGlobalDefaults(Properties props) { return GLOBAL_DEFAULT = props; } public static Properties getGlobalDefaults() { return GLOBAL_DEFAULT; } public DataSourceFactory getDataSourceFactory() { return dataSourceFactory; } @Inject public void setDataSourceFactory(DataSourceFactory dataSourceFactory) { this.dataSourceFactory = dataSourceFactory; } public String getDataSourceName() { return dataSourceName; } public void setDataSourceName(String dataSourceName) { this.dataSourceName = dataSourceName; } public String getQuery() { return query; } public void setQuery(String query) { this.query = query; } public String getKeyColumnName() { return keyColumnName; } public void setKeyColumnName(String keyColumnName) { this.keyColumnName = keyColumnName; } public String getValueColumnName() { return valueColumnName; } public void setValueColumnName(String valueColumnName) { this.valueColumnName = valueColumnName; } public List<RefreshableFixedDelayPollingScheduler> getSchedulers() { return schedulers; } @Inject public void setSchedulers(List<RefreshableFixedDelayPollingScheduler> schedulers) { this.schedulers = schedulers; } }