package ibis.ipl;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
/**
* Properties management for Ibis. The
* {@link #getDefaultProperties()} method obtains the properties in the
* following order: first, some hardcoded properties are set. Next, a file
* <code>ibis.properties</code> is searched for in the current directory,
* the classpath, or the user home directory, in that order.
* If found, it is read as a properties file, and the properties contained in
* it are set, possibly overriding the hardcoded properties.
* Finally, the system properties are obtained. These, too, may override
* the properties set so far.
*/
public final class IbisProperties {
/** Filename for the properties. */
public static final String PROPERTIES_FILENAME = "ibis.properties";
/** All our own properties start with this prefix. */
public static final String PREFIX = "ibis.";
/** Property name for selecting an Ibis. */
public static final String IMPLEMENTATION = PREFIX + "implementation";
/** Last resort Ibis starters that are loaded with Class.forName if others fail */
public static final String STARTER = PREFIX + "starter";
/** Property name of the property file. */
public static final String PROPERTIES_FILE = PREFIX + "properties.file";
/** Property name for the path used to find Ibis implementations. */
public static final String IMPLEMENTATION_PATH = PREFIX + "implementation.path";
/** Property name for verbosity. */
public static final String VERBOSE = PREFIX + "verbose";
/** Property name for setting the name of the pool. */
public static final String POOL_NAME = PREFIX + "pool.name";
/** Property name for setting the size of the pool. */
public static final String POOL_SIZE = PREFIX + "pool.size";
/** Property name for setting the address of the IPL-server. */
public static final String SERVER_ADDRESS = PREFIX + "server.address";
/** Property name for setting indicating if the server is also a SmartSockets hub. */
public static final String SERVER_IS_HUB = PREFIX + "server.is.hub";
/** Property name for specifying a comma separated list of hubs. */
public static final String HUB_ADDRESSES = PREFIX + "hub.addresses";
/** Property name for specifying the implementation of the registry. */
public static final String REGISTRY_IMPLEMENTATION = PREFIX + "registry.implementation";
/** Property name for location. */
public static final String LOCATION = PREFIX + "location";
/** Property name for location color. */
public static final String LOCATION_COLOR = PREFIX + "location.color";
/** List of {NAME, DESCRIPTION, DEFAULT_VALUE} for properties. */
private static final String[][] propertiesList =
new String[][] {
{ POOL_NAME, null, "String: name of the pool this ibis belongs to" },
{ POOL_SIZE, null,
"Integer: size of the pool this ibis belongs to" },
{ SERVER_ADDRESS, null, "Address of the central ibis server" },
{ SERVER_IS_HUB, "true", "Boolean: if true, the server is also used as a SmartSockets hub" },
{ HUB_ADDRESSES, null,
"Comma seperated list of hub addresses."
+ " The server address is appended to this list,"
+ " and thus is the default hub if no hub is specified" },
{ IMPLEMENTATION, null,
"Nickname or classname of an Ibis implementation. " +
"The specified implementation is used, bypassing the automatic" +
" selection mechanism of Ibis."},
{ PROPERTIES_FILE, null,
"Name of the property file used for the configuration of Ibis" },
{ IMPLEMENTATION_PATH, null, "Path used to find Ibis implementations" },
{ VERBOSE, "false",
"Boolean: If true, makes Ibis more verbose, if false, does not" },
{ LOCATION, null,
"Set the location of Ibis. Specified as multiple levels, "
+ "seperated by a '@', e.g. machine@cluster@site@grid@world."
+ " Defaults to a multi level location based on the FQDN of the machine" },
{ LOCATION_COLOR, null,
"Color code (in html color notation e.g #545432) for this ibis."},
{ REGISTRY_IMPLEMENTATION, "central",
"Nickname or classname of the implementation of the registry. Not all Ibis implementations use this property" },
};
private static Properties defaultProperties;
/**
* Private constructor, to prevent construction of an IbisProperties object.
*/
private IbisProperties() {
// nothing
}
/**
* Returns the hard-coded properties of Ibis.
*
* @return
* the resulting properties.
*/
public static Properties getHardcodedProperties() {
Properties properties = new Properties();
for (String[] element : propertiesList) {
if (element[1] != null) {
properties.setProperty(element[0], element[1]);
}
}
return properties;
}
/**
* Returns a map mapping hard-coded property names to their descriptions.
*
* @return
* the name/description map.
*/
public static Map<String, String> getDescriptions() {
Map<String, String> result = new LinkedHashMap<String, String>();
for (String[] element : propertiesList) {
result.put(element[0], element[2]);
}
return result;
}
/**
* Adds the properties as loaded from the specified stream to the specified
* properties.
*
* @param inputStream
* the input stream.
* @param properties
* the properties.
*/
private static void load(InputStream inputStream, Properties properties) {
if (inputStream != null) {
try {
properties.load(inputStream);
} catch (IOException e) {
// ignored
} finally {
try {
inputStream.close();
} catch (Throwable e1) {
// ignored
}
}
}
}
/**
* Loads properties from the standard configuration file locations.
* @return properties loaded from the standard configuration file locations.
*
*/
@SuppressWarnings("unchecked")
public static synchronized Properties getDefaultProperties() {
if (defaultProperties == null) {
defaultProperties = getHardcodedProperties();
// Load properties from the classpath
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
InputStream inputStream =
classLoader.getResourceAsStream(PROPERTIES_FILENAME);
load(inputStream, defaultProperties);
// See if there is an ibis.properties file in the current
// directory.
try {
inputStream =
new FileInputStream(PROPERTIES_FILENAME);
load(inputStream, defaultProperties);
} catch (FileNotFoundException e) {
// ignored
}
Properties systemProperties = System.getProperties();
// Then see if the user specified an properties file.
String file =
systemProperties.getProperty(PROPERTIES_FILE);
if (file != null) {
try {
inputStream = new FileInputStream(file);
load(inputStream, defaultProperties);
} catch (FileNotFoundException e) {
System.err.println("User specified preferences \"" + file
+ "\" not found!");
}
}
// Finally, add the properties from the command line to the result,
// possibly overriding entries from file or the defaults.
for (Enumeration<String> e = (Enumeration<String>)systemProperties.propertyNames(); e.hasMoreElements();) {
String key = e.nextElement();
String value = systemProperties.getProperty(key);
defaultProperties.setProperty(key, value);
}
}
return new Properties(defaultProperties);
}
}