changeset 2:13a5cb11acd7

adding a very basic and very crappy agent
author Omair Majid <omajid@redhat.com>
date Mon, 21 Nov 2011 18:22:13 -0500
parents d5de7e857b51
children 0d1762f6bcd9
files src/com/redhat/thermostat/agent/Agent.java src/com/redhat/thermostat/agent/AgentState.java src/com/redhat/thermostat/agent/AgentStateListener.java src/com/redhat/thermostat/agent/ArgumentParser.java src/com/redhat/thermostat/agent/Main.java src/com/redhat/thermostat/agent/RuntimeConfiguration.java src/com/redhat/thermostat/agent/StartupConfiguration.java src/com/redhat/thermostat/backend/Backend.java src/com/redhat/thermostat/backend/BackendFeature.java src/com/redhat/thermostat/backend/BackendRegistry.java src/com/redhat/thermostat/common/Constants.java src/com/redhat/thermostat/common/LogFormatter.java src/com/redhat/thermostat/common/utils/LoggingUtils.java src/com/redhat/thermostat/common/utils/StringUtils.java
diffstat 14 files changed, 744 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/redhat/thermostat/agent/Agent.java	Mon Nov 21 18:22:13 2011 -0500
@@ -0,0 +1,122 @@
+package com.redhat.thermostat.agent;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.UUID;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DB;
+import com.mongodb.DBCollection;
+import com.mongodb.DBObject;
+import com.mongodb.WriteConcern;
+import com.redhat.thermostat.backend.Backend;
+import com.redhat.thermostat.backend.BackendRegistry;
+import com.redhat.thermostat.common.Constants;
+
+/**
+ * Represents the Agent running on a host.
+ */
+public class Agent {
+
+    private final UUID id;
+    private final BackendRegistry backendRegistry;
+    private final List<AgentStateListener> listeners;
+    private final RuntimeConfiguration runtimeConfig;
+    private final StartupConfiguration startupConfig;
+
+    private AgentState currentState;
+    private DB database;
+
+    public Agent(BackendRegistry backendRegistry, StartupConfiguration startupConfiguration) {
+        this(backendRegistry,
+                UUID.randomUUID(),
+                startupConfiguration,
+                new RuntimeConfiguration());
+    }
+
+    public Agent(BackendRegistry registry, UUID agentId, StartupConfiguration startup, RuntimeConfiguration runtime) {
+        this.id = agentId;
+        this.backendRegistry = registry;
+        this.listeners = new CopyOnWriteArrayList<AgentStateListener>();
+        this.currentState = AgentState.DISCONNECTED;
+        this.startupConfig = startup;
+        this.runtimeConfig = runtime;
+        updateConfig();
+    }
+
+    /**
+     * Update the agent configuration from backends
+     */
+    private void updateConfig() {
+        for (Backend backend : backendRegistry.getAll()) {
+            String isActive = Boolean.toString(Arrays.asList(startupConfig.getBackendsToStart()).contains(backend.getName()));
+            runtimeConfig.addConfig(backend.getName(), Constants.AGENT_CONFIG_KEY_BACKEND_ACTIVE, isActive);
+            Map<String, String> settings = backend.getSettings();
+            for (Entry<String, String> e : settings.entrySet()) {
+                runtimeConfig.addConfig(backend.getName(), e.getKey(), e.getValue());
+            }
+        }
+    }
+
+    public void setDatabase(DB database) {
+        this.database = database;
+    }
+
+    /**
+     * Advertises the agent as active to the world.
+     */
+    public void publish() {
+        DBCollection configCollection = database.getCollection(Constants.AGENT_CONFIG_COLLECTION_NAME);
+        DBObject toInsert = runtimeConfig.toBson();
+        toInsert.put(Constants.AGENT_ID, id.toString());
+        configCollection.insert(toInsert, WriteConcern.SAFE);
+        setState(AgentState.ACTIVE);
+    }
+
+    /**
+     * Removes the agent info published to the world
+     */
+    public void unpublish() {
+        DBCollection configCollection = database.getCollection(Constants.AGENT_CONFIG_COLLECTION_NAME);
+        BasicDBObject toRemove = new BasicDBObject(Constants.AGENT_ID, id.toString());
+        configCollection.remove(toRemove);
+        setState(AgentState.DISCONNECTED);
+    }
+
+    public synchronized AgentState getState() {
+        return currentState;
+    }
+
+    public synchronized void setState(AgentState newState) {
+        if (currentState != newState) {
+            currentState = newState;
+            emitStateChanged();
+        }
+    }
+
+    private void emitStateChanged() {
+        for (AgentStateListener listener : listeners) {
+            listener.stateChanged(this);
+        }
+    }
+
+    public void addStateListener(AgentStateListener listener) {
+        listeners.add(listener);
+    }
+
+    public void removeStateListener(AgentStateListener listener) {
+        listeners.remove(listener);
+    }
+
+    public UUID getId() {
+        return id;
+    }
+
+    public BackendRegistry getBackendRegistry() {
+        return backendRegistry;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/redhat/thermostat/agent/AgentState.java	Mon Nov 21 18:22:13 2011 -0500
@@ -0,0 +1,19 @@
+package com.redhat.thermostat.agent;
+
+public enum AgentState {
+    /**
+     * the agent in the default state. It has no connection. It is not doing
+     * anything
+     */
+    DISCONNECTED,
+    /** just connected. setting up data structures */
+    CONNECTED,
+    /** collecting data and doing stuff */
+    ACTIVE,
+    /**
+     * server was disconnected abruptly. cache data until we can send it over
+     * again
+     */
+    CACHING,
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/redhat/thermostat/agent/AgentStateListener.java	Mon Nov 21 18:22:13 2011 -0500
@@ -0,0 +1,5 @@
+package com.redhat.thermostat.agent;
+
+public interface AgentStateListener {
+    public void stateChanged(Agent agent);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/redhat/thermostat/agent/ArgumentParser.java	Mon Nov 21 18:22:13 2011 -0500
@@ -0,0 +1,71 @@
+package com.redhat.thermostat.agent;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.logging.Level;
+
+import com.redhat.thermostat.common.Constants;
+
+public class ArgumentParser {
+
+    private final boolean inSingleMode;
+    private final String connectionURL;
+    private final Level logLevel;
+
+    public ArgumentParser(StartupConfiguration startupConfig, String[] args) {
+        List<String> arguments = new ArrayList<String>(Arrays.asList(args));
+        boolean single = false;
+        String url = Constants.MONGO_DEFAULT_URL;
+        Level level = Level.WARNING;
+        int port = -1;
+
+        int index = 0;
+        while (index < arguments.size()) {
+            if (arguments.get(index).equals("--loglevel")) {
+                int next = index + 1;
+                if (next < arguments.size()) {
+                    level = Level.parse(arguments.get(next).toUpperCase());
+                    System.out.println("log level is: " + level);
+                    index++;
+                }
+            } else if (arguments.get(index).equals("--local")) {
+                single = true;
+            } else if (arguments.get(index).equals("--remote")) {
+                single = false;
+                int next = index + 1;
+                if (next < arguments.size()) {
+                    port = Integer.parseInt(arguments.get(next));
+                    index++;
+                }
+            }
+
+            index++;
+        }
+
+        if (port != -1) {
+            url = url + ":" + port + "/";
+        } else if (single) {
+            url = url + ":" + startupConfig.getPortForLocal() + "/";
+        } else {
+            url = url + ":" + startupConfig.getPortForRemote() + "/";
+        }
+
+        inSingleMode = single;
+        connectionURL = url;
+        logLevel = level;
+    }
+
+    public boolean inSingleMode() {
+        return inSingleMode;
+    }
+
+    public String getConnectionURL() {
+        return connectionURL;
+    }
+
+    public Level getLogLevel() {
+        return logLevel;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/redhat/thermostat/agent/Main.java	Mon Nov 21 18:22:13 2011 -0500
@@ -0,0 +1,76 @@
+package com.redhat.thermostat.agent;
+
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.net.UnknownHostException;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+
+import com.mongodb.DB;
+import com.mongodb.Mongo;
+import com.mongodb.MongoURI;
+import com.redhat.thermostat.backend.BackendRegistry;
+import com.redhat.thermostat.common.Constants;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.common.utils.StringUtils;
+
+public final class Main {
+
+    private Main() {
+        throw new IllegalStateException("Should not be instantiated");
+    }
+
+    public static void main(String[] args) {
+        try {
+            LogManager.getLogManager().readConfiguration(
+                    StringUtils.toInputStream(Constants.LOGGING_CONFIG));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        LoggingUtils.resetAndGetRootLogger();
+        Logger logger = LoggingUtils.getLogger(Main.class);
+
+        StartupConfiguration startupConfig = null;
+        try {
+            startupConfig = new StartupConfiguration(new FileReader(Constants.AGENT_CONFIG_FILE_LOCATION));
+        } catch (FileNotFoundException fnfe) {
+            System.err.println("unable to read config file at " + Constants.AGENT_CONFIG_FILE_LOCATION);
+            System.exit(Constants.EXIT_UNABLE_TO_READ_CONFIG);
+        }
+
+        ArgumentParser argumentParser = new ArgumentParser(startupConfig, args);
+
+        logger.setLevel(argumentParser.getLogLevel());
+
+        BackendRegistry backendRegistry = BackendRegistry.getInstance();
+
+        Mongo mongo = null;
+        try {
+            String uri = argumentParser.getConnectionURL();
+            logger.fine("connecting to " + uri);
+            mongo = new Mongo(new MongoURI(uri));
+            DB db = mongo.getDB(Constants.THERMOSTAT_DB);
+            logger.fine("connected");
+            Agent agent = new Agent(backendRegistry, startupConfig);
+            agent.setDatabase(db);
+            agent.publish();
+            logger.fine("agent published");
+
+            try {
+                System.in.read();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+
+            agent.unpublish();
+            logger.fine("agent unpublished");
+        } catch (UnknownHostException uhe) {
+            System.err.println("unknown host");
+            uhe.printStackTrace();
+            System.exit(Constants.EXIT_UNABLE_TO_CONNECT_TO_DATABASE);
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/redhat/thermostat/agent/RuntimeConfiguration.java	Mon Nov 21 18:22:13 2011 -0500
@@ -0,0 +1,125 @@
+package com.redhat.thermostat.agent;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Random;
+import java.util.Set;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
+import com.redhat.thermostat.common.Constants;
+
+/**
+ * The current run time configuration of the agent.
+ */
+public class RuntimeConfiguration {
+
+    private String agentName;
+    private Backends backendConfig;
+
+    public RuntimeConfiguration() {
+        agentName = "agent " + new Random().nextLong();
+        backendConfig = new Backends();
+    }
+
+    public static RuntimeConfiguration fromBson(DBObject remote) {
+        RuntimeConfiguration config = new RuntimeConfiguration();
+        BasicDBObject other = (BasicDBObject) remote;
+        // TODO deal with missing/bad keys/values
+        config.agentName = other.getString(Constants.AGENT_CONFIG_KEY_AGENT_NAME);
+        BasicDBObject remoteBackends = (BasicDBObject) other.get(Constants.AGENT_CONFIG_KEY_BACKENDS);
+        for (Entry<String, Object> remoteBackendEntry : remoteBackends.entrySet()) {
+            String backendName = remoteBackendEntry.getKey();
+            BasicDBObject backendConfig = (BasicDBObject) remoteBackendEntry.getValue();
+            for (Entry<String, Object> e : backendConfig.entrySet()) {
+                config.backendConfig.addConfig(backendName, e.getKey(), (String) e.getValue());
+            }
+        }
+        return config;
+    }
+
+    public DBObject toBson() {
+        BasicDBObject result = new BasicDBObject();
+        result.put(Constants.AGENT_CONFIG_KEY_AGENT_NAME, agentName);
+        result.put(Constants.AGENT_CONFIG_KEY_BACKENDS, backendConfig.toDBObject());
+        return result;
+    }
+
+    public void setAvailableBackends(String[] backends) {
+        for (String backend : backends) {
+            backendConfig.addBackend(backend);
+        }
+    }
+
+    public String[] getAllBackends() {
+        return backendConfig.getBackends().toArray(new String[0]);
+    }
+
+    public String[] getActiveBackends() {
+        return backendConfig.getMatchingBackends(Constants.AGENT_CONFIG_KEY_BACKEND_ACTIVE, Boolean.TRUE.toString()).toArray(new String[0]);
+    }
+
+    public void addConfig(String backend, String key, String value) {
+        backendConfig.addConfig(backend, key, value);
+    }
+
+    public String getConfig(String backendName, String configKey) {
+        return backendConfig.getConfig(backendName).get(configKey);
+    }
+
+    /**
+     * A wrapper around the backend-specific information
+     */
+    private static class Backends {
+        /** {backend-name: { opt1: va1, opt2:val2, } } */
+        private Map<String, Map<String, String>> info;
+
+        public Backends() {
+            info = new HashMap<String, Map<String, String>>();
+        }
+
+        public void addBackend(String backendName) {
+            if (!info.containsKey(backendName)) {
+                info.put(backendName, new HashMap<String, String>());
+            }
+        }
+
+        public Object toDBObject() {
+            BasicDBObject result = new BasicDBObject();
+            for (Entry<String, Map<String, String>> e : info.entrySet()) {
+                BasicDBObject config = new BasicDBObject();
+                config.putAll(e.getValue());
+                result.put(e.getKey(), config);
+            }
+            return result;
+        }
+
+        public Set<String> getBackends() {
+            return info.keySet();
+        }
+
+        public Set<String> getMatchingBackends(String key, String value) {
+            // TODO perhaps extend this to regex?
+            Set<String> matched = new HashSet<String>();
+            for (Entry<String, Map<String, String>> e : info.entrySet()) {
+                if (e.getValue().get(key) != null && e.getValue().get(key).equals(value)) {
+                    matched.add(e.getKey());
+                }
+            }
+            return matched;
+        }
+
+        public void addConfig(String backend, String key, String value) {
+            addBackend(backend);
+            info.get(backend).put(key, value);
+        }
+
+        public Map<String, String> getConfig(String backend) {
+            return info.get(backend);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/redhat/thermostat/agent/StartupConfiguration.java	Mon Nov 21 18:22:13 2011 -0500
@@ -0,0 +1,41 @@
+package com.redhat.thermostat.agent;
+
+import java.io.Reader;
+import java.util.Properties;
+
+/**
+ * Configuration used by the agent during startup, initialization. As opposed to
+ * {@link RuntimeConfiguration}, this configuration is not exported.
+ */
+public class StartupConfiguration {
+
+    private final int localPort;
+    private final int remotePort;
+    private final String[] backends;
+
+    public StartupConfiguration(Reader configReader) {
+        Properties properties = new Properties();
+        try {
+            properties.load(configReader);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        localPort = Integer.valueOf(properties.getProperty("mongod_port"));
+        remotePort = Integer.valueOf(properties.getProperty("mongos_port"));
+        backends = properties.getProperty("backends").trim().split(",");
+
+    }
+
+    public int getPortForLocal() {
+        return localPort;
+    }
+
+    public int getPortForRemote() {
+        return remotePort;
+    }
+
+    public String[] getBackendsToStart() {
+        return backends;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/redhat/thermostat/backend/Backend.java	Mon Nov 21 18:22:13 2011 -0500
@@ -0,0 +1,56 @@
+package com.redhat.thermostat.backend;
+
+import java.util.Map;
+
+/**
+ * Represents a monitoring back-end. All the {@link Backend}s should be
+ * registered with the {@link BackendRegistry}.
+ */
+public interface Backend {
+
+    /** Returns the name of the {@link Backend} */
+    public String getName();
+
+    /** Returns the description of the {@link Backend} */
+    public String getDescription();
+
+    /** Returns the vendor of the {@link Backend} */
+    public String getVendor();
+
+    /** Returns the version of the {@link Backend} */
+    public String getVersion();
+
+    /**
+     * Returns an array of {@link BackendFeature}s supported by this backend. To
+     * indicate no supported features, return an empty array, not null.
+     */
+    public BackendFeature[] getSupportedFeatures();
+
+    /**
+     * Returns a map containing the settings of this backend
+     */
+    public Map<String, String> getSettings();
+
+    /**
+     * Activate the {@link Backend}. The backend should start gathering general
+     * data (not specific to any vm) and start sending it
+     *
+     * @return true on success, false if there was an error
+     */
+    public boolean activate();
+
+    /**
+     * Deactivate the {@link Backend}. The backend should release resources at
+     * this point.
+     *
+     * @return true on success
+     */
+    public boolean deactivate();
+
+    /**
+     * Returns a boolean indicating if the backend is currently active on this
+     * host
+     */
+    public boolean isActive();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/redhat/thermostat/backend/BackendFeature.java	Mon Nov 21 18:22:13 2011 -0500
@@ -0,0 +1,43 @@
+package com.redhat.thermostat.backend;
+
+/**
+ * A specific feature provided by a {@link Backend}. Each {@link Backend}
+ * provides a different set of features. Some may even provide none.
+ */
+public class BackendFeature {
+    public static final BackendFeature MXBEANS = new BackendFeature("mxbeans");
+    public static final BackendFeature PERF_COUNTER = new BackendFeature("perfcounter");
+    public static final BackendFeature PROC = new BackendFeature("proc");
+    public static final BackendFeature STARTUP_ARGUMENTS = new BackendFeature("startup-arguments");
+    public static final BackendFeature SYSTEM_PROPERTIES = new BackendFeature("system-properties");
+    public static final BackendFeature HEAP = new BackendFeature("heap");
+
+    private String featureName;
+
+    public BackendFeature(String featureName) {
+        this.featureName = featureName;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == null) {
+            return false;
+        }
+        if (other == this) {
+            return true;
+        }
+        if (other.getClass() == this.getClass()) {
+            BackendFeature otherFeature = (BackendFeature) other;
+            if (otherFeature.featureName.equals(featureName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return featureName.hashCode();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/redhat/thermostat/backend/BackendRegistry.java	Mon Nov 21 18:22:13 2011 -0500
@@ -0,0 +1,71 @@
+package com.redhat.thermostat.backend;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+/**
+ * A registry for {@link Backend}s. Each {@link Backend} should call
+ * {@link #register(Backend, BackendFeature[])} to register itself.
+ */
+public final class BackendRegistry {
+
+    private static BackendRegistry INSTANCE = null;
+
+    private static ServiceLoader<Backend> backendLoader = ServiceLoader.load(Backend.class);
+
+    private final List<Backend> registeredBackends;
+    private final Map<BackendFeature, Set<Backend>> featureToBackend;
+
+    private BackendRegistry() {
+        registeredBackends = new ArrayList<Backend>();
+        featureToBackend = new HashMap<BackendFeature, Set<Backend>>();
+
+        for (Backend newBackend : backendLoader) {
+            register(newBackend, newBackend.getSupportedFeatures());
+        }
+    }
+
+    public static synchronized BackendRegistry getInstance() {
+        if (INSTANCE == null) {
+            INSTANCE = new BackendRegistry();
+        }
+        return INSTANCE;
+    }
+
+    public synchronized void register(Backend backend, BackendFeature[] features) {
+        registeredBackends.add(backend);
+        for (BackendFeature feature : features) {
+            if (!featureToBackend.containsKey(feature)) {
+                featureToBackend.put(feature, new HashSet<Backend>());
+            }
+            featureToBackend.get(feature).add(backend);
+        }
+    }
+
+    public synchronized void unregister(Backend backend) {
+        registeredBackends.remove(backend);
+    }
+
+    public synchronized Backend[] getAll() {
+        return registeredBackends.toArray(new Backend[0]);
+    }
+
+    public synchronized Backend getByName(String name) {
+        for (Backend backend : registeredBackends) {
+            if (backend.getName().equals((name))) {
+                return backend;
+            }
+        }
+        return null;
+    }
+
+    public synchronized Backend[] getBackendsForFeature(BackendFeature feature) {
+        return featureToBackend.get(feature).toArray(new Backend[0]);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/redhat/thermostat/common/Constants.java	Mon Nov 21 18:22:13 2011 -0500
@@ -0,0 +1,29 @@
+package com.redhat.thermostat.common;
+
+/**
+ * A grab bag of constants. This could be cleaned up later, but lets throw
+ * things here for now.
+ */
+public class Constants {
+
+    public static final String LOGGING_CONFIG = "com.redhat.thermostat.level=ALL";
+
+    public static final String AGENT_CONFIG_FILE_LOCATION = "config/agent.properties";
+
+    public static final int EXIT_UNKNOWN_ERROR = 1;
+    public static final int EXIT_UNABLE_TO_CONNECT_TO_DATABASE = 2;
+    public static final int EXIT_UNABLE_TO_READ_CONFIG = 3;
+
+    public static final String THERMOSTAT_DB = "thermostat";
+    public static final String MONGO_DEFAULT_URL = "mongodb://127.0.0.1";
+
+    public static final String AGENT_CONFIG_COLLECTION_NAME = "agent-configs";
+    public static final String AGENT_ID = "agent-id";
+
+    public static final int SAMPLING_INTERVAL_UNKNOWN = -1;
+
+    public static final String AGENT_CONFIG_KEY_AGENT_NAME = "agent-name";
+    public static final String AGENT_CONFIG_KEY_BACKENDS = "backends";
+    public static final String AGENT_CONFIG_KEY_BACKEND_ACTIVE = "active";
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/redhat/thermostat/common/LogFormatter.java	Mon Nov 21 18:22:13 2011 -0500
@@ -0,0 +1,17 @@
+package com.redhat.thermostat.common;
+
+import java.util.logging.Formatter;
+import java.util.logging.LogRecord;
+
+public class LogFormatter extends Formatter {
+
+    @Override
+    public synchronized String format(LogRecord record) {
+        StringBuilder sb = new StringBuilder();
+        sb.append(record.getLevel());
+        sb.append(": ");
+        sb.append(record.getMessage());
+        sb.append("\n");
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/redhat/thermostat/common/utils/LoggingUtils.java	Mon Nov 21 18:22:13 2011 -0500
@@ -0,0 +1,49 @@
+package com.redhat.thermostat.common.utils;
+
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.common.LogFormatter;
+
+/**
+ * A few helper functions to facilitate using loggers
+ * <p>
+ * It would be good idea to call {@link LogManager#readConfiguration()} with a
+ * properties file that sets an appropriate value for ".level"
+ */
+public final class LoggingUtils {
+
+    private LoggingUtils() {
+        /* should not be instantiated */
+    }
+
+    /**
+     * Should be called once, very-early during program initialization. This
+     * works around http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4462908
+     */
+    public static Logger resetAndGetRootLogger() {
+        Logger root = Logger.getLogger("");
+        Handler[] handlers = root.getHandlers();
+        for (Handler handler : handlers) {
+            root.removeHandler(handler);
+        }
+
+        ConsoleHandler handler = new ConsoleHandler();
+        handler.setFormatter(new LogFormatter());
+        handler.setLevel(Level.ALL);
+        root.addHandler(handler);
+
+        return root;
+    }
+
+    /**
+     * Returns an appropriate logger to be used by class klass.
+     */
+    public static Logger getLogger(Class<?> klass) {
+        return Logger.getLogger(klass.getPackage().getName());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/redhat/thermostat/common/utils/StringUtils.java	Mon Nov 21 18:22:13 2011 -0500
@@ -0,0 +1,20 @@
+package com.redhat.thermostat.common.utils;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+
+public class StringUtils {
+
+    private StringUtils() {
+        /* should not be instantiated */
+    }
+
+    public static InputStream toInputStream(String toConvert) {
+        try {
+            return new ByteArrayInputStream(toConvert.getBytes("UTF-8"));
+        } catch (UnsupportedEncodingException e) {
+            throw new IllegalStateException("UTF-8 not supported");
+        }
+    }
+}