/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, 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;
import java.io.File;
import java.lang.reflect.Type;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;
import org.jboss.bootstrap.spi.Server;
import org.jboss.bootstrap.spi.ServerConfig;
import org.jboss.logging.Logger;
import org.jboss.managed.api.annotation.ManagementComponent;
import org.jboss.managed.api.annotation.ManagementObject;
import org.jboss.managed.api.annotation.ManagementProperties;
import org.jboss.managed.api.annotation.ManagementProperty;
import org.jboss.managed.api.annotation.ViewUse;
import org.jboss.metatype.api.annotations.MetaMapping;
import org.jboss.metatype.api.types.MetaType;
import org.jboss.metatype.api.types.SimpleMetaType;
import org.jboss.metatype.api.values.MetaValue;
import org.jboss.metatype.api.values.SimpleValue;
import org.jboss.metatype.api.values.SimpleValueSupport;
import org.jboss.metatype.spi.values.MetaMapper;
import org.jboss.util.NestedRuntimeException;
import org.jboss.util.Null;
import org.jboss.util.Primitives;
import org.jboss.util.platform.Java;
/**
* A container for the basic configuration elements required to create
* a Server instance.
*
* <p>MalformedURLException are rethrown as NestedRuntimeExceptions, so that
* code that needs to access these values does not have to directly
* worry about problems with lazy construction of final URL values.
*
* <p>Most values are determined durring first call to getter. All values
* when determined will have equivilent system properties set.
*
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
* @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
* @author Scott.Stark@jboss.org
* @version <tt>$Revision: 41281 $</tt>
*/
@ManagementObject(name = "jboss.system:type=ServerConfig",
isRuntime = true,
properties = ManagementProperties.EXPLICIT,
description = "provides a view of server config information",
componentType = @ManagementComponent(type = "MCBean", subtype = "*"))
public class BaseServerConfig implements ServerConfig
{
/** The configuration properties to pull data from. */
private Properties props;
private URL bootstrapURL;
private File homeDir;
private URL homeURL;
private URL libraryURL;
/**
* The base URL where patch files will be loaded from. This is
* typed as an Object to allow its value to contain Null.VALUE
* or a URL. If value is Null.VALUE then we have determined
* that there is no user configuration for this value and it will
* be passed back as null to the requesting client.
*/
private Object patchURL;
private String serverSpecificationVersion;
private String serverName;
private File serverBaseDir;
private File serverHomeDir;
private File serverLogDir;
private File serverTempDir;
private File serverDataDir;
private URL serverBaseURL;
private URL serverHomeURL;
private URL serverLibraryURL;
private URL serverConfigURL;
private URL commonBaseURL;
private URL commonLibraryURL;
/** Exit on shutdown flag. */
private Boolean exitOnShutdown;
private Boolean blockingShutdown;
private Boolean requireJBossURLStreamHandlerFactory;
private Boolean platformMBeanServer;
private Boolean installLifeThread;
private String rootDeployableFilename;
/**
* Construct a new <tt>ServerConfigImpl</tt> instance.
*
* @param props Configuration properties.
*
* @throws Exception Missing or invalid configuration.
*/
public BaseServerConfig(final Properties props) throws Exception
{
this.props = props;
// Must have HOME_DIR
homeDir = getFileFromProperty(ServerConfig.HOME_DIR);
if (homeDir == null)
throw new Exception("Missing configuration value for: " + ServerConfig.HOME_DIR);
System.setProperty(ServerConfig.HOME_DIR, homeDir.getAbsolutePath());
// Setup the SERVER_HOME_DIR system property
getServerHomeDir();
Package thisPackage = getClass().getPackage();
serverSpecificationVersion = thisPackage.getSpecificationVersion();
}
/** Breakout the initialization of URLs from the constructor as we need
* the ServerConfig.HOME_DIR set for log setup, but we cannot create any
* file URLs prior to the
*
* @throws MalformedURLException for a bad home url
*/
public void initURLs()
throws MalformedURLException
{
// If not set then default to homeDir
homeURL = getURL(ServerConfig.HOME_URL);
if (homeURL == null)
{
homeURL = homeDir.toURL();
}
System.setProperty(ServerConfig.HOME_URL, homeURL.toString());
}
/////////////////////////////////////////////////////////////////////////
// Typed Access //
/////////////////////////////////////////////////////////////////////////
@ManagementProperty(description = "the bootstrap url",
use={ViewUse.STATISTIC})
public URL getBootstrapURL()
{
if (bootstrapURL == null)
{
try
{
bootstrapURL = getURL(ServerConfig.BOOTSTRAP_URL);
if (bootstrapURL != null)
System.setProperty(ServerConfig.BOOTSTRAP_URL, bootstrapURL.toString());
}
catch (MalformedURLException e)
{
throw new NestedRuntimeException(e);
}
}
return bootstrapURL;
}
@ManagementProperty(description = "the local home directory which the server is running from", use =
{ViewUse.STATISTIC})
@MetaMapping(FileMetaMapper.class)
public File getHomeDir()
{
return homeDir;
}
@ManagementProperty(description="home URL which the server is running from",
use={ViewUse.STATISTIC})
public URL getHomeURL()
{
return homeURL;
}
@ManagementProperty(description="the bootstrap library URL for the server.",
use={ViewUse.STATISTIC})
public URL getLibraryURL()
{
if (libraryURL == null)
{
try
{
libraryURL = getURL(ServerConfig.LIBRARY_URL);
if (libraryURL == null)
{
libraryURL = new URL(homeURL, ServerConfig.LIBRARY_URL_SUFFIX);
}
System.setProperty(ServerConfig.LIBRARY_URL, libraryURL.toString());
}
catch (MalformedURLException e)
{
throw new NestedRuntimeException(e);
}
}
return libraryURL;
}
public URL getPatchURL()
{
if (patchURL == null)
{
try
{
patchURL = getURL(ServerConfig.PATCH_URL);
if (patchURL == null)
{
patchURL = Null.VALUE;
}
else
{
System.setProperty(ServerConfig.PATCH_URL, patchURL.toString());
}
}
catch (MalformedURLException e)
{
throw new NestedRuntimeException(e);
}
}
if (patchURL == Null.VALUE)
return null;
return (URL) patchURL;
}
@ManagementProperty(description="the name of the active profile the sever is using",
use={ViewUse.STATISTIC})
public String getServerName()
{
if (serverName == null)
{
serverName = props.getProperty(ServerConfig.SERVER_NAME, ServerConfig.DEFAULT_SERVER_NAME);
System.setProperty(ServerConfig.SERVER_NAME, serverName);
}
return serverName;
}
@ManagementProperty(description="the base directory for calculating server home directories",
use={ViewUse.STATISTIC})
@MetaMapping(FileMetaMapper.class)
public File getServerBaseDir()
{
if (serverBaseDir == null)
{
serverBaseDir = getFileFromProperty(ServerConfig.SERVER_BASE_DIR);
if (serverBaseDir == null)
{
serverBaseDir = new File(homeDir, ServerConfig.SERVER_BASE_DIR_SUFFIX);
System.setProperty(ServerConfig.SERVER_BASE_DIR, serverBaseDir.toString());
}
}
return serverBaseDir;
}
@ManagementProperty(description="the server home directory",
use={ViewUse.STATISTIC})
@MetaMapping(FileMetaMapper.class)
public File getServerHomeDir()
{
if (serverHomeDir == null)
{
serverHomeDir = getFileFromProperty(ServerConfig.SERVER_HOME_DIR);
if (serverHomeDir == null)
{
serverHomeDir = new File(getServerBaseDir(), getServerName());
System.setProperty(ServerConfig.SERVER_HOME_DIR, serverHomeDir.toString());
}
}
return serverHomeDir;
}
/**
* Get the directory where temporary files will be stored. The associated
* ServerConfig.SERVER_LOG_DIR system property needs to be set before
* the logging framework is used.
*
* @see ServerConfig#SERVER_LOG_DIR
* @return the writable temp directory
*/
@ManagementProperty(description="the server log directory",
use={ViewUse.STATISTIC})
@MetaMapping(FileMetaMapper.class)
public File getServerLogDir()
{
if (serverLogDir == null)
{
serverLogDir = getFileFromProperty(ServerConfig.SERVER_LOG_DIR);
if (serverLogDir == null)
{
serverLogDir = new File(getServerHomeDir(), ServerConfig.SERVER_LOG_DIR_SUFFIX);
System.setProperty(ServerConfig.SERVER_LOG_DIR, serverLogDir.toString());
}
}
return serverLogDir;
}
/**
* Get the directory where temporary files will be stored.
*
* @return the writable temp directory
*/
@ManagementProperty(description="the directory where temporary files will be stored",
use={ViewUse.STATISTIC})
@MetaMapping(FileMetaMapper.class)
public File getServerTempDir()
{
if (serverTempDir == null)
{
serverTempDir = getFileFromProperty(ServerConfig.SERVER_TEMP_DIR);
if (serverTempDir == null)
{
serverTempDir = new File(getServerHomeDir(), ServerConfig.SERVER_TEMP_DIR_SUFFIX);
System.setProperty(ServerConfig.SERVER_TEMP_DIR, serverTempDir.toString());
}
}
return serverTempDir;
}
/**
* Get the directory where local data will be stored.
*
* @return the data directory
*/
@ManagementProperty(description="the directory where local data will be stored",
use={ViewUse.STATISTIC})
@MetaMapping(FileMetaMapper.class)
public File getServerDataDir()
{
if (serverDataDir == null)
{
serverDataDir = getFileFromProperty(ServerConfig.SERVER_DATA_DIR);
if (serverDataDir == null)
{
serverDataDir = new File(getServerHomeDir(), ServerConfig.SERVER_DATA_DIR_SUFFIX);
System.setProperty(ServerConfig.SERVER_DATA_DIR, serverDataDir.toString());
}
}
return serverDataDir;
}
/**
* Get the native dir for unpacking
*
* @return the directory
*/
@ManagementProperty(description="the directory for platform native files",
use={ViewUse.STATISTIC})
@MetaMapping(FileMetaMapper.class)
public File getServerNativeDir()
{
try
{
String fileName = this.getNativeDirProperty();
if (fileName != null)
{
return new File(fileName);
}
return new File(getServerTempDir(), "native");
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
/**
* Obtains the property value of the native directory
*
* Extracted to package-private for testing of
* JBBOOT-6
*
* @return
*/
String getNativeDirProperty()
{
String property = this.props.getProperty(NATIVE_DIR_PROPERTY);
return property != null ? property : System.getProperty(NATIVE_DIR_PROPERTY);
}
/**
* Get the temporary deployment dir for unpacking
*
* @return the directory
*/
@ManagementProperty(description="the temporary deployment dir",
use={ViewUse.STATISTIC})
@MetaMapping(FileMetaMapper.class)
public File getServerTempDeployDir()
{
try
{
return new File(getServerTempDir(), "deploy");
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
@ManagementProperty(description="the base URL for calculating server home URLs",
use={ViewUse.STATISTIC})
public URL getServerBaseURL()
{
if (serverBaseURL == null)
{
try
{
serverBaseURL = getURL(ServerConfig.SERVER_BASE_URL);
if (serverBaseURL == null)
{
serverBaseURL = new URL(homeURL, ServerConfig.SERVER_BASE_URL_SUFFIX);
}
System.setProperty(ServerConfig.SERVER_BASE_URL, serverBaseURL.toString());
}
catch (MalformedURLException e)
{
throw new NestedRuntimeException(e);
}
}
return serverBaseURL;
}
@ManagementProperty(description="the server home URL",
use={ViewUse.STATISTIC})
public URL getServerHomeURL()
{
if (serverHomeURL == null)
{
try
{
serverHomeURL = getURL(ServerConfig.SERVER_HOME_URL);
if (serverHomeURL == null)
{
serverHomeURL = new URL(getServerBaseURL(), getServerName() + "/");
}
System.setProperty(ServerConfig.SERVER_HOME_URL, serverHomeURL.toString());
}
catch (MalformedURLException e)
{
throw new NestedRuntimeException(e);
}
}
return serverHomeURL;
}
@ManagementProperty(description="the server home URL",
use={ViewUse.STATISTIC})
public URL getServerLibraryURL()
{
if (serverLibraryURL == null)
{
try
{
serverLibraryURL = getURL(ServerConfig.SERVER_LIBRARY_URL);
if (serverLibraryURL == null)
{
serverLibraryURL = new URL(getServerHomeURL(), ServerConfig.LIBRARY_URL_SUFFIX);
}
System.setProperty(ServerConfig.SERVER_LIBRARY_URL, serverLibraryURL.toString());
}
catch (MalformedURLException e)
{
throw new NestedRuntimeException(e);
}
}
return serverLibraryURL;
}
@ManagementProperty(description="the common library URL base",
use={ViewUse.STATISTIC})
public URL getCommonBaseURL()
{
if (commonBaseURL == null)
{
try
{
commonBaseURL = getURL(ServerConfig.COMMON_BASE_URL);
if (commonBaseURL == null)
{
commonBaseURL = new URL(getHomeURL(), ServerConfig.COMMON_BASE_URL_SUFFIX);
}
System.setProperty(ServerConfig.COMMON_BASE_URL, commonBaseURL.toString());
}
catch (MalformedURLException e)
{
throw new NestedRuntimeException(e);
}
}
return commonBaseURL;
}
@ManagementProperty(description="the URL for the common library jars",
use={ViewUse.STATISTIC})
public URL getCommonLibraryURL()
{
if (commonLibraryURL == null)
{
try
{
commonLibraryURL = getURL(ServerConfig.COMMON_LIBRARY_URL);
if (commonLibraryURL == null)
{
commonLibraryURL = new URL(getCommonBaseURL(), ServerConfig.LIBRARY_URL_SUFFIX);
}
System.setProperty(ServerConfig.COMMON_LIBRARY_URL, commonLibraryURL.toString());
}
catch (MalformedURLException e)
{
throw new NestedRuntimeException(e);
}
}
return commonLibraryURL;
}
public URL getServerConfigURL()
{
if (serverConfigURL == null)
{
try
{
serverConfigURL = getURL(ServerConfig.SERVER_CONFIG_URL);
if (serverConfigURL == null)
{
serverConfigURL = new URL(getServerHomeURL(), ServerConfig.SERVER_CONFIG_URL_SUFFIX);
}
System.setProperty(ServerConfig.SERVER_CONFIG_URL, serverConfigURL.toString());
}
catch (MalformedURLException e)
{
throw new NestedRuntimeException(e);
}
}
return serverConfigURL;
}
/**
* Get the current value of the flag that indicates if we are
* using the platform MBeanServer as the main jboss server.
* Both the {@link ServerConfig#PLATFORM_MBEANSERVER}
* property must be set, and the jvm must be jdk1.5+
*
* @return true if jboss runs on the jvm platfrom MBeanServer
*/
public boolean getPlatformMBeanServer()
{
if (platformMBeanServer == null)
{
if (Java.isCompatible(Java.VERSION_1_5))
{
// get whatever the user has specified or the default
String value = props.getProperty(ServerConfig.PLATFORM_MBEANSERVER,
(new Boolean(ServerConfig.DEFAULT_PLATFORM_MBEANSERVER)).toString());
// treat empty string as true
value = "".equals(value) ? "true" : value;
// true or false
platformMBeanServer = new Boolean(value);
}
else
{
// negative :)
platformMBeanServer = Boolean.FALSE;
}
}
return platformMBeanServer.booleanValue();
}
/**
* Enable or disable exiting the JVM when {@link Server#shutdown()} is called.
* If enabled, then shutdown calls {@link Server#exit()}. If disabled, then
* only the shutdown hook will be run.
*
* @param flag True to enable calling exit on shutdown.
*/
public void setExitOnShutdown(final boolean flag)
{
exitOnShutdown = Primitives.valueOf(flag);
}
/**
* Get the current value of the exit on shutdown flag.
*
* @return The current value of the exit on shutdown flag.
*/
public boolean getExitOnShutdown()
{
if (exitOnShutdown == null)
{
String value = props.getProperty(ServerConfig.EXIT_ON_SHUTDOWN, null);
if (value == null)
{
exitOnShutdown = Primitives.valueOf(ServerConfig.DEFAULT_EXIT_ON_SHUTDOWN);
}
else
{
exitOnShutdown = new Boolean(value);
}
}
return exitOnShutdown.booleanValue();
}
public void setInstallLifeThread(final boolean flag)
{
installLifeThread = Primitives.valueOf(flag);
}
public boolean isInstallLifeThread()
{
if (installLifeThread == null)
{
String value = props.getProperty(ServerConfig.INSTALL_LIFE_THREAD, null);
if (value == null)
{
installLifeThread = Primitives.valueOf(ServerConfig.DEFAULT_INSTALL_LIFE_THREAD);
}
else
{
installLifeThread = new Boolean(value);
}
}
return installLifeThread.booleanValue();
}
/**
* Enable or disable blocking when {@link Server#shutdown} is
* called. If enabled, then shutdown will be called in the current
* thread. If disabled, then the shutdown hook will be run
* ansynchronously in a separate thread.
*
* @param flag True to enable blocking shutdown.
*/
public void setBlockingShutdown(final boolean flag)
{
blockingShutdown = Primitives.valueOf(flag);
}
/**
* Get the current value of the blocking shutdown flag.
*
* @return The current value of the blocking shutdown flag.
*/
public boolean getBlockingShutdown()
{
if (blockingShutdown == null)
{
String value = props.getProperty(ServerConfig.BLOCKING_SHUTDOWN, null);
if (value == null)
{
blockingShutdown = Primitives.valueOf(ServerConfig.DEFAULT_BLOCKING_SHUTDOWN);
}
else
{
blockingShutdown = new Boolean(value);
}
}
return blockingShutdown.booleanValue();
}
/**
* Set the RequireJBossURLStreamHandlerFactory flag. if false,
* exceptions when setting the URLStreamHandlerFactory will be
* logged and ignored.
*
* @param flag True to enable blocking shutdown.
*/
public void setRequireJBossURLStreamHandlerFactory(final boolean flag)
{
requireJBossURLStreamHandlerFactory = Primitives.valueOf(flag);
}
/**
* Get the current value of the requireJBossURLStreamHandlerFactory flag.
*
* @return The current value of the requireJBossURLStreamHandlerFactory flag.
*/
public boolean getRequireJBossURLStreamHandlerFactory()
{
if (requireJBossURLStreamHandlerFactory == null)
{
String value = props.getProperty(ServerConfig.REQUIRE_JBOSS_URL_STREAM_HANDLER_FACTORY, null);
if (value == null)
{
requireJBossURLStreamHandlerFactory = Primitives.valueOf(ServerConfig.DEFAULT_REQUIRE_JBOSS_URL_STREAM_HANDLER_FACTORY);
}
else
{
requireJBossURLStreamHandlerFactory = new Boolean(value);
}
}
return requireJBossURLStreamHandlerFactory.booleanValue();
}
/**
* Set the filename of the root deployable that will be used to finalize
* the bootstrap process.
*
* @param filename The filename of the root deployable.
*/
public void setRootDeploymentFilename(final String filename)
{
this.rootDeployableFilename = filename;
}
/**
* Get the filename of the root deployable that will be used to finalize
* the bootstrap process.
*
* @return The filename of the root deployable.
*/
@ManagementProperty(description="the filename of the root deployable that will be used to finalize the bootstrap process",
use={ViewUse.STATISTIC})
public String getRootDeploymentFilename()
{
if (rootDeployableFilename == null)
{
rootDeployableFilename = props.getProperty(ServerConfig.ROOT_DEPLOYMENT_FILENAME,
ServerConfig.DEFAULT_ROOT_DEPLOYMENT_FILENAME);
}
return rootDeployableFilename;
}
/**
* Get a URL from configuration.
*/
private URL getURL(final String name) throws MalformedURLException
{
String value = props.getProperty(name, null);
if (value != null)
{
if (!value.endsWith("/")) value += "/";
return new URL(value);
}
return null;
}
/**
* Get a File from configuration.
* @return the CanonicalFile form for the given name.
*/
private File getFileFromProperty(final String name)
{
String value = props.getProperty(name, null);
if (value != null)
{
File f = new File(value);
return f;
}
return null;
}
@ManagementProperty(description="the server Specification-Version",
use={ViewUse.STATISTIC})
public String getSpecificationVersion()
{
return serverSpecificationVersion;
}
/**
* TODO: move to managed project, JBMAN-49
*/
public static class FileMetaMapper extends MetaMapper<File>
{
@Override
public MetaValue createMetaValue(MetaType metaType, File object)
{
return SimpleValueSupport.wrap(object.getAbsolutePath());
}
@Override
public MetaType getMetaType()
{
return SimpleMetaType.STRING;
}
@Override
public Type mapToType()
{
return File.class;
}
@Override
public File unwrapMetaValue(MetaValue metaValue)
{
SimpleValue svalue = (SimpleValue) metaValue;
File f = null;
if (svalue != null)
{
f = new File(svalue.getValue().toString());
}
return f;
}
}
}