org.rhq.cassandra.DeploymentOptions.java Source code

Java tutorial

Introduction

Here is the source code for org.rhq.cassandra.DeploymentOptions.java

Source

/*
 *
 *  * RHQ Management Platform
 *  * Copyright (C) 2005-2012 Red Hat, Inc.
 *  * All rights reserved.
 *  *
 *  * This program is free software; you can redistribute it and/or modify
 *  * it under the terms of the GNU General Public License, version 2, as
 *  * published by the Free Software Foundation, and/or the GNU Lesser
 *  * General Public License, version 2.1, also as published by the Free
 *  * Software Foundation.
 *  *
 *  * This program is distributed in the hope that it will be useful,
 *  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  * GNU General Public License and the GNU Lesser General Public License
 *  * for more details.
 *  *
 *  * You should have received a copy of the GNU General Public License
 *  * and the GNU Lesser General Public License along with this program;
 *  * if not, write to the Free Software Foundation, Inc.,
 *  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

package org.rhq.cassandra;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.rhq.core.util.TokenReplacingProperties;
import org.rhq.core.util.file.FileUtil;

/**
 * <p>
 * A container for deployment options and Cassandra configuration settings. A
 * DeploymentOptions object represents the merger of properties defined in
 * cassandra.properties or defined as system properties. System properties take precedence
 * over corresponding properties in cassandra.properties.
 * </p>
 * <p>
 * Properties are "sticky". Like Ant properties, once set a property's value cannot be
 * changed. This means that if you set a property by calling its setter method prior to
 * invoking {@link #load()}, that value will be retained even if that property is also
 * defined as a system property and in cassandra.properties.
 * </p>
 *
 * @author John Sanda
 */
public class DeploymentOptions {

    private final Log log = LogFactory.getLog(DeploymentOptions.class);

    private boolean loaded;

    // If you add a new field make sure that it is exposed as a "sticky" property. In
    // other words, once set the property's value does not change again. See
    // setClusterDir below for an example.

    private String clusterDir;
    private String basedir;
    private Integer numNodes;
    private Boolean embedded;
    private String loggingLevel;
    private Integer numTokens;
    private Integer cqlPort;
    private Boolean startRpc;
    private Integer rpcPort;
    private Integer nativeTransportMaxThreads;
    private String username;
    private String password;
    private String authenticator;
    private String authorizer;
    private String dataDir;
    private String commitLogDir;
    private String savedCachesDir;
    private String listenAddress;
    private String rpcAddress;
    private Integer jmxPort;
    private Integer gossipPort;
    private String seeds;
    private String heapSize;
    private String heapNewSize;
    private String logFileName;
    private String stackSize;

    DeploymentOptions() {
    }

    /**
     * Initializes any properties that are not already set. Values are assigned from
     * system properties and from the cassandra.properties file that is expected to
     * be on the classpath. System properties are given precedence over corresponding
     * properties in cassandra.properties.
     *
     * @throws IOException If an error occurs loading cassandra.properties
     */
    public void load() throws IOException {
        if (loaded) {
            return;
        }
        InputStream stream = null;
        try {
            stream = getClass().getResourceAsStream("/cassandra.properties");
            Properties props = new Properties();
            props.load(stream);

            init(props);
            loaded = true;
        } catch (IOException e) {
            log.warn("Unable to load deployment options from cassandra.properties.");
            log.info("The following error occurred while trying to load options.", e);
            throw e;
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                    String msg = "An error occurred while closing input stream on cassandra.properties";
                    log.info(msg, e);
                }
            }
        }
    }

    private void init(Properties properties) {
        setUsername(loadProperty("rhq.storage.username", properties));
        setPassword(loadProperty("rhq.storage.password", properties));

        setBasedir(loadProperty("rhq.storage.basedir", properties));
        setClusterDir(loadProperty("rhq.storage.cluster.dir", properties));
        setNumNodes(Integer.parseInt(loadProperty("rhq.storage.cluster.num-nodes", properties)));
        setEmbedded(Boolean.valueOf(loadProperty("rhq.storage.cluster.is-embedded", properties)));

        setLoggingLevel(loadProperty("rhq.storage.logging.level", properties));
        setLogFileName(loadProperty("rhq.storage.log.file", properties));

        setRpcPort(Integer.valueOf(loadProperty("rhq.storage.rpc-port", properties)));
        setCqlPort(Integer.valueOf(loadProperty("rhq.storage.cql-port", properties)));
        setJmxPort(Integer.valueOf(loadProperty("rhq.storage.jmx-port", properties)));
        setGossipPort(Integer.valueOf(loadProperty("rhq.storage.gossip-port", properties)));

        setNumTokens(Integer.valueOf(loadProperty("rhq.storage.num-tokens", properties)));
        setNativeTransportMaxThreads(
                Integer.valueOf(loadProperty("rhq.storage.native-transport-max-threads", properties)));

        setAuthenticator(loadProperty("rhq.storage.authenticator", properties));
        setAuthorizer(loadProperty("rhq.storage.authorizer", properties));

        setDataDir(loadProperty("rhq.storage.data", properties));
        setCommitLogDir(loadProperty("rhq.storage.commitlog", properties));
        setSavedCachesDir(loadProperty("rhq.storage.saved-caches", properties));

        setSeeds(loadProperty("rhq.storage.seeds", properties));
        setListenAddress(loadProperty("rhq.storage.listen.address", properties));
        setStartRpc(Boolean.valueOf(loadProperty("rhq.storage.start_rpc", properties)));
        setRpcAddress(loadProperty("rhq.storage.rpc.address", properties));

        setHeapSize(loadProperty("rhq.storage.heap-size", properties));
        setHeapNewSize(loadProperty("rhq.storage.heap-new-size", properties));
        setStackSize(loadProperty("rhq.storage.stack-size", properties));
    }

    private String loadProperty(String key, Properties properties) {
        String value = System.getProperty(key);
        if (value == null || value.isEmpty()) {
            return properties.getProperty(key);
        }
        return value;
    }

    public void merge(DeploymentOptions other) {
        setClusterDir(other.clusterDir);
        setNumNodes(other.numNodes);
        setEmbedded(other.embedded);
        setLoggingLevel(other.loggingLevel);
        setNumTokens(other.numTokens);
        setCqlPort(cqlPort);
        setNativeTransportMaxThreads(other.nativeTransportMaxThreads);
        setUsername(other.username);
        setPassword(other.password);
        setAuthenticator(other.authenticator);
        setAuthorizer(other.authorizer);
        setDataDir(other.dataDir);
        setCommitLogDir(other.commitLogDir);
        setSavedCachesDir(other.savedCachesDir);
        setLogFileName(other.logFileName);
        setListenAddress(other.listenAddress);
        setRpcAddress(other.rpcAddress);
        setStartRpc(other.startRpc);
        setRpcPort(other.rpcPort);
        setJmxPort(other.jmxPort);
        setGossipPort(other.gossipPort);
        setSeeds(other.seeds);
        setBasedir(other.basedir);
        setHeapSize(other.heapSize);
        setHeapNewSize(other.heapNewSize);
        setStackSize(other.stackSize);
    }

    public TokenReplacingProperties toMap() {
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(DeploymentOptions.class);
            Map<String, String> properties = new TreeMap<String, String>();

            for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {
                if (pd.getReadMethod() == null) {
                    throw new RuntimeException("The [" + pd.getName() + "] property must define a getter method");
                }
                Method method = pd.getReadMethod();
                DeploymentProperty deploymentProperty = method.getAnnotation(DeploymentProperty.class);
                if (deploymentProperty != null) {
                    Object value = method.invoke(this, null);
                    if (value != null) {
                        properties.put(deploymentProperty.name(), value.toString());
                    }
                }
            }
            return new TokenReplacingProperties(properties);
        } catch (Exception e) {
            throw new RuntimeException("Failed to convert " + DeploymentOptions.class.getName() + " to a map", e);
        }
    }

    /**
     * @return The directory in which nodes will be installed. This only applies to
     * embedded clusters.
     */
    @DeploymentProperty(name = "cluster.dir")
    public String getClusterDir() {
        return clusterDir;
    }

    /**
     * @param dir The directory in which nodes will be installed. This only applies to
     *            embedded clusters.
     */
    public void setClusterDir(String dir) {
        if (clusterDir == null) {
            clusterDir = FileUtil.useForwardSlash(dir);
        }
    }

    /**
     * @return The directory in which the node will be installed.
     */
    @DeploymentProperty(name = "rhq.storage.basedir")
    public String getBasedir() {
        return basedir;
    }

    /**
     * @param dir The directory in which the node will be installed.
     */
    public void setBasedir(String dir) {
        if (basedir == null) {
            basedir = FileUtil.useForwardSlash(dir);
        }
    }

    /**
     * @return The number of nodes in the cluster. This only applies to embedded clusters.
     */
    @DeploymentProperty(name = "rhq.storage.cluster.num-nodes")
    public int getNumNodes() {
        return numNodes;
    }

    /**
     * @param numNodes The number of nodes in the cluster. This only applies to embedded
     *                 clusters.
     */
    public void setNumNodes(int numNodes) {
        if (this.numNodes == null) {
            this.numNodes = numNodes;
        }
    }

    /**
     * @return true is this is an embedded deployment, false otherwise. Note that an
     * embedded cluster is one in which all nodes run on a single host and can only accept
     * requests from that same host.
     */
    @DeploymentProperty(name = "rhq.storage.cluster.is-embedded")
    public boolean isEmbedded() {
        return embedded;
    }

    /**
     * @param embedded A flag that indicates whether or not this is an embedded deployment.
     * Note than embedded cluster is one in which all nodes run on a single host and can
     * only accept requests from that same host.
     */
    public void setEmbedded(boolean embedded) {
        if (this.embedded == null) {
            this.embedded = embedded;
        }
    }

    /**
     * @return The log4j logging level that Cassandra uses
     */
    @DeploymentProperty(name = "rhq.storage.logging.level")
    public String getLoggingLevel() {
        return loggingLevel;
    }

    /**
     * @param loggingLevel The log4j logging level that Cassandra uses
     */
    public void setLoggingLevel(String loggingLevel) {
        if (this.loggingLevel == null) {
            this.loggingLevel = loggingLevel;
        }
    }

    /**
     * @return The number of tokens assigned to this the node on the ring. Defaults to 256.
     */
    @DeploymentProperty(name = "rhq.storage.num_tokens")
    public Integer getNumTokens() {
        return numTokens;
    }

    /**
     * @param numTokens The number of tokens assigned to this node on the ring. Defaults to
     * 256.
     */
    public void setNumTokens(int numTokens) {
        if (this.numTokens == null) {
            this.numTokens = numTokens;
        }
    }

    /**
     * @return The port on which Cassandra listens for client requests.
     */
    @DeploymentProperty(name = "rhq.storage.cql-port")
    public Integer getCqlPort() {
        return cqlPort;
    }

    /**
     * @param port The port on which Cassandra listens for client requests.
     */
    public void setCqlPort(Integer port) {
        if (cqlPort == null) {
            cqlPort = port;
        }
    }

    /**
     * @return true whether the Thrift-based RPC should be started
     */
    @DeploymentProperty(name = "rhq.storage.start_rpc")
    public Boolean getStartRpc() {
        return startRpc;
    }

    /**
     * @param startRpc whether the Thrift-based RPC should be started
     */
    public void setStartRpc(Boolean startRpc) {
        if (this.startRpc == null) {
            this.startRpc = startRpc;
        }
    }

    @DeploymentProperty(name = "rhq.storage.rpc_port")
    public Integer getRpcPort() {
        return rpcPort;
    }

    public void setRpcPort(Integer port) {
        if (rpcPort == null) {
            rpcPort = port;
        }
    }

    /**
     * @return The max number of threads to handle CQL requests
     */
    @DeploymentProperty(name = "rhq.storage.native_transport_max_threads")
    public Integer getNativeTransportMaxThreads() {
        return nativeTransportMaxThreads;
    }

    /**
     * @param numThreads The max number of threads to handle CQL requests
     */
    public void setNativeTransportMaxThreads(Integer numThreads) {
        if (nativeTransportMaxThreads == null) {
            nativeTransportMaxThreads = numThreads;
        }
    }

    /**
     * @return The username RHQ will use to make client connections to Cassandra. This is
     * <strong>not</strong> a Cassandra configuration property. This deployment property is
     * written to rhq-server.properties at build time by the rhq-container.build.xml script.
     */
    @DeploymentProperty(name = "rhq.storage.username")
    public String getUsername() {
        return username;
    }

    /**
     * @param username The username RHQ will use to make client connections to Cassandra.
     * This is <strong>not</strong> a Cassandra configuration property. This deployment
     * property is written to rhq-server.properties at build time by the
     * rhq-container.build.xml script.
     */
    public void setUsername(String username) {
        if (this.username == null) {
            this.username = username;
        }
    }

    /**
     * @return The password RHQ will use to make client connections to Cassandra. This is
     * <strong>not</strong> a Cassandra configuration property. This deployment property is
     * written to rhq-server.properties at build time by the rhq-container.build.xml script.
     */
    @DeploymentProperty(name = "rhq.storage.password")
    public String getPassword() {
        return password;
    }

    /**
     * @param password The password RHQ will use to make client connections to Cassandra.
     * This is <strong>not</strong> a Cassandra configuration property. This deployment
     * property is written to rhq-server.properties at build time by the
     * rhq-container.build.xml script.
     */
    public void setPassword(String password) {
        if (this.password == null) {
            this.password = password;
        }
    }

    /**
     * @return The FQCN of the class that handles Cassandra authentication
     */
    @DeploymentProperty(name = "rhq.storage.authenticator")
    public String getAuthenticator() {
        return authenticator;
    }

    /**
     * @param authenticator The FQCN of the class that handles Cassandra authentication
     */
    public void setAuthenticator(String authenticator) {
        if (this.authenticator == null) {
            this.authenticator = authenticator;
        }
    }

    /**
     * @return The FQCN of the class that handles Cassandra authorization
     */
    @DeploymentProperty(name = "rhq.storage.authorizer")
    public String getAuthorizer() {
        return authorizer;
    }

    /**
     * @param authorizer The FQCN of the class that handles Cassandra authorization
     */
    public void setAuthorizer(String authorizer) {
        if (this.authorizer == null) {
            this.authorizer = authorizer;
        }
    }

    /**
     * @return The directory where Cassandra stores data on disk
     */
    @DeploymentProperty(name = "rhq.storage.data")
    public String getDataDir() {
        return dataDir;
    }

    /**
     * @param dir The directory where Cassandra stores data on disk
     */
    public void setDataDir(String dir) {
        if (dataDir == null) {
            dataDir = FileUtil.useForwardSlash(dir);
        }
    }

    /**
     * @return The directory where Cassandra stores commit log files
     */
    @DeploymentProperty(name = "rhq.storage.commitlog")
    public String getCommitLogDir() {
        return commitLogDir;
    }

    /**
     * @param dir The directory where Cassandra stores commit log files
     */
    public void setCommitLogDir(String dir) {
        if (commitLogDir == null) {
            commitLogDir = FileUtil.useForwardSlash(dir);
        }
    }

    /**
     * @return The directory where Cassandra stores saved caches on disk
     */
    @DeploymentProperty(name = "rhq.storage.saved-caches")
    public String getSavedCachesDir() {
        return savedCachesDir;
    }

    /**
     * @param dir The direcotry where Cassandra stores saved caches on disk
     */
    public void setSavedCachesDir(String dir) {
        if (savedCachesDir == null) {
            savedCachesDir = FileUtil.useForwardSlash(dir);
        }
    }

    /**
     * @return The full path of the Log4J log file to which Cassandra writes.
     */
    @DeploymentProperty(name = "rhq.storage.log.file")
    public String getLogFileName() {
        return logFileName;
    }

    /**
     * @param name The full path of the Log4J log file to which Cassandra writes.
     */
    public void setLogFileName(String name) {
        if (logFileName == null) {
            logFileName = FileUtil.useForwardSlash(name);
        }
    }

    /**
     * @return The address to which Cassandra binds and tells other node to connect to
     */
    @DeploymentProperty(name = "rhq.storage.listen.address")
    public String getListenAddress() {
        return listenAddress;
    }

    /**
     * @param address The address to which Cassandra binds and tells other nodes to connect to
     */
    public void setListenAddress(String address) {
        if (listenAddress == null) {
            listenAddress = address;
        }
    }

    @DeploymentProperty(name = "rpc.address")
    public String getRpcAddress() {
        return rpcAddress;
    }

    public void setRpcAddress(String address) {
        if (rpcAddress == null) {
            rpcAddress = address;
        }
    }

    /**
     * @return The port on which Cassandra listens for JMX connections
     */
    @DeploymentProperty(name = "rhq.storage.jmx-port")
    public Integer getJmxPort() {
        return jmxPort;
    }

    /**
     * @param port The port on which Cassandra listens for JMX connections
     */
    public void setJmxPort(Integer port) {
        if (jmxPort == null) {
            jmxPort = port;
        }
    }

    /**
     * @return The port on which Cassandra listens for gossip requests
     */
    @DeploymentProperty(name = "rhq.storage.gossip-port")
    public Integer getGossipPort() {
        return gossipPort;
    }

    /**
     * @param port The port on which Cassandra listens for gossip requests
     */
    public void setGossipPort(Integer port) {
        if (gossipPort == null) {
            gossipPort = port;
        }
    }

    /**
     * @return A comma-delimited list of IP addresses/host names that are deemed contact
     * points during node start up to learn about the ring topology.
     */
    @DeploymentProperty(name = "rhq.storage.seeds")
    public String getSeeds() {
        return seeds;
    }

    /**
     * @param seeds A comma-delimited list of IP addresses/host names that are deemed
     * contact points during node start up to learn about the ring topology.
     */
    public void setSeeds(String seeds) {
        if (this.seeds == null) {
            this.seeds = seeds;
        }
    }

    /**
     * @return The value to use for both the max and min heap sizes. Defaults to
     * ${MAX_HEAP_SIZE} which allows the cassandra-env.sh script to determine the value.
     */
    @DeploymentProperty(name = "rhq.storage.heap-size")
    public String getHeapSize() {
        return heapSize;
    }

    /**
     * @param heapSize The value to use for both the max and min heap sizes. This needs to
     * be a value value recognized by the -Xmx and -Xms options such as 512M.
     */
    public void setHeapSize(String heapSize) {
        if (this.heapSize == null) {
            this.heapSize = heapSize;
        }
    }

    /**
     * @return The value to use for the size of the new generation. Defaults to
     * ${HEAP_NEWSIZE} which allows the cassandra-env.sh script to determine the value.
     */
    @DeploymentProperty(name = "rhq.storage.heap-new-size")
    public String getHeapNewSize() {
        return heapNewSize;
    }

    /**
     * @param heapNewSize The value to use for the size of the new generation. This needs
     * to be a valid value recognized by the -Xmn option such as 256M.
     * is passed directly to the -Xmn option so it
     */
    public void setHeapNewSize(String heapNewSize) {
        if (this.heapNewSize == null) {
            this.heapNewSize = heapNewSize;
        }
    }

    /**
     * @return The value to use for the JVM stack size. This is passed directly to the -Xss
     * JVM start up option.
     */
    @DeploymentProperty(name = "rhq.storage.stack-size")
    public String getStackSize() {
        return stackSize;
    }

    /**
     * @param size The value to use for the JVM stack size which is passed directly to the
     * -Xss JVM start up option.
     */
    public void setStackSize(String size) {
        if (stackSize == null) {
            stackSize = size;
        }
    }

}