/* * Constellation - An open source and standard compliant SDI * http://www.constellation-sdi.org * * Copyright 2015 Geomatys. * * 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 org.constellation.configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Map; import java.util.Properties; /** * Utility class that gathers and merge configurations from embedded/external property files, * system properties and system environment variables. * The resolving order is : * <ol> * <li>System environment variables. Evaluated at runtime and use env variable convention naming</li> * <li>System property variables (with <code>-Dvar=value</code> or <code>System.setProperty("var", "value");</code>). Evaluated at runtime</li> * <li>External property file (referenced with <code>-Dcstl.config=/path/to/config.properties</code> option). Evaluated once.</li> * <li>Embedded property file in resources. Evaluated once</li> * </ol> * * Usage : <br\> * <code> * String cstlHome = Application.getProperty(Application.CSTL_HOME_KEY); * </code> * @author Quentin Boileau (Geomatys) */ public final class Application { private static final Logger LOGGER = LoggerFactory.getLogger("org.constellation.configuration"); private static final Properties APP_PROPERTIES = new Properties(); //lazy singleton to call initialization private static final Application INSTANCE = new Application(); private Application() { //load embedded configuration file final String resourcePath = "/org/constellation/configuration/constellation.properties"; try (final InputStream classLoaderSettings = Application.class.getResourceAsStream(resourcePath)) { LOGGER.info("Load default configuration."); APP_PROPERTIES.load(classLoaderSettings); } catch (IOException e) { throw new ConfigurationRuntimeException("Unable to load default configuration file from current class loader", e); } //search for external configuration file final String externalConf = System.getProperty(AppProperty.CSTL_CONFIG.getKey()); if (externalConf != null) { LOGGER.info("Load external configuration from "+externalConf); final File externalFile = new File(externalConf); if (!externalFile.isFile()) { LOGGER.warn("Unable to load external configuration because path is not a valid file."); } try (FileInputStream fin = new FileInputStream(externalFile)) { APP_PROPERTIES.load(fin); } catch (IOException e) { //no need to crash application because of an invalid external configuration file. LOGGER.warn("Unable to load properties from external configuration file", e); } } } /** * Get all constellation settings. * * @return a merge of default, external and environment properties */ private static Properties getProperties() { return (Properties) APP_PROPERTIES.clone(); } /** * Search for the property with the specified key in {@link #getProperties()} * Look first in system environment variables and if nothing found, fallback * to application properties. * * @param key AppProperty * @return property value or <code>null</code> if not found. */ public static String getProperty(AppProperty key) { return getProperty(key.getKey(), null); } /** * Search for the property with the specified key in {@link #getProperties()} * Look first in system environment variables and if nothing found, fallback * to application properties. * * @param key property key * @return property value or <code>null</code> if not found. */ public static String getProperty(String key) { return getProperty(key, null); } /** * Search for the property with the specified key in {@link #getProperties()} * Look first in system environment variables and if nothing found, fallback * to application properties. * * @param key AppProperty * @param fallback fallback used if property not found. * @return property value or fallback value if not found. */ public static String getProperty(AppProperty key, String fallback) { return getProperty(key.getKey(), fallback); } /** * Search for the property with the specified key in {@link #getProperties()} * Look first in system environment variables and if nothing found, fallback * to application properties. * * @param key property key * @param fallback fallback used if property not found. * @return property value or fallback value if not found. */ public static String getProperty(String key, String fallback) { //check env String envKey = toEnvConvention(key); final String envValue = System.getenv(envKey); if (envValue != null) { return envValue; } //check system properties final String propValue = System.getProperty(key); if (propValue != null) { return propValue; } //check conf return getProperties().getProperty(key, fallback); } /** * Translate a property key from java convention ("path.to.property") into an * environment variable convention ("PATH_TO_PROPERTY") * @param key in java convention * @return translated key */ private static String toEnvConvention(String key) { return key.toUpperCase().replace('.', '_'); } /** * Search for all application properties matching given prefix. * * @param prefix property key * @return all property that match given prefix. Output {@link Properties} can be * empty but never null. */ public static Properties getProperties(String prefix) { Properties properties = new Properties(); final Properties appProperties = getProperties(); for (Map.Entry<Object, Object> appProp : appProperties.entrySet()) { if (((String)appProp.getKey()).startsWith(prefix)) { properties.put(appProp.getKey(), appProp.getValue()); } } //override with system properties variables final Properties systemProperties = System.getProperties(); for (Map.Entry<Object, Object> sysProp : systemProperties.entrySet()) { if (((String)sysProp.getKey()).startsWith(prefix)) { properties.put(sysProp.getKey(), sysProp.getValue()); } } //override with system environment variables String envPrefix = toEnvConvention(prefix); final Map<String, String> envProps = System.getenv(); for (Map.Entry<String, String> env : envProps.entrySet()) { if (env.getKey().startsWith(envPrefix)) { properties.put(env.getKey(), env.getValue()); } } return properties; } }