/*
* JBoss, Home of Professional Open Source.
* Copyright 2009, Red Hat Middleware LLC, 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.bootstrap.impl.as.config;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import org.jboss.bootstrap.api.as.config.JBossASBasedServerConfig;
import org.jboss.bootstrap.api.as.config.JBossASServerConfig;
import org.jboss.bootstrap.api.config.InvalidConfigurationException;
import org.jboss.bootstrap.impl.base.config.AbstractBasicConfigurationInitializer;
import org.jboss.bootstrap.impl.base.config.InvalidBootstrapURLException;
import org.jboss.bootstrap.spi.as.config.JBossASBasedConfigurationInitializer;
import org.jboss.logging.Logger;
/**
* JBossASConfigurationInitializerImpl
*
* Configuration Initializer for JBossAS
*
* @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
* @version $Revision: $
*/
public class JBossASConfigurationInitializerImpl<T extends JBossASBasedServerConfig<T>>
extends
AbstractBasicConfigurationInitializer<T> implements JBossASBasedConfigurationInitializer<T>
{
//-------------------------------------------------------------------------------||
// Class Members ----------------------------------------------------------------||
//-------------------------------------------------------------------------------||
private static final Logger log = Logger.getLogger(JBossASConfigurationInitializerImpl.class);
/**
* File denoting the present working directory, used in
* defaulting $JBOSS_HOME
*/
private static final File FILE_PRESENT_WORKING_DIRECTORY = new File("");
/**
* Represents a trailing slash
*/
private static final String TRAILING_SLASH = "/";
//-------------------------------------------------------------------------------||
// Required Implementations -----------------------------------------------------||
//-------------------------------------------------------------------------------||
/* (non-Javadoc)
* @see org.jboss.bootstrap.spi.config.AbstractBasicConfigurationInitializer#initialize(org.jboss.bootstrap.spi.config.ServerConfig)
*/
@Override
public void initialize(T config) throws InvalidConfigurationException, IllegalArgumentException,
IllegalStateException
{
// Log
log.debugf("Initializing: %s", config);
// Get the configuration properties
final Map<String, String> configProps = config.getProperties();
// $JBOSS_HOME
final String pwd = FILE_PRESENT_WORKING_DIRECTORY.getAbsolutePath() + "/";
final String currentJBossHome = config.getJBossHome() != null ? config.getJBossHome().toExternalForm() : null;
String jbossHome = this.resolvePropertyValue(JBossASServerConfig.PROP_KEY_JBOSSAS_HOME,
JBossASServerConfig.ENV_VAR_JBOSSAS_HOME, currentJBossHome, pwd, configProps);
jbossHome = this.adjustToTrailingSlash(jbossHome);
config.jbossHome(jbossHome);
// ${jboss.bind.address}
final String bindAddress = this.resolvePropertyValue(JBossASServerConfig.PROP_KEY_JBOSSAS_BIND_ADDRESS, config
.getBindAddress(), JBossASBasedConfigurationInitializer.VALUE_BIND_ADDRESS_DEFAULT, configProps);
config.bindAddress(bindAddress);
// ${jboss.server.name}
final String serverName = this.resolvePropertyValue(JBossASServerConfig.PROP_KEY_JBOSSAS_SERVER_NAME, config
.getServerName(), JBossASBasedConfigurationInitializer.VALUE_SERVER_NAME_DEFAULT, configProps);
config.serverName(serverName);
// ${jboss.lib.url}
final URL bootLibLocation = config.getBootLibraryLocation();
final String bootLibDefault = jbossHome + JBossASBasedConfigurationInitializer.VALUE_LIBRARY_URL_SUFFIX_DEFAULT;
final String currentBootLibLocation = bootLibLocation != null ? bootLibLocation.toExternalForm() : null;
String resolvedBootLibLocation = this.resolvePropertyValue(JBossASServerConfig.PROP_KEY_JBOSSAS_BOOT_LIBRARY_URL,
currentBootLibLocation, bootLibDefault, configProps);
resolvedBootLibLocation = this.adjustToTrailingSlash(resolvedBootLibLocation);
config.bootLibraryLocation(resolvedBootLibLocation);
// ${jboss.server.base.url} / ${jboss.server.base.dir}
final URL serverBaseLocation = config.getServerBaseLocation();
final String serverBaseDefault = jbossHome
+ JBossASBasedConfigurationInitializer.VALUE_SERVER_BASE_URL_SUFFIX_DEFAULT;
final String currentServerBaseLocation = serverBaseLocation != null ? serverBaseLocation.toExternalForm() : null;
String resolvedServerBaseLocation = this.resolvePropertyValue(
JBossASServerConfig.PROP_KEY_JBOSSAS_SERVER_BASE_URL, currentServerBaseLocation, serverBaseDefault,
configProps);
resolvedServerBaseLocation = this.adjustToTrailingSlash(resolvedServerBaseLocation);
config.serverBaseLocation(resolvedServerBaseLocation);
// ${jboss.server.home.url} / ${jboss.server.home.dir}
final URL serverHomeLocation = config.getServerHomeLocation();
final String serverHomeDefault = resolvedServerBaseLocation + serverName;
final String currentServerHomeLocation = serverHomeLocation != null ? serverHomeLocation.toExternalForm() : null;
String resolvedServerHomeLocation = this.resolvePropertyValue(
JBossASServerConfig.PROP_KEY_JBOSSAS_SERVER_HOME_URL, currentServerHomeLocation, serverHomeDefault,
configProps);
resolvedServerHomeLocation = this.adjustToTrailingSlash(resolvedServerHomeLocation);
config.serverHomeLocation(resolvedServerHomeLocation);
// ${jboss.common.base.url}
final URL commonBaseLocation = config.getCommonBaseLocation();
final String commonBaseDefault = jbossHome
+ JBossASBasedConfigurationInitializer.VALUE_COMMON_BASE_URL_SUFFIX_DEFAULT;
final String currentCommonBaseLocation = commonBaseLocation != null ? commonBaseLocation.toExternalForm() : null;
String resolvedCommonBaseLocation = this.resolvePropertyValue(
JBossASServerConfig.PROP_KEY_JBOSSAS_COMMON_BASE_URL, currentCommonBaseLocation, commonBaseDefault,
configProps);
resolvedCommonBaseLocation = this.adjustToTrailingSlash(resolvedCommonBaseLocation);
config.commonBaseLocation(resolvedCommonBaseLocation);
// ${jboss.common.lib.url}
final URL commonLibLocation = config.getCommonLibLocation();
final String commonLibDefault = resolvedCommonBaseLocation
+ JBossASBasedConfigurationInitializer.VALUE_LIBRARY_URL_SUFFIX_DEFAULT;
final String currentCommonLibLocation = commonLibLocation != null ? commonLibLocation.toExternalForm() : null;
String resolvedCommonLibLocation = this.resolvePropertyValue(
JBossASServerConfig.PROP_KEY_JBOSSAS_COMMON_LIBRARY_URL, currentCommonLibLocation, commonLibDefault,
configProps);
resolvedCommonLibLocation = this.adjustToTrailingSlash(resolvedCommonLibLocation);
config.commonLibLocation(resolvedCommonLibLocation);
// ${jboss.server.log.dir}
final URL serverLogLocation = config.getServerLogLocation();
final String serverLogDefault = resolvedServerHomeLocation
+ JBossASBasedConfigurationInitializer.VALUE_SERVER_LOG_DIR_SUFFIX_DEFAULT;
final String currentServerLogLocation = serverLogLocation != null ? serverLogLocation.toExternalForm() : null;
String resolvedServerLogLocation = this.resolvePropertyValue(JBossASServerConfig.PROP_KEY_JBOSSAS_SERVER_LOG_DIR,
currentServerLogLocation, serverLogDefault, configProps);
resolvedServerLogLocation = this.adjustToTrailingSlash(resolvedServerLogLocation);
config.serverLogLocation(resolvedServerLogLocation);
// ${jboss.server.conf.url}
final URL serverConfLocation = config.getServerConfLocation();
final String serverConfDefault = resolvedServerHomeLocation
+ JBossASBasedConfigurationInitializer.VALUE_SERVER_CONFIG_URL_SUFFIX_DEFAULT;
final String currentServerConfLocation = serverConfLocation != null ? serverConfLocation.toExternalForm() : null;
String resolvedServerConfLocation = this.resolvePropertyValue(
JBossASServerConfig.PROP_KEY_JBOSSAS_SERVER_CONF_URL, currentServerConfLocation, serverConfDefault,
configProps);
resolvedServerConfLocation = this.adjustToTrailingSlash(resolvedServerConfLocation);
config.serverConfLocation(resolvedServerConfLocation);
// Init the super config, must be done after we set jboss.server.conf.url
// so that bootstrap configs are set properly
super.initialize(config);
// ${jboss.server.lib.url}
final URL serverLibLocation = config.getServerLibLocation();
final String serverLibDefault = resolvedServerHomeLocation
+ JBossASBasedConfigurationInitializer.VALUE_LIBRARY_URL_SUFFIX_DEFAULT;
final String currentServerLibLocation = serverLibLocation != null ? serverLibLocation.toExternalForm() : null;
String resolvedServerLibLocation = this.resolvePropertyValue(
JBossASServerConfig.PROP_KEY_JBOSSAS_SERVER_LIBRARY_URL, currentServerLibLocation, serverLibDefault,
configProps);
resolvedServerLibLocation = this.adjustToTrailingSlash(resolvedServerLibLocation);
config.serverLibLocation(resolvedServerLibLocation);
// ${jboss.server.data.dir}
final URL serverDataLocation = config.getServerDataLocation();
final String serverDataDefault = resolvedServerHomeLocation
+ JBossASBasedConfigurationInitializer.VALUE_SERVER_DATA_DIR_SUFFIX_DEFAULT;
final String currentServerDataLocation = serverDataLocation != null ? serverDataLocation.toExternalForm() : null;
String resolvedServerDataLocation = this.resolvePropertyValue(
JBossASServerConfig.PROP_KEY_JBOSSAS_SERVER_DATA_DIR, currentServerDataLocation, serverDataDefault,
configProps);
resolvedServerDataLocation = this.adjustToTrailingSlash(resolvedServerDataLocation);
config.serverDataLocation(resolvedServerDataLocation);
// ${jboss.server.tmp.dir}
final URL serverTempLocation = config.getServerTempLocation();
final String serverTempDefault = resolvedServerHomeLocation
+ JBossASBasedConfigurationInitializer.VALUE_SERVER_TEMP_DIR_SUFFIX_DEFAULT;
final String currentServerTempLocation = serverTempLocation != null ? serverTempLocation.toExternalForm() : null;
String resolvedServerTempLocation = this.resolvePropertyValue(
JBossASServerConfig.PROP_KEY_JBOSSAS_SERVER_TEMP_DIR, currentServerTempLocation, serverTempDefault,
configProps);
resolvedServerTempLocation = this.adjustToTrailingSlash(resolvedServerTempLocation);
config.serverTempLocation(resolvedServerTempLocation);
// Bootstrap Name and Home for AS
final String resolvedBootstrapName = this.resolvePropertyValue(JBossASServerConfig.PROP_KEY_BOOTSTRAP_NAME, null,
JBossASBasedConfigurationInitializer.VALUE_BOOTSTRAP_NAME_DEFAULT, configProps);
config.bootstrapName(resolvedBootstrapName);
final String bootstrapHomeDefault = resolvedServerConfLocation;
// Resolve
final URL bootstrapHome = config.getBootstrapHome();
final String currentBootstrapHome = bootstrapHome == null ? null : bootstrapHome.toExternalForm();
String resolvedBootstrapHome = this.resolvePropertyValue(JBossASServerConfig.PROP_KEY_BOOTSTRAP_HOME_URL, currentBootstrapHome,
bootstrapHomeDefault, configProps);
resolvedBootstrapHome = this.adjustToTrailingSlash(resolvedBootstrapHome);
config.bootstrapHome(resolvedBootstrapHome);
// Initialize the bootstrap URL
this.initializeBootstrapUrl(config);
// ${jboss.partition.name}
final String partitionName = this.resolvePropertyValue(JBossASServerConfig.PROP_KEY_JBOSSAS_PARTITION_NAME,
config.getPartitionName(), JBossASBasedConfigurationInitializer.VALUE_PARTITION_NAME_DEFAULT, configProps);
config.partitionName(partitionName);
// ${jboss.partition.udpGroup}
final String udpGroup = this.resolvePropertyValue(JBossASServerConfig.PROP_KEY_JBOSSAS_PARTITION_UDP_GROUP,
config.getUdpGroup(), null, configProps);
config.udpGroup(udpGroup);
// ${jboss.jgroups.udp.mcast_port}
final Integer udpPort = config.getUdpPort();
final String udpPortString = udpPort != null ? udpPort.toString() : null;
final String udpPortResolved = this.resolvePropertyValue(JBossASServerConfig.PROP_KEY_JBOSSAS_PARTITION_UDP_PORT,
udpPortString, null, configProps);
if (udpPortResolved != null)
{
try
{
final int udpPortOverride = Integer.parseInt(udpPortResolved);
config.udpPort(udpPortOverride);
}
catch (final NumberFormatException nfe)
{
throw new InvalidConfigurationException("UDP Port overridden to non-integer value", nfe);
}
}
// ${jboss.native.load}
final Boolean loadNative = config.isLoadNative();
final String loadNativeString = loadNative != null ? loadNative.toString() : null;
final String loadNativeResolved = this.resolvePropertyValue(JBossASServerConfig.PROP_KEY_JBOSSAS_NATIVE_LOAD,
loadNativeString, JBossASBasedConfigurationInitializer.VALUE_NATIVE_LOAD_DEFAULT.toString(), configProps);
if (loadNativeResolved != null)
{
final boolean loadNativeOverride = Boolean.parseBoolean(loadNativeResolved);
config.loadNative(loadNativeOverride);
}
// ${jboss.native.dir}
final URL nativeLibLocation = config.getNativeLibraryLocation();
final String nativeLibDefault = resolvedServerTempLocation
+ JBossASBasedConfigurationInitializer.VALUE_NATIVE_DIR_SUFFIX_DEFAULT;
final String currentNativeLibLocation = nativeLibLocation != null ? nativeLibLocation.toExternalForm() : null;
String resolvedNativeLibLocation = this.resolvePropertyValue(JBossASServerConfig.PROP_KEY_JBOSSAS_NATIVE_DIR,
currentNativeLibLocation, nativeLibDefault, configProps);
resolvedNativeLibLocation = this.adjustToTrailingSlash(resolvedNativeLibLocation);
config.nativeLibraryLocation(resolvedNativeLibLocation);
// ${jboss.platform.mbeanserver}
final Boolean platformMBeanServer = config.isUsePlatformMBeanServer();
final String platformMBeanServerString = platformMBeanServer != null ? platformMBeanServer.toString() : null;
final String platformMBeanServerResolved = this.resolvePropertyValue(
JBossASServerConfig.PROP_KEY_JBOSSAS_PLATFORM_MBEANSERVER, platformMBeanServerString,
JBossASBasedConfigurationInitializer.VALUE_PLATFORM_MBEAN_SERVER_DEFAULT.toString(), configProps);
if (platformMBeanServerResolved != null)
{
final boolean platformMbeanServerOverride = Boolean.parseBoolean(platformMBeanServerResolved);
config.usePlatformMBeanServer(platformMbeanServerOverride);
}
}
//-------------------------------------------------------------------------------||
// Functional Methods -----------------------------------------------------------||
//-------------------------------------------------------------------------------||
/**
* Returns the value of the specified String, appending a trailing
* slash "/", if not found. Otherwise returns the argument.
*
* @param string The String to which we should optionally append a "/"
*/
private String adjustToTrailingSlash(final String string)
{
// Init
String newString = string;
// If we need a trailing slash
if (!newString.endsWith(TRAILING_SLASH))
{
// Append it
newString = newString + TRAILING_SLASH;
}
// Return
return newString;
}
/**
* Applies the following preference in resolving a property's value:
*
* 1) Config Property (which is originated from sys props)
* 2) Object Model (Current Value)
* 3) Default Value
*
* Lower numbers above denote higher priority.
*
* @param propertyName The name of the system/configuration property
* @param currentValue The value of the property within the object model
* @param defaultValue The value of the default if none others are specified
* @param properties The configuration properties
*
* @throws IllegalArgumentException If propertyName is null/empty or
* properties are null
*/
private String resolvePropertyValue(final String propertyName, final String currentValue, final String defaultValue,
final Map<String, String> properties) throws IllegalArgumentException
{
// Pass along, using null env var
return this.resolvePropertyValue(propertyName, null, currentValue, defaultValue, properties);
}
/**
* Applies the following preference in resolving a property's value:
*
* 1) Config Property (which is originated from sys props)
* 2) Object Model (Current Value)
* 3) Environment Variable
* 4) Default Value
*
* Lower numbers above denote higher priority. This method is package-private
* for direct unit testing.
*
* @param propertyName The name of the system/configuration property
* @param envVarName The name of the environment variable, or null if not used
* @param currentValue The value of the property within the object model
* @param defaultValue The value of the default if none others are specified
* @param properties The configuration properties
*
* @throws IllegalArgumentException If propertyName is null/empty or
* properties are null
*/
String resolvePropertyValue(final String propertyName, final String envVarName, final String currentValue,
final String defaultValue, final Map<String, String> properties) throws IllegalArgumentException
{
// Precondition checks
if (propertyName == null || propertyName.length() == 0)
{
throw new IllegalArgumentException("Property name is a required argument");
}
if (properties == null)
{
throw new IllegalArgumentException("Properties is a required argument");
}
// Log
if (log.isTraceEnabled())
{
log.trace("Determining true value for property: " + propertyName);
}
// Start at the default value
String returnValue = defaultValue;
if (log.isTraceEnabled())
{
log.trace("Default value of \"" + propertyName + "\" is: " + defaultValue);
}
// If the environment variable is defined, this overrides the default
if (envVarName != null)
{
final String envVarValue = SecurityActions.getEnvironmentVariable(envVarName);
if (envVarValue != null)
{
returnValue = envVarValue;
// Log at trace
log.tracef("Found environment variable \"%s\", so using value as override: %s", envVarName, envVarValue);
}
}
// If the object model value is specified, use it
if (currentValue != null && currentValue.length() > 0)
{
log.tracef("Object model has specified value for \"%s\": %s", propertyName, currentValue);
returnValue = currentValue;
}
// Get the override value
final String override = properties.get(propertyName);
// If the override value is specified, use it
if (override != null && override.length() > 0)
{
// Log as debug here as property-based override may be from command-line,
// so give the user a greater hint of what's going on
log.debugf("Got configuration property %s, so using as override: %s", propertyName, override);
returnValue = override;
}
// Return
log
.tracef(
"Resolved property: %s with currentValue = %s, environment variable name = %s, and defaultValue = %s to: %s",
propertyName, currentValue, envVarName, defaultValue, returnValue);
return returnValue;
}
/**
* @see org.jboss.bootstrap.impl.base.config.AbstractBasicConfigurationInitializer#applyPropertyOverrides(org.jboss.bootstrap.api.config.ServerConfig)
*/
@Override
protected void applyPropertyOverrides(T config) throws IllegalArgumentException
{
// Log
log.trace("Applying system property overrides...");
// Precondition check
if (config == null)
{
throw new IllegalArgumentException("Supplied configuration is null");
}
// Get Properties
final Map<String, String> properties = config.getProperties();
/*
* Apply overrides if present
*/
// Home
final String overrideHome = this.getOverrideValue(T.PROP_KEY_BOOTSTRAP_HOME_URL, properties);
if (overrideHome != null)
{
config.bootstrapHome(overrideHome);
}
// URL
final String overrideUrl = this.getOverrideValue(T.PROP_KEY_BOOTSTRAP_URL, properties);
if (overrideUrl != null)
{
config.bootstrapUrl(overrideUrl);
}
// Name
final String overrideName = this.getOverrideValue(T.PROP_KEY_BOOTSTRAP_NAME, properties);
if (overrideName != null)
{
config.bootstrapName(overrideName);
}
}
//-------------------------------------------------------------------------------||
// Internal Helper Methods ------------------------------------------------------||
//-------------------------------------------------------------------------------||
/**
* Initializes the bootstrap URL from bootstrapHome+bootstrapName (if specified),
* or directly from the bootstrapURL property (if specified this takes priority).
* @param config
*/
void initializeBootstrapUrl(final T config)
{
/*
* Default the config
*/
final URL bootstrapUrl = config.getBootstrapUrl();
final URL home = config.getBootstrapHome();
final String name = config.getBootstrapName();
/*
* If bootstrapURL is not directly defined, construct it from
* home+name (assuming they both *are* defined)
*/
if (bootstrapUrl == null && (home != null && name != null))
{
// Log
log.trace("No bootstrap URL defined, constructing it from home and name...");
// Bootstrap name should not start with a slash when being treated as a relative URL
// to the bootstrap home.
if (name.startsWith(TRAILING_SLASH))
{
throw new InvalidBootstrapURLException("Invalid bootstrap name: " + name
+ ". Bootstrap name can not start with '" + TRAILING_SLASH + "'.");
}
// Construct
URL newBootstrapUrl = null;
try
{
newBootstrapUrl = new URL(home, name);
}
catch (MalformedURLException e)
{
throw new IllegalArgumentException(new InvalidConfigurationException(
"Cannot construct bootstrapURL from home and name", e));
}
// Log
log.debugf("New bootstrap URL: %s", newBootstrapUrl.toExternalForm());
// Set
config.bootstrapUrl(newBootstrapUrl);
}
/*
* If bootstrapConf was not initialized, set it from either home or URL base
*/
final URL defaultBootstrapHome = config.getServerConfLocation();
// If there's no name, default it, then run this config again to
// default other properties if necessary
if (name == null || name.length() == 0)
{
final String defaultBootstrapName = JBossASBasedConfigurationInitializer.VALUE_BOOTSTRAP_NAME_DEFAULT;
config.bootstrapName(defaultBootstrapName);
this.initializeBootstrapUrl(config);
}
// If there's no home, default it, then run this config again
if (home == null)
{
final URL newHome = defaultBootstrapHome;
config.bootstrapHome(newHome);
this.initializeBootstrapUrl(config);
}
}
/**
* Returns the override value for the specified property name in the specified
* properties, additionally logging if found. If not found, null will be returned.
*
* @throws IllegalArgumentException If either argument is null
*/
private String getOverrideValue(final String propertyName, final Map<String, String> properties)
throws IllegalArgumentException
{
// Get the override value
String override = properties.get(propertyName);
// Adjust to null if empty
if (override != null && override.length() == 0)
{
override = null;
}
// Log if we'll use it
if (override != null && override.length() > 0)
{
log.tracef("Got system property %s, so using as override: %s", propertyName, override);
}
// Return
return override;
}
}