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); } }