package edu.hawaii.ics.yucheng;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Properties;
/**
* An immutable class that contains the configuration information for a cluster
* of nodes and a catalog. They are parsed from the 'clustercfg' file.
*
* @author Cheng Jade
* @assignment ICS 421 Assignment 1
* @date Feb 10, 2010
* @bugs None
*/
public final class Configuration {
// The catalog node configuration
private final ConfigurationNode catalog;
// The array of nodes configurations.
private final ConfigurationNode[] nodeList;
/**
* Initializes a new instance of the Configuration class.
*
* @param path
* The path to a file that contains configuration data.
*
* @throws NullPointerException
* @throws ProgramException
* Thrown if it cann't read the DDL command file, or the
* specified path is null.
*/
public Configuration(final String path) throws ProgramException {
// Throw an exception if the specified path is null.
if (null == path)
throw new NullPointerException("path");
// Declare a Properties object and load it with the specified file.
final Properties properties = getProperties(path);
// Obtain the 'numnodes' field indicating the number of nodes to fetch.
final String numNodesText = properties.getProperty("numnodes");
if (null == numNodesText)
throw new ProgramException(
"Property 'numnodes' not found in configuration file.");
final int numNodes;
try {
numNodes = Integer.parseInt(numNodesText);
} catch (final NumberFormatException e) {
throw new ProgramException("Cannot parse number of nodes.", e);
}
// Obtain the catalog configuration.
this.catalog = new ConfigurationNode(properties, "catalog");
// Obtain each nodes' configuration.
this.nodeList = new ConfigurationNode[numNodes];
for (int i = 0; i < numNodes; i++) {
final String prefix = "node" + (i + 1);
this.nodeList[i] = new ConfigurationNode(properties, prefix);
}
}
/**
* Returns the catalog configuration.
*
* @return The catalog configuration.
*/
public ConfigurationNode getCatalog() {
return this.catalog;
}
/**
* Returns an object capable of iterating over the configuration nodes.
*
* @return An object capable of iterating over the configuration nodes.
*/
public Iterable<ConfigurationNode> getNodes() {
return Arrays.asList(this.nodeList);
}
/**
* Returns a readable version of the contents of the configuration.
*
* @return A readable version of the contents of the configuration.
*/
@Override
public String toString() {
// If the directory is empty, return a special note.
if (this.nodeList.length == 0)
return "The configuration list is empty.\n";
// Loop over each item, and add it to the string builder.
final StringBuilder builder = new StringBuilder();
builder.append("The configuration file contains:\n\n");
builder.append("Catalog: \n");
builder.append(this.catalog);
for (int i = 0; i < this.nodeList.length; i++) {
builder.append("\n\nNode ");
builder.append(i + 1);
builder.append(": \n");
builder.append(nodeList[i]);
}
// Return the string created above.
return builder.toString();
}
/**
* Open a file, check for errors, and return a loaded properties object.
*
* @param path
* The path to the properties file.
*
* @return A loaded properties object.
*
* @throws ProgramException
* Thrown if there is a problem reading the configuration file.
*/
private static Properties getProperties(final String path)
throws ProgramException {
assert null != path;
try {
final FileInputStream file = new FileInputStream(path);
try {
final Properties properties = new Properties();
properties.load(file);
return properties;
} finally {
file.close();
}
} catch (final IOException e) {
throw new ProgramException("Cannot read configuration file.", e);
}
}
/**
* The test main, the entry point when testing this class.
*
* @param args
* The command line arguments.
*/
public static void main(final String[] args) {
assert null != args;
// Print usage information, if wrong number of arguments were used.
if (args.length != 1) {
final String name = Configuration.class.getSimpleName();
System.err.println("Usage: java " + name + " <path>");
System.err.println(" <path> path to a configuration file");
System.exit(1);
return;
}
// Declare a Configuration object and populate it with data from a file
// that is specified as the only command line argument.
try {
assert null != args[0];
System.out.println(new Configuration(args[0]));
} catch (final ProgramException e) {
System.err.println(e.getMessage());
System.exit(1);
return;
}
// Exit cleanly while debugging from Eclipse.
System.exit(0);
}
}