AppConfig.java
/* This file is part of Openrouteservice.
*
* Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the
* GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
* This library 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 Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License along with this library;
* if not, see <https://www.gnu.org/licenses/>.
*/
package org.heigit.ors.config;
import com.graphhopper.util.Helper;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import com.typesafe.config.ConfigObject;
import com.typesafe.config.ConfigValue;
import org.apache.log4j.Logger;
import org.heigit.ors.util.FileUtility;
import org.heigit.ors.util.StringUtility;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class AppConfig {
public static final String PREFIX_ORS_SERVICES = "ors.services.";
private Config config;
private static AppConfig global;
private static String osmMd5Hash = null;
private static final Logger LOGGER = Logger.getLogger(AppConfig.class.getName());
private static final String SERVICE_NAME_ROUTING = "routing";
private static final String SERVICE_NAME_ISOCHRONES = "isochrones";
public AppConfig(String path) {
File file = new File(path);
config = ConfigFactory.parseFile(file);
}
public AppConfig() {
try {
File configFile;
String appConfigResource = "app.config";
if (System.getProperty("ors_config") != null) {
configFile = new FileSystemResource(System.getProperty("ors_config")).getFile();
LOGGER.info("System property 'ors_config' used as configuration path");
} else if (System.getProperty("ors_app_config") != null) {
configFile = new FileSystemResource(System.getProperty("ors_app_config")).getFile();
LOGGER.info("System property 'ors_app_config' used as configuration path");
LOGGER.warn("""
DEPRECATION NOTICE: The system property 'ors_app_config' will be not be supported in the\
future\
""");
LOGGER.warn("Use 'ors_config' instead");
} else if (System.getenv("ORS_CONFIG") != null) {
configFile = new FileSystemResource(System.getenv("ORS_CONFIG")).getFile();
LOGGER.info("Environment variable 'ORS_CONFIG' used as configuration path");
} else if (System.getenv("ORS_APP_CONFIG") != null) {
configFile = new ClassPathResource(System.getenv("ORS_APP_CONFIG")).getFile();
LOGGER.info("Environment variable 'ORS_APP_CONFIG' used as configuration path");
LOGGER.warn("""
DEPRECATION NOTICE: The Environment variable 'ORS_APP_CONFIG' will be not be supported\
in the future\
""");
LOGGER.warn("Use 'ORS_CONFIG' instead");
} else if (new ClassPathResource("ors-config.json").isFile()) {
configFile = new ClassPathResource("ors-config.json").getFile();
LOGGER.info("Default path of 'ors-config.json' used for configuration");
if (new ClassPathResource(appConfigResource).isFile()) {
LOGGER.warn("""
DEPRECATION NOTICE: You seem to have an unused 'app.config' file, which won't be \
supported in the future\
""");
}
} else if (new ClassPathResource(appConfigResource).isFile()) {
configFile = new ClassPathResource(appConfigResource).getFile();
LOGGER.info("Deprecated path of 'app.config' used");
LOGGER.warn("""
DEPRECATION NOTICE: The used 'app.config' configuration path will not be supported in the \
future.\
""");
LOGGER.warn("Use 'ors-config.json' instead.");
} else {
throw new IOException("""
No valid configuration file found in 'ors-api/src/main/resources'. \
Did you copy ors-config-sample.json to ors-config.json?\
""");
}
LOGGER.info("Loading configuration from " + configFile);
config = ConfigFactory.parseFile(configFile);
config = overrideFromEnvVariables(config);
LOGGER.warn("Deprecation notice: Old configuration method with JSON files is deprecated. Switch to ors-config.yml files!");
} catch (IOException ioe) {
// no deprecated JSON config found
}
//Modification by H Leuschner: Save md5 hash of map file in static String for access with every request
String graphPath = getServiceParameter("routing.profiles.default_params", "graphs_root_path");
if (graphPath != null) {
File graphsDir = new File(graphPath);
File[] md5Files = graphsDir.listFiles(pathname -> pathname.getName().endsWith(".md5"));
if (md5Files != null && md5Files.length == 1) {
try {
osmMd5Hash = FileUtility.readFile(md5Files[0].toString()).trim();
} catch (IOException e) {
LOGGER.error(e);
}
}
}
}
public static AppConfig getGlobal() {
if (global == null)
global = new AppConfig();
return global;
}
public String getParameter(String section, String paramName) {
try {
return config.getString("ors." + section + "." + paramName);
} catch (Exception e) {
// IGNORE
}
return null;
}
public List<String> getStringList(String path) {
try {
return config.getStringList(path);
} catch (Exception e) {
// IGNORE
}
return new ArrayList<>();
}
public String getServiceParameter(String serviceName, String paramName) {
try {
return config.getString(PREFIX_ORS_SERVICES + serviceName + "." + paramName);
} catch (Exception e) {
// IGNORE
}
return null;
}
private Config overrideFromEnvVariables(Config baseConfig) {
if (System.getenv("GRAPHS_FOLDER") != null) {
LOGGER.info("Environment variable 'GRAPHS_FOLDER' used as graphs folder path");
String graphsFolderPath = System.getenv("GRAPHS_FOLDER");
Config newConfig = ConfigFactory.parseString("ors.services.routing.profiles.default_params.graphs_root_path=".concat(graphsFolderPath));
baseConfig = newConfig.withFallback(baseConfig);
}
if (System.getenv("ELEVATION_CACHE_FOLDER") != null) {
LOGGER.info("Environment variable 'ELEVATION_CACHE_FOLDER' used as elevation cache folder path");
String elevationCacheFolder = System.getenv("ELEVATION_CACHE_FOLDER");
Config newConfig = ConfigFactory.parseString("ors.services.routing.profiles.default_params.elevation_cache_path=".concat(elevationCacheFolder));
baseConfig = newConfig.withFallback(baseConfig);
}
if (System.getenv("PBF_FILE_PATH") != null) {
LOGGER.info("Environment variable 'PBF_FILE_PATH' used as pbf file path");
String pbfPath = System.getenv("PBF_FILE_PATH");
Config newConfig = ConfigFactory.parseString("ors.services.routing.sources=[".concat(pbfPath).concat("]"));
baseConfig = newConfig.withFallback(baseConfig);
}
if (System.getenv("LOGS_FOLDER") != null) {
LOGGER.info("Environment variable 'LOGS_FOLDER' used as logs folder path");
String logsFolder = System.getenv("LOGS_FOLDER");
Config newConfig = ConfigFactory.parseString("ors.logging.location=".concat(logsFolder));
baseConfig = newConfig.withFallback(baseConfig);
}
return baseConfig;
}
public String getRoutingProfileParameter(String profile, String paramName) {
try {
String rootPath = PREFIX_ORS_SERVICES + "routing.profiles";
ConfigObject configObj = config.getObject(rootPath);
for (String key : configObj.keySet()) {
if (key.startsWith("profile-")) {
String profileName = getServiceParameter(SERVICE_NAME_ROUTING, "profiles." + key + ".profiles");
if (profile.equals(profileName)) {
String profileValue = getServiceParameter(SERVICE_NAME_ROUTING, "profiles." + key + ".parameters." + paramName);
if (profileValue != null) {
return profileValue;
}
}
}
}
return config.getString(rootPath + ".default_params." + paramName);
} catch (Exception e) {
// IGNORE
}
return null;
}
public List<? extends ConfigObject> getObjectList(String serviceName, String paramName) {
try {
return config.getObjectList(PREFIX_ORS_SERVICES + serviceName + "." + paramName);
} catch (Exception e) {
// IGNORE
}
return new ArrayList<>();
}
public boolean getBoolean(String path) {
try {
ConfigObject configObj = config.getObject("ors");
return configObj.toConfig().getBoolean(path);
} catch (Exception e) {
// IGNORE
}
return false;
}
public double getDouble(String path) {
try {
ConfigObject configObj = config.getObject("ors");
return configObj.toConfig().getDouble(path);
} catch (Exception e) {
// IGNORE
}
return Double.NaN;
}
public List<? extends ConfigObject> getObjectList(String paramName) {
try {
return config.getObjectList("ors." + paramName);
} catch (Exception e) {
// IGNORE
}
return new ArrayList<>();
}
public List<Double> getDoubleList(String serviceName, String paramName) {
try {
return config.getDoubleList(PREFIX_ORS_SERVICES + serviceName + "." + paramName);
} catch (Exception e) {
// IGNORE
}
return new ArrayList<>();
}
public List<String> getServiceParametersList(String serviceName, String paramName) {
try {
return config.getStringList(PREFIX_ORS_SERVICES + serviceName + "." + paramName);
} catch (Exception e) {
// IGNORE
}
return new ArrayList<>();
}
public static boolean hasValidMD5Hash() {
return osmMd5Hash != null;
}
public static String getMD5Hash() {
return osmMd5Hash;
}
public Map<String, Object> getServiceParametersMap(String serviceName, String paramName, boolean quotedStrings) {
Map<String, Object> result = null;
try {
String rootPath = PREFIX_ORS_SERVICES + serviceName + "." + paramName;
ConfigObject configObj = config.getObject(rootPath);
result = new HashMap<>();
for (String key : configObj.keySet()) {
Object value = null;
ConfigValue paramValue = config.getValue(rootPath + "." + key);
switch (paramValue.valueType()) {
case NUMBER:
case LIST:
case BOOLEAN:
value = paramValue.unwrapped();
break;
case OBJECT:
value = getServiceParametersMap(serviceName, paramName + "." + key, quotedStrings);
break;
case STRING:
if (quotedStrings)
value = paramValue.render();
else
value = StringUtility.trim(paramValue.render(), '"');
break;
default:
break;
}
result.put(key, value);
}
} catch (Exception ex) {
// IGNORE
}
return result;
}
public static String getRoutingParameter(String paramName) {
return getGlobal().getServiceParameter(SERVICE_NAME_ROUTING, paramName);
}
public static String getRoutingParameter(String paramName, boolean notNull) {
String value = getGlobal().getServiceParameter(SERVICE_NAME_ROUTING, paramName);
if (notNull && Helper.isEmpty(value))
throw new IllegalArgumentException("Parameter '" + paramName + "' must not be null or empty.");
return value;
}
public static List<String> getRoutingParametersList(String paramName) {
return getGlobal().getServiceParametersList(SERVICE_NAME_ROUTING, paramName);
}
public static Map<String, Object> getRoutingParametersMap(String paramName, boolean quotedStrings) {
return getGlobal().getServiceParametersMap(SERVICE_NAME_ROUTING, paramName, quotedStrings);
}
public static List<String> getIsochronesParametersList(String paramName) {
return getGlobal().getServiceParametersList(SERVICE_NAME_ISOCHRONES, paramName);
}
public static Map<String, Object> getIsochronesParametersMap(String paramName, boolean quotedStrings) {
return getGlobal().getServiceParametersMap(SERVICE_NAME_ISOCHRONES, paramName, quotedStrings);
}
}