Configuration.java

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);
    }
}
Valid HTML 4.01 Valid CSS