ConfigurationNode.java

package edu.hawaii.ics.yucheng;

import java.io.PrintStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Properties;

/**
 * An immutable class that contains the configuration information of a node.
 * 
 * @author Cheng Jade
 * @assignment ICS 421 Project
 * @date Feb 29, 2010
 * @bugs None
 */
public final class ConfigurationNode {

    /** The driver name used for the database connection. */
    public final String driver;

    /** The host name URI for the database server. */
    public final String hostname;

    /** A name used for identifying the thread responsible for this instance. */
    public final String name;

    /** The password for the database connection. */
    public final String password;

    /** The user name for the database connection. */
    public final String username;

    /**
     * Initializes a new instance of the ConfigurationNode class.
     * 
     * @param name
     *            The name used for identifying the thread responsible for this
     *            instance.
     * @param driver
     *            The driver name used for the database connection.
     * @param hostname
     *            The host name URI for the database server.
     * @param username
     *            The user name for the database connection.
     * @param password
     *            The password for the database connection.
     * 
     * @throws NullPointerException
     * @throws ProgramException
     *             Thrown if any parameter is null.
     */
    public ConfigurationNode(final String name, final String driver, final String hostname, final String username, final String password) throws ProgramException {

        // Check if any parameter is null, and throw exception in that case.
        if (null == name)
            throw new NullPointerException("name");
        if (null == driver)
            throw new NullPointerException("driver");
        if (null == hostname)
            throw new NullPointerException("hostname");
        if (null == username)
            throw new NullPointerException("username");
        if (null == password)
            throw new NullPointerException("password");

        // Assign the parameter values to the class fields.
        this.name = name;
        this.driver = driver;
        this.hostname = hostname;
        this.username = username;
        this.password = password;
    }

    /**
     * Initializes a new instance of the ConfigurationNode class.
     * 
     * @param properties
     *            A properties object that the configuration node will be loaded
     *            from.
     * @param name
     *            The name used for identifying the thread responsible for this
     *            instance.
     * 
     * @throws NullPointerException
     * @throws ProgramException
     *             Thrown if the reading properties goes wrong.
     */
    public ConfigurationNode(final Properties properties, final String name) throws ProgramException {

        // Read the corresponding lines from the properties object, and use the
        // values as the parameters to call the other constructor, which assigns
        // the class fields to those values.
        this(name, read(properties, name, "driver"), read(properties, name, "hostname"), read(properties, name, "username"), read(properties, name, "passwd"));
    }

    /**
     * Creates a key and looks up a value in the properties object. The value is
     * returned if it is found; otherwise, an exception is thrown.
     * 
     * @return The key word to search for in the properties file.
     * 
     * @throws NullPointerException
     * @throws ProgramException
     *             Thrown if the key is not found in the properties object.
     */
    private static String read(final Properties properties, final String prefix, final String name) throws ProgramException {
        assert null != name;

        // Check if the properties and prefix are not nulls.
        if (null == properties)
            throw new NullPointerException("properties");
        if (null == prefix)
            throw new NullPointerException("prefix");

        // Create the key to search for according to the prefix and name.
        final String key = prefix + "." + name;

        // Search for the key and return the corresponding value.
        final String value = properties.getProperty(key);
        if (null == value)
            throw new ProgramException("Property '" + key + "' not found in configuration file.");

        return value;
    }

    /**
     * Logs a message to a specified output stream.
     * 
     * @param stream
     *            The output stream, e.g. System.out.
     * 
     * @param message
     *            The message to log.
     */
    public void log(final PrintStream stream, final String message) {
        assert null != stream;

        stream.println("[" + this.hostname + "]: " + message);
    }

    public ArrayList<ConfigurationNode> getNodesFromCatalog(final String tableName) throws ProgramException {
        final ArrayList<ConfigurationNode> nodes = new ArrayList<ConfigurationNode>();
        // connect the catalog and retrieve the nodes.
        try {
            this.runStatement(new StatementRunner() {
                public void run(final Statement statement) throws ProgramException, SQLException {
                    final ResultSet set = statement.executeQuery("SELECT * FROM DTABLES WHERE TNAME = '" + tableName + "' OR TNAME = " + "UCASE('" + tableName + "')");
                    while (set.next()) {
                        final String driver = set.getString("NODEDRIVER").trim();
                        final String url = set.getString("NODEURL").trim();
                        final String user = set.getString("NODEUSER").trim();
                        final String password = set.getString("NODEPASSWD").trim();
                        final String name = "node" + set.getString("NODEID").trim();
                        nodes.add(new ConfigurationNode(name, driver, url, user, password));
                    }
                }
            });
        } catch (final Exception e) {
            throw new ProgramException(e.getMessage(), e);
        }
        return nodes;
    }

    /**
     * Creates a new statement and executes it through the specified statement
     * runner.
     * 
     * @param runner
     *            The statement runner.
     * 
     * @throws NullPointerException
     * @throws ProgramException
     *             Thrown if there is an error executing the statement.
     */
    public void runStatement(final StatementRunner runner) throws ProgramException {
        if (null == runner)
            throw new NullPointerException("runner");

        // Open the connection.
        try {
            final Connection connection = this.getConnection();

            // Create the statement object.
            try {
                final Statement statement = connection.createStatement();
                try {
                    // Execute the statement.
                    runner.run(statement);
                } finally {
                    // Always close the statement.
                    statement.close();
                }
            } finally {
                // Always close the connection.
                connection.close();
            }
        } catch (final SQLException e) {
            // Wrap and re-throw SQL exceptions.
            throw new ProgramException(e);
        }
    }

    /**
     * Returns a readable version of the contents of the Configuration Node.
     * 
     * @return A readable version of the contents of the Configuration Node.
     */
    @Override
    public String toString() {
        final StringBuilder builder = new StringBuilder();
        builder.append("    Name:      ");
        builder.append(this.name);
        builder.append("\n    Driver:    ");
        builder.append(this.driver);
        builder.append("\n    Hostname:  ");
        builder.append(this.hostname);
        builder.append("\n    Username:  ");
        builder.append(this.username);
        builder.append("\n    Password:  ");
        builder.append(this.password);
        return builder.toString();
    }

    /**
     * Checks the DBMS driver is available.
     * 
     * @throws ProgramException
     *             Thrown if the DBMS driver is not available.
     */
    private void checkDriver() throws ProgramException {

        // Create an instance of the driver if possible.
        try {
            Class.forName(this.driver).newInstance();
            return;

        } catch (final InstantiationException e) {
            System.out.println("InstantiationException");
        } catch (final IllegalAccessException e) {
            System.out.println("IllegalAccessException");
        } catch (final ClassNotFoundException e) {
            System.out.println("ClassNotFoundException: " + e.getMessage());
        }

        // In any other case, throw an exception indicating the failure.
        throw new ProgramException("Cannot load driver '" + this.driver + "'.");
    }

    /**
     * Gets a connection to the DBMS database.
     * 
     * @throws ProgramException
     *             Thrown if the connection cannot be made.
     */
    private Connection getConnection() throws ProgramException {

        // First, check the driver is available.
        this.checkDriver();

        // Next, create and return a new connection based on the instance data.
        try {
            return DriverManager.getConnection(this.hostname, this.username, this.password);

        } catch (final SQLException e) {
            // Wrap and re-throw SQL exceptions.
            final String message = "Cannot connect to '" + this.hostname + "'.";
            throw new ProgramException(message, e);
        }
    }

    /**
     * The entry point for a test for this class.
     * 
     * @param args
     *            The command line arguments (not used).
     */
    public static void main(final String[] args) {

        // Declare, initialize, and print a ConfigurationNode object.
        try {
            System.out.println(new ConfigurationNode("a", "b", "c", "d", "e"));

        } 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