/* * (C) Copyright 2006-2016 Nuxeo SA (http://nuxeo.com/) and others. * * 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. * * Contributors: * bstefanescu, jcarsique */ package org.nuxeo.common; import java.io.File; import java.net.URL; import java.util.Properties; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> */ public class Environment { private static Log logger = LogFactory.getLog(Environment.class); /** * Constants that identifies possible hosts for the framework. */ public static final String JBOSS_HOST = "JBoss"; // Jetty or GF3 embedded public static final String NXSERVER_HOST = "NXServer"; public static final String TOMCAT_HOST = "Tomcat"; public static final String NUXEO_HOME_DIR = "nuxeo.home.dir"; /** * @since 5.6 */ public static final String NUXEO_HOME = "nuxeo.home"; /** * @since 5.4.2 */ public static final String NUXEO_RUNTIME_HOME = "nuxeo.runtime.home"; public static final String NUXEO_DATA_DIR = "nuxeo.data.dir"; /** * @since 5.9.4 */ public static final String DEFAULT_DATA_DIR = "data"; public static final String NUXEO_LOG_DIR = "nuxeo.log.dir"; /** * @since 5.9.4 */ public static final String DEFAULT_LOG_DIR = "log"; public static final String NUXEO_PID_DIR = "nuxeo.pid.dir"; public static final String NUXEO_TMP_DIR = "nuxeo.tmp.dir"; /** * @since 5.9.4 */ public static final String DEFAULT_TMP_DIR = "tmp"; public static final String NUXEO_CONFIG_DIR = "nuxeo.config.dir"; /** * @since 5.9.4 */ public static final String DEFAULT_CONFIG_DIR = "config"; public static final String NUXEO_WEB_DIR = "nuxeo.web.dir"; /** * @since 5.9.4 */ public static final String DEFAULT_WEB_DIR = "web"; /** * @since 5.9.4 */ public static final String NUXEO_MP_DIR = "nuxeo.mp.dir"; /** * @since 5.9.4 */ public static final String DEFAULT_MP_DIR = "packages"; /** * @since 5.6 */ public static final String NUXEO_CONTEXT_PATH = "org.nuxeo.ecm.contextPath"; /** * The application layout (optional): directory containing nuxeo runtime osgi bundles. */ public static final String BUNDLES_DIR = "nuxeo.osgi.app.bundles"; public static final String BUNDLES = "nuxeo.osgi.bundles"; private static volatile Environment DEFAULT; protected final File home; protected File data; protected File log; protected File config; protected File web; protected File temp; protected final Properties properties; protected String[] args; protected boolean isAppServer; protected String hostAppName; protected String hostAppVersion; protected Iterable<URL> configProvider; // Handy parameter to distinguish from (Runtime)home private File serverHome = null; // Handy parameter to distinguish from (Server)home private File runtimeHome = null; public static final String SERVER_STATUS_KEY = "server.status.key"; public static final String DISTRIBUTION_NAME = "org.nuxeo.distribution.name"; public static final String DISTRIBUTION_VERSION = "org.nuxeo.distribution.version"; /** * @since 7.10 */ public static final String DISTRIBUTION_SERVER = "org.nuxeo.distribution.server"; /** * @since 7.10 */ public static final String DISTRIBUTION_DATE = "org.nuxeo.distribution.date"; /** * @since 7.10 */ public static final String DISTRIBUTION_PACKAGE = "org.nuxeo.distribution.package"; /** * @since 7.10 */ public static final String PRODUCT_NAME = "org.nuxeo.ecm.product.name"; /** * @since 7.10 */ public static final String PRODUCT_VERSION = "org.nuxeo.ecm.product.version"; // proxy /** * @since 6.0 */ public static final String NUXEO_HTTP_PROXY_HOST = "nuxeo.http.proxy.host"; /** * @since 6.0 */ public static final String NUXEO_HTTP_PROXY_PORT = "nuxeo.http.proxy.port"; /** * @since 6.0 */ public static final String NUXEO_HTTP_PROXY_LOGIN = "nuxeo.http.proxy.login"; /** * @since 6.0 */ public static final String NUXEO_HTTP_PROXY_PASSWORD = "nuxeo.http.proxy.password"; /** * @since 7.4 */ public static final String CRYPT_ALGO = "server.crypt.algorithm"; /** * @since 7.4 */ public static final String CRYPT_KEY = "server.crypt.secretkey"; /** * @since 7.4 */ public static final String CRYPT_KEYALIAS = "server.crypt.keyalias"; /** * @since 7.4 */ public static final String CRYPT_KEYSTORE_PATH = "server.crypt.keystore.path"; /** * @since 7.4 */ public static final String CRYPT_KEYSTORE_PASS = "server.crypt.keystore.pass"; /** * @since 7.4 */ public static final String JAVA_DEFAULT_KEYSTORE = "javax.net.ssl.keyStore"; /** * @since 7.4 */ public static final String JAVA_DEFAULT_KEYSTORE_PASS = "javax.net.ssl.keyStorePassword"; /** * Call to that constructor should be followed by a call to {@link #init()}. Depending on the available System * properties, you may want to also call {@link #loadProperties(Properties)} or {@link #setServerHome(File)} methods * before {@link #init()}; here is the recommended order: * * <pre> * Environment env = new Environment(home); * Environment.setDefault(env); * env.loadProperties(properties); * env.setServerHome(home); * env.init(); * </pre> * * @param home Root path used for most defaults. It is recommended to make it match the server home rather than the * runtime home. * @see #init() */ public Environment(File home) { this(home, null); } /** * Call to that constructor should be followed by a call to {@link #init()}. Depending on the available System * properties, you may want to also call {@link #setServerHome(File)} method before {@link #init()}; here is the * recommended order: * * <pre> * Environment env = new Environment(home, properties); * Environment.setDefault(env); * env.setServerHome(home); * env.init(); * </pre> * * @param home Root path used for most defaults. It is recommended to make it match the server home rather than the * runtime home. * @param properties Source properties for initialization. It is used as an {@code Hashtable}: ie only the custom * values are read, the properties default values are ignored if any. * @see #init() */ public Environment(File home, Properties properties) { this.home = home.getAbsoluteFile(); this.properties = new Properties(); if (properties != null) { loadProperties(properties); } } public static synchronized void setDefault(Environment env) { DEFAULT = env; } public static Environment getDefault() { if (DEFAULT == null) { tryInitEnvironment(); } return DEFAULT; } private static synchronized void tryInitEnvironment() { String homeDir = System.getProperty(NUXEO_HOME); if (homeDir != null) { File home = new File(homeDir); if (home.isDirectory()) { DEFAULT = new Environment(home); DEFAULT.init(); } } } public File getHome() { return home; } public boolean isApplicationServer() { return isAppServer; } public void setIsApplicationServer(boolean isAppServer) { this.isAppServer = isAppServer; } public String getHostApplicationName() { return hostAppName; } public String getHostApplicationVersion() { return hostAppVersion; } public void setHostApplicationName(String name) { hostAppName = name; } public void setHostApplicationVersion(String version) { hostAppVersion = version; } public File getTemp() { if (temp == null) { setTemp(properties.getProperty(NUXEO_TMP_DIR, DEFAULT_TMP_DIR)); } return temp; } /** * Resolve the path against {@link Environment#serverHome} if not absolute. * * @since 8.1 */ public void setTemp(String temp) { setTemp(getServerHome().toPath().resolve(temp).toFile()); } public void setTemp(File temp) { this.temp = temp.getAbsoluteFile(); setProperty(NUXEO_TMP_DIR, temp.getAbsolutePath()); temp.mkdirs(); } public File getConfig() { if (config == null) { setConfig(properties.getProperty(NUXEO_CONFIG_DIR, DEFAULT_CONFIG_DIR)); } return config; } /** * Resolve the path against {@link Environment#runtimeHome} if not absolute. * * @since 8.1 */ public void setConfig(String config) { File configFile = getRuntimeHome().toPath().resolve(config).toFile(); setConfig(configFile); } public void setConfig(File config) { this.config = config.getAbsoluteFile(); setProperty(NUXEO_CONFIG_DIR, config.getAbsolutePath()); config.mkdirs(); } public File getLog() { if (log == null) { setLog(properties.getProperty(NUXEO_LOG_DIR, DEFAULT_LOG_DIR)); } return log; } /** * Resolve the path against {@link Environment#serverHome} if not absolute. * * @since 8.1 */ public void setLog(String log) { setLog(getServerHome().toPath().resolve(log).toFile()); } public void setLog(File log) { this.log = log.getAbsoluteFile(); setProperty(NUXEO_LOG_DIR, log.getAbsolutePath()); log.mkdirs(); } public File getData() { if (data == null) { setData(properties.getProperty(NUXEO_DATA_DIR, DEFAULT_DATA_DIR)); } return data; } /** * Resolve the path against {@link Environment#runtimeHome} if not absolute. * * @since 8.1 */ public void setData(String data) { setData(getRuntimeHome().toPath().resolve(data).toFile()); } public void setData(File data) { this.data = data.getAbsoluteFile(); setProperty(NUXEO_DATA_DIR, data.getAbsolutePath()); data.mkdirs(); } public File getWeb() { if (web == null) { setWeb(properties.getProperty(NUXEO_WEB_DIR, DEFAULT_WEB_DIR)); } return web; } /** * Resolve the path against {@link Environment#runtimeHome} if not absolute. * * @since 8.1 */ public void setWeb(String web) { setWeb(getRuntimeHome().toPath().resolve(web).toFile()); } public void setWeb(File web) { this.web = web; setProperty(NUXEO_WEB_DIR, web.getAbsolutePath()); } /** * @since 5.4.2 */ public File getRuntimeHome() { initRuntimeHome(); return runtimeHome; } /** * @since 5.4.2 */ public void setRuntimeHome(File runtimeHome) { this.runtimeHome = runtimeHome.getAbsoluteFile(); setProperty(NUXEO_RUNTIME_HOME, runtimeHome.getAbsolutePath()); } public String[] getCommandLineArguments() { return args; } public void setCommandLineArguments(String[] args) { this.args = args; } public String getProperty(String key) { return properties.getProperty(key); } public String getProperty(String key, String defaultValue) { String val = properties.getProperty(key); return val == null ? defaultValue : val; } /** * If setting a path property, consider using {@link #setPath(String, String)} */ public void setProperty(String key, String value) { properties.setProperty(key, value); } public Properties getProperties() { return properties; } public void loadProperties(Properties props) { properties.putAll(props); } public boolean isJBoss() { return JBOSS_HOST.equals(hostAppName); } public boolean isJetty() { return NXSERVER_HOST.equals(hostAppName); } public boolean isTomcat() { return TOMCAT_HOST.equals(hostAppName); } /** * Initialization with System properties to avoid issues due to home set with runtime home instead of server home. * If {@link #NUXEO_HOME} System property is not set, or if you want to set a custom server home, then you should * call {@link #setServerHome(File)} before. * * @since 5.4.1 */ public void init() { initServerHome(); initRuntimeHome(); String dataDir = System.getProperty(NUXEO_DATA_DIR); if (StringUtils.isNotEmpty(dataDir)) { setData(new File(dataDir)); } String configDir = System.getProperty(NUXEO_CONFIG_DIR); if (StringUtils.isNotEmpty(configDir)) { setConfig(new File(configDir)); } String logDir = System.getProperty(NUXEO_LOG_DIR); if (StringUtils.isNotEmpty(logDir)) { setLog(new File(logDir)); } String tmpDir = System.getProperty(NUXEO_TMP_DIR); if (StringUtils.isNotEmpty(tmpDir)) { setTemp(new File(tmpDir)); } String mpDir = System.getProperty(NUXEO_MP_DIR); setPath(NUXEO_MP_DIR, StringUtils.isNotEmpty(mpDir) ? mpDir : DEFAULT_MP_DIR, getServerHome()); } private void initRuntimeHome() { if (runtimeHome != null) { return; } String runtimeDir = System.getProperty(NUXEO_RUNTIME_HOME); if (runtimeDir != null && !runtimeDir.isEmpty()) { setRuntimeHome(new File(runtimeDir)); } else { setRuntimeHome(home); } } /** * This method always returns the server home (or {@link #getHome()} if {@link #NUXEO_HOME_DIR} is not set). * * @since 5.4.2 * @return Server home */ public File getServerHome() { initServerHome(); return serverHome; } /** * @since 5.4.2 */ public void setServerHome(File serverHome) { this.serverHome = serverHome.getAbsoluteFile(); setProperty(NUXEO_HOME_DIR, serverHome.getAbsolutePath()); } private void initServerHome() { if (serverHome != null) { return; } String homeDir = System.getProperty(NUXEO_HOME, System.getProperty(NUXEO_HOME_DIR)); if (homeDir != null && !homeDir.isEmpty()) { setServerHome(new File(homeDir)); } else { logger.warn(String.format("Could not set the server home from %s or %s system properties, will use %s", NUXEO_HOME, NUXEO_HOME_DIR, home)); setServerHome(home); } logger.debug(this); } public void setConfigurationProvider(Iterable<URL> configProvider) { this.configProvider = configProvider; } public Iterable<URL> getConfigurationProvider() { return configProvider; } @Override public String toString() { return ToStringBuilder.reflectionToString(this); } /** * Add a file path as a property * * @param key Property key * @param value Property value: an absolute or relative file * @param baseDir The directory against which the file will be resolved if not absolute * @since 8.1 * @see #setProperty(String, String) * @see #setPath(String, String, File) * @see #setPath(String, File) */ public void setPath(String key, File value, File baseDir) { setProperty(key, baseDir.toPath().resolve(value.toPath()).toFile().getAbsolutePath()); } /** * Add a file path as a property * * @param key Property key * @param value Property value: an absolute or relative file path * @param baseDir The directory against which the file will be resolved if not absolute * @since 8.1 * @see #setProperty(String, String) * @see #setPath(String, File, File) * @see #setPath(String, File) */ public void setPath(String key, String value, File baseDir) { setProperty(key, baseDir.toPath().resolve(value).toFile().getAbsolutePath()); } /** * Add a file path as a property * * @param key Property key * @param value Property value: an absolute or relative file; if relative, it will be resolved against {@link #home} * @since 8.1 * @see #setProperty(String, String) * @see #setPath(String, File, File) */ public void setPath(String key, File value) { setPath(key, value, home); } /** * Add a file path as a property * * @param key Property key * @param value Property value: an absolute or relative file path; if relative, it will be resolved against * {@link #home} * @since 8.1 * @see #setProperty(String, String) * @see #setPath(String, String, File) */ public void setPath(String key, String value) { setPath(key, value, home); } /** * @return the file which path is associated with the given key. The file is guaranteed to be absolute if it has * been set with {@link #setPath(String, File)} * @since 8.1 */ public File getPath(String key) { return getPath(key, null); } /** * @param key the property key * @param defaultValue the default path, absolute or relative to server home * @return the file which path is associated with the given key. The file is guaranteed to be absolute if it has * been set with {@link #setPath(String, File)} * @since 8.1 */ public File getPath(String key, String defaultValue) { String path = properties.getProperty(key); if (path != null) { return new File(path); } else if (defaultValue != null) { return getServerHome().toPath().resolve(defaultValue).toFile(); } return null; } }