/*
* Copyright 2007-2010 Sun Microsystems, Inc.
*
* This file is part of Project Darkstar Server.
*
* Project Darkstar Server is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation and
* distributed hereunder to you.
*
* Project Darkstar Server 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* --
*/
package com.sun.sgs.system;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URISyntaxException;
import java.util.logging.Logger;
import java.util.logging.Level;
/**
* Defines environment variables used by the bootstrapper
* to locate and configure the necessary environment pieces
* to launch a Project Darkstar Server.
* <p>
* This class also provides utility methods to load configuration properties
* from a config file into a {@link SubstitutionProperties} object.
*/
public final class BootEnvironment {
private static final Logger logger = Logger.getLogger(
BootEnvironment.class.getName());
/**
* This class should not be instantiated.
*/
private BootEnvironment() {
}
/**
* Default location of the bootstrapper jar relative to {@code SGS_HOME}.
*/
public static final String SGS_JAR =
"bin" + File.separator + "sgs-boot.jar";
/**
* Name of the properties file to locate and retrieve properties
* for the environment.
*/
public static final String SGS_BOOT = "sgs-boot.properties";
/**
* Denotes the installation directory for the Project Darkstar server.
*/
public static final String SGS_HOME = "SGS_HOME";
/**
* The directory where deployed applications should place jar files
* and application properties files.
*/
public static final String SGS_DEPLOY = "SGS_DEPLOY";
/**
* The directory where extension jar files should be placed.
*/
public static final String SGS_EXT = "SGS_EXT";
/**
* The properties file used to configure the Project Darkstar kernel.
* This file should be fed to the Project Darkstar Kernel.
*/
public static final String SGS_PROPERTIES = "SGS_PROPERTIES";
/**
* The logging properties file for the Project Darkstar server.
*/
public static final String SGS_LOGGING = "SGS_LOGGING";
/**
* The name of the log file to send output to.
*/
public static final String SGS_OUTPUT = "SGS_OUTPUT";
/**
* A toggle used to specify which flavor of Berkeley DB is to be
* used by the application.
*/
public static final String BDB_TYPE = "BDB_TYPE";
/**
* The location of the Berkeley DB natives to include as part
* of the {@code java.library.path}.
*/
public static final String BDB_NATIVES = "BDB_NATIVES";
/**
* A custom set of native library directories to include as part of the
* {@code java.library.path}.
*/
public static final String CUSTOM_NATIVES = "CUSTOM_NATIVES";
/**
* A custom set of additional jar files to include on the classpath.
*/
public static final String CUSTOM_CLASSPATH_ADD = "CUSTOM_CLASSPATH_ADD";
/**
* Location of the JDK to use when booting up the Kernel.
*/
public static final String JAVA_HOME = "JAVA_HOME";
/**
* Command line arguments for the JVM.
*/
public static final String JAVA_OPTS = "JAVA_OPTS";
/**
* Port number used for JMX connections.
*/
public static final String JMX_PORT = "JMX_PORT";
/**
* Whether or not to disable JMX security controls.
*/
public static final String DISABLE_JMX_SECURITY = "DISABLE_JMX_SECURITY";
/**
* The default value for the {@code SGS_DEPLOY} property.
*/
public static final String DEFAULT_SGS_DEPLOY =
"${SGS_HOME}" + File.separator + "deploy";
/**
* The default value for the {@code SGS_EXT} property.
*/
public static final String DEFAULT_SGS_EXT =
"${SGS_HOME}" + File.separator + "ext";
/**
* The default value for the {@code SGS_PROPERTIES} property.
*/
public static final String DEFAULT_SGS_PROPERTIES =
"${SGS_HOME}" + File.separator + "conf" + File.separator +
"sgs-server.properties";
/**
* The default value for the {@code SGS_LOGGING} property.
*/
public static final String DEFAULT_SGS_LOGGING =
"${SGS_HOME}" + File.separator + "conf" + File.separator +
"sgs-logging.properties";
/**
* The default value for the java.util.logging.config.class.
*/
public static final String DEFAULT_SGS_LOGGING_CLASS =
"com.sun.sgs.impl.kernel.LoggerPropertiesInit";
/**
* The default value for the {@code BDB_TYPE} property.
*/
public static final String DEFAULT_BDB_TYPE = "db";
/**
* The standard location to look for application properties config
* file in jars from the {@code SGS_DEPLOY} directory.
*/
public static final String DEFAULT_APP_PROPERTIES =
"META-INF/app.properties";
/**
* The default port used for JMX connections.
*/
public static final String DEFAULT_JMX_PORT = "62974";
/**
* The default security state for JMX, which is disabled.
*/
public static final String DEFAULT_DISABLE_JMX_SECURITY = "true";
/**
* The default directory of the BDB native libraries.
*/
public static final String DEFAULT_BDB_ROOT =
"${SGS_HOME}" + File.separator +
"lib" + File.separator + "natives";
/**
* Default subdirectory of Linux x86 BDB native libraries.
*/
public static final String DEFAULT_BDB_LINUX_X86 =
DEFAULT_BDB_ROOT + File.separator + "linux-x86";
/**
* Default subdirectory of Linux x86_64 BDB native libraries.
*/
public static final String DEFAULT_BDB_LINUX_X86_64 =
DEFAULT_BDB_ROOT + File.separator + "linux-x86_64";
/**
* Default subdirectory of Mac OSX x86 BDB native libraries.
*/
public static final String DEFAULT_BDB_MACOSX_X86 =
DEFAULT_BDB_ROOT + File.separator + "macosx-x86";
/**
* Default subdirectory of Solaris Sparc BDB native libraries.
*/
public static final String DEFAULT_BDB_SOLARIS_SPARC =
DEFAULT_BDB_ROOT + File.separator + "solaris-sparc";
/**
* Default subdirectory of Solaris x86 BDB native libraries.
*/
public static final String DEFAULT_BDB_SOLARIS_X86 =
DEFAULT_BDB_ROOT + File.separator + "solaris-x86";
/**
* Default subdirectory of Win32 x86 BDB native libraries.
*/
public static final String DEFAULT_BDB_WIN32_X86 =
DEFAULT_BDB_ROOT + File.separator + "win32-x86";
/**
* The name of the Kernel class used to boot PDS.
*/
public static final String KERNEL_CLASS = "com.sun.sgs.impl.kernel.Kernel";
/**
* Loads configuration properties from a file into a
* {@link SubstitutionProperties} object. If the given filename is not
* {@code null}, it is used as the configuration file. Otherwise, the
* resource located at {@link #SGS_BOOT} is used as the configuration file.
* <p>
* The properties included in the configuration file must conform to
* the rules allowed by {@link SubstitutionProperties}.
*
* @param filename name of the config file or {@code null} for default
* @return a {@code SubstitutionProperties} object representing the
* configuration parameters in the file
* @throws IOException if there is a problem loading the file
* @throws URISyntaxException if the filename is invalid
*/
public static SubstitutionProperties loadProperties(String filename)
throws IOException, URISyntaxException {
//load properties from configuration file
SubstitutionProperties properties = new SubstitutionProperties();
URL sgsBoot = null;
InputStream is = null;
try {
if (filename == null) {
sgsBoot = ClassLoader.getSystemResource(
BootEnvironment.SGS_BOOT);
} else {
sgsBoot = new File(filename).toURI().toURL();
}
is = sgsBoot.openStream();
properties.load(is);
} catch (IOException e) {
logger.log(Level.SEVERE, "Unable to load initial configuration", e);
throw e;
} finally {
try {
if (is != null) {
is.close();
}
} catch (IOException ignore) {
logger.log(Level.FINEST, "Unable to close stream", ignore);
}
}
//determine SGS_HOME
String sgsHome = properties.getProperty(BootEnvironment.SGS_HOME);
if (sgsHome == null) {
properties.clear();
URL jarLocation = BootEnvironment.class.
getProtectionDomain().getCodeSource().getLocation();
//get a File from the URL to convert URL escaped characters
File jarFile = new File(jarLocation.toURI());
String jarPath = jarFile.getPath();
int jarFileIndex = jarPath.indexOf(BootEnvironment.SGS_JAR);
if (jarFileIndex == -1) {
logger.log(Level.SEVERE, "Unable to determine SGS_HOME");
throw new IllegalStateException("Unable to determine SGS_HOME");
} else {
sgsHome = jarPath.substring(0, jarFileIndex - 1);
properties.setProperty(BootEnvironment.SGS_HOME, sgsHome);
//reload the properties so that the value for SGS_HOME
//is interpolated correctly in any other variables
is = null;
try {
is = sgsBoot.openStream();
properties.load(is);
} catch (IOException e) {
logger.log(Level.SEVERE,
"Unable to load initial configuration", e);
throw e;
} finally {
try {
if (is != null) {
is.close();
}
} catch (IOException ignore) {
logger.log(Level.FINEST,
"Unable to close stream", ignore);
}
}
}
}
logger.log(Level.CONFIG, "SGS_HOME = " + sgsHome);
//load defaults for missing properties
configureDefaultProperties(properties);
return properties;
}
/**
* Loads default values for the given set of properties if any
* required properties are missing.
*
* @param properties the set of boot configuration properties
*/
private static void configureDefaultProperties(
SubstitutionProperties properties) {
//load defaults for any missing properties
if (properties.getProperty(BootEnvironment.SGS_DEPLOY) == null) {
properties.setProperty(BootEnvironment.SGS_DEPLOY,
BootEnvironment.DEFAULT_SGS_DEPLOY);
}
if (properties.getProperty(BootEnvironment.SGS_LOGGING) == null) {
properties.setProperty(BootEnvironment.SGS_LOGGING,
BootEnvironment.DEFAULT_SGS_LOGGING);
}
if (properties.getProperty(BootEnvironment.SGS_PROPERTIES) == null) {
properties.setProperty(BootEnvironment.SGS_PROPERTIES,
BootEnvironment.DEFAULT_SGS_PROPERTIES);
}
if (properties.getProperty(BootEnvironment.BDB_TYPE) == null) {
properties.setProperty(BootEnvironment.BDB_TYPE,
BootEnvironment.DEFAULT_BDB_TYPE);
}
if (properties.getProperty(BootEnvironment.JMX_PORT) == null) {
properties.setProperty(BootEnvironment.JMX_PORT,
BootEnvironment.DEFAULT_JMX_PORT);
}
if (properties.
getProperty(BootEnvironment.DISABLE_JMX_SECURITY) == null)
{
properties.setProperty(BootEnvironment.DISABLE_JMX_SECURITY,
BootEnvironment.
DEFAULT_DISABLE_JMX_SECURITY);
}
if (properties.getProperty(BootEnvironment.SGS_EXT) == null) {
properties.setProperty(BootEnvironment.SGS_EXT,
BootEnvironment.DEFAULT_SGS_EXT);
}
//autodetect BDB libraries if necessary
if (properties.getProperty(BootEnvironment.BDB_NATIVES) == null) {
String name = System.getProperty("os.name");
String arch = System.getProperty("os.arch");
String version = System.getProperty("os.version");
String bdb = null;
if ("Linux".equals(name) && "i386".equals(arch)) {
bdb = BootEnvironment.DEFAULT_BDB_LINUX_X86;
} else if ("Linux".equals(name) &&
("x86_64".equals(arch) || "amd64".equals(arch))) {
bdb = BootEnvironment.DEFAULT_BDB_LINUX_X86_64;
} else if ("Mac OS X".equals(name) &&
("i386".equals(arch) || "x86_64".equals(arch))) {
bdb = BootEnvironment.DEFAULT_BDB_MACOSX_X86;
} else if ("SunOS".equals(name) && "sparc".equals(arch)) {
bdb = BootEnvironment.DEFAULT_BDB_SOLARIS_SPARC;
} else if ("SunOS".equals(name) && "x86".equals(arch)) {
bdb = BootEnvironment.DEFAULT_BDB_SOLARIS_X86;
} else if (name != null && name.startsWith("Windows")) {
bdb = BootEnvironment.DEFAULT_BDB_WIN32_X86;
} else {
logger.log(Level.SEVERE, "Unsupported platform: \n" +
"Name : " + name + "\n" +
"Arch : " + arch + "\n" +
"Version : " + version);
throw new IllegalStateException("Unsupported platform");
}
properties.setProperty(BootEnvironment.BDB_NATIVES, bdb);
}
//configure JAVA_HOME automatically if necessary
if (properties.getProperty(BootEnvironment.JAVA_HOME) == null) {
properties.setProperty(BootEnvironment.JAVA_HOME,
System.getProperty("java.home"));
}
}
}