org.jboss.as.server.ServerEnvironment Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source.
* Copyright 2010, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This 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 software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.server;
import static org.jboss.as.server.ServerMessages.MESSAGES;
import java.io.File;
import java.io.Serializable;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;
import org.jboss.as.controller.ControllerMessages;
import org.jboss.as.controller.OperationFailedException;
import org.jboss.as.controller.ProcessType;
import org.jboss.as.controller.RunningMode;
import org.jboss.as.controller.RunningModeControl;
import org.jboss.as.controller.audit.ManagedAuditLogger;
import org.jboss.as.controller.audit.ManagedAuditLoggerImpl;
import org.jboss.as.controller.interfaces.InetAddressUtil;
import org.jboss.as.controller.operations.common.ProcessEnvironment;
import org.jboss.as.controller.persistence.ConfigurationFile;
import org.jboss.as.version.ProductConfig;
import org.jboss.as.version.Version;
import org.jboss.modules.Module;
import org.jboss.modules.ModuleIdentifier;
import org.jboss.modules.ModuleLoader;
import org.wildfly.security.manager.WildFlySecurityManager;
/**
* Encapsulates the runtime environment for a server.
* This is parsed when the server is initially started, a process reload reuses the server environment.
*
* @author Brian Stansberry
* @author Mike M. Clark
*/
public class ServerEnvironment extends ProcessEnvironment implements Serializable {
private static final long serialVersionUID = 1725061010357265545L;
/** The manner in which a server can be launched */
public static enum LaunchType {
/** Launched by a Host Controller in a managed domain */
DOMAIN(ProcessType.DOMAIN_SERVER),
/** Launched from the command line */
STANDALONE(ProcessType.STANDALONE_SERVER),
/** Launched by another process in which the server is embedded */
EMBEDDED(ProcessType.EMBEDDED_SERVER),
/** Launched by a Java EE appclient */
APPCLIENT(ProcessType.APPLICATION_CLIENT);
private final ProcessType processType;
LaunchType(final ProcessType processType) {
this.processType = processType;
}
public ProcessType getProcessType() {
return processType;
}
}
// ///////////////////////////////////////////////////////////////////////
// Configuration Value Identifiers //
// ///////////////////////////////////////////////////////////////////////
/**
* Constant that holds the name of the system property for specifying the JDK extension directory paths.
*/
public static final String JAVA_EXT_DIRS = "java.ext.dirs";
/**
* Constant that holds the name of the system property for specifying {@link #getHomeDir() the JBoss home directory}.
*/
public static final String HOME_DIR = "jboss.home.dir";
/**
* Constant that holds the name of the system property for specifying the directory returned from
* {@link #getModulesDir()}.
*
*
* Defaults to HOME_DIR/modules/
*
*
* This system property has no real meaning and should not be regarded as providing any sort of useful
* information. The "modules" directory is the default location from which JBoss Modules looks to find
* modules. However, this behavior is in no way controlled by this system property, nor is it guaranteed that
* modules will be loaded from only one directory, nor is it guaranteed that the "modules" directory will be one
* of the directories used. Finally, the structure and contents of any directories from which JBoss Modules loads
* resources is not something available from this class. Users wishing to interact with the modular classloading
* system should use the APIs provided by JBoss Modules
*
*
* @deprecated has no useful meaning
*/
@Deprecated
public static final String MODULES_DIR = "jboss.modules.dir";
/**
* Constant that holds the name of the system property for specifying {@link #getBundlesDir() the bundles directory}.
*
*
* Defaults to HOME_DIR/bundles/
*/
public static final String BUNDLES_DIR = "jboss.bundles.dir";
/**
* VFS module identifier.
*/
public static final String VFS_MODULE_IDENTIFIER = "org.jboss.vfs";
/**
* Constant that holds the name of the system property for specifying
* {@link #getServerBaseDir() the server base directory}.
*
*
* Defaults to HOME_DIR/standalone.
*/
public static final String SERVER_BASE_DIR = "jboss.server.base.dir";
/**
* Constant that holds the name of the system property for specifying
* {@link #getServerConfigurationDir()} () the server configuration directory}.
*
*
* Defaults to SERVER_BASE_DIR/configuration .
*/
public static final String SERVER_CONFIG_DIR = "jboss.server.config.dir";
/**
* Constant that holds the name of the system property for specifying
* {@link #getServerDataDir()} () the server data directory}.
*
*
* Defaults to SERVER_BASE_DIR/data.
*/
public static final String SERVER_DATA_DIR = "jboss.server.data.dir";
/**
* Constant that holds the name of the system property for specifying
* {@link #getServerContentDir() the server managed content repository directory}.
*
*
* Defaults to SERVER_DATA_DIR/content.
*/
public static final String SERVER_CONTENT_DIR = "jboss.server.content.dir";
/**
* Deprecated variant of {@link #SERVER_CONTENT_DIR}.
*
* @deprecated use {@link #SERVER_CONTENT_DIR}
*/
@Deprecated
public static final String SERVER_DEPLOY_DIR = "jboss.server.deploy.dir";
/**
* Constant that holds the name of the system property for specifying
* {@link #getServerLogDir() the server log directory}.
*
*
* Defaults to SERVER_BASE_DIR/log.
*/
public static final String SERVER_LOG_DIR = "jboss.server.log.dir";
/**
* Constant that holds the name of the system property for specifying t
* {@link #getServerTempDir() the server temp directory}.
*
*
* Defaults to SERVER_BASE_DIR/tmp .
*/
public static final String SERVER_TEMP_DIR = "jboss.server.temp.dir";
/**
* Common alias between domain and standalone mode. Equivalent to jboss.domain.temp.dir in a managed domain,
* and jboss.server.temp.dir on a standalone server.
*/
public static final String CONTROLLER_TEMP_DIR = "jboss.controller.temp.dir";
/**
* Constant that holds the name of the system property for specifying the node name within a cluster.
*/
public static final String NODE_NAME = "jboss.node.name";
/**
* Constant that holds the name of the system property for specifying the name of this server instance.
*/
public static final String SERVER_NAME = "jboss.server.name";
/**
* Constant that holds the name of the system property for specifying the local part of the name
* of the host machine that this server is running on.
*/
public static final String HOST_NAME = "jboss.host.name";
/**
* Constant that holds the name of the system property for specifying the fully-qualified name of the host
* machine that this server is running on.
*/
public static final String QUALIFIED_HOST_NAME = "jboss.qualified.host.name";
/**
* Constant that holds the name of the system property for specifying the max threads used by the bootstrap ServiceContainer.
*/
public static final String BOOTSTRAP_MAX_THREADS = "org.jboss.server.bootstrap.maxThreads";
/**
* The default system property used to store bind address information from the command-line (-b).
*/
public static final String JBOSS_BIND_ADDRESS = "jboss.bind.address";
/**
* Prefix for the system property used to store qualified bind address information from the command-line (-bxxx).
*/
public static final String JBOSS_BIND_ADDRESS_PREFIX = JBOSS_BIND_ADDRESS + ".";
/**
* The default system property used to store bind address information from the command-line (-b).
*/
public static final String JBOSS_DEFAULT_MULTICAST_ADDRESS = "jboss.default.multicast.address";
/**
* The system property used to store the name of the default server configuration file. If not set,
* the default domain configuration file is "standalone.xml". The default domain configuration file is only
* relevant if the user does not use the {@code -c} or {@code --server-config} command line switches
* to explicitly set the server configuration file.
*/
public static final String JBOSS_SERVER_DEFAULT_CONFIG = "jboss.server.default.config";
/**
* The system property used to indicate whether the server was configured to persist changes to the configuration
* files.
*
* @deprecated for internal us only, may change or be removed at any time without notice
*/
@Deprecated
public static final String JBOSS_PERSIST_SERVER_CONFIG = "jboss.server.persist.config";
protected static final String DOMAIN_BASE_DIR = "jboss.domain.base.dir";
protected static final String DOMAIN_CONFIG_DIR = "jboss.domain.config.dir";
/** Properties that cannot be set via {@link #systemPropertyUpdated(String, String)} */
private static final Set ILLEGAL_PROPERTIES = new HashSet(Arrays.asList(DOMAIN_BASE_DIR,
DOMAIN_CONFIG_DIR, JAVA_EXT_DIRS, HOME_DIR, "modules.path", SERVER_BASE_DIR, SERVER_CONFIG_DIR,
SERVER_DATA_DIR, SERVER_DEPLOY_DIR, SERVER_LOG_DIR, BOOTSTRAP_MAX_THREADS, CONTROLLER_TEMP_DIR,
JBOSS_SERVER_DEFAULT_CONFIG, JBOSS_PERSIST_SERVER_CONFIG));
/** Properties that can only be set via {@link #systemPropertyUpdated(String, String)} during server boot. */
private static final Set BOOT_PROPERTIES = new HashSet(Arrays.asList(BUNDLES_DIR, SERVER_TEMP_DIR,
NODE_NAME, SERVER_NAME, HOST_NAME, QUALIFIED_HOST_NAME));
/** Properties that we care about that were provided to the constructor (i.e. by the user via cmd line) */
private final Properties primordialProperties;
/**
* Properties that we care about that have been provided by the user either via cmd line or
* via {@link #systemPropertyUpdated(String, String)}
*/
private final Properties providedProperties;
/** Whether the server name has been provided via {@link #setProcessName(String)} */
private volatile boolean processNameSet;
private final LaunchType launchType;
private final String hostControllerName;
private volatile String qualifiedHostName;
private volatile String hostName;
private volatile String serverName;
private volatile String nodeName;
private final File[] javaExtDirs;
private final File homeDir;
private final File modulesDir;
private final File serverBaseDir;
private final File serverConfigurationDir;
private final ConfigurationFile serverConfigurationFile;
private final File serverLogDir;
private final File controllerTempDir;
private volatile File serverDataDir;
private volatile File serverContentDir;
private volatile File serverTempDir;
private volatile File bundlesDir;
private final File domainBaseDir;
private final File domainConfigurationDir;
private final boolean standalone;
private final boolean allowModelControllerExecutor;
private final RunningMode initialRunningMode;
private final ProductConfig productConfig;
private final RunningModeControl runningModeControl;
public ServerEnvironment(final String hostControllerName, final Properties props, final Map env, final String serverConfig, final String initialServerConfig,
final LaunchType launchType, final RunningMode initialRunningMode, ProductConfig productConfig) {
if (props == null) {
throw ControllerMessages.MESSAGES.nullVar("props");
}
this.launchType = launchType;
this.standalone = launchType != LaunchType.DOMAIN;
this.initialRunningMode = initialRunningMode == null ? RunningMode.NORMAL : initialRunningMode;
this.runningModeControl = new RunningModeControl(this.initialRunningMode);
this.hostControllerName = hostControllerName;
if (standalone && hostControllerName != null) {
throw MESSAGES.hostControllerNameNonNullInStandalone();
}
if (!standalone && hostControllerName == null) {
throw MESSAGES.hostControllerNameNullInDomain();
}
// Calculate qualified and unqualified host names, default server name, cluster node name
configureQualifiedHostName(props.getProperty(QUALIFIED_HOST_NAME), props.getProperty(HOST_NAME), props, env);
// Java system-wide extension dirs
javaExtDirs = getFilesFromProperty(JAVA_EXT_DIRS, props);
// Must have HOME_DIR
homeDir = getFileFromProperty(HOME_DIR, props);
if (homeDir == null) {
throw MESSAGES.missingHomeDirConfiguration(HOME_DIR);
}
if (!homeDir.exists() || !homeDir.isDirectory()) {
throw MESSAGES.homeDirectoryDoesNotExist(homeDir);
}
@SuppressWarnings("deprecation")
File tmp = getFileFromProperty(MODULES_DIR, props);
if (tmp == null) {
tmp = new File(homeDir, "modules");
} else if (!tmp.exists() || !tmp.isDirectory()) {
throw MESSAGES.modulesDirectoryDoesNotExist(tmp);
}
modulesDir = tmp;
configureBundlesDir(props.getProperty(BUNDLES_DIR), props);
tmp = getFileFromProperty(SERVER_BASE_DIR, props);
if (tmp == null) {
tmp = new File(homeDir, standalone ? "standalone" : "domain/servers/" + serverName);
}
if (standalone) {
if (!tmp.exists()) {
throw MESSAGES.serverBaseDirectoryDoesNotExist(tmp);
} else if (!tmp.isDirectory()) {
throw MESSAGES.serverBaseDirectoryIsNotADirectory(tmp);
}
} else {
if (tmp.exists()) {
if (!tmp.isDirectory()) {
throw MESSAGES.serverBaseDirectoryIsNotADirectory(tmp);
}
}
else if (!tmp.mkdirs()) {
throw MESSAGES.couldNotCreateServerBaseDirectory(tmp);
}
}
serverBaseDir = tmp;
tmp = getFileFromProperty(SERVER_CONFIG_DIR, props);
if (tmp == null) {
tmp = new File(serverBaseDir, "configuration");
}
serverConfigurationDir = tmp;
if (standalone && (!serverConfigurationDir.exists() || !serverConfigurationDir.isDirectory())) {
throw MESSAGES.configDirectoryDoesNotExist(serverConfigurationDir);
}
String defaultServerConfig = WildFlySecurityManager.getPropertyPrivileged(JBOSS_SERVER_DEFAULT_CONFIG, "standalone.xml");
String config = initialServerConfig == null ? serverConfig : initialServerConfig;
boolean persist = initialServerConfig == null;
serverConfigurationFile = standalone ? new ConfigurationFile(serverConfigurationDir, defaultServerConfig, config, persist) : null;
// Adds a system property to indicate whether or not the server configuration should be persisted
@SuppressWarnings("deprecation")
final String propertyKey = JBOSS_PERSIST_SERVER_CONFIG;
WildFlySecurityManager.setPropertyPrivileged(propertyKey, Boolean.toString(persist));
tmp = getFileFromProperty(SERVER_DATA_DIR, props);
if (tmp == null) {
tmp = new File(serverBaseDir, "data");
}
serverDataDir = tmp;
if (serverDataDir.exists()) {
if (!serverDataDir.isDirectory()) {
throw MESSAGES.serverDataDirectoryIsNotDirectory(serverDataDir);
}
} else {
if (!serverDataDir.mkdirs()) {
throw MESSAGES.couldNotCreateServerDataDirectory(serverDataDir);
}
}
tmp = getFileFromProperty(SERVER_CONTENT_DIR, props);
if (tmp == null) {
@SuppressWarnings("deprecation")
String deprecatedProp = SERVER_DEPLOY_DIR;
tmp = getFileFromProperty(deprecatedProp, props);
}
if (tmp == null) {
tmp = new File(serverDataDir, "content");
}
serverContentDir = tmp;
if (serverContentDir.exists()) {
if (!serverContentDir.isDirectory()) {
throw MESSAGES.serverContentDirectoryIsNotDirectory(serverContentDir);
}
} else if (!serverContentDir.mkdirs()) {
throw MESSAGES.couldNotCreateServerContentDirectory(serverContentDir);
}
tmp = getFileFromProperty(SERVER_LOG_DIR, props);
if (tmp == null) {
tmp = new File(serverBaseDir, "log");
}
if (tmp.exists()) {
if (!tmp.isDirectory()) {
throw MESSAGES.logDirectoryIsNotADirectory(tmp);
}
} else if (!tmp.mkdirs()) {
throw MESSAGES.couldNotCreateLogDirectory(tmp);
}
serverLogDir = tmp;
tmp = configureServerTempDir(props.getProperty(SERVER_TEMP_DIR), props);
if (tmp.exists()) {
if (!tmp.isDirectory()) {
throw MESSAGES.serverTempDirectoryIsNotADirectory(tmp);
}
} else if (!tmp.mkdirs()){
throw MESSAGES.couldNotCreateServerTempDirectory(tmp);
}
tmp = getFileFromProperty(CONTROLLER_TEMP_DIR, props);
if (tmp == null) {
tmp = serverTempDir;
}
if (tmp.exists()) {
if (!tmp.isDirectory()) {
throw MESSAGES.controllerTempDirectoryIsNotADirectory(tmp);
}
} else if (!tmp.mkdirs()){
throw MESSAGES.couldNotCreateControllerTempDirectory(tmp);
}
controllerTempDir = tmp;
// Optional paths for the domain mode
tmp = getFileFromProperty(DOMAIN_BASE_DIR, props);
if (tmp != null) {
if (!tmp.exists() || !tmp.isDirectory()) {
throw MESSAGES.domainBaseDirDoesNotExist(tmp);
}
this.domainBaseDir = tmp;
} else {
this.domainBaseDir = null;
}
tmp = getFileFromProperty(DOMAIN_CONFIG_DIR, props);
if (tmp != null) {
if (!tmp.exists() || !tmp.isDirectory()) {
throw MESSAGES.domainConfigDirDoesNotExist(tmp);
}
this.domainConfigurationDir = tmp;
} else {
this.domainConfigurationDir = null;
}
boolean allowExecutor = true;
String maxThreads = WildFlySecurityManager.getPropertyPrivileged(BOOTSTRAP_MAX_THREADS, null);
if (maxThreads != null && maxThreads.length() > 0) {
try {
Integer.decode(maxThreads);
// Property was set to a valid value; user wishes to control core service threads
allowExecutor = false;
} catch(NumberFormatException ex) {
ServerLogger.ROOT_LOGGER.failedToParseCommandLineInteger(BOOTSTRAP_MAX_THREADS, maxThreads);
}
}
allowModelControllerExecutor = allowExecutor;
this.productConfig = productConfig;
// Keep a copy of the original properties
this.primordialProperties = new Properties();
copyProperties(props, primordialProperties);
// Create a separate copy for tracking later changes
this.providedProperties = new Properties();
copyProperties(primordialProperties, providedProperties);
// Provide standard system properties for environment items
WildFlySecurityManager.setPropertyPrivileged(QUALIFIED_HOST_NAME, qualifiedHostName);
WildFlySecurityManager.setPropertyPrivileged(HOST_NAME, hostName);
WildFlySecurityManager.setPropertyPrivileged(SERVER_NAME, serverName);
WildFlySecurityManager.setPropertyPrivileged(NODE_NAME, nodeName);
WildFlySecurityManager.setPropertyPrivileged(HOME_DIR, homeDir.getAbsolutePath());
WildFlySecurityManager.setPropertyPrivileged(MODULES_DIR, modulesDir.getAbsolutePath());
WildFlySecurityManager.setPropertyPrivileged(SERVER_BASE_DIR, serverBaseDir.getAbsolutePath());
WildFlySecurityManager.setPropertyPrivileged(SERVER_CONFIG_DIR, serverConfigurationDir.getAbsolutePath());
WildFlySecurityManager.setPropertyPrivileged(SERVER_DATA_DIR, serverDataDir.getAbsolutePath());
WildFlySecurityManager.setPropertyPrivileged(SERVER_DEPLOY_DIR, serverContentDir.getAbsolutePath());
WildFlySecurityManager.setPropertyPrivileged(SERVER_LOG_DIR, serverLogDir.getAbsolutePath());
WildFlySecurityManager.setPropertyPrivileged(SERVER_TEMP_DIR, serverTempDir.getAbsolutePath());
if(launchType.getProcessType() == ProcessType.DOMAIN_SERVER) {
if(domainBaseDir != null) {
WildFlySecurityManager.setPropertyPrivileged(DOMAIN_BASE_DIR, domainBaseDir.getAbsolutePath());
}
if(domainConfigurationDir != null) {
WildFlySecurityManager.setPropertyPrivileged(DOMAIN_CONFIG_DIR, domainConfigurationDir.getAbsolutePath());
}
}
// Register the vfs module as URLStreamHandlerFactory
try {
ModuleLoader bootLoader = Module.getBootModuleLoader();
Module vfsModule = bootLoader.loadModule(ModuleIdentifier.create(VFS_MODULE_IDENTIFIER));
Module.registerURLStreamHandlerFactoryModule(vfsModule);
} catch (Exception ex) {
ServerLogger.ROOT_LOGGER.cannotAddURLStreamHandlerFactory(ex, VFS_MODULE_IDENTIFIER);
}
}
private static void copyProperties(Properties src, Properties dest) {
for (Map.Entry