changeset 1766:9f64931e2c2f

Merge.
author Jon VanAlten <jon.vanalten@redhat.com>
date Tue, 23 Jun 2015 10:16:17 -0600
parents 1cd7c7d68a6a (current diff) 36ac62292ea5 (diff)
children 51debcf29b2c
files build-deps/pom.xml common/pom.xml dev/perflog-analyzer/pom.xml distribution/pom.xml integration-tests/itest-run/pom.xml pom.xml storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/Id.java vm-profiler/jvm-agent/pom.xml
diffstat 109 files changed, 2297 insertions(+), 987 deletions(-) [+]
line wrap: on
line diff
--- a/agent/cli/src/main/java/com/redhat/thermostat/agent/cli/impl/AgentApplication.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/agent/cli/src/main/java/com/redhat/thermostat/agent/cli/impl/AgentApplication.java	Tue Jun 23 10:16:17 2015 -0600
@@ -177,7 +177,7 @@
                 } catch (ConnectionException e) {
                     logger.log(Level.SEVERE, "Could not connect to storage (" + e.getMessage() + ")");
                     // log stack trace as info only
-                    logger.log(Level.INFO, "Could nto connect to storage", e);
+                    logger.log(Level.INFO, "Could not connect to storage", e);
                     shutdown(ExitStatus.EXIT_ERROR);
                 }
                 
--- a/agent/cli/src/main/java/com/redhat/thermostat/agent/cli/impl/ServiceCommand.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/agent/cli/src/main/java/com/redhat/thermostat/agent/cli/impl/ServiceCommand.java	Tue Jun 23 10:16:17 2015 -0600
@@ -86,7 +86,7 @@
         ServiceReference launcherRef = context.getServiceReference(Launcher.class);
         requireNonNull(launcherRef, translator.localize(LocaleResources.LAUNCHER_UNAVAILABLE));
         launcher = (Launcher) context.getService(launcherRef);
-        String[] storageStartArgs = new String[] { "storage", "--start", "--permitLocalhostException"};
+        String[] storageStartArgs = new String[] { "storage", "--start" };
         launcher.run(storageStartArgs, listeners, false);
         agentBarrier.acquireUninterruptibly();
         
--- a/agent/cli/src/test/java/com/redhat/thermostat/agent/cli/impl/ServiceCommandTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/agent/cli/src/test/java/com/redhat/thermostat/agent/cli/impl/ServiceCommandTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -78,7 +78,7 @@
     private static ActionEvent<ApplicationState> mockActionEvent;
     private static Collection<ActionListener<ApplicationState>> listeners;
 
-    private static final String[] STORAGE_START_ARGS = { "storage", "--start", "--permitLocalhostException" };
+    private static final String[] STORAGE_START_ARGS = { "storage", "--start" };
     private static final String[] STORAGE_STOP_ARGS = { "storage", "--stop" };
     private static final String[] AGENT_ARGS = {"agent", "-d", "Test String"};
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/annotations/src/main/java/com/redhat/thermostat/annotations/internal/CacioTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2012-2015 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.annotations.internal;
+
+/**
+ * Temporary workaround for PR2282: Caciocavallo tests fail with JDK 8 u40
+ * Use this annotation on test classes to exclude them from being run by the maven-surefire-plugin
+ */
+public interface CacioTest {
+}
--- a/build-deps/pom.xml	Thu Jun 04 01:14:43 2015 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,299 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Copyright 2012-2015 Red Hat, Inc.
-
- This file is part of Thermostat.
-
- Thermostat is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
-
- Thermostat 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 for more details.
-
- You should have received a copy of the GNU General Public License
- along with Thermostat; see the file COPYING.  If not see
- <http://www.gnu.org/licenses/>.
-
- Linking this code with other modules is making a combined work
- based on this code.  Thus, the terms and conditions of the GNU
- General Public License cover the whole combination.
-
- As a special exception, the copyright holders of this code give
- you permission to link this code with independent modules to
- produce an executable, regardless of the license terms of these
- independent modules, and to copy and distribute the resulting
- executable under terms of your choice, provided that you also
- meet, for each linked independent module, the terms and conditions
- of the license of that module.  An independent module is a module
- which is not derived from or based on this code.  If you modify
- this code, you may extend this exception to your version of the
- library, but you are not obligated to do so.  If you do not wish
- to do so, delete this exception statement from your version.
-
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-
-  <parent>
-    <artifactId>thermostat</artifactId>
-    <groupId>com.redhat.thermostat</groupId>
-    <version>1.99.4-SNAPSHOT</version>
-  </parent>
-  
-  <artifactId>thermostat-build-deps</artifactId>
-  <packaging>pom</packaging>
-  <name>Thermostat Build Artifact Dependencies</name>
-
-  <!-- List all dependencies for release builds here.
-       Extra deps for development builds go into
-       ../distribution/pom.xml (dev-build profile)
-       directly. It is assumed that release-build artifacts
-       are a subset of devel-build artifacts -->
-  <dependencies>
-    <!-- thermostat core parts. Be sure to
-         also adjust ../distribution/assembly/core-assembly.xml -->
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-main</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-launcher</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-client-swing</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-swing-components</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-client-command</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-client-cli</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-        <groupId>com.redhat.thermostat</groupId>
-        <artifactId>thermostat-osgi-living-vm-filter-swing</artifactId>
-        <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-agent-core</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-agent-cli</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-storage-cli</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-agent-command</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-agent-proxy-server</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-killvm-agent</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-        <groupId>com.redhat.thermostat</groupId>
-        <artifactId>thermostat-killvm-client-swing</artifactId>
-        <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-common-core</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-common-command</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-        <groupId>com.redhat.thermostat</groupId>
-        <artifactId>thermostat-osgi-process-handler</artifactId>
-        <version>${project.version}</version>
-    </dependency>
-    <dependency>
-        <groupId>com.redhat.thermostat</groupId>
-        <artifactId>thermostat-keyring</artifactId>
-        <version>${project.version}</version>
-    </dependency>
-    <dependency>
-        <groupId>com.redhat.thermostat</groupId>
-        <artifactId>thermostat-laf-utils</artifactId>
-        <version>${project.version}</version>
-    </dependency>
-    <dependency>
-        <groupId>com.redhat.thermostat</groupId>
-        <artifactId>thermostat-web-client</artifactId>
-        <version>${project.version}</version>
-    </dependency>
-    <!-- depend on the web archive to be built in order
-         to be able to copy the exploded war into the
-         image directory -->
-    <dependency>
-        <groupId>com.redhat.thermostat</groupId>
-        <artifactId>thermostat-web-war</artifactId>
-        <version>${project.version}</version>
-        <type>war</type>
-    </dependency>
-    <dependency>
-        <groupId>com.redhat.thermostat</groupId>
-        <artifactId>thermostat-system-backend</artifactId>
-        <version>${project.version}</version>
-    </dependency>
-    <dependency>
-        <groupId>com.redhat.thermostat</groupId>
-        <artifactId>thermostat-storage-mongodb</artifactId>
-        <version>${project.version}</version>
-    </dependency>
-    
-    <!-- Plugins -->
-
-    <!-- Be sure to add the distribution module of your plugin below
-         with type "zip", and also to ../distribution/assembly/all-plugin-assembly.xml -->
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-host-cpu-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-validate-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-host-memory-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-host-overview-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-notes-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-numa-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-storage-profile-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-thread-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-vm-classstat-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-vm-cpu-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-vm-gc-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-vm-heap-analysis-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-vm-io-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-vm-jmx-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-vm-memory-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-vm-overview-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-vm-profiler-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-web-endpoint-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-killvm-distribution</artifactId>
-      <version>${project.version}</version>
-      <type>zip</type>
-    </dependency>
-  </dependencies>
-</project>
--- a/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/host/swing/DeadHostIconDecoratorTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/host/swing/DeadHostIconDecoratorTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -43,13 +43,16 @@
 
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.swing.UIDefaults;
 import com.redhat.thermostat.client.ui.PlatformIcon;
 import com.redhat.thermostat.storage.core.HostRef;
 import com.redhat.thermostat.storage.core.VmRef;
 import com.redhat.thermostat.storage.dao.HostInfoDAO;
 
+@Category(CacioTest.class)
 public class DeadHostIconDecoratorTest {
 
     private DeadHostIconDecorator decorator;
--- a/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/host/swing/HostIconDecoratorTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/host/swing/HostIconDecoratorTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -45,12 +45,15 @@
 
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.swing.UIDefaults;
 import com.redhat.thermostat.client.ui.PlatformIcon;
 import com.redhat.thermostat.storage.core.HostRef;
 import com.redhat.thermostat.storage.core.VmRef;
 
+@Category(CacioTest.class)
 public class HostIconDecoratorTest {
 
     private HostIconDecorator decorator;
--- a/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/VMFilterActivatorTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/VMFilterActivatorTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -41,9 +41,10 @@
 import static org.mockito.Mockito.when;
 
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.filter.host.swing.DeadHostIconDecorator;
-import com.redhat.thermostat.client.filter.host.swing.HostIconDecorator;
 import com.redhat.thermostat.client.filter.host.swing.HostInfoLabelDecorator;
 import com.redhat.thermostat.client.swing.UIDefaults;
 import com.redhat.thermostat.client.ui.ReferenceFieldIconDecorator;
@@ -53,6 +54,7 @@
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
 import com.redhat.thermostat.testutils.StubBundleContext;
 
+@Category(CacioTest.class)
 public class VMFilterActivatorTest {
     
     @Test
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/MenuHelperTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/MenuHelperTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -63,9 +63,11 @@
 import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.ui.MenuAction;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class MenuHelperTest {
 
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/ActionButtonTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/ActionButtonTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -57,10 +57,13 @@
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class ActionButtonTest {
 
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/FontAwesomeIconTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/FontAwesomeIconTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -43,7 +43,11 @@
 import java.awt.image.BufferedImage;
 
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
+
+@Category(CacioTest.class)
 public class FontAwesomeIconTest {
 
     @Test
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/HeaderPanelTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/HeaderPanelTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -57,14 +57,17 @@
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertEquals;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class HeaderPanelTest {
 
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/RecentTimeSeriesChartPanelTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/RecentTimeSeriesChartPanelTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -41,6 +41,7 @@
 import java.util.concurrent.TimeUnit;
 import javax.swing.JFrame;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.ui.RecentTimeSeriesChartController;
 import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
 import org.fest.swing.annotation.GUITest;
@@ -55,8 +56,10 @@
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class RecentTimeSeriesChartPanelTest {
 
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/SearchFieldTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/SearchFieldTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -62,11 +62,12 @@
 import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
-import com.redhat.thermostat.client.swing.components.SearchField;
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class SearchFieldTest {
 
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/experimental/RecentTimeControlPanelTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/experimental/RecentTimeControlPanelTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -46,6 +46,7 @@
 import javax.swing.JFrame;
 import javax.swing.JComboBox;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.core.experimental.Duration;
 import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
 import org.fest.swing.annotation.GUITest;
@@ -58,8 +59,10 @@
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class RecentTimeControlPanelTest {
 
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/experimental/SingleValueChartPanelTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/experimental/SingleValueChartPanelTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -44,6 +44,7 @@
 import java.util.concurrent.TimeUnit;
 import javax.swing.JFrame;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.core.experimental.Duration;
 import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
 import org.fest.swing.annotation.GUITest;
@@ -58,8 +59,10 @@
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class SingleValueChartPanelTest {
 
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/models/NullSelectionModelTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/models/NullSelectionModelTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -53,8 +53,12 @@
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
+
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class NullSelectionModelTest {
 
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/experimental/ComponentVisibilityNotifierTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/experimental/ComponentVisibilityNotifierTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -55,13 +55,13 @@
 import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.core.views.BasicView;
 import com.redhat.thermostat.client.core.views.BasicView.Action;
-import com.redhat.thermostat.client.swing.experimental.ComponentVisibilityNotifier;
 import com.redhat.thermostat.common.ActionNotifier;
 
 @GUITest
-@Category(GUITest.class)
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class ComponentVisibilityNotifierTest {
 
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/MainWindowTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/MainWindowTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -61,12 +61,14 @@
 import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.core.views.BasicView;
 import com.redhat.thermostat.client.ui.MenuAction;
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class MainWindowTest {
 
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/StatusBarTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/StatusBarTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -58,10 +58,13 @@
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class StatusBarTest {
 
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/accordion/AccordionTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/accordion/AccordionTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -67,8 +67,10 @@
 import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.swing.components.EmptyIcon;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class AccordionTest {
 
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/accordion/TitledPaneTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/accordion/TitledPaneTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -57,10 +57,13 @@
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.swing.components.VerticalLayout;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class TitledPaneTest {
 
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/views/AgentInformationDisplayFrameTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/views/AgentInformationDisplayFrameTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -66,12 +66,13 @@
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.core.views.AgentInformationDisplayView;
 import com.redhat.thermostat.client.core.views.AgentInformationDisplayView.ConfigurationAction;
-import com.redhat.thermostat.client.swing.internal.views.AgentInformationDisplayFrame;
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class AgentInformationDisplayFrameTest {
 
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/views/ClientConfigurationSwingTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/views/ClientConfigurationSwingTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -62,12 +62,13 @@
 import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.core.views.ClientConfigurationView;
-import com.redhat.thermostat.client.swing.internal.views.ClientConfigurationSwing;
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
 import com.redhat.thermostat.test.Bug;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class ClientConfigurationSwingTest {
     
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/views/HostInformationPanelTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/views/HostInformationPanelTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -48,13 +48,16 @@
 import org.fest.swing.edt.GuiActionRunner;
 import org.fest.swing.edt.GuiQuery;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.core.views.UIComponent;
 import com.redhat.thermostat.client.swing.FrameWithPanelTest;
 import com.redhat.thermostat.client.swing.TabbedPaneMatcher;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class HostInformationPanelTest extends FrameWithPanelTest<HostInformationPanel> {
 
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/views/VmInformationPanelTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/views/VmInformationPanelTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -43,12 +43,15 @@
 import org.fest.swing.edt.GuiActionRunner;
 import org.fest.swing.edt.GuiQuery;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.core.views.UIComponent;
 import com.redhat.thermostat.client.swing.FrameWithPanelTest;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class VmInformationPanelTest extends FrameWithPanelTest<VmInformationPanel> {
 
--- a/common/core/src/main/java/com/redhat/thermostat/common/utils/LoggingUtils.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/common/core/src/main/java/com/redhat/thermostat/common/utils/LoggingUtils.java	Tue Jun 23 10:16:17 2015 -0600
@@ -60,14 +60,35 @@
  */
 public final class LoggingUtils {
 
-    /*
-     * Custom log level, intended for use with Thermostat's internal performance
-     * analysis framework.  Log messages at this level should be formatted using
-     * {@link com.redhat.thermostat.shared.perflog.PerformanceLogFormatter}.
-     */
-    public static final Level PERFLOG = new Level("PERFLOG", 50) {
-        private static final long serialVersionUID = 1L;
-    };
+    public enum LogLevel {
+        /*
+         * Custom log level, intended for use with Thermostat's internal performance
+         * analysis framework.  Log messages at this level should be formatted using
+         * {@link com.redhat.thermostat.shared.perflog.PerformanceLogFormatter}.
+         */
+        PERFLOG(new Level("PERFLOG", 50) {
+            private static final long serialVersionUID = 1L;
+        }),
+        ALL(Level.ALL),
+        CONFIG(Level.CONFIG),
+        FINE(Level.FINE),
+        FINER(Level.FINER),
+        FINEST(Level.FINEST),
+        INFO(Level.INFO),
+        OFF(Level.OFF),
+        SEVERE(Level.SEVERE),
+        WARNING(Level.WARNING);
+
+        private Level level;
+
+        LogLevel(Level level) {
+            this.level = level;
+        }
+
+        public Level getLevel() {
+            return level;
+        }
+    }
 
     // package private for testing
     static final String ROOTNAME = "com.redhat.thermostat";
--- a/common/pom.xml	Thu Jun 04 01:14:43 2015 -0500
+++ b/common/pom.xml	Tue Jun 23 10:16:17 2015 -0600
@@ -56,6 +56,12 @@
       <artifactId>junit</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-annotations</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <modules>
--- a/dev/perflog-analyzer/pom.xml	Thu Jun 04 01:14:43 2015 -0500
+++ b/dev/perflog-analyzer/pom.xml	Tue Jun 23 10:16:17 2015 -0600
@@ -62,6 +62,13 @@
       <artifactId>mockito-core</artifactId>
       <scope>test</scope>
     </dependency>
+
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-annotations</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
   
   <build>
--- a/distribution/config/agent.auth	Thu Jun 04 01:14:43 2015 -0500
+++ b/distribution/config/agent.auth	Tue Jun 23 10:16:17 2015 -0600
@@ -6,4 +6,3 @@
 #
 #username=thermostat
 #password=thermostat
-${agent.auth.snippet}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/distribution/config/examples/thermostat-roles-example.properties	Tue Jun 23 10:16:17 2015 -0600
@@ -0,0 +1,60 @@
+# This file is used if the PropertiesUsernameRolesLoginModule is used
+# as a delegate in the JAAS configuration *and* the 'roles.properties' option
+# has not been specified for the login module.
+#
+# If that is the case, this file does two things:
+#    1.  It maps user names to roles.
+#    2.  Defines an optional recursive set of roles. This is useful in order to
+#        define role sets. Users can then be members of such defined role sets.
+#        Note that every line which does not have a user name (as defined in the
+#        corresponding users.properties file) on the left hand side of the
+#        equals sign ('='), represents a role.
+#
+# A user is assigned multiple roles by separating them by a comma ','. Every
+# entity in this file which isn't a user name, will be implicitly defined as a
+# role.
+#
+##############################################################################
+# The following makes user 'agent-tester' a user suitable for running
+# "thermostat agent".
+agent-tester=thermostat-agent, thermostat-grant-write-files-all-agent
+
+##############################################################################
+# The following makes user 'client-tester' a user suitable for running the GUI and/or
+# shell client. needs thermostat-purge role for clean-data command to work
+client-tester=thermostat-grant-read-all-client, thermostat-cmdc, thermostat-purge
+
+# Agent recursive role
+thermostat-agent = thermostat-cmdc-verify, \
+                   thermostat-login, \
+                   thermostat-prepare-statement, \
+                   thermostat-purge, \
+                   thermostat-register-category, \
+                   thermostat-realm, \
+                   thermostat-save-file, \
+                   thermostat-write
+# Grant agent role so as to be able to write any file
+thermostat-grant-write-files-all-agent = thermostat-files-grant-write-filename-ALL
+                   
+# Client recursive role (granting a client to read all data + all files)
+thermostat-grant-read-all-client = thermostat-agents-grant-read-agentId-ALL, \
+                    thermostat-cmdc-generate, \
+                    thermostat-hosts-grant-read-hostname-ALL, \
+                    thermostat-load-file, \
+                    thermostat-login, \
+                    thermostat-prepare-statement, \
+                    thermostat-query, \
+                    thermostat-realm, \
+                    thermostat-register-category, \
+                    thermostat-vms-grant-read-username-ALL, \
+                    thermostat-vms-grant-read-vmId-ALL, \
+                    thermostat-files-grant-read-filename-ALL, \
+                    thermostat-write
+# Grants all command channel operations
+thermostat-cmdc = thermostat-cmdc-grant-garbage-collect, \
+                  thermostat-cmdc-grant-dump-heap, \
+                  thermostat-cmdc-grant-thread-harvester, \
+                  thermostat-cmdc-grant-killvm, \
+                  thermostat-cmdc-grant-profile-vm, \
+                  thermostat-cmdc-grant-ping, \
+                  thermostat-cmdc-grant-jmx-toggle-notifications
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/distribution/config/examples/thermostat-users-example.properties	Tue Jun 23 10:16:17 2015 -0600
@@ -0,0 +1,14 @@
+# This file is used if the PropertiesUsernameRolesLoginModule is used
+# as a delegate in the JAAS configuration *and* the 'users.properties' option
+# has not been specified for the login module.
+#
+# If that is the case, this defines the database of users with corresponding
+# passwords, the thermostat web storage servlet knows about.
+# 
+# WARNING: Passwords of users are in plain text. This needs to be considered
+#          when using this module in production. The main goal of this login
+#          module is to provide a simple way to define thermostat users and
+#          their corresponding passwords.
+# 
+agent-tester=tester
+client-tester=tester
--- a/distribution/config/thermostat-roles.properties	Thu Jun 04 01:14:43 2015 -0500
+++ b/distribution/config/thermostat-roles.properties	Tue Jun 23 10:16:17 2015 -0600
@@ -75,4 +75,3 @@
 #                  thermostat-cmdc-grant-profile-vm, \
 #                  thermostat-cmdc-grant-ping, \
 #                  thermostat-cmdc-grant-jmx-toggle-notifications
-${dev.roles.snippet}
--- a/distribution/config/thermostat-users.properties	Thu Jun 04 01:14:43 2015 -0500
+++ b/distribution/config/thermostat-users.properties	Tue Jun 23 10:16:17 2015 -0600
@@ -17,4 +17,3 @@
 # user2=password2
 # ...
 #
-${dev.users.snippet}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/distribution/config/thermostatrc	Tue Jun 23 10:16:17 2015 -0600
@@ -0,0 +1,68 @@
+#!/bin/bash
+#
+# Copyright 2012-2015 Red Hat, Inc.
+#
+# This file is part of Thermostat.
+#
+# Thermostat is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 2, or (at your
+# option) any later version.
+#
+# Thermostat 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Thermostat; see the file COPYING.  If not see
+# <http://www.gnu.org/licenses/>.
+#
+# Linking this code with other modules is making a combined work
+# based on this code.  Thus, the terms and conditions of the GNU
+# General Public License cover the whole combination.
+#
+# As a special exception, the copyright holders of this code give
+# you permission to link this code with independent modules to
+# produce an executable, regardless of the license terms of these
+# independent modules, and to copy and distribute the resulting
+# executable under terms of your choice, provided that you also
+# meet, for each linked independent module, the terms and conditions
+# of the license of that module.  An independent module is a module
+# which is not derived from or based on this code.  If you modify
+# this code, you may extend this exception to your version of the
+# library, but you are not obligated to do so.  If you do not wish
+# to do so, delete this exception statement from your version.
+#
+#####################################################################
+#
+# Environment variables for the system Thermostat profile. You
+# can assume that THERMOSTAT_HOME variable is correctly set and you
+# may override system variables via a user profile in
+# USER_THERMOSTAT_HOME/etc/thermostatrc.
+#
+#####################################################################
+
+#
+# Extra jar files which need to be on the classpath when
+# Thermostat boots.
+# 
+THERMOSTAT_EXT_BOOT_CLASSPATH="@java.home@/../lib/tools.jar"
+# FIXME: Remove once jfreechart is a real OSGi bundle upstream
+THERMOSTAT_EXT_BOOT_CLASSPATH="${THERMOSTAT_EXT_BOOT_CLASSPATH}:${THERMOSTAT_HOME}/libs/jfreechart-@jfreechart.version@.jar"
+THERMOSTAT_EXT_BOOT_CLASSPATH="${THERMOSTAT_EXT_BOOT_CLASSPATH}:${THERMOSTAT_HOME}/libs/jcommon-@jcommon.version@.jar"
+# Needed to parse web.xml files without network connection See PR 2029.
+THERMOSTAT_EXT_BOOT_CLASSPATH="${THERMOSTAT_EXT_BOOT_CLASSPATH}:${THERMOSTAT_HOME}/plugins/embedded-web-endpoint/jetty-schemas-@jetty-schemas.version@.jar"
+export THERMOSTAT_EXT_BOOT_CLASSPATH
+
+#
+# Extra java options
+#
+#THERMOSTAT_EXT_JAVA_OPTS="-Xint -ea"
+#export THERMOSTAT_EXT_JAVA_OPTS
+
+#
+# Extra options passed on to the Thermostat main class
+#
+#THERMOSTAT_EXT_OPTS="--ignore-bundle-versions"
+#export THERMOSTAT_EXT_OPTS
--- a/distribution/config/web.auth	Thu Jun 04 01:14:43 2015 -0500
+++ b/distribution/config/web.auth	Tue Jun 23 10:16:17 2015 -0600
@@ -4,8 +4,8 @@
 
 # Username to use for connecting to the backing storage
 # implementation
-${web.war.backingstorage.username.snippet}
+# storage.username=username
 
 # Password to use for connecting to the backing storage
 # implementation
-${web.war.backingstorage.password.snippet}
+# storage.password=password
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/distribution/lib/create-user.js	Tue Jun 23 10:16:17 2015 -0600
@@ -0,0 +1,22 @@
+db = db.getSiblingDB("thermostat")
+var v = db.version()
+var majorVersion = v.substring(0, v.indexOf('.'))
+var minorMicro = v.substr(v.indexOf('.') + 1)
+var minorVersion = minorMicro.substr(0, minorMicro.indexOf('.'))
+if ( majorVersion < 2 || ( majorVersion == 2 && minorVersion <= 2 ) ) {
+    // mongodb version 2.2 and below don't have the third argument.
+    // this should create the user as read + write.
+    db.addUser("$USERNAME","$PASSWORD")
+} else if ( majorVersion == 2 && minorVersion <= 4 ) {
+    db.addUser({ user: "$USERNAME", pwd: "$PASSWORD", roles: [ "readWrite" ] })
+} else if ( majorVersion == 2 ) {
+    db.createUser({ user: "$USERNAME", pwd: "$PASSWORD", roles: [ "readWrite" ] })
+} else if ( majorVersion == 3 ) {
+    db = db.getSiblingDB("admin")
+    db.createUser({ user: "thermostat-admin", pwd: "$PASSWORD", roles: [ "dbOwner", "userAdminAnyDatabase" ] })
+    db.auth("thermostat-admin", "$PASSWORD")
+    db = db.getSiblingDB("thermostat")
+    db.createUser({ user: "$USERNAME", pwd: "$PASSWORD", roles: [ "readWrite" ] })
+} else {
+    throw "Unknown mongo version: " + v
+}
--- a/distribution/pom.xml	Thu Jun 04 01:14:43 2015 -0500
+++ b/distribution/pom.xml	Tue Jun 23 10:16:17 2015 -0600
@@ -150,6 +150,14 @@
                   <filtering>true</filtering>
                 </resource>
                 <resource>
+                  <directory>lib</directory>
+                  <targetPath>image/lib</targetPath>
+                  <filtering>true</filtering>
+                  <includes>
+                    <include>create-user.js</include>
+                  </includes>
+                </resource>
+                <resource>
                   <directory>config</directory>
                   <targetPath>image/etc</targetPath>
                   <filtering>true</filtering>
@@ -159,6 +167,7 @@
                     <include>agent.auth</include>
                     <include>web.auth</include>
                     <include>ssl.properties</include>
+                    <include>thermostatrc</include>
                     <include>thermostat-users.properties</include>
                     <include>thermostat-roles.properties</include>
                     <include>thermostat_jaas.conf</include>
@@ -170,6 +179,16 @@
                   </includes>
                 </resource>
                 <resource>
+                  <directory>config/examples</directory>
+                  <targetPath>image/etc/examples</targetPath>
+                  <filtering>false</filtering>
+                  <includes>
+                    <!-- Example files with real users. agent-tester and client-tester -->
+                    <include>thermostat-users-example.properties</include>
+                    <include>thermostat-roles-example.properties</include>
+                  </includes>
+                </resource>
+                <resource>
                   <directory>config</directory>
                   <targetPath>image/etc/plugins.d</targetPath>
                   <filtering>true</filtering>
@@ -267,80 +286,257 @@
       </plugin>
     </plugins>
   </build>
-  <!-- Define two build profiles. One for development builds. Another for
-       release builds. All dependencies for release builds are specified in
-       build-deps/pom.xml. Any extra dependencies for a devel-build
-       go into the dev-build profile directly.
-  -->
-  <profiles>
 
-    <profile> <!-- dev-build -->
-      <id>dev-build</id>
-      <activation>
-        <property>
-          <name>environment.type</name>
-          <value>!release</value>
-        </property>
-      </activation>
-      <dependencies>
-        <dependency>
-          <groupId>com.redhat.thermostat</groupId>
-          <artifactId>thermostat-build-deps</artifactId>
-          <version>${project.version}</version>
-          <type>pom</type>
-        </dependency>
-        <!-- This duplication needs to be here since copy-dependencies plugin
-             which prepares the exploded web archive would fail
-             otherwise -->
-        <dependency>
-          <groupId>com.redhat.thermostat</groupId>
-          <artifactId>thermostat-web-war</artifactId>
-          <version>${project.version}</version>
-          <type>war</type>
-        </dependency>
-
-        <!-- Plugins -->
-
-        <!-- Be sure to add the distribution module of your plugin below
-             with type "zip", and also to distribution/assembly/all-plugin-assembly.xml -->
+  <dependencies>
+    <!-- thermostat core parts. Be sure to
+         also adjust ../distribution/assembly/core-assembly.xml -->
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-main</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-launcher</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-client-swing</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-swing-components</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-client-command</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-client-cli</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+        <groupId>com.redhat.thermostat</groupId>
+        <artifactId>thermostat-osgi-living-vm-filter-swing</artifactId>
+        <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-agent-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-agent-cli</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-storage-cli</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-agent-command</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-agent-proxy-server</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-killvm-agent</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+        <groupId>com.redhat.thermostat</groupId>
+        <artifactId>thermostat-killvm-client-swing</artifactId>
+        <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-common-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-common-command</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+        <groupId>com.redhat.thermostat</groupId>
+        <artifactId>thermostat-osgi-process-handler</artifactId>
+        <version>${project.version}</version>
+    </dependency>
+    <dependency>
+        <groupId>com.redhat.thermostat</groupId>
+        <artifactId>thermostat-keyring</artifactId>
+        <version>${project.version}</version>
+    </dependency>
+    <dependency>
+        <groupId>com.redhat.thermostat</groupId>
+        <artifactId>thermostat-laf-utils</artifactId>
+        <version>${project.version}</version>
+    </dependency>
+    <dependency>
+        <groupId>com.redhat.thermostat</groupId>
+        <artifactId>thermostat-web-client</artifactId>
+        <version>${project.version}</version>
+    </dependency>
+    <!-- depend on the web archive to be built in order
+         to be able to copy the exploded war into the
+         image directory -->
+    <dependency>
+        <groupId>com.redhat.thermostat</groupId>
+        <artifactId>thermostat-web-war</artifactId>
+        <version>${project.version}</version>
+        <type>war</type>
+    </dependency>
+    <dependency>
+        <groupId>com.redhat.thermostat</groupId>
+        <artifactId>thermostat-system-backend</artifactId>
+        <version>${project.version}</version>
+    </dependency>
+    <dependency>
+        <groupId>com.redhat.thermostat</groupId>
+        <artifactId>thermostat-storage-mongodb</artifactId>
+        <version>${project.version}</version>
+    </dependency>
+    
+    <!-- Plugins -->
 
-        <!-- build list-categories command for dev builds only -->
-        <dependency>
-          <groupId>com.redhat.thermostat</groupId>
-          <artifactId>thermostat-schema-info-distribution</artifactId>
-          <version>${project.version}</version>
-          <type>zip</type>
-        </dependency>
-      </dependencies>
-    </profile> <!-- dev-build -->
+    <!-- Be sure to add the distribution module of your plugin below
+         with type "zip", and also to ../distribution/assembly/all-plugin-assembly.xml -->
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-host-cpu-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-validate-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-host-memory-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-host-overview-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-notes-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-numa-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-storage-profile-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-thread-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-vm-classstat-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-vm-cpu-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-vm-gc-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-vm-heap-analysis-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-vm-io-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-vm-jmx-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-vm-memory-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-vm-overview-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-vm-profiler-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-web-endpoint-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-killvm-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
 
-    <profile> <!-- release-build -->
-      <id>release-build</id>
-      <activation>
-        <property>
-          <name>environment.type</name>
-          <value>release</value>
-        </property>
-      </activation>
-      <dependencies>
-        <dependency>
-          <groupId>com.redhat.thermostat</groupId>
-          <artifactId>thermostat-build-deps</artifactId>
-          <version>${project.version}</version>
-          <type>pom</type>
-        </dependency>
-        <!-- This duplication needs to be here since copy-dependencies plugin
-             which prepares the exploded web archive would fail
-             otherwise -->
-        <dependency>
-          <groupId>com.redhat.thermostat</groupId>
-          <artifactId>thermostat-web-war</artifactId>
-          <version>${project.version}</version>
-          <type>war</type>
-        </dependency>
-      </dependencies>
-    </profile> <!-- release-build -->
+    <!-- list-categories command -->
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-schema-info-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+  </dependencies>
 
-  </profiles>
 </project>
 
--- a/distribution/scripts/thermostat	Thu Jun 04 01:14:43 2015 -0500
+++ b/distribution/scripts/thermostat	Tue Jun 23 10:16:17 2015 -0600
@@ -1,6 +1,6 @@
 #!/bin/bash
 #
-# Copyright 2012-2014 Red Hat, Inc.
+# Copyright 2012-2015 Red Hat, Inc.
 #
 # This file is part of Thermostat.
 #
@@ -35,35 +35,44 @@
 # to do so, delete this exception statement from your version.
 #
 #####################################################################
-#
-JAVA="@java.home@/bin/java"
 
-if [ x"$THERMOSTAT_INSTALL_DIR" = x ] ; then
-  THERMOSTAT_INSTALL_DIR="@thermostat.home@"
-fi
-# Not always are installation directory and thermostat home one and
-# the same location.
-if [ x"$THERMOSTAT_HOME" = x ] ; then
-  THERMOSTAT_HOME=${THERMOSTAT_INSTALL_DIR}
+if [ x"${THERMOSTAT_HOME}" = x ]; then
+  THERMOSTAT_HOME="@thermostat.home@"
   export THERMOSTAT_HOME
 fi
-THERMOSTAT_LIBS="${THERMOSTAT_HOME}/libs"
+if [ x"${USER_THERMOSTAT_HOME}" = x ]; then
+  USER_THERMOSTAT_HOME="@user.thermostat.home@"
+  export USER_THERMOSTAT_HOME
+fi
 
-# need tools from the JVM
-TOOLS_JAR="@java.home@/../lib/tools.jar"
+# Source system thermostat profile
+. ${THERMOSTAT_HOME}/etc/thermostatrc 
+# Source user thermostat profile (if any)
+if [ -f ${USER_THERMOSTAT_HOME}/etc/thermostatrc ]; then
+  . ${USER_THERMOSTAT_HOME}/etc/thermostatrc
+fi
+
+# NOTE: The following variables come from the system/user
+#       profiles (if any)
+#
+# THERMOSTAT_EXT_BOOT_CLASSPATH
+# THERMOSTAT_EXT_JAVA_OPTS
+# THERMOSTAT_EXT_OPTS
+
+JAVA="@java.home@/bin/java"
+THERMOSTAT_LIBS="${THERMOSTAT_HOME}/libs"
 
 # This is the minimal boot classpath thermostat needs. Other dependencies
 # will get started by the OSGi framework once that's up.
-SERVICE_CLASSPATH="${THERMOSTAT_LIBS}/org.apache.felix.framework-@felix.framework.version@.jar"
-SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-launcher-@project.version@.jar"
-SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-main-@project.version@.jar"
-SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-shared-config-@project.version@.jar"
-# FIXME: Remove once jfreechart is a real OSGi bundle upstream
-SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/jfreechart-@jfreechart.version@.jar"
-SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_LIBS}/jcommon-@jcommon.version@.jar"
-# Needed to parse web.xml files without network connection See PR 2029.
-SERVICE_CLASSPATH="${SERVICE_CLASSPATH}:${THERMOSTAT_HOME}/plugins/embedded-web-endpoint/jetty-schemas-@jetty-schemas.version@.jar"
-SERVICE_CLASSPATH="${TOOLS_JAR}:${SERVICE_CLASSPATH}"
+BOOT_CLASSPATH="${THERMOSTAT_LIBS}/org.apache.felix.framework-@felix.framework.version@.jar"
+BOOT_CLASSPATH="${BOOT_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-launcher-@project.version@.jar"
+BOOT_CLASSPATH="${BOOT_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-main-@project.version@.jar"
+BOOT_CLASSPATH="${BOOT_CLASSPATH}:${THERMOSTAT_LIBS}/thermostat-shared-config-@project.version@.jar"
+
+# Append extra class path entries coming from the profiles
+if [ ! -z ${THERMOSTAT_EXT_BOOT_CLASSPATH} ]; then
+  BOOT_CLASSPATH="${BOOT_CLASSPATH}:${THERMOSTAT_EXT_BOOT_CLASSPATH}"
+fi
 
 THERMOSTAT_MAIN="com.redhat.thermostat.main.Thermostat"
 
@@ -106,19 +115,23 @@
 done
 
 # Finally run thermostat (optionally in the background)
-if [ $RUN_IN_BG -eq 1 ]; then
+if [ ${RUN_IN_BG} -eq 1 ]; then
     # The thermostat-agent-sysd script uses this.
-    if [ x"$PID_FILE" = "x" ]; then
+    if [ x"${PID_FILE}" = "x" ]; then
         usage 
     else
-        ${JAVA} "${JAVA_ARGS[@]}" -cp ${SERVICE_CLASSPATH} ${THERMOSTAT_MAIN} "${ARGS[@]}" &
+        ${JAVA} ${THERMOSTAT_EXT_JAVA_OPTS} "${JAVA_ARGS[@]}" \
+                -cp ${BOOT_CLASSPATH} \
+                ${THERMOSTAT_MAIN} ${THERMOSTAT_EXT_OPTS} "${ARGS[@]}" &
         retval=$?
-        echo $! > $PID_FILE
-        retval=$(( $retval + $? ))
+        echo $! > ${PID_FILE}
+        retval=$(( ${retval} + $? ))
     fi
 else
-    ${JAVA} "${JAVA_ARGS[@]}" -cp ${SERVICE_CLASSPATH} ${THERMOSTAT_MAIN} "${ARGS[@]}"
+    ${JAVA} ${THERMOSTAT_EXT_JAVA_OPTS} "${JAVA_ARGS[@]}" \
+            -cp ${BOOT_CLASSPATH} \
+            ${THERMOSTAT_MAIN} ${THERMOSTAT_EXT_OPTS} "${ARGS[@]}"
     retval=$?
 fi
-exit $retval
+exit ${retval}
 
--- a/distribution/scripts/thermostat-devsetup	Thu Jun 04 01:14:43 2015 -0500
+++ b/distribution/scripts/thermostat-devsetup	Tue Jun 23 10:16:17 2015 -0600
@@ -61,5 +61,10 @@
   exit $retval
 fi
 
-# Copy the agent.auth file into USER_THERMOSTAT_HOME
-cp -v $THERMOSTAT_HOME/etc/agent.auth $USER_THERMOSTAT_HOME/etc/agent.auth
+# Use example users/roles files:
+#  thermostat-users-example.properties
+#  thermostat-roles-example.properties
+cp -v $THERMOSTAT_HOME/etc/examples/thermostat-users-example.properties $THERMOSTAT_HOME/etc/thermostat-users.properties
+cp -v $THERMOSTAT_HOME/etc/examples/thermostat-roles-example.properties $THERMOSTAT_HOME/etc/thermostat-roles.properties
+# Use the agent-tester user as defined in thermostat-users-example.properties
+echo -e 'username=agent-tester\npassword=tester' > $USER_THERMOSTAT_HOME/etc/agent.auth
--- a/distribution/scripts/thermostat-setup	Thu Jun 04 01:14:43 2015 -0500
+++ b/distribution/scripts/thermostat-setup	Tue Jun 23 10:16:17 2015 -0600
@@ -186,11 +186,6 @@
   setupMongodbUser
   TH_WEB_AUTH="$THERMOSTAT_HOME/etc/web.auth"
   
-  if [ ! -e $TH_WEB_AUTH ]; then
-    echo "File not found: $TH_WEB_AUTH" 1>&2
-    exitFail
-  fi
-
   if [ ! -w $TH_WEB_AUTH ]; then
     echo -e "\n\n$(readlink -f $TH_WEB_AUTH) is NOT writable."
     mkdir -p "$USER_THERMOSTAT_HOME/etc/"
@@ -277,25 +272,13 @@
     exitFail
   fi
   sleep 3
-  mongo 127.0.0.1:27518 << EOF
-use thermostat
-var v = db.version();
-var minorMicro = v.substr(v.indexOf('.') + 1)
-var minorVersion = minorMicro.substr(0, minorMicro.indexOf('.'))
-if ( minorVersion <= 2 ) {
-    // mongodb version 2.2 and below don't have the third argument.
-    // this should create the user as read + write.
-    db.addUser("$USERNAME","$PASSWORD")
-} else {
-  if ( minorVersion <= 4 ) {
-    db.addUser({ user: "$USERNAME", pwd: "$PASSWORD", roles: [ "readWrite" ] })
-  } else {
-    db.createUser({ user: "$USERNAME", pwd: "$PASSWORD", roles: [ "readWrite" ] })
-  }
-}
-quit()
-EOF
+  mkdir -p $USER_THERMOSTAT_HOME
+  touch $USER_THERMOSTAT_HOME/creds.js
+  chmod u=rw $USER_THERMOSTAT_HOME/creds.js
+  sed -e s/'\$USERNAME'/"$USERNAME"/g -e s/'\$PASSWORD'/"$PASSWORD"/g $THERMOSTAT_HOME/lib/create-user.js > $USER_THERMOSTAT_HOME/creds.js
+  mongo 127.0.0.1:27518/thermostat $USER_THERMOSTAT_HOME/creds.js
   MONGO_SETUP_RETVAL="$?"
+  rm $USER_THERMOSTAT_HOME/creds.js
   if [ "$MONGO_SETUP_RETVAL" -ne 0 ] ; then
     echo -e "\nMongodb user setup failed." 1>&2
     exitFail
--- a/integration-tests/itest-run/pom.xml	Thu Jun 04 01:14:43 2015 -0500
+++ b/integration-tests/itest-run/pom.xml	Tue Jun 23 10:16:17 2015 -0600
@@ -87,7 +87,6 @@
         <configuration>
           <argLine>
             -Djava.security.auth.login.config=${thermostat.home}/etc/thermostat_jaas.conf
-            -Ddevel.build=${devel.build}
             ${coverageAgent}
           </argLine>
           <skip>true</skip>
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/DevWebStorageTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/DevWebStorageTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -44,19 +44,36 @@
 import java.nio.file.NoSuchFileException;
 import java.util.Map;
 
-import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
 import expectj.Spawn;
 
-public class DevWebStorageTest extends IntegrationTest {
+public class DevWebStorageTest extends WebStorageUsingIntegrationTest {
     
     private static final String THERMOSTAT_DEV_SETUP_SCRIPT = "thermostat-devsetup";
+
+    @BeforeClass
+    public static void setUp() throws IOException {
+        clearStorageDataDirectory();
+        backupOriginalCredentialsFiles();
+        try {
+            runThermostatDevSetup();
+        } catch (Exception e) {
+            e.printStackTrace();
+            restoreBackedUpCredentialsFiles();
+        }
+    }
+
     
-    @After
-    public void tearDown() throws IOException {
+    @AfterClass
+    public static void tearDown() throws IOException {
         removeSetupCompleteStampFiles();
         removeAgentAuthFile();
+
+        restoreBackedUpCredentialsFiles();
+        clearStorageDataDirectory();
     }
     
     private static void removeAgentAuthFile() throws IOException {
@@ -68,35 +85,17 @@
         }
     }
 
+    /**
+     * Singleton sanity check test whether web-storage-service works OK.
+     * 
+     * @throws Exception
+     */
     @Test
     public void canRunWebStorageService() throws Exception {
-        if (isDevelopmentBuild()) {
-            // test setup
-            removeSetupCompleteStampFiles();
-            
-            // run the test methods
-            runThermostatSetup();
-            runWebStorageTest();
-        }
-        // otherwise service is not build so don't run the
-        // test.
-    }
-
-    private void runThermostatSetup() throws Exception {
-        Spawn setup = spawnScript(THERMOSTAT_DEV_SETUP_SCRIPT, new String[] {});
-        setup.expectClose();
-        String stdout = setup.getCurrentStandardOutContents();
-        // cp -v of thermostat-devsetup should produce this
-        assertTrue("was agent.auth copied?", stdout.contains("distribution/target/user-home/etc/agent.auth"));
-        assertTrue(stdout.contains("Thermostat setup complete!"));
-        assertTrue(stdout.contains("mongodevuser"));
-    }
-
-    private void runWebStorageTest() throws Exception {
         Map<String, String> testProperties = getVerboseModeProperties();
         SpawnResult spawnResult = spawnThermostatWithPropertiesSetAndGetProcess(testProperties, "web-storage-service");
         Spawn service = spawnResult.spawn;
-
+        
         try {
             service.expect("Agent started.");
         } finally {
@@ -110,7 +109,19 @@
                 // ignore if second try of stopping storage failed.
             }
         }
-
+        
         service.expectClose();
     }
+
+    /*
+     * This overwrites stock thermostat-users/roles.properties files. Therefore
+     * we back them up before we run the test.
+     */
+    private static void runThermostatDevSetup() throws Exception {
+        Spawn setup = spawnScript(THERMOSTAT_DEV_SETUP_SCRIPT, new String[] {});
+        setup.expectClose();
+        String stdout = setup.getCurrentStandardOutContents();
+        assertTrue(stdout.contains("Thermostat setup complete!"));
+        assertTrue(stdout.contains("mongodevuser"));
+    }
 }
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/IntegrationTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/IntegrationTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -42,12 +42,16 @@
 import java.io.File;
 import java.io.IOException;
 import java.lang.reflect.Field;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.NoSuchFileException;
+import java.nio.file.StandardOpenOption;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 import java.util.logging.Level;
 
 import com.redhat.thermostat.common.utils.StreamUtils;
@@ -115,11 +119,12 @@
 
     private static final String THERMOSTAT_SCRIPT = "thermostat";
     
-    private static void createUserThermostatHomeAndEtc() {
+    private static File createUserThermostatHomeAndEtc() {
         File userThHome = new File(getUserThermostatHome());
         userThHome.mkdir();
         File etcThHome = new File(userThHome, "etc");
         etcThHome.mkdir();
+        return etcThHome;
     }
     
     /**
@@ -198,6 +203,20 @@
         return testProperties;
     }
 
+    static protected void createAgentAuthFile(String userName, String password) throws IOException {
+        File etcHome = createUserThermostatHomeAndEtc();
+
+        List<String> lines = new ArrayList<>();
+        lines.add("username=" + userName);
+        lines.add("password=" + password);
+        Files.write(new File(etcHome, "agent.auth").toPath(), lines, StandardCharsets.UTF_8,
+                StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
+    }
+
+    protected void deleteAgentAuthFile() throws IOException {
+        Files.delete(new File(new File(getUserThermostatHome(), "etc"), "agent.auth").toPath());
+    }
+
     /* This is a mirror of paths from c.r.t.shared.Configuration */
 
     public static String getThermostatHome() {
@@ -255,12 +274,44 @@
         }
     }
 
+    /** pre-conditions:
+     *    storage must *NOT* be running.
+     *    No users set up
+     */
+    public static void addUserToStorage(String username, String password) throws Exception {
+        startStorage("--permitLocalhostException");
+
+        TimeUnit.SECONDS.sleep(3);
+
+        try {
+            ExpectJ mongo = new ExpectJ(TIMEOUT_IN_SECONDS);
+            Spawn mongoSpawn = mongo.spawn("mongo 127.0.0.1:27518/thermostat");
+            File createUser = new File(new File(getThermostatHome(), "lib"), "create-user.js");
+            String contents = new String(Files.readAllBytes(createUser.toPath()), StandardCharsets.UTF_8);
+            contents = contents.replaceAll("\\$USERNAME", username);
+            contents = contents.replaceAll("\\$PASSWORD", password);
+            mongoSpawn.send(contents);
+            mongoSpawn.send("quit();\n");
+            mongoSpawn.expectClose();
+
+            TimeUnit.SECONDS.sleep(3);
+
+        } finally {
+            stopStorage();
+        }
+    }
+
     public static Spawn spawnThermostat(String... args) throws IOException {
         return spawnThermostat(false, args);
     }
     
-    public static Spawn startStorage() throws Exception {
-        Spawn storage = spawnThermostat("storage", "--start", "--permitLocalhostException");
+    public static Spawn startStorage(String... extraArgs) throws Exception {
+        List<String> args = new ArrayList<>(Arrays.asList(new String[] { "storage", "--start", }));
+        if (extraArgs != null) {
+            args.addAll(Arrays.asList(extraArgs));
+        }
+
+        Spawn storage = spawnThermostat(args.toArray(new String[0]));
         try {
             storage.expect("pid:");
         } catch (IOException e) {
@@ -344,11 +395,6 @@
 
     }
 
-    protected static boolean isDevelopmentBuild() {
-        boolean isDevelBuild = Boolean.getBoolean("devel.build");
-        return isDevelBuild;
-    }
-
     /**
      * Kill the process and all its children, recursively. Sends SIGTERM.
      */
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/MongoQueriesTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/MongoQueriesTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -96,6 +96,9 @@
  */
 public class MongoQueriesTest extends IntegrationTest {
 
+    static final String USERNAME = "foobar";
+    static final String PASSWORD = "baz";
+
     private static class CountdownConnectionListener implements ConnectionListener {
 
         private final ConnectionStatus target;
@@ -122,8 +125,10 @@
 
     @BeforeClass
     public static void setUpOnce() throws Exception {
+        clearStorageDataDirectory();
         createFakeSetupCompleteFile();
-        clearStorageDataDirectory();
+        addUserToStorage(USERNAME, PASSWORD);
+
         startStorage();
 
         addCpuData(4);
@@ -135,6 +140,7 @@
 
         stopStorage();
         removeSetupCompleteStampFiles();
+        clearStorageDataDirectory();
     }
 
     /*
@@ -144,17 +150,15 @@
     private static BackingStorage getAndConnectStorage(ConnectionListener listener) {
         final String url = "mongodb://127.0.0.1:27518";
         StorageCredentials creds = new StorageCredentials() {
-
             @Override
             public String getUsername() {
-                return null;
+                return USERNAME;
             }
 
             @Override
             public char[] getPassword() {
-                return null;
+                return PASSWORD.toCharArray();
             }
-            
         };
         CommonPaths paths = mock(CommonPaths.class);
         File tmpFile = new File("/tmp");
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/StorageTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/StorageTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -81,6 +81,10 @@
 
     @Test
     public void testServiceStartAndKilling() throws Exception {
+        clearStorageDataDirectory();
+        addUserToStorage("foo", "bar");
+        createAgentAuthFile("foo", "bar");
+
         Map<String, String> testProperties = getVerboseModeProperties();
         SpawnResult spawnResult = spawnThermostatWithPropertiesSetAndGetProcess(testProperties, "service");
         Spawn service = spawnResult.spawn;
@@ -101,6 +105,7 @@
         service.stop();
         service.expectClose();
 
+        deleteAgentAuthFile();
     }
 
 }
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/VmCommandsTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/VmCommandsTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -51,10 +51,16 @@
 /** Integration tests for the various vm commands */
 public class VmCommandsTest extends IntegrationTest {
 
+    private static final String USERNAME = "foo";
+    private static final String PASSWORD = "bar";
+
     @BeforeClass
     public static void setUpOnce() throws Exception {
         createFakeSetupCompleteFile();
         clearStorageDataDirectory();
+        addUserToStorage(USERNAME, PASSWORD);
+        createAgentAuthFile(USERNAME, PASSWORD);
+
         startStorage();
 
         // TODO insert actual data into the database and test that
@@ -152,7 +158,7 @@
 
         shell.expect(SHELL_DISCONNECT_PROMPT);
         shell.send("list-vms -d " + storageURL + "\n");
-        handleAuthPrompt(shell, storageURL, "", "");
+        handleAuthPrompt(shell, storageURL, USERNAME, PASSWORD);
 
         shell.expect(SHELL_CONNECT_PROMPT);
 
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/WebAppTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/WebAppTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -51,8 +51,6 @@
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -65,7 +63,6 @@
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.eclipse.jetty.server.Server;
@@ -118,7 +115,6 @@
 
 import expectj.ExpectJ;
 import expectj.Spawn;
-import expectj.TimeoutException;
 
 /**
  * This test class starts up a mongod instance and a web storage instance
@@ -136,7 +132,7 @@
  * Please don't introduce any more sporadic test failures to this
  * integration test!!!
  */
-public class WebAppTest extends IntegrationTest {
+public class WebAppTest extends WebStorageUsingIntegrationTest {
 
     /*
      * Registry of descriptors this test needs to allow in order to avoid
@@ -242,37 +238,25 @@
     private static final String TEST_USER = "testuser";
     private static final String TEST_PASSWORD = "testpassword";
     private static final double EQUALS_DELTA = 0.00000000000001;
-    private static final String THERMOSTAT_USERS_FILE = getConfigurationDir() + "/thermostat-users.properties";
-    private static final String THERMOSTAT_ROLES_FILE = getConfigurationDir() + "/thermostat-roles.properties";
-    private static final String THERMOSTAT_WEB_AUTH_FILE = getConfigurationDir() + "/web.auth";
+    
     private static final String VM_ID1 = "vmId1";
     private static final String VM_ID2 = "vmId2";
     private static final String VM_ID3 = "vmId3";
 
     private static Server server;
     private static int port;
-    private static Path backupUsers;
-    private static Path backupRoles;
-    private static Path backupWebAuth;
+    
 
     @BeforeClass
     public static void setUpOnce() throws Exception {
         clearStorageDataDirectory();
 
-        backupUsers = Files.createTempFile("itest-backup-thermostat-users", "");
-        backupRoles = Files.createTempFile("itest-backup-thermostat-roles", "");
-        backupWebAuth = Files.createTempFile("itest-backup-webapp-auth", "");
-        backupRoles.toFile().deleteOnExit();
-        backupUsers.toFile().deleteOnExit();
-        backupWebAuth.toFile().deleteOnExit();
-        Files.copy(new File(THERMOSTAT_USERS_FILE).toPath(), backupUsers, StandardCopyOption.REPLACE_EXISTING);
-        Files.copy(new File(THERMOSTAT_ROLES_FILE).toPath(), backupRoles, StandardCopyOption.REPLACE_EXISTING);
-        Files.copy(new File(THERMOSTAT_WEB_AUTH_FILE).toPath(), backupWebAuth, StandardCopyOption.REPLACE_EXISTING);
+        backupOriginalCredentialsFiles();
 
         createFakeSetupCompleteFile();
         createFakeUserSetupDoneFile();
 
-        setupMongodbUser();
+        addUserToStorage(getMongodbUsername(), getMongodbPassword());
 
         startStorage();
 
@@ -285,7 +269,6 @@
         mongoSpawn.send("db[\"fake\"].insert({foo:\"bar\", baz: 1})\n");
         mongoSpawn.send("db[\"fake\"].findOne()\n");
         mongoSpawn.send("show collections\n");
-        mongoSpawn.send("show users\n");
 
         createWebAuthFile();
 
@@ -326,10 +309,9 @@
                     throw e;
                 } finally {
                     removeSetupCompleteStampFiles();
-                    Files.copy(backupUsers, new File(THERMOSTAT_USERS_FILE).toPath(), StandardCopyOption.REPLACE_EXISTING);
-                    Files.copy(backupRoles, new File(THERMOSTAT_ROLES_FILE).toPath(), StandardCopyOption.REPLACE_EXISTING);
-                    Files.copy(backupWebAuth, new File(THERMOSTAT_WEB_AUTH_FILE).toPath(), StandardCopyOption.REPLACE_EXISTING);
+                    restoreBackedUpCredentialsFiles();
                     System.out.println("RESTORED backed-up files!");
+                    clearStorageDataDirectory();
                 }
             }
         }
@@ -350,65 +332,6 @@
         }
     }
 
-    // PRE: storage started with --permitLocalhostException
-    private static void setupMongodbUser() throws Exception {
-        String mongodbUsername = getMongodbUsername();
-        String mongodbPassword = getMongodbPassword();
-
-        final String HOST = "127.0.0.1";
-        final String PORT = "27518";
-
-        try {
-            System.out.println("THERMOSTAT_HOME: " + getThermostatHome());
-            System.out.println("USER_THERMOSTAT_HOME: " + getUserThermostatHome());
-
-            // start mongod
-            startStorage();
-
-            System.out.println("Started mongod");
-            TimeUnit.SECONDS.sleep(3);
-
-            ExpectJ mongo = new ExpectJ(TIMEOUT_IN_SECONDS);
-            Spawn mongoSpawn = mongo.spawn("mongo " + HOST + ":" + PORT);
-            mongoSpawn.send("use thermostat\n");
-            mongoSpawn.send("var v = db.version()\n");
-            mongoSpawn.send("var minorMicro = v.substr(v.indexOf('.') + 1)\n");
-            mongoSpawn.send("var minorVersion = minorMicro.substr(0, minorMicro.indexOf('.'))\n");
-            mongoSpawn.send("if ( minorVersion <= 2 ) {");
-            mongoSpawn.send(String.format("db.addUser(\"%s\", \"%s\")", mongodbUsername, mongodbPassword));
-            mongoSpawn.send("} else {");
-            mongoSpawn.send("if ( minorVersion <= 4 ) {");
-            mongoSpawn.send(String.format("db.addUser({ user: \"%s\", pwd: \"%s\", roles: [ \"readWrite\" ] })",
-                    mongodbUsername, mongodbPassword));
-            mongoSpawn.send("} else {");
-            mongoSpawn.send(String.format("db.createUser({ user: \"%s\", pwd: \"%s\", roles: [ \"readWrite\" ] })",
-                    mongodbUsername, mongodbPassword));
-            mongoSpawn.send("}\n");
-            mongoSpawn.send("}\n");
-            mongoSpawn.send("quit()\n");
-            mongoSpawn.expectClose();
-
-            mongo = new ExpectJ(TIMEOUT_IN_SECONDS);
-            mongoSpawn = mongo.spawn("mongo " + HOST + ":" + PORT);
-            mongoSpawn.send("use thermostat\n");
-            mongoSpawn.expect("switched to db thermostat");
-            mongoSpawn.send(String.format("db.auth(\"%s\", \"%s\")\n", mongodbUsername, mongodbPassword));
-            mongoSpawn.expect("1");
-
-            // now insert some fake data and display some information that
-            // might be useful for post-mortem analysis if this test fails
-            mongoSpawn.send("db[\"fake\"].insert({foo:\"bar\", baz: 1})\n");
-            mongoSpawn.send("db[\"fake\"].findOne()\n");
-            mongoSpawn.send("show collections\n");
-            mongoSpawn.send("show users\n");
-            
-        } catch (TimeoutException | IOException e) {
-            throw e;
-        } finally {
-            stopStorage();
-        }
-    }
-
     private static void createWebAuthFile() throws IOException {
         System.out.println("WRITING auth file: " + getMongodbUsername() + "/" + getMongodbPassword());
         List<String> lines = new ArrayList<String>();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/WebStorageUsingIntegrationTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2012-2015 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.itest;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+
+public class WebStorageUsingIntegrationTest extends IntegrationTest {
+
+    protected static final String THERMOSTAT_USERS_FILE = getConfigurationDir() + "/thermostat-users.properties";
+    protected static final String THERMOSTAT_ROLES_FILE = getConfigurationDir() + "/thermostat-roles.properties";
+    protected static final String THERMOSTAT_WEB_AUTH_FILE = getConfigurationDir() + "/web.auth";
+    
+    private static Path backupUsers;
+    private static Path backupRoles;
+    private static Path backupWebAuth;
+    
+    protected static void backupOriginalCredentialsFiles() throws IOException {
+        backupUsers = Files.createTempFile("itest-backup-thermostat-users", "");
+        backupRoles = Files.createTempFile("itest-backup-thermostat-roles", "");
+        backupWebAuth = Files.createTempFile("itest-backup-webapp-auth", "");
+        backupRoles.toFile().deleteOnExit();
+        backupUsers.toFile().deleteOnExit();
+        backupWebAuth.toFile().deleteOnExit();
+        Files.copy(new File(THERMOSTAT_USERS_FILE).toPath(), backupUsers, StandardCopyOption.REPLACE_EXISTING);
+        Files.copy(new File(THERMOSTAT_ROLES_FILE).toPath(), backupRoles, StandardCopyOption.REPLACE_EXISTING);
+        Files.copy(new File(THERMOSTAT_WEB_AUTH_FILE).toPath(), backupWebAuth, StandardCopyOption.REPLACE_EXISTING);
+    }
+    
+    protected static void restoreBackedUpCredentialsFiles() throws IOException {
+        Files.copy(backupUsers, new File(THERMOSTAT_USERS_FILE).toPath(), StandardCopyOption.REPLACE_EXISTING);
+        Files.copy(backupRoles, new File(THERMOSTAT_ROLES_FILE).toPath(), StandardCopyOption.REPLACE_EXISTING);
+        Files.copy(backupWebAuth, new File(THERMOSTAT_WEB_AUTH_FILE).toPath(), StandardCopyOption.REPLACE_EXISTING);
+    }
+}
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/standalone/AllStandaloneTests.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/standalone/AllStandaloneTests.java	Tue Jun 23 10:16:17 2015 -0600
@@ -40,7 +40,6 @@
 import org.junit.runners.Suite;
 
 import com.redhat.thermostat.itest.CliTest;
-import com.redhat.thermostat.itest.PluginTest;
 import com.redhat.thermostat.itest.StorageConnectionTest;
 import com.redhat.thermostat.itest.StorageTest;
 import com.redhat.thermostat.itest.UserPluginsTest;
@@ -69,6 +68,7 @@
  *   $ mvn clean package 
  *   $ java -Dcom.redhat.thermostat.itest.thermostatHome=/path/to/thermostat/install \
  *            -Dcom.redhat.thermostat.itest.thermostatUserHome=$(echo ~/.thermostat) \
+ *            -Dthermostat.agent.verbose=true \
  *            -cp $(ls integration-tests/standalone/target/thermostat-integration-tests-standalone-*.jar)
  *            com.redhat.thermostat.itest.standalone.ItestRunner
  * </pre>
--- a/killvm/command/src/main/java/com/redhat/thermostat/killvm/command/internal/Activator.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/killvm/command/src/main/java/com/redhat/thermostat/killvm/command/internal/Activator.java	Tue Jun 23 10:16:17 2015 -0600
@@ -71,7 +71,7 @@
             public void dependenciesAvailable(Map<String, Object> services) {
                 AgentInfoDAO agentDao = (AgentInfoDAO) services.get(AgentInfoDAO.class.getName());
                 VmInfoDAO vmDao = (VmInfoDAO) services.get(VmInfoDAO.class.getName());
-                KillVMRequest request= (KillVMRequest) services.get(KillVMRequest.class.getName());
+                KillVMRequest request = (KillVMRequest) services.get(KillVMRequest.class.getName());
 
                 command.setAgentInfoDAO(agentDao);
                 command.setVmInfoDAO(vmDao);
--- a/killvm/command/src/test/java/com/redhat/thermostat/killvm/command/KillVmCommandTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/killvm/command/src/test/java/com/redhat/thermostat/killvm/command/KillVmCommandTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -85,7 +85,8 @@
     public void testKillLiveVM() throws CommandException, InterruptedException {
         String vmId = "liveVM";
 
-        VmInfo vmInfo = mock(VmInfo.class);
+        VmInfo vmInfo = new VmInfo("myAgent", vmId, 123, 0, 0, null, null, null, null, null, null, null, null, null,
+                null, null,0, "myUsername");
         when(vmInfoDAO.getVmInfo(any(VmId.class))).thenReturn(vmInfo);
 
         CommandContext ctx = createContext(vmId);
@@ -93,9 +94,7 @@
         setServices();
         cmd.run(ctx);
 
-        verify(request).sendKillVMRequestToAgent(any(AgentId.class), any(int.class), any(AgentInfoDAO.class), any
-                (RequestResponseListener
-                .class));
+        verify(request).sendKillVMRequestToAgent(any(AgentId.class), any(int.class), any(AgentInfoDAO.class), any(RequestResponseListener.class));
     }
 
     @Test(expected = CommandException.class)
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/ShellCommand.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/ShellCommand.java	Tue Jun 23 10:16:17 2015 -0600
@@ -37,17 +37,14 @@
 package com.redhat.thermostat.launcher.internal;
 
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Map;
-import java.util.Collection;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import jline.Terminal;
 import jline.TerminalFactory;
 import jline.console.ConsoleReader;
-import jline.console.completer.FileNameCompleter;
 import jline.console.history.FileHistory;
 import jline.console.history.History;
 import jline.console.history.PersistentHistory;
@@ -67,11 +64,6 @@
 import com.redhat.thermostat.shared.config.InvalidConfigurationException;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.storage.core.DbService;
-import jline.console.completer.AggregateCompleter;
-import jline.console.completer.ArgumentCompleter;
-import jline.console.completer.Completer;
-import jline.console.completer.StringsCompleter;
-import org.apache.commons.cli.Option;
 
 public class ShellCommand extends AbstractCommand {
 
@@ -159,7 +151,7 @@
     private void shellMainLoop(CommandContext ctx, History history, Terminal term) throws IOException, CommandException {
         ConsoleReader reader = new ConsoleReader(ctx.getConsole().getInput(), ctx.getConsole().getOutput(), term);
         if (reader.getCompleters().isEmpty() && commandInfoSource != null) {
-            setupTabCompletion(reader);
+            TabCompletion.setupTabCompletion(reader, commandInfoSource);
         }
         if (history != null) {
             reader.setHistory(history);
@@ -224,38 +216,5 @@
         this.commandInfoSource = source;
     }
 
-    private void setupTabCompletion(ConsoleReader reader) {
-        Collection<Completer> commands = new ArrayList<>();
-        Collection<String> options = new ArrayList<>();
-        Collection<Completer> completers = new ArrayList<>();
-        for (CommandInfo info : commandInfoSource.getCommandInfos()) {
-
-            if (info.getEnvironments().contains(Environment.SHELL)) {
-                commands.clear();
-                options.clear();
-                commands.add(new StringsCompleter(info.getName()));
-                for (Option option : (Collection<Option>) info.getOptions().getOptions()) {
-                    if (option.getLongOpt() != null) {
-                        options.add("--" + option.getLongOpt());
-                    }
-                    if (option.getOpt() != null) {
-                        options.add("-" + option.getOpt());
-                    }
-                }
-
-                if (info.needsFileTabCompletions()) {
-                    AggregateCompleter optionsAndFiles = new AggregateCompleter(new StringsCompleter(options), new FileNameCompleter());
-                    commands.add(optionsAndFiles);
-                } else {
-                    commands.add(new StringsCompleter(options));
-                }
-
-                completers.add(new ArgumentCompleter(new ArrayList<>(commands)));
-            }
-        }
-        AggregateCompleter aggregateCompleter = new AggregateCompleter(completers);
-        reader.addCompleter(aggregateCompleter);
-    }
-
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/TabCompletion.java	Tue Jun 23 10:16:17 2015 -0600
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2012-2015 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.launcher.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import com.redhat.thermostat.common.utils.LoggingUtils;
+import jline.console.ConsoleReader;
+import jline.console.completer.FileNameCompleter;
+import org.apache.commons.cli.Option;
+
+import static com.redhat.thermostat.launcher.internal.TreeCompleter.createStringNode;
+
+public class TabCompletion {
+
+    private static final String LONG_OPTION_PREFIX = "--";
+    private static final String SHORT_OPTION_PREFIX = "-";
+
+    public static void setupTabCompletion(ConsoleReader reader, CommandInfoSource commandInfoSource) {
+        List<String> logLevels = new ArrayList<>();
+
+        for (LoggingUtils.LogLevel level : LoggingUtils.LogLevel.values()) {
+            logLevels.add(level.getLevel().getName());
+        }
+
+        TreeCompleter treeCompleter = new TreeCompleter();
+        for (CommandInfo info : commandInfoSource.getCommandInfos()) {
+
+            if (info.getEnvironments().contains(Environment.SHELL)) {
+                String commandName = info.getName();
+                TreeCompleter.Node command = createStringNode(commandName);
+
+                for (Option option : (Collection<Option>) info.getOptions().getOptions()) {
+                    if (option.getLongOpt().equals("logLevel")) {
+                        setupLogLevelCompletion(logLevels, command, option);
+                    } else {
+                        setupDefaultCompletion(command, option);
+                    }
+
+                }
+
+                if (info.needsFileTabCompletions()) {
+                    TreeCompleter.Node files = new TreeCompleter.Node(new FileNameCompleter());
+                    files.setRestartNode(command);
+                    command.addBranch(files);
+                }
+                treeCompleter.addBranch(command);
+            }
+        }
+
+        reader.addCompleter(treeCompleter);
+    }
+
+    private static void setupDefaultCompletion(final TreeCompleter.Node command, final Option option) {
+        if (option.getLongOpt() != null) {
+            String optionLongName = LONG_OPTION_PREFIX + option.getLongOpt();
+            TreeCompleter.Node defaultNode = createStringNode(optionLongName);
+            defaultNode.setRestartNode(command);
+            command.addBranch(defaultNode);
+        }
+        if (option.getOpt() != null) {
+            String optionShortName = SHORT_OPTION_PREFIX + option.getOpt();
+            TreeCompleter.Node defaultNode = createStringNode(optionShortName);
+            defaultNode.setRestartNode(command);
+            command.addBranch(defaultNode);
+        }
+    }
+
+    private static void setupLogLevelCompletion( final List<String> logLevels, final TreeCompleter.Node command, final Option option) {
+        if (option.getLongOpt() != null) {
+            String optionLongName = LONG_OPTION_PREFIX + option.getLongOpt();
+            TreeCompleter.Node logLevelOption = createStringNode(optionLongName);
+            TreeCompleter.Node logLevelChoices = createStringNode(logLevels);
+            logLevelChoices.setRestartNode(command);
+            logLevelOption.addBranch(logLevelChoices);
+            command.addBranch(logLevelOption);
+        }
+        if (option.getOpt() != null) {
+            String optionShortName = SHORT_OPTION_PREFIX + option.getOpt();
+            TreeCompleter.Node logLevelOption = createStringNode(optionShortName);
+            TreeCompleter.Node logLevelChoices = createStringNode(logLevels);
+            logLevelChoices.setRestartNode(command);
+            logLevelOption.addBranch(logLevelChoices);
+            command.addBranch(logLevelOption);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/TreeCompleter.java	Tue Jun 23 10:16:17 2015 -0600
@@ -0,0 +1,295 @@
+/*
+ * Copyright 2012-2015 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.launcher.internal;
+
+import static java.util.Objects.requireNonNull;
+import static jline.console.completer.ArgumentCompleter.ArgumentDelimiter;
+import static jline.console.completer.ArgumentCompleter.ArgumentList;
+import static jline.console.completer.ArgumentCompleter.WhitespaceArgumentDelimiter;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import jline.console.completer.Completer;
+import jline.console.completer.StringsCompleter;
+
+public class TreeCompleter implements Completer {
+
+    private final ArgumentDelimiter delimiter;
+
+    private final List<Node> branches;
+
+    private Node currentNode;
+    private ArgumentList list;
+
+    public static final int NOT_FOUND = -1;
+    private static final String EMPTY_SPACE = " ";
+    private static final Node START_NODE = null;
+
+    /**
+     * This method adds a child branch to the start node
+     * @param child a node containing a completer
+     */
+    public void addBranch(final Node child) {
+        branches.add(child);
+    }
+
+    /**
+     * This method adds child branches to the start node
+     * @param branchList a list of nodes containing a completer each
+     */
+    public void addBranches(final List<Node> branchList) {
+        for (final Node branch : branchList) {
+            addBranch(branch);
+        }
+    }
+
+    /**
+     * @return the start node branches
+     */
+    public List<Node> getBranches() {
+        return branches;
+    }
+
+    public TreeCompleter() {
+        delimiter = new WhitespaceArgumentDelimiter();
+        branches = new ArrayList<>();
+    }
+
+    /**
+     * This method is called when attempting to tab complete
+     * @param buffer the input that will be tab completed
+     * @param cursorPosition the position of the cursorPosition within the buffer
+     * @param candidates the list of possible completions will get filled when found
+     * @return the new position of the cursorPosition, a return of NOT_FOUND means no completion
+     * was found or completion is finished, resulting in no change of the cursorPosition position
+     */
+    @Override
+    public int complete(final String buffer, final int cursorPosition, final List<CharSequence> candidates) {
+        requireNonNull(candidates);
+
+        if (cursorPosition > buffer.length()) {
+            return NOT_FOUND;
+        }
+        final String currentBuffer = buffer.substring(0, cursorPosition);
+        refreshCompleter();
+
+        list = delimiter.delimit(currentBuffer, cursorPosition);
+        if (list.getCursorArgumentIndex() < 0) {
+            return NOT_FOUND;
+        }
+
+        int position = cursorPosition;
+        currentNode = traverseBranches(currentBuffer, Arrays.asList(list.getArguments()));
+        final List<Completer> completers = getAllCompleters(currentNode);
+
+        //Complete possible arguments off a space or the current word up to the cursor
+        if (currentBuffer.endsWith(EMPTY_SPACE)) {
+            completeList(candidates, completers);
+        } else {
+            if (currentNode != START_NODE && currentNode.getBranches().isEmpty()) {
+                currentNode = currentNode.getRestartNode();
+            }
+            final List<Completer> relevantCompleters = filterRelevantCompleters(completers, list.getCursorArgument());
+            for (final Completer completer : relevantCompleters) {
+                position = getInlinedCursorPosition(completer, candidates);
+            }
+        }
+
+        return position;
+    }
+
+    private int getInlinedCursorPosition(final Completer completer, final List<CharSequence> candidates) {
+        int cursor = completer.complete(list.getCursorArgument(), list.getArgumentPosition(), candidates);
+        return cursor + list.getBufferPosition() - list.getArgumentPosition();
+    }
+
+    private void refreshCompleter() {
+        currentNode = START_NODE;
+    }
+
+    private Node traverseBranches(final String currentBuffer, final List<String> arguments) {
+        Node resultNode = START_NODE;
+        for (final Iterator<String> it = arguments.iterator(); it.hasNext();) {
+            final String arg = it.next();
+            if (!it.hasNext() && !currentBuffer.endsWith(" ")) {
+                //inline completion detected
+                break;
+            }
+            final int branchIndex = getBranchIndex(arg, getPossibleMatches(resultNode));
+            if (branchIndex != NOT_FOUND) {
+                resultNode = findBranches(resultNode).get(branchIndex);
+            }
+        }
+        return resultNode;
+    }
+
+    private void completeList(final List<CharSequence> candidates, final List<Completer> completerList) {
+        for (final Completer completer : completerList) {
+            completer.complete(null, 0, candidates);
+        }
+    }
+
+    private List<Completer> getAllCompleters(final Node currentNode) {
+        final List<Completer> completersFromBranches = new ArrayList<>();
+        for (final Node node : findBranches(currentNode)) {
+            completersFromBranches.add(node.getCompleter());
+        }
+        return completersFromBranches;
+    }
+
+    private List<Node> getChildNodesFromRestartNode(final Node node) {
+        final List<Node> childrenNodeList;
+        if (node.getRestartNode() == START_NODE) {
+            childrenNodeList = getBranches();
+        } else {
+            childrenNodeList = node.getRestartNode().getBranches();
+        }
+        currentNode = node.getRestartNode();
+        return childrenNodeList;
+    }
+
+    private List<Completer> filterRelevantCompleters(final List<Completer> completersFromBranches, final String cursorArgument) {
+        final List<Completer> completers = new ArrayList<>();
+        for (final Completer branchCompleter : completersFromBranches) {
+            final List<CharSequence> candidates = new LinkedList<>();
+            branchCompleter.complete(cursorArgument, 0, candidates);
+            if (!candidates.isEmpty()) {
+                completers.add(branchCompleter);
+            }
+        }
+        return completers;
+    }
+
+    private List<CharSequence> findCompletions(final Completer branchCompleter) {
+        final List<CharSequence> candidates = new LinkedList<>();
+        branchCompleter.complete(null, 0, candidates);
+        return candidates;
+    }
+
+    private int getBranchIndex(final String argument, final List<List<CharSequence>> listOfPossibleMatches) {
+        for (final List<CharSequence> possibleMatches : listOfPossibleMatches) {
+            for (final CharSequence word : possibleMatches) {
+                if (word.toString().trim().equals(argument.trim())) {
+                    return listOfPossibleMatches.indexOf(possibleMatches);
+                }
+            }
+        }
+        return NOT_FOUND;
+    }
+
+    private List<List<CharSequence>> getPossibleMatches(final Node node) {
+        final List<List<CharSequence>> possibleMatches = new LinkedList<>();
+        for (final Node branch : findBranches(node)) {
+            possibleMatches.add(findCompletions(branch.getCompleter()));
+        }
+        return possibleMatches;
+    }
+
+    private List<Node> findBranches(final Node node) {
+        if (node == START_NODE) {
+            return getBranches();
+        } else {
+            if (node.getBranches().isEmpty()) {
+                return getChildNodesFromRestartNode(node);
+            }
+            return node.getBranches();
+        }
+    }
+
+    /**
+     * A class to be used with the TreeCompleter
+     * Each node contains a completer that will be used by the TreeCompleter
+     * to check completion. Each node contains branches that are possible
+     * paths for the completion to follow. Once completion has reached a node
+     * with no branches it will use the restartNode to continue to find
+     * any further completions.
+     */
+    public static class Node {
+        private final Completer completer;
+        private final List<Node> branches;
+        private Node restartNode = START_NODE;
+
+        public Node(final Completer data) {
+            requireNonNull(data);
+            this.completer = data;
+            branches = new ArrayList<>();
+        }
+
+        public void addBranch(final Node branch) {
+            branches.add(branch);
+        }
+
+        public Completer getCompleter() {
+            return completer;
+        }
+
+        public List<Node> getBranches() {
+            return branches;
+        }
+
+        public void setRestartNode(final Node restartNode) {
+            this.restartNode = restartNode;
+        }
+
+        public Node getRestartNode() {
+            return restartNode;
+        }
+
+    }
+
+    /**
+     * A helper method to quickly create a node containing a strings completer
+     * @param strings the strings to be completed by the strings completer
+     * @return the node containing the string completer
+     */
+    public static Node createStringNode(String... strings) {
+        return new Node(new StringsCompleter(strings));
+    }
+
+    /**
+     * A helper method to quickly create a node containing a strings completer
+     * @param strings the strings to be completed by the strings completer
+     * @return the node containing the string completer
+     */
+    public static Node createStringNode(List<String> strings) {
+        return new Node(new StringsCompleter(strings));
+    }
+}
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/ShellCommandTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/ShellCommandTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -566,7 +566,7 @@
         createTempFile(filename + "12345678");
 
         TestCommandContextFactory ctxFactory = new TestCommandContextFactory(bundleContext);
-        ctxFactory.setInput("validate --dbUrl -a -l -d " + dir.getAbsolutePath() + File.separator + "testFil\t\nexit\n");
+        ctxFactory.setInput("validate --dbUrl -d " + dir.getAbsolutePath() + File.separator + "testFil\t\nexit\n");
         Arguments args = new SimpleArguments();
         CommandContext ctx = ctxFactory.createContext(args);
         cmd.run(ctx);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/TreeCompleterTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -0,0 +1,482 @@
+/*
+ * Copyright 2012-2015 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.launcher.internal;
+
+import static com.redhat.thermostat.launcher.internal.TreeCompleter.createStringNode;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.redhat.thermostat.common.cli.CommandException;
+import jline.console.completer.FileNameCompleter;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TreeCompleterTest {
+
+    private File testDir;
+    private TreeCompleter tree;
+
+    @Before
+    public void setUp() throws IOException {
+        tree = new TreeCompleter();
+
+        testDir = new File(System.getProperty("java.io.tmpdir") + File.separator + "treecompleter");
+        testDir.deleteOnExit();
+        testDir.mkdirs();
+        setupTreeCompleter();
+    }
+
+    @Test
+    public void testInlineCompletion() throws IOException, CommandException {
+        List<String> candidates = completeBuffer("other");
+
+        assertTrue(candidates.contains("otherCommand"));
+    }
+
+    @Test
+    public void testBaseIndexCompletion() throws IOException, CommandException {
+        List<String> candidates = completeBuffer("");
+
+        assertTrue(candidates.contains("otherCommand"));
+        assertTrue(candidates.contains("command1"));
+        assertTrue(candidates.contains("command2"));
+        assertTrue(candidates.contains("anotherCommand"));
+    }
+
+    @Test
+    public void testVeryLongCompletion() throws IOException, CommandException {
+        String[] longChainOfWords = { "otherCommand", "create", "a", "long", "chain", "of", "tab", "completing", "words"};
+        List<String> chain = new ArrayList<String>();
+        Collections.addAll(chain, longChainOfWords);
+        String firstPart = "";
+        for (String word : chain) {
+            firstPart += word + " ";
+            List<String> tabOutput = completeBuffer(firstPart + " ");
+
+            if (chain.indexOf(word) == 0) {
+                assertTrue(tabOutput.contains("list"));
+                assertTrue(tabOutput.contains("create"));
+                assertTrue(tabOutput.contains("start"));
+            } else if (chain.indexOf(word) == chain.size() - 1) {
+                assertTrue(tabOutput.contains("otherCommand"));
+                assertTrue(tabOutput.contains("anotherCommand"));
+                assertTrue(tabOutput.contains("command1"));
+                assertTrue(tabOutput.contains("command2"));
+            } else {
+                assertTrue(tabOutput.contains(chain.get(chain.indexOf(word) + 1)));
+            }
+
+        }
+    }
+
+    @Test
+    public void testVeryLongCompletionRestartedTwice() throws IOException, CommandException {
+        String[] longChainOfWords = { "otherCommand", "create", "a", "long", "chain", "of", "tab", "completing", "words"};
+        List<String> chain = new ArrayList<String>();
+        Collections.addAll(chain, longChainOfWords);
+        Collections.addAll(chain, longChainOfWords);
+        Collections.addAll(chain, longChainOfWords);
+        String firstPart = "";
+        for (String word : chain) {
+            firstPart += word + " ";
+            List<String> tabOutput = completeBuffer(firstPart + " ");
+
+            if (chain.indexOf(word) == 0) {
+                assertTrue(tabOutput.contains("list"));
+                assertTrue(tabOutput.contains("create"));
+                assertTrue(tabOutput.contains("start"));
+            } else if (chain.indexOf(word) == chain.size() - 1) {
+                assertTrue(tabOutput.contains("otherCommand"));
+                assertTrue(tabOutput.contains("anotherCommand"));
+                assertTrue(tabOutput.contains("command1"));
+                assertTrue(tabOutput.contains("command2"));
+            } else {
+                assertTrue(tabOutput.contains(chain.get(chain.indexOf(word) + 1)));
+            }
+
+        }
+    }
+
+    @Test
+    public void testRestartIndexOtherThanZero() throws CommandException {
+        String[] input = { "command1", "list", "nothing"};
+        List<String> chain = new ArrayList<String>();
+        Collections.addAll(chain, input);
+        String firstPart = "";
+        for (String word : chain) {
+            firstPart += word + " ";
+            List<String> tabOutput = completeBuffer(firstPart + " ");
+
+            if (chain.indexOf(word) == 0) {
+                assertTrue(tabOutput.contains("list"));
+                assertTrue(tabOutput.contains("create"));
+                assertTrue(tabOutput.contains("delete"));
+            } else if (chain.indexOf(word) == chain.size() - 1) {
+                assertTrue(tabOutput.contains("list"));
+                assertTrue(tabOutput.contains("create"));
+                assertTrue(tabOutput.contains("delete"));
+            } else {
+                assertTrue(tabOutput.contains(chain.get(chain.indexOf(word) + 1)));
+            }
+
+        }
+    }
+
+    @Test
+    public void testCompletionOfSameTextInDifferentBranchesReturnsDifferentResults() throws CommandException {
+        List<String> firstOutput = completeBuffer("otherCommand list ");
+        List<String> secondOutput = completeBuffer("command1 list ");
+
+        assertTrue(firstOutput.contains("parts"));
+        assertTrue(firstOutput.contains("assemblies"));
+        assertTrue(firstOutput.contains("degreesOfFreedom"));
+        assertTrue(firstOutput.contains("bolts"));
+        assertTrue(firstOutput.contains("tools"));
+
+        assertFalse(firstOutput.contains("everything"));
+        assertFalse(firstOutput.contains("nothing"));
+        assertFalse(firstOutput.contains("firstHalf"));
+        assertFalse(firstOutput.contains("secondHalf"));
+
+        assertTrue(secondOutput.contains("everything"));
+        assertTrue(secondOutput.contains("nothing"));
+        assertTrue(secondOutput.contains("firstHalf"));
+        assertTrue(secondOutput.contains("secondHalf"));
+
+        assertFalse(secondOutput.contains("parts"));
+        assertFalse(secondOutput.contains("assemblies"));
+        assertFalse(secondOutput.contains("degreesOfFreedom"));
+        assertFalse(secondOutput.contains("bolts"));
+        assertFalse(secondOutput.contains("tools"));
+    }
+
+    @Test
+    public void testRestartIndexOne() throws CommandException {
+        List<String> output = completeBuffer("command2 stop yes ");
+
+        assertTrue(output.contains("find"));
+        assertTrue(output.contains("climb"));
+        assertTrue(output.contains("stop"));
+    }
+
+    @Test
+    public void testRestartIndexTwo() throws CommandException {
+        List<String> output = completeBuffer("command1 list firstHalf ");
+
+        assertTrue(output.contains("everything"));
+        assertTrue(output.contains("nothing"));
+        assertTrue(output.contains("firstHalf"));
+        assertTrue(output.contains("secondHalf"));
+    }
+
+    @Test
+    public void testParametersDoNotInterfereWithInlineCompletion() throws CommandException {
+        List<String> inlineOutput = completeBuffer("command1 blah list blue red green notValid second");
+
+        assertTrue(inlineOutput.contains("secondHalf"));
+    }
+
+    @Test
+    public void testParametersDoNotInterfereWithCompletion() throws CommandException {
+        List<String> output = completeBuffer("otherCommand blue green list red purple ");
+
+        assertTrue(output.contains("parts"));
+        assertTrue(output.contains("assemblies"));
+        assertTrue(output.contains("degreesOfFreedom"));
+        assertTrue(output.contains("bolts"));
+        assertTrue(output.contains("tools"));
+    }
+
+    @Test
+    public void testFileCompletion() throws CommandException, IOException {
+        String filename1 = "testFilesNow";
+        String filename2 = "document";
+        String filename3 = "musicFile";
+        String filename4 = "slideshow";
+
+        createTempFile(filename1);
+        createTempFile(filename2);
+        createTempFile(filename3);
+        createTempFile(filename4);
+
+        List<String> output = completeBuffer("command2 find " + testDir.getAbsolutePath() + File.separator);
+
+        assertTrue(output.contains(filename1));
+        assertTrue(output.contains(filename2));
+        assertTrue(output.contains(filename3));
+        assertTrue(output.contains(filename4));
+    }
+
+    @Test
+    public void testFileCompletionInline() throws CommandException, IOException {
+        String filename1 = "testFilesNow";
+        String filename2 = "document";
+        String filename3 = "musicFile";
+        String filename4 = "slideshow";
+
+        createTempFile(filename1);
+        createTempFile(filename2);
+        createTempFile(filename3);
+        createTempFile(filename4);
+
+        List<String> output = completeBuffer("command2 find " + testDir.getAbsolutePath() + File.separator);
+
+        assertTrue(output.contains(filename2));
+    }
+
+    @Test
+    public void testCursorInMiddleOfWord() {
+        List<String> output = completeBuffer("command1 ", 3);
+
+        assertTrue(output.contains("command1"));
+        assertTrue(output.contains("command2"));
+        assertFalse(output.contains("otherCommand"));
+        assertFalse(output.contains("anotherCommand"));
+    }
+
+    @Test
+    public void testCursorBeforeWord() {
+        List<String> output = completeBuffer("command1 ", 0);
+
+        assertTrue(output.contains("command1"));
+        assertTrue(output.contains("command2"));
+        assertTrue(output.contains("otherCommand"));
+        assertTrue(output.contains("anotherCommand"));
+    }
+
+    @Test
+    public void testCursorBeforeSpace() {
+        List<String> output = completeBuffer("command1 ", 8);
+
+        assertTrue(output.contains("command1"));
+        assertFalse(output.contains("command2"));
+        assertFalse(output.contains("otherCommand"));
+        assertFalse(output.contains("anotherCommand"));
+    }
+
+    @Test
+    public void testCursorAtSpace() {
+        List<String> output = completeBuffer("command1 ", 9);
+
+        assertTrue(output.contains("list"));
+        assertTrue(output.contains("create"));
+        assertTrue(output.contains("delete"));
+    }
+
+    @Test
+    public void testCursorAtSpaceBeforeAnotherWord() {
+        List<String> output = completeBuffer("command1 list", 9);
+
+        assertTrue(output.contains("list"));
+        assertTrue(output.contains("create"));
+        assertTrue(output.contains("delete"));
+    }
+
+    @Test
+    public void testCursorInMiddleOfSecondWord() {
+        List<String> output = completeBuffer("command1 list", 11);
+
+        assertTrue(output.contains("list"));
+        assertFalse(output.contains("create"));
+        assertFalse(output.contains("delete"));
+    }
+
+    @Test
+    public void testCursorLongerThanBufferLength() {
+        List<CharSequence> candidates = new LinkedList<>();
+
+        int cursor = tree.complete("command1 ", 503, candidates);
+        List<String> convertedCandidates = convertToStringList(candidates);
+        assertEquals(TreeCompleter.NOT_FOUND, cursor);
+        assertTrue(convertedCandidates.isEmpty());
+    }
+
+    private List<String> completeBuffer(String buffer) {
+        return completeBuffer(buffer, buffer.length());
+    }
+
+    private List<String> completeBuffer(String buffer, int cursor) {
+        List<CharSequence> candidates = new LinkedList<>();
+
+        tree.complete(buffer, cursor, candidates);
+        List<String> convertedCandidates = convertToStringList(candidates);
+        return convertedCandidates;
+    }
+
+    private List<String> convertToStringList(List<CharSequence> list) {
+        List<String> stringsList = new ArrayList<>();
+        for (CharSequence chars : list) {
+            stringsList.add(chars.toString().trim());
+        }
+        return stringsList;
+    }
+
+    private void createTempFile(String name) throws IOException {
+        File file = new File(testDir, name);
+        file.deleteOnExit();
+        file.createNewFile();
+    }
+
+    public void setupTreeCompleter() throws IOException {
+
+        List<TreeCompleter.Node> commands = new ArrayList<>();
+        TreeCompleter.Node command1 = createStringNode("command1");
+        {
+            TreeCompleter.Node create = createStringNode("create");
+            TreeCompleter.Node delete = createStringNode("delete");
+            TreeCompleter.Node list = createStringNode("list");
+            {
+                TreeCompleter.Node everything = createStringNode("everything");
+                TreeCompleter.Node nothing = createStringNode("nothing");
+                nothing.setRestartNode(command1);
+                TreeCompleter.Node firstHalf = createStringNode("firstHalf");
+                firstHalf.setRestartNode(list);
+                TreeCompleter.Node secondHalf = createStringNode("secondHalf");
+                secondHalf.setRestartNode(list); // maybe secondHalf
+                list.addBranch(everything);
+                list.addBranch(nothing);
+                list.addBranch(firstHalf);
+                list.addBranch(secondHalf);
+            }
+            command1.addBranch(list);
+            command1.addBranch(create);
+            command1.addBranch(delete);
+        }
+
+        TreeCompleter.Node command2 = createStringNode("command2");
+        {
+            TreeCompleter.Node find = createStringNode("find");
+            {
+                TreeCompleter.Node files = new TreeCompleter.Node(new FileNameCompleter());
+                find.addBranch(files);
+            }
+            TreeCompleter.Node climb = createStringNode("climb");
+            TreeCompleter.Node stop = createStringNode("stop");
+            {
+                TreeCompleter.Node yes = createStringNode("yes");
+                yes.setRestartNode(command2);
+                TreeCompleter.Node no = createStringNode("no");
+                stop.addBranch(yes);
+                stop.addBranch(no);
+            }
+            command2.addBranch(find);
+            command2.addBranch(climb);
+            command2.addBranch(stop);
+        }
+        TreeCompleter.Node otherCommand = createStringNode("otherCommand");
+        {
+            TreeCompleter.Node list = createStringNode("list");
+            {
+                TreeCompleter.Node parts = createStringNode("parts");
+                TreeCompleter.Node assemblies = createStringNode("assemblies");
+                assemblies.setRestartNode(otherCommand);
+                TreeCompleter.Node degreesOfFreedom = createStringNode("degreesOfFreedom");
+                degreesOfFreedom.setRestartNode(list);
+                TreeCompleter.Node bolts = createStringNode("bolts");
+                bolts.setRestartNode(list);
+                TreeCompleter.Node tools = createStringNode("tools");
+                tools.setRestartNode(list);
+                list.addBranch(parts);
+                list.addBranch(assemblies);
+                list.addBranch(degreesOfFreedom);
+                list.addBranch(bolts);
+                list.addBranch(tools);
+            }
+            TreeCompleter.Node create = createStringNode("create");
+            {
+                TreeCompleter.Node a = createStringNode("a");
+                TreeCompleter.Node longNode = createStringNode("long");
+                TreeCompleter.Node chain = createStringNode("chain");
+                TreeCompleter.Node of = createStringNode("of");
+                TreeCompleter.Node tab = createStringNode("tab");
+                TreeCompleter.Node completing = createStringNode("completing");
+                TreeCompleter.Node words = createStringNode("words");
+                completing.addBranch(words);
+                tab.addBranch(completing);
+                of.addBranch(tab);
+                chain.addBranch(of);
+                longNode.addBranch(chain);
+                a.addBranch(longNode);
+                create.addBranch(a);
+            }
+            TreeCompleter.Node start = createStringNode("start");
+            {
+                TreeCompleter.Node yes = createStringNode("yes");
+                yes.setRestartNode(otherCommand);
+                TreeCompleter.Node no = createStringNode("no");
+                start.addBranch(yes);
+                start.addBranch(no);
+            }
+            otherCommand.addBranch(list);
+            otherCommand.addBranch(create);
+            otherCommand.addBranch(start);
+        }
+        TreeCompleter.Node anotherCommand = createStringNode("anotherCommand");
+        {
+            TreeCompleter.Node list = createStringNode("list");
+            {
+                TreeCompleter.Node everything = createStringNode("everything");
+                TreeCompleter.Node nothing = createStringNode("nothing");
+                TreeCompleter.Node firstHalf = createStringNode("firstHalf");
+                TreeCompleter.Node secondHalf = createStringNode("secondHalf");
+                TreeCompleter.Node twentyFifthToSeventyFifthPart = createStringNode("25to75part");
+                list.addBranch(everything);
+                list.addBranch(nothing);
+                list.addBranch(firstHalf);
+                list.addBranch(secondHalf);
+                list.addBranch(twentyFifthToSeventyFifthPart);
+            }
+            anotherCommand.addBranch(list);
+        }
+
+        commands.add(command1);
+        commands.add(command2);
+        commands.add(otherCommand);
+        commands.add(anotherCommand);
+
+        tree.addBranches(commands);
+    }
+
+}
--- a/numa/client-swing/src/test/java/com/redhat/thermostat/numa/client/swing/internal/NumaPanelTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/numa/client-swing/src/test/java/com/redhat/thermostat/numa/client/swing/internal/NumaPanelTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -46,12 +46,15 @@
 import org.fest.swing.fixture.Containers;
 import org.fest.swing.fixture.FrameFixture;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.core.views.BasicView;
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class NumaPanelTest {
 
--- a/pom.xml	Thu Jun 04 01:14:43 2015 -0500
+++ b/pom.xml	Tue Jun 23 10:16:17 2015 -0600
@@ -96,94 +96,23 @@
         <surefire-argline>-XX:-UseSplitVerifier -XX:MaxPermSize=300m</surefire-argline>
       </properties>
     </profile>
-    <!-- Development settings for web.xml. Release builds should
-         have the "environment.type=release" property. -->
     <profile>
-      <id>dev-build</id>
+      <!-- Temporary workaround for PR2282: Caciocavallo tests fail with JDK 8 u40 -->
+      <id>java-8-skip-cacio-tests</id>
       <activation>
-        <property>
-          <name>environment.type</name>
-          <value>!release</value>
-        </property>
+        <jdk>1.8</jdk>
       </activation>
-      <properties>
-        <!--
-             The devel.build property is used in the WebAppTest integration
-             test. For this test to work for devel builds, we need
-             to perform actual setup of the below mongodb credentials.
-             Why? Because the snippet for a devel build has the
-             storage username/password NOT commented out in the
-             web.xml of the web archive. That results in MongoConnection
-             of WebAppTest use non-null creds. If those are used mongodb
-             connections would fail with auth-fail if the creds are not
-             set up.
-        -->
-        <devel.build>true</devel.build>
-        <agent.dev.username> agent-tester </agent.dev.username>
-        <agent.dev.password> tester </agent.dev.password>
-        <mongodb.dev.username> mongodevuser </mongodb.dev.username>
-        <mongodb.dev.password> mongodevpassword </mongodb.dev.password>
-        <!-- used in web.xml of the war artifact -->
-        <web.war.backingstorage.username.snippet>
-storage.username=${mongodb.dev.username}
-        </web.war.backingstorage.username.snippet>
-        <!-- used in web.xml of the war artifact -->
-        <web.war.backingstorage.password.snippet>
-storage.password=${mongodb.dev.password}
-        </web.war.backingstorage.password.snippet>
-        <!--
-             Used in thermostat-users.properties. We define two users.
-             One client user and one agent user.
-        -->
-        <dev.users.snippet>
-${agent.dev.username}=${agent.dev.password}
-client-tester=tester
-        </dev.users.snippet>
-        <dev.roles.snippet>
-# Roles for our two dev users
-${agent.dev.username}=thermostat-agent, thermostat-grant-write-files-all-agent
-# client-tester needs thermostat-purge role for clean-data command to work
-client-tester=thermostat-grant-read-all-client, thermostat-cmdc, thermostat-purge
-# Agent recursive role
-thermostat-agent = thermostat-cmdc-verify, \
-                   thermostat-login, \
-                   thermostat-prepare-statement, \
-                   thermostat-purge, \
-                   thermostat-register-category, \
-                   thermostat-realm, \
-                   thermostat-save-file, \
-                   thermostat-write
-# Grant agent to write any file
-thermostat-grant-write-files-all-agent = thermostat-files-grant-write-filename-ALL
-                   
-# Client recursive role (granting a client to read all data + all files)
-thermostat-grant-read-all-client = thermostat-agents-grant-read-agentId-ALL, \
-                    thermostat-cmdc-generate, \
-                    thermostat-hosts-grant-read-hostname-ALL, \
-                    thermostat-load-file, \
-                    thermostat-login, \
-                    thermostat-prepare-statement, \
-                    thermostat-query, \
-                    thermostat-realm, \
-                    thermostat-register-category, \
-                    thermostat-vms-grant-read-username-ALL, \
-                    thermostat-vms-grant-read-vmId-ALL, \
-                    thermostat-files-grant-read-filename-ALL, \
-                    thermostat-write
-# Grants all command channel operations
-thermostat-cmdc = thermostat-cmdc-grant-garbage-collect, \
-                  thermostat-cmdc-grant-dump-heap, \
-                  thermostat-cmdc-grant-thread-harvester, \
-                  thermostat-cmdc-grant-killvm, \
-                  thermostat-cmdc-grant-profile-vm, \
-                  thermostat-cmdc-grant-ping, \
-                  thermostat-cmdc-grant-jmx-toggle-notifications
-        </dev.roles.snippet>
-        <agent.auth.snippet>
-username=${agent.dev.username}
-password=${agent.dev.password}
-        </agent.auth.snippet>
-      </properties>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <configuration>
+              <excludedGroups>com.redhat.thermostat.annotations.internal.CacioTest</excludedGroups>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
     </profile>
     <profile>
       <id>skip-license-check-on-skip-tests</id>
@@ -223,6 +152,7 @@
     <thermostat.build.directory>target</thermostat.build.directory>
     <thermostat.java.version>1.7</thermostat.java.version>
     <thermostat.home>${user.dir}/distribution/target/image/</thermostat.home>
+    <user.thermostat.home>$HOME/.thermostat</user.thermostat.home>
     <!-- used in systemd service files. Set this to the username thermostat should run
          under when run via systemd. -->
     <thermostat.system.user>thermostat</thermostat.system.user>
@@ -246,9 +176,9 @@
          See the main thermostat bash script where this property is
          used. -->
     <jcommon.version>1.0.17</jcommon.version>
-    <mongo-driver.version>2.11.4</mongo-driver.version>
+    <mongo-driver.version>2.13.2</mongo-driver.version>
     <!-- the OSGi Bundle-Version; should match the manifest in the jar -->
-    <mongo-driver.osgi-version>2.11.4.RELEASE</mongo-driver.osgi-version>
+    <mongo-driver.osgi-version>2.13.2.RELEASE</mongo-driver.osgi-version>
     <commons-beanutils.version>1.8.3</commons-beanutils.version>
     <commons-cli.version>1.2</commons-cli.version>
     <commons-io.version>2.4</commons-io.version>
@@ -293,26 +223,11 @@
          to change to a newer version, unless you abolutely have to. -->
     <javax.servlet.version>2.5</javax.servlet.version>
 
-    <!-- used in web.xml of the war artifact -->
-    <web.war.backingstorage.username.snippet>
-#storage.username=thermostat-mongodb-user
-    </web.war.backingstorage.username.snippet>
-    <!-- used in web.xml of the war artifact -->
-    <web.war.backingstorage.password.snippet>
-#storage.password=supersecrit
-    </web.war.backingstorage.password.snippet>
-    <!--
-         Used in thermostat-users.properties and
-         thermostat-roles.properties respectively. We don't define
-         users or roles for release builds. Hence, those
-         empty property definitions.
-    -->
-    <dev.users.snippet /> <!-- intentionally empty -->
-    <dev.roles.snippet /> <!-- intentionally empty -->
-    <agent.auth.snippet /> <!-- intentionally empty -->
     <!-- see web/common/pom.xml for an example as to how this is used -->
     <surefire-perftests-exclusion>com.redhat.thermostat.testutils.PerformanceTest</surefire-perftests-exclusion>
     <surefire-argline /> <!-- intentionally empty -->
+    <mongodb.dev.username> mongodevuser </mongodb.dev.username>
+    <mongodb.dev.password> mongodevpassword </mongodb.dev.password>
   </properties>
 
   <modules>
@@ -350,9 +265,6 @@
     <module>thermostat-plugin-validator</module>
     <module>validate-command</module>
     <module>config</module>
-    <!-- pom-only artifact for reducing duplication
-         of deps across dev/release build profiles -->
-    <module>build-deps</module>
     <!-- development related modules -->
     <module>integration-tests</module>
     <module>dev</module>
--- a/storage/cli/src/main/java/com/redhat/thermostat/storage/cli/internal/MongoProcessRunner.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/storage/cli/src/main/java/com/redhat/thermostat/storage/cli/internal/MongoProcessRunner.java	Tue Jun 23 10:16:17 2015 -0600
@@ -52,6 +52,7 @@
 import com.redhat.thermostat.common.tools.ApplicationException;
 import com.redhat.thermostat.common.utils.LoggedExternalProcess;
 import com.redhat.thermostat.common.utils.LoggingUtils;
+import com.redhat.thermostat.common.utils.StringUtils;
 import com.redhat.thermostat.service.process.UnixProcessUtilities;
 import com.redhat.thermostat.shared.config.InvalidConfigurationException;
 import com.redhat.thermostat.shared.locale.LocalizedString;
@@ -179,6 +180,8 @@
         List<String> commands = null;
         commands = getStartupCommand(dbVersion);
         
+        logger.log(Level.FINEST, "Executing mongo: " + StringUtils.join(" ", commands));
+
         display(translator.localize(LocaleResources.STARTING_STORAGE_SERVER));
         
         LoggedExternalProcess process = new LoggedExternalProcess(commands);
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/AgentId.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/AgentId.java	Tue Jun 23 10:16:17 2015 -0600
@@ -37,32 +37,12 @@
 package com.redhat.thermostat.storage.core;
 
 /**
+ * This class uniquely identifies a Thermostat agent
  *
  */
-public class AgentId {
-    String uuid;
+public class AgentId extends Id {
 
     public AgentId(String id) {
-        this.uuid = id;
-    }
-
-    public String get() {
-        return uuid;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        AgentId agentId = (AgentId) o;
-
-        return uuid.equals(agentId.uuid);
-
-    }
-
-    @Override
-    public int hashCode() {
-        return uuid.hashCode();
+        super(id);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/Id.java	Tue Jun 23 10:16:17 2015 -0600
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012-2015 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.storage.core;
+
+import java.util.Objects;
+import java.util.UUID;
+
+/**
+ *
+ */
+public class Id {
+    private String id;
+
+    public Id() {
+        id = UUID.randomUUID().toString();
+    }
+
+    public Id(String id) {
+        this.id = Objects.requireNonNull(id);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Id other = (Id) o;
+        return Objects.equals(this.id, other.get());
+    }
+
+    public String get() {
+        return id;
+    }
+
+    @Override
+    public int hashCode() {
+        return id != null ? id.hashCode() : 0;
+    }
+}
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/QueuedStorage.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/QueuedStorage.java	Tue Jun 23 10:16:17 2015 -0600
@@ -287,7 +287,7 @@
             Cursor<T> result = queryDelegate.execute();
             long end = System.nanoTime();
             String msg = String.format(TimedStatement.DB_READ_FORMAT, descriptor);
-            logger.log(LoggingUtils.PERFLOG, perfLogFormatter.format(LogTag.STORAGE_BACKING_PROXIED, msg, (end - start)));
+            logger.log(LoggingUtils.LogLevel.PERFLOG.getLevel(), perfLogFormatter.format(LogTag.STORAGE_BACKING_PROXIED, msg, (end - start)));
             return result;
         }
         
@@ -316,7 +316,7 @@
                     int retval = write.doApply();
                     long end = System.nanoTime();
                     String msg = String.format(TimedStatement.DB_WRITE_FORMAT, retval, descriptor);
-                    logger.log(LoggingUtils.PERFLOG, perfLogFormatter.format(LogTag.STORAGE_BACKING_PROXIED, msg, (end - start)));
+                    logger.log(LoggingUtils.LogLevel.PERFLOG.getLevel(), perfLogFormatter.format(LogTag.STORAGE_BACKING_PROXIED, msg, (end - start)));
                 }
                 
             });
@@ -379,7 +379,7 @@
             Cursor<T> result = stmtDelegate.executeQuery();
             long end = System.nanoTime();
             String msg = String.format(DB_READ_FORMAT, descriptor);
-            logger.log(LoggingUtils.PERFLOG, perfLogFormatter.format(LogTag.STORAGE_FRONT_END, msg, (end - start)));
+            logger.log(LoggingUtils.LogLevel.PERFLOG.getLevel(), perfLogFormatter.format(LogTag.STORAGE_FRONT_END, msg, (end - start)));
             return result;
         }
         
@@ -395,7 +395,7 @@
                         int retval = d.doExecute();
                         long end = System.nanoTime();
                         String msg = String.format(DB_WRITE_FORMAT, retval, descriptor);
-                        logger.log(LoggingUtils.PERFLOG, perfLogFormatter.format(LogTag.STORAGE_FRONT_END, msg, (end - start)));
+                        logger.log(LoggingUtils.LogLevel.PERFLOG.getLevel(), perfLogFormatter.format(LogTag.STORAGE_FRONT_END, msg, (end - start)));
                     } catch (StatementExecutionException e) {
                         // There isn't much we can do in case of invalid
                         // patch or the likes. Log it and move on.
@@ -510,7 +510,7 @@
         this.delegate = delegate;
         this.fileExecutor = fileExecutor;
         this.isBackingStorageInProxy = !(delegate instanceof SecureStorage) && Boolean.getBoolean(Constants.IS_PROXIED_STORAGE);
-        this.isTimedStatements = LoggingUtils.getEffectiveLogLevel(logger).intValue() <= LoggingUtils.PERFLOG.intValue();
+        this.isTimedStatements = LoggingUtils.getEffectiveLogLevel(logger).intValue() <= LoggingUtils.LogLevel.PERFLOG.getLevel().intValue();
         // set up queue counting executor if so requested
         if (isTimedStatements) {
             LogTag logTag = (isBackingStorageInProxy ? LogTag.STORAGE_BACKING_PROXIED : LogTag.STORAGE_FRONT_END);
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/VmId.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/VmId.java	Tue Jun 23 10:16:17 2015 -0600
@@ -37,16 +37,12 @@
 package com.redhat.thermostat.storage.core;
 
 /**
+ * This class uniquely identifies a Java Virtual Machine
  *
  */
-public class VmId {
-    String uuid;
+public class VmId extends Id {
 
     public VmId(String id) {
-        this.uuid = id;
-    }
-
-    public String get() {
-        return uuid;
+        super(id);
     }
 }
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/BeanAdapter.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/BeanAdapter.java	Tue Jun 23 10:16:17 2015 -0600
@@ -40,6 +40,7 @@
 import com.redhat.thermostat.storage.core.Category;
 import com.redhat.thermostat.storage.core.Cursor;
 import com.redhat.thermostat.storage.core.DescriptorParsingException;
+import com.redhat.thermostat.storage.core.Id;
 import com.redhat.thermostat.storage.core.PreparedStatement;
 import com.redhat.thermostat.storage.core.StatementDescriptor;
 import com.redhat.thermostat.storage.core.StatementExecutionException;
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/Criterion.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/Criterion.java	Tue Jun 23 10:16:17 2015 -0600
@@ -36,6 +36,8 @@
 
 package com.redhat.thermostat.storage.core.experimental.statement;
 
+import com.redhat.thermostat.storage.core.Id;
+
 /**
  *
  */
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/Id.java	Thu Jun 04 01:14:43 2015 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright 2012-2015 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat 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 for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.storage.core.experimental.statement;
-
-import java.util.UUID;
-
-/**
- *
- */
-public class Id {
-    private String id;
-
-    public Id() {
-        id = UUID.randomUUID().toString();
-    }
-
-    public Id(String id) {
-        this.id = id;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        Id sessionID = (Id) o;
-
-        if (id != null ? !id.equals(sessionID.id) : sessionID.id != null)
-            return false;
-
-        return true;
-    }
-
-    public String get() {
-        return id;
-    }
-
-    @Override
-    public int hashCode() {
-        return id != null ? id.hashCode() : 0;
-    }
-}
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/LimitCriterion.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/LimitCriterion.java	Tue Jun 23 10:16:17 2015 -0600
@@ -36,6 +36,8 @@
 
 package com.redhat.thermostat.storage.core.experimental.statement;
 
+import com.redhat.thermostat.storage.core.Id;
+
 /**
  *
  */
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/Query.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/Query.java	Tue Jun 23 10:16:17 2015 -0600
@@ -36,6 +36,7 @@
 
 package com.redhat.thermostat.storage.core.experimental.statement;
 
+import com.redhat.thermostat.storage.core.Id;
 import com.redhat.thermostat.storage.model.Pojo;
 import java.util.ArrayList;
 import java.util.Collections;
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/QueryValues.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/QueryValues.java	Tue Jun 23 10:16:17 2015 -0600
@@ -40,6 +40,8 @@
 import java.util.List;
 import java.util.Map;
 
+import com.redhat.thermostat.storage.core.Id;
+
 /**
  *
  */
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/SortCriterion.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/SortCriterion.java	Tue Jun 23 10:16:17 2015 -0600
@@ -36,6 +36,8 @@
 
 package com.redhat.thermostat.storage.core.experimental.statement;
 
+import com.redhat.thermostat.storage.core.Id;
+
 /**
  *
  */
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/WhereCriterion.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/experimental/statement/WhereCriterion.java	Tue Jun 23 10:16:17 2015 -0600
@@ -38,6 +38,8 @@
 
 import java.util.Objects;
 
+import com.redhat.thermostat.storage.core.Id;
+
 /**
  *
  */
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/CountingDecorator.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/CountingDecorator.java	Tue Jun 23 10:16:17 2015 -0600
@@ -97,7 +97,7 @@
             
         });
         String msg = String.format(QUEUE_SIZE_FORMAT, queueLength.get());
-        logger.log(LoggingUtils.PERFLOG, perfLogFormatter.format(logTag, msg));
+        logger.log(LoggingUtils.LogLevel.PERFLOG.getLevel(), perfLogFormatter.format(logTag, msg));
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/storage/core/src/test/java/com/redhat/thermostat/storage/core/AgentIdTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012-2015 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.storage.core;
+
+public class AgentIdTest extends IdTest {
+
+    @Override
+    protected AgentId createId(String id) { return new AgentId(id); }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/storage/core/src/test/java/com/redhat/thermostat/storage/core/IdTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012-2015 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.storage.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class IdTest {
+
+    protected Id fooId1;
+    protected Id fooId2;
+    protected Id barId;
+
+    protected Id createId(String id) { return new Id(id); }
+
+    @Before
+    public void setup() {
+        fooId1 = createId("foo");
+        fooId2 = createId("foo");
+        barId = createId("bar");
+    }
+
+    @Test
+    public void testEquals() {
+        assertTrue(fooId1.equals(fooId1));
+        assertTrue(fooId1.equals(fooId2));
+    }
+
+    @Test
+    public void testNotEquals() {
+        assertFalse(fooId1.equals(null));
+        assertFalse(fooId1.equals(barId));
+    }
+
+    @Test
+    public void testEqualsHaveIdenticalHashcode() {
+        assertEquals(fooId1, fooId2);
+
+        assertEquals(fooId1.hashCode(), fooId1.hashCode());
+        assertEquals(fooId1.hashCode(), fooId2.hashCode());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/storage/core/src/test/java/com/redhat/thermostat/storage/core/VmIdTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012-2015 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.storage.core;
+
+public class VmIdTest extends IdTest {
+
+    @Override
+    protected VmId createId(String id) { return new VmId(id); }
+}
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/core/experimental/statement/BeanAdapterBuilderTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/storage/core/src/test/java/com/redhat/thermostat/storage/core/experimental/statement/BeanAdapterBuilderTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -37,6 +37,7 @@
 package com.redhat.thermostat.storage.core.experimental.statement;
 
 import com.redhat.thermostat.storage.core.DescriptorParsingException;
+import com.redhat.thermostat.storage.core.Id;
 import com.redhat.thermostat.storage.core.StatementDescriptor;
 import com.redhat.thermostat.storage.internal.statement.StatementDescriptorTester;
 import java.util.ArrayList;
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/core/experimental/statement/BeanAdapterTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/storage/core/src/test/java/com/redhat/thermostat/storage/core/experimental/statement/BeanAdapterTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -37,6 +37,7 @@
 package com.redhat.thermostat.storage.core.experimental.statement;
 
 import com.redhat.thermostat.storage.core.Cursor;
+import com.redhat.thermostat.storage.core.Id;
 import com.redhat.thermostat.storage.core.PreparedStatement;
 import com.redhat.thermostat.storage.core.StatementDescriptor;
 import com.redhat.thermostat.storage.core.Storage;
--- a/storage/core/src/test/java/com/redhat/thermostat/storage/core/experimental/statement/QueryValuesTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/storage/core/src/test/java/com/redhat/thermostat/storage/core/experimental/statement/QueryValuesTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -44,6 +44,8 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import com.redhat.thermostat.storage.core.Id;
+
 public class QueryValuesTest {
 
     private Query query;
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/MongoStorageProvider.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/MongoStorageProvider.java	Tue Jun 23 10:16:17 2015 -0600
@@ -63,7 +63,7 @@
     @Override
     public Storage createStorage() {
         MongoStorage storage = new MongoStorage(url, creds, sslConf);
-        if (LoggingUtils.getEffectiveLogLevel(LoggingUtils.getLogger(MongoStorageProvider.class)).intValue() <= LoggingUtils.PERFLOG.intValue()) {
+        if (LoggingUtils.getEffectiveLogLevel(LoggingUtils.getLogger(MongoStorageProvider.class)).intValue() <= LoggingUtils.LogLevel.PERFLOG.getLevel().intValue()) {
             PerformanceLogFormatterBuilder builder = PerformanceLogFormatterBuilder.create();
             PerformanceLogFormatter lf = builder.setLoggedTimeUnit(TimeUnit.NANOSECONDS)
                                               .build();
--- a/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoConnectionTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoConnectionTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -261,14 +261,6 @@
         }
         assertEquals(23452, addr.getPort());
         assertEquals("127.0.1.1", addr.getHost());
-
-        connection = new MongoConnection("fluff://willnotwork.com:23452", creds, sslConf);
-        try {
-            connection.getServerAddress();
-            fail("should not have been able to parse address");
-        } catch (UnknownHostException e) {
-            // pass
-        }
     }
 
     @PrepareForTest({ MongoConnection.class })
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/DistributionInformation.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/DistributionInformation.java	Tue Jun 23 10:16:17 2015 -0600
@@ -66,7 +66,13 @@
     // package-private for testing
     static DistributionInformation get(EtcOsRelease etcOsRelease, LsbRelease lsbRelease) {
         try {
-            return etcOsRelease.getDistributionInformation();
+            DistributionInformation etcOsDistroInfo = etcOsRelease.getDistributionInformation();
+            // if both name and version are unknown defer to lsb fallback
+            if (!DistributionInformation.UNKNOWN_NAME.equals(etcOsDistroInfo.getName()) &&
+                !DistributionInformation.UNKNOWN_VERSION.equals(etcOsDistroInfo.getVersion())) {
+                return etcOsDistroInfo;
+            }
+            logger.log(Level.FINE, "/etc/os-release existing, but does not contain useful info");
         } catch (IOException e) {
             // Log only at level FINE, since we have the LSB fallback
             logger.log(Level.FINE, "unable to use os-release", e);
--- a/system-backend/src/main/java/com/redhat/thermostat/backend/system/EtcOsRelease.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/system-backend/src/main/java/com/redhat/thermostat/backend/system/EtcOsRelease.java	Tue Jun 23 10:16:17 2015 -0600
@@ -44,6 +44,7 @@
 
 public class EtcOsRelease implements DistributionInformationSource {
 
+    private static final String EMPTY_STRING = "";
     private static final String OS_RELEASE = "/etc/os-release";
     private final String osReleaseFile;
     
@@ -72,10 +73,15 @@
     }
 
     public DistributionInformation getFromOsRelease(BufferedReader reader) throws IOException {
-        String name = "Linux";
         String version = DistributionInformation.UNKNOWN_VERSION;
+        String name = DistributionInformation.UNKNOWN_NAME;
         String line = null;
         while ((line = reader.readLine()) != null) {
+            // skip whitespace only lines
+            line = line.trim();
+            if (line.equals(EMPTY_STRING)) {
+                continue;
+            }
             if (line.matches("^NAME *=.*")) {
                 name = readShellVariable(line);
             }
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/DistributionInformationTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/DistributionInformationTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -37,7 +37,10 @@
 package com.redhat.thermostat.backend.system;
 
 import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
+import java.io.IOException;
 import java.util.logging.Handler;
 import java.util.logging.Logger;
 
@@ -115,6 +118,23 @@
         assertEquals(DistributionInformation.UNKNOWN_NAME, info.getName());
         assertEquals(DistributionInformation.UNKNOWN_VERSION, info.getVersion());
     }
+    
+    @Test
+    public void verifyFallbackToLsbWhenEtcOsReturnsUnknown() throws IOException {
+        EtcOsRelease mockEtcOsRelease = mock(EtcOsRelease.class);
+        DistributionInformation mockDistro = mock(DistributionInformation.class);
+        when(mockEtcOsRelease.getDistributionInformation()).thenReturn(mockDistro);
+        when(mockDistro.getName()).thenReturn(DistributionInformation.UNKNOWN_NAME);
+        when(mockDistro.getVersion()).thenReturn(DistributionInformation.UNKNOWN_VERSION);
+        
+        LsbRelease mockLsbRelease = mock(LsbRelease.class);
+        DistributionInformation mockLsbDistro = mock(DistributionInformation.class);
+        when(mockLsbRelease.getDistributionInformation()).thenReturn(mockLsbDistro);
+        
+        DistributionInformation info = DistributionInformation.get(mockEtcOsRelease, mockLsbRelease);
+        assertSame("Expected lsb info to be used since etc returns unknown",
+                   mockLsbDistro, info);
+    }
 
     private void assertTestHandlerRegistered() {
         assertNotNull(logger);
--- a/system-backend/src/test/java/com/redhat/thermostat/backend/system/EtcOsReleaseTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/system-backend/src/test/java/com/redhat/thermostat/backend/system/EtcOsReleaseTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -87,6 +87,23 @@
         assertEquals("12.1 (Asparagus)", info.getVersion());
     }
     
+    /**
+     * DistributionInformation falls back on LSB when /etc/os-release contains
+     * inconclusive content (empty in this case). It should not return some
+     * info as "Linux".
+     * 
+     * @throws IOException
+     */
+    @Test
+    public void testEmpty() throws IOException {
+        String output = "";
+        BufferedReader reader = new BufferedReader(new StringReader(output));
+        
+        DistributionInformation info = new EtcOsRelease().getFromOsRelease(reader);
+        assertEquals(DistributionInformation.UNKNOWN_NAME, info.getName());
+        assertEquals(DistributionInformation.UNKNOWN_VERSION, info.getVersion());
+    }
+    
     @Test
     public void getDistributionInformationThrowsIOExceptionIfFileNotThere() {
         EtcOsRelease etcOsRelease = new EtcOsRelease(NOT_EXISTING_OS_RELEASE_FILE);
--- a/thread/client-swing/src/test/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadViewTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/thread/client-swing/src/test/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadViewTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -36,6 +36,7 @@
 
 package com.redhat.thermostat.thread.client.swing.impl;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.swing.UIDefaults;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.thread.client.common.locale.LocaleResources;
@@ -61,6 +62,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class SwingThreadViewTest {
 
--- a/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoImpl.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDaoImpl.java	Tue Jun 23 10:16:17 2015 -0600
@@ -49,7 +49,7 @@
 import com.redhat.thermostat.storage.core.VmRef;
 import com.redhat.thermostat.storage.core.experimental.statement.BeanAdapter;
 import com.redhat.thermostat.storage.core.experimental.statement.BeanAdapterBuilder;
-import com.redhat.thermostat.storage.core.experimental.statement.Id;
+import com.redhat.thermostat.storage.core.Id;
 import com.redhat.thermostat.storage.core.experimental.statement.Query;
 import com.redhat.thermostat.storage.core.experimental.statement.QueryValues;
 import com.redhat.thermostat.storage.core.experimental.statement.ResultHandler;
--- a/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/statement/SessionQueries.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/statement/SessionQueries.java	Tue Jun 23 10:16:17 2015 -0600
@@ -36,8 +36,13 @@
 
 package com.redhat.thermostat.thread.dao.impl.statement;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import com.redhat.thermostat.storage.core.Id;
 import com.redhat.thermostat.storage.core.experimental.statement.FieldDescriptor;
-import com.redhat.thermostat.storage.core.experimental.statement.Id;
 import com.redhat.thermostat.storage.core.experimental.statement.LimitCriterion;
 import com.redhat.thermostat.storage.core.experimental.statement.Query;
 import com.redhat.thermostat.storage.core.experimental.statement.SortCriterion;
@@ -45,10 +50,6 @@
 import com.redhat.thermostat.storage.core.experimental.statement.TypeMapper;
 import com.redhat.thermostat.storage.core.experimental.statement.WhereCriterion;
 import com.redhat.thermostat.thread.model.ThreadSession;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
 
 /**
  *
--- a/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/statement/StateQueries.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/statement/StateQueries.java	Tue Jun 23 10:16:17 2015 -0600
@@ -37,7 +37,7 @@
 package com.redhat.thermostat.thread.dao.impl.statement;
 
 import com.redhat.thermostat.storage.core.experimental.statement.FieldDescriptor;
-import com.redhat.thermostat.storage.core.experimental.statement.Id;
+import com.redhat.thermostat.storage.core.Id;
 import com.redhat.thermostat.storage.core.experimental.statement.LimitCriterion;
 import com.redhat.thermostat.storage.core.experimental.statement.Query;
 import com.redhat.thermostat.storage.core.experimental.statement.SortCriterion;
--- a/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/statement/SummaryQuery.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/statement/SummaryQuery.java	Tue Jun 23 10:16:17 2015 -0600
@@ -37,7 +37,7 @@
 package com.redhat.thermostat.thread.dao.impl.statement;
 
 import com.redhat.thermostat.storage.core.experimental.statement.FieldDescriptor;
-import com.redhat.thermostat.storage.core.experimental.statement.Id;
+import com.redhat.thermostat.storage.core.Id;
 import com.redhat.thermostat.storage.core.experimental.statement.LimitCriterion;
 import com.redhat.thermostat.storage.core.experimental.statement.Query;
 import com.redhat.thermostat.storage.core.experimental.statement.SortCriterion;
--- a/thread/collector/src/main/java/com/redhat/thermostat/thread/model/SessionID.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/model/SessionID.java	Tue Jun 23 10:16:17 2015 -0600
@@ -36,7 +36,7 @@
 
 package com.redhat.thermostat.thread.model;
 
-import com.redhat.thermostat.storage.core.experimental.statement.Id;
+import com.redhat.thermostat.storage.core.Id;
 
 /**
  *
--- a/vm-classstat/client-swing/src/test/java/com/redhat/thermostat/vm/classstat/client/swing/VmClassStatPanelTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/vm-classstat/client-swing/src/test/java/com/redhat/thermostat/vm/classstat/client/swing/VmClassStatPanelTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -51,10 +51,13 @@
 import org.fest.swing.edt.GuiTask;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.storage.model.DiscreteTimeData;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class VmClassStatPanelTest {
 
--- a/vm-gc/remote-collector-client-swing/src/test/java/com/redhat/thermostat/gc/remote/client/swing/ToolbarGCButtonTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/vm-gc/remote-collector-client-swing/src/test/java/com/redhat/thermostat/gc/remote/client/swing/ToolbarGCButtonTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -57,12 +57,15 @@
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.swing.components.HeaderPanel;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 import com.redhat.thermostat.gc.remote.client.common.RequestGCAction;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class ToolbarGCButtonTest {
 
--- a/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/HeapDetailsSwingTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/HeapDetailsSwingTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -58,14 +58,14 @@
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.swing.EdtHelper;
 import com.redhat.thermostat.shared.locale.LocalizedString;
-import com.redhat.thermostat.vm.heap.analysis.client.swing.internal.HeapDetailsSwing;
-import com.redhat.thermostat.vm.heap.analysis.client.swing.internal.HistogramPanel;
-import com.redhat.thermostat.vm.heap.analysis.client.swing.internal.ObjectDetailsPanel;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class HeapDetailsSwingTest {
 
--- a/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/HeapDumpListViewTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/HeapDumpListViewTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -59,8 +59,10 @@
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
 import com.redhat.thermostat.vm.heap.analysis.client.core.HeapDumpListView;
@@ -68,6 +70,7 @@
 
 import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class HeapDumpListViewTest {
 
--- a/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/HeapSwingViewTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/HeapSwingViewTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -48,7 +48,6 @@
 import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
 
 import org.fest.swing.annotation.GUITest;
-import org.fest.swing.core.Robot;
 import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
 import org.fest.swing.edt.GuiActionRunner;
 import org.fest.swing.edt.GuiTask;
@@ -65,8 +64,10 @@
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.swing.components.OverlayPanel;
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
@@ -79,6 +80,7 @@
 import com.redhat.thermostat.vm.heap.analysis.common.HeapDump;
 import com.redhat.thermostat.vm.heap.analysis.common.model.HeapInfo;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class HeapSwingViewTest {
 
--- a/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/ObjectDetailsPanelTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/ObjectDetailsPanelTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -64,17 +64,19 @@
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.client.swing.components.SearchField;
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
 import com.redhat.thermostat.vm.heap.analysis.client.core.HeapObjectUI;
 import com.redhat.thermostat.vm.heap.analysis.client.core.ObjectDetailsView.ObjectAction;
-import com.redhat.thermostat.vm.heap.analysis.client.swing.internal.ObjectDetailsPanel;
 import com.sun.tools.hat.internal.model.JavaClass;
 import com.sun.tools.hat.internal.model.JavaHeapObject;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class ObjectDetailsPanelTest {
 
--- a/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/ObjectRootsFrameTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/ObjectRootsFrameTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -60,16 +60,18 @@
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
 import com.redhat.thermostat.vm.heap.analysis.client.core.HeapObjectUI;
 import com.redhat.thermostat.vm.heap.analysis.client.core.ObjectRootsView;
 import com.redhat.thermostat.vm.heap.analysis.client.core.ObjectRootsView.Action;
-import com.redhat.thermostat.vm.heap.analysis.client.swing.internal.ObjectRootsFrame;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class ObjectRootsFrameTest {
 
--- a/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/stats/OverlayComponentTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/stats/OverlayComponentTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -60,10 +60,13 @@
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.vm.heap.analysis.common.HeapDump;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class OverlayComponentTest {
 
--- a/vm-heap-analysis/command/src/main/java/com/redhat/thermostat/vm/heap/analysis/command/internal/Activator.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/vm-heap-analysis/command/src/main/java/com/redhat/thermostat/vm/heap/analysis/command/internal/Activator.java	Tue Jun 23 10:16:17 2015 -0600
@@ -36,28 +36,64 @@
 
 package com.redhat.thermostat.vm.heap.analysis.command.internal;
 
+import java.util.Map;
+
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 
+import com.redhat.thermostat.client.command.RequestQueue;
+import com.redhat.thermostat.common.MultipleServiceTracker;
 import com.redhat.thermostat.common.cli.Command;
 import com.redhat.thermostat.common.cli.CommandRegistry;
 import com.redhat.thermostat.common.cli.CommandRegistryImpl;
+import com.redhat.thermostat.storage.dao.AgentInfoDAO;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
 
 public class Activator implements BundleActivator {
 
     private CommandRegistry reg;
+    private MultipleServiceTracker serviceTracker;
+    private DumpHeapCommand dumpHeapCommand = new DumpHeapCommand();
 
     @Override
     public void start(final BundleContext context) throws Exception {
         reg = new CommandRegistryImpl(context);
 
-        registerCommand("dump-heap", new DumpHeapCommand());
+        registerCommand("dump-heap", dumpHeapCommand);
         registerCommand("list-heap-dumps", new ListHeapDumpsCommand());
         registerCommand("save-heap-dump-to-file", new SaveHeapDumpToFileCommand());
         registerCommand("show-heap-histogram", new ShowHeapHistogramCommand());
         registerCommand("find-objects", new FindObjectsCommand());
         registerCommand("object-info", new ObjectInfoCommand());
         registerCommand("find-root", new FindRootCommand());
+
+        Class<?>[] serviceDeps = new Class<?>[] {
+                AgentInfoDAO.class,
+                VmInfoDAO.class,
+                RequestQueue.class,
+        };
+
+        serviceTracker = new MultipleServiceTracker(context, serviceDeps, new MultipleServiceTracker.Action() {
+            @Override
+            public void dependenciesAvailable(Map<String, Object> services) {
+                VmInfoDAO vmDao = (VmInfoDAO) services.get(VmInfoDAO.class.getName());
+                AgentInfoDAO agentDao = (AgentInfoDAO) services.get(AgentInfoDAO.class.getName());
+                RequestQueue queue = (RequestQueue) services.get(RequestQueue.class.getName());
+
+                dumpHeapCommand.setAgentInfoDAO(agentDao);
+                dumpHeapCommand.setVmInfoDAO(vmDao);
+                dumpHeapCommand.setRequestQueue(queue);
+            }
+
+            @Override
+            public void dependenciesUnavailable() {
+                dumpHeapCommand.setAgentInfoDAO(null);
+                dumpHeapCommand.setVmInfoDAO(null);
+                dumpHeapCommand.setRequestQueue(null);
+            }
+        });
+
+        serviceTracker.open();
     }
 
     private void registerCommand(String name, Command command) {
@@ -66,6 +102,7 @@
 
     @Override
     public void stop(BundleContext context) throws Exception {
+        serviceTracker.close();
         reg.unregisterCommands();
     }
     
--- a/vm-heap-analysis/command/src/main/java/com/redhat/thermostat/vm/heap/analysis/command/internal/DumpHeapCommand.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/vm-heap-analysis/command/src/main/java/com/redhat/thermostat/vm/heap/analysis/command/internal/DumpHeapCommand.java	Tue Jun 23 10:16:17 2015 -0600
@@ -38,18 +38,17 @@
 
 import java.util.concurrent.Semaphore;
 
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.ServiceReference;
-
 import com.redhat.thermostat.client.cli.HostVMArguments;
 import com.redhat.thermostat.client.command.RequestQueue;
 import com.redhat.thermostat.common.cli.AbstractCommand;
 import com.redhat.thermostat.common.cli.CommandContext;
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.shared.locale.Translate;
+import com.redhat.thermostat.storage.core.AgentId;
+import com.redhat.thermostat.storage.core.VmId;
 import com.redhat.thermostat.storage.dao.AgentInfoDAO;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
+import com.redhat.thermostat.storage.model.VmInfo;
 import com.redhat.thermostat.vm.heap.analysis.command.locale.LocaleResources;
 
 
@@ -57,24 +56,35 @@
 
     private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
 
-    private BundleContext context;
     private final DumpHeapHelper implementation;
 
+    private VmInfoDAO vmInfoDAO;
+    private AgentInfoDAO agentInfoDAO;
+    private RequestQueue queue;
+
     public DumpHeapCommand() {
-        this(FrameworkUtil.getBundle(DumpHeapCommand.class).getBundleContext(), new DumpHeapHelper());
+        this(new DumpHeapHelper());
     }
 
-    DumpHeapCommand(BundleContext context, DumpHeapHelper impl) {
-        this.context = context;
+    DumpHeapCommand(DumpHeapHelper impl) {
         this.implementation = impl;
     }
 
     @Override
     public void run(final CommandContext ctx) throws CommandException {
-        final HostVMArguments args = new HostVMArguments(ctx.getArguments());
+        requireNonNull(vmInfoDAO, translator.localize(LocaleResources.VM_SERVICE_UNAVAILABLE));
+        requireNonNull(agentInfoDAO, translator.localize(LocaleResources.AGENT_SERVICE_UNAVAILABLE));
+        requireNonNull(queue, translator.localize(LocaleResources.REQUEST_QUEUE_UNAVAILABLE));
+
+        final HostVMArguments args = new HostVMArguments(ctx.getArguments(), false, true);
+
+        VmId vmId = new VmId(args.getVM().getVmId());
+        final VmInfo vmInfo = vmInfoDAO.getVmInfo(vmId);
+        final AgentId agentId = new AgentId(vmInfo.getAgentId());
 
         final CommandException[] ex = new CommandException[1];
         final Semaphore s = new Semaphore(0);
+
         Runnable successHandler = new Runnable() {
             @Override
             public void run() {
@@ -82,32 +92,16 @@
                 s.release();
             }
         };
+
         Runnable errorHandler = new Runnable() {
             public void run() {
                 ex[0] = new CommandException(translator.localize(
-                        LocaleResources.HEAP_DUMP_ERROR, args.getHost()
-                                .getStringID(), args.getVM().getVmId()));
+                        LocaleResources.HEAP_DUMP_ERROR, vmInfo.getAgentId(), vmInfo.getVmId()));
                 s.release();
             }
         };
 
-        ServiceReference vmInfoRef = context.getServiceReference(VmInfoDAO.class.getName());
-        requireNonNull(vmInfoRef, translator.localize(LocaleResources.VM_SERVICE_UNAVAILABLE));
-        VmInfoDAO vmInfoDAO = (VmInfoDAO) context.getService(vmInfoRef);
-        
-        ServiceReference agentInfoRef = context.getServiceReference(AgentInfoDAO.class.getName());
-        requireNonNull(agentInfoRef, translator.localize(LocaleResources.AGENT_SERVICE_UNAVAILABLE));
-        AgentInfoDAO agentInfoDAO = (AgentInfoDAO) context.getService(agentInfoRef);
-        
-        ServiceReference requestQueueRef = context.getServiceReference(RequestQueue.class.getName());
-        requireNonNull(requestQueueRef, translator.localize(LocaleResources.REQUEST_QUEUE_UNAVAILABLE));
-        RequestQueue queue = (RequestQueue) context.getService(requestQueueRef);
-        
-        implementation.execute(vmInfoDAO, agentInfoDAO, args.getVM(), queue, successHandler, errorHandler);
-        
-        context.ungetService(vmInfoRef);
-        context.ungetService(agentInfoRef);
-        context.ungetService(requestQueueRef);
+        implementation.execute(vmInfoDAO, agentInfoDAO, agentId, vmId, queue, successHandler, errorHandler);
         
         try {
             s.acquire();
@@ -120,5 +114,17 @@
         }
     }
 
+    public void setVmInfoDAO(VmInfoDAO vmInfoDAO) {
+        this.vmInfoDAO = vmInfoDAO;
+    }
+
+    public void setAgentInfoDAO(AgentInfoDAO agentInfoDAO) {
+        this.agentInfoDAO = agentInfoDAO;
+    }
+
+    public void setRequestQueue(RequestQueue queue) {
+        this.queue = queue;
+    }
+
 }
 
--- a/vm-heap-analysis/command/src/main/java/com/redhat/thermostat/vm/heap/analysis/command/internal/DumpHeapHelper.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/vm-heap-analysis/command/src/main/java/com/redhat/thermostat/vm/heap/analysis/command/internal/DumpHeapHelper.java	Tue Jun 23 10:16:17 2015 -0600
@@ -44,8 +44,8 @@
 import com.redhat.thermostat.common.command.RequestResponseListener;
 import com.redhat.thermostat.common.command.Response;
 import com.redhat.thermostat.common.command.Response.ResponseType;
-import com.redhat.thermostat.storage.core.HostRef;
-import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.core.AgentId;
+import com.redhat.thermostat.storage.core.VmId;
 import com.redhat.thermostat.storage.dao.AgentInfoDAO;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
 import com.redhat.thermostat.storage.model.VmInfo;
@@ -82,24 +82,22 @@
 
     }
 
-    public void execute(VmInfoDAO vmInfoDAO, AgentInfoDAO agentInfoDAO, VmRef reference,
-            RequestQueue queue, Runnable heapDumpSuccessAction,
-            Runnable heapDumpFailureAction) {
+    public void execute(VmInfoDAO vmInfoDAO, AgentInfoDAO agentInfoDAO, AgentId agentId, VmId vmId,
+                        RequestQueue queue, Runnable heapDumpSuccessAction,
+                        Runnable heapDumpFailureAction) {
         // Get PID
-        VmInfo info = vmInfoDAO.getVmInfo(reference);
+        VmInfo info = vmInfoDAO.getVmInfo(vmId);
         int pid = info.getVmPid();
         
-        HostRef targetHostRef = reference.getHostRef();
-        InetSocketAddress target = agentInfoDAO.getAgentInformation(targetHostRef).getRequestQueueAddress();
+        InetSocketAddress target = agentInfoDAO.getAgentInformation(agentId).getRequestQueueAddress();
         Request req = new Request(RequestType.RESPONSE_EXPECTED, target);
         req.setReceiver(RECEIVER_CLASS_NAME);
         req.setParameter(Request.ACTION, CMD_CHANNEL_ACTION_NAME);
-        req.setParameter(VM_ID_PARAM, reference.getVmId());
+        req.setParameter(VM_ID_PARAM, vmId.get());
         req.setParameter(VM_PID_PARAM, String.valueOf(pid));
         req.addListener(new HeapDumpListener(heapDumpSuccessAction, heapDumpFailureAction));
 
         queue.putRequest(req);
-
     }
 
 }
--- a/vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/DumpHeapCommandTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/DumpHeapCommandTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -45,6 +45,7 @@
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
@@ -55,11 +56,12 @@
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.SimpleArguments;
 import com.redhat.thermostat.shared.locale.Translate;
-import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.core.AgentId;
+import com.redhat.thermostat.storage.core.VmId;
 import com.redhat.thermostat.storage.dao.AgentInfoDAO;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
+import com.redhat.thermostat.storage.model.VmInfo;
 import com.redhat.thermostat.test.TestCommandContextFactory;
-import com.redhat.thermostat.testutils.StubBundleContext;
 import com.redhat.thermostat.vm.heap.analysis.command.locale.LocaleResources;
 
 public class DumpHeapCommandTest {
@@ -68,14 +70,13 @@
             .createLocalizer();
 
     @Test
-    public void verifyAcuallyCallsWorker() throws CommandException {
+    public void verifyActuallyCallsWorker() throws CommandException {
         VmInfoDAO vmInfoDao = mock(VmInfoDAO.class);
         AgentInfoDAO agentInfoDao = mock(AgentInfoDAO.class);
         RequestQueue queue = mock(RequestQueue.class);
-        StubBundleContext context = new StubBundleContext();
-        context.registerService(VmInfoDAO.class, vmInfoDao, null);
-        context.registerService(AgentInfoDAO.class, agentInfoDao, null);
-        context.registerService(RequestQueue.class, queue, null);
+        VmInfo vmInfo = new VmInfo("myAgent", "foo", 123, 0, 0, null, null, null, null, null, null, null, null, null,
+                null, null,0, "myUsername");
+        when(vmInfoDao.getVmInfo(new VmId("foo"))).thenReturn(vmInfo);
 
         DumpHeapHelper impl = mock(DumpHeapHelper.class);
         final ArgumentCaptor<Runnable> successHandler = ArgumentCaptor
@@ -87,36 +88,39 @@
                 successHandler.getValue().run();
                 return null;
             }
-        }).when(impl).execute(eq(vmInfoDao), eq(agentInfoDao), any(VmRef.class), eq(queue),
+        }).when(impl).execute(eq(vmInfoDao), eq(agentInfoDao), any(AgentId.class), any(VmId.class), eq(queue),
                 successHandler.capture(), any(Runnable.class));
 
-        DumpHeapCommand command = new DumpHeapCommand(context, impl);
+        DumpHeapCommand command = new DumpHeapCommand(impl);
+
+        command.setVmInfoDAO(vmInfoDao);
+        command.setAgentInfoDAO(agentInfoDao);
+        command.setRequestQueue(queue);
 
         TestCommandContextFactory factory = new TestCommandContextFactory();
 
         SimpleArguments args = new SimpleArguments();
-        args.addArgument("hostId", "foo");
-        args.addArgument("vmId", "bar");
+        args.addArgument("vmId", "foo");
 
         command.run(factory.createContext(args));
 
-        verify(impl).execute(eq(vmInfoDao), eq(agentInfoDao), isA(VmRef.class), eq(queue),
+        verify(impl).execute(eq(vmInfoDao), eq(agentInfoDao), isA(AgentId.class), isA(VmId.class), eq(queue),
                 any(Runnable.class), any(Runnable.class));
         assertEquals("Done\n", factory.getOutput());
     }
 
     @Test
-    public void verifyNeedsHostAndVmId() throws CommandException {
+    public void verifyNeedsVmId() throws CommandException {
         VmInfoDAO vmInfoDao = mock(VmInfoDAO.class);
         AgentInfoDAO agentInfoDao = mock(AgentInfoDAO.class);
         RequestQueue queue = mock(RequestQueue.class);
-        StubBundleContext context = new StubBundleContext();
-        context.registerService(VmInfoDAO.class, vmInfoDao, null);
-        context.registerService(AgentInfoDAO.class, agentInfoDao, null);
-        context.registerService(RequestQueue.class, queue, null);
 
         DumpHeapHelper impl = mock(DumpHeapHelper.class);
-        DumpHeapCommand command = new DumpHeapCommand(context, impl);
+        DumpHeapCommand command = new DumpHeapCommand(impl);
+
+        command.setVmInfoDAO(vmInfoDao);
+        command.setAgentInfoDAO(agentInfoDao);
+        command.setRequestQueue(queue);
 
         TestCommandContextFactory factory = new TestCommandContextFactory();
 
@@ -126,7 +130,7 @@
             command.run(factory.createContext(args));
             assertTrue("should not reach here", false);
         } catch (CommandException ce) {
-            assertEquals("a hostId is required", ce.getMessage());
+            assertEquals("a vmId is required", ce.getMessage());
         }
     }
 
@@ -134,17 +138,16 @@
     public void verifyFailsIfAgentDaoIsNotAvailable() {
         VmInfoDAO vmInfoDao = mock(VmInfoDAO.class);
         RequestQueue queue = mock(RequestQueue.class);
-        StubBundleContext context = new StubBundleContext();
-        context.registerService(VmInfoDAO.class, vmInfoDao, null);
-        context.registerService(RequestQueue.class, queue, null);
 
         DumpHeapHelper impl = mock(DumpHeapHelper.class);
-        DumpHeapCommand command = new DumpHeapCommand(context, impl);
+        DumpHeapCommand command = new DumpHeapCommand(impl);
+
+        command.setVmInfoDAO(vmInfoDao);
+        command.setRequestQueue(queue);
 
         TestCommandContextFactory factory = new TestCommandContextFactory();
 
         SimpleArguments args = new SimpleArguments();
-        args.addArgument("hostId", "foo");
         args.addArgument("vmId", "bar");
 
         try {
@@ -159,17 +162,16 @@
     public void verifyFailsIfRequestQueueIsNotAvailable() {
         VmInfoDAO vmInfoDao = mock(VmInfoDAO.class);
         AgentInfoDAO agentInfoDao = mock(AgentInfoDAO.class);
-        StubBundleContext context = new StubBundleContext();
-        context.registerService(VmInfoDAO.class, vmInfoDao, null);
-        context.registerService(AgentInfoDAO.class, agentInfoDao, null);
 
         DumpHeapHelper impl = mock(DumpHeapHelper.class);
-        DumpHeapCommand command = new DumpHeapCommand(context, impl);
+        DumpHeapCommand command = new DumpHeapCommand(impl);
+
+        command.setVmInfoDAO(vmInfoDao);
+        command.setAgentInfoDAO(agentInfoDao);
 
         TestCommandContextFactory factory = new TestCommandContextFactory();
 
         SimpleArguments args = new SimpleArguments();
-        args.addArgument("hostId", "foo");
         args.addArgument("vmId", "bar");
         args.addArgument("vmPid", "123");
 
@@ -185,17 +187,16 @@
     public void verifyFailsIfVmDaoIsNotAvailable() {
         AgentInfoDAO agentInfoDao = mock(AgentInfoDAO.class);
         RequestQueue queue = mock(RequestQueue.class);
-        StubBundleContext context = new StubBundleContext();
-        context.registerService(AgentInfoDAO.class, agentInfoDao, null);
-        context.registerService(RequestQueue.class, queue, null);
 
         DumpHeapHelper impl = mock(DumpHeapHelper.class);
-        DumpHeapCommand command = new DumpHeapCommand(context, impl);
+        DumpHeapCommand command = new DumpHeapCommand(impl);
+
+        command.setAgentInfoDAO(agentInfoDao);
+        command.setRequestQueue(queue);
 
         TestCommandContextFactory factory = new TestCommandContextFactory();
 
         SimpleArguments args = new SimpleArguments();
-        args.addArgument("hostId", "foo");
         args.addArgument("vmId", "bar");
 
         try {
@@ -208,41 +209,52 @@
 
     @Test
     public void verifyErrorMessage() {
-        final String HOST_ID = "myHost";
+        final String AGENT_ID = "myAgent";
         final String VM_ID = "myVm";
         VmInfoDAO vmInfoDao = mock(VmInfoDAO.class);
         AgentInfoDAO agentInfoDao = mock(AgentInfoDAO.class);
         RequestQueue queue = mock(RequestQueue.class);
-        StubBundleContext context = new StubBundleContext();
-        context.registerService(VmInfoDAO.class, vmInfoDao, null);
-        context.registerService(AgentInfoDAO.class, agentInfoDao, null);
-        context.registerService(RequestQueue.class, queue, null);
+        VmInfo vmInfo = new VmInfo(AGENT_ID, VM_ID, 123, 0, 0, null, null, null, null, null, null, null, null,
+                null, null, null, 0, null);
+        VmId vmId = new VmId(VM_ID);
+        AgentId agentId = new AgentId(AGENT_ID);
+
+        when(vmInfoDao.getVmInfo(vmId)).thenReturn(vmInfo);
 
         DumpHeapHelper impl = mock(DumpHeapHelper.class);
-        DumpHeapCommand command = new DumpHeapCommand(context, impl);
+        DumpHeapCommand command = new DumpHeapCommand(impl);
+
+        final ArgumentCaptor<Runnable> errorHandler = ArgumentCaptor.forClass(Runnable.class);
+
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                errorHandler.getValue().run();
+                return null;
+            }
+        }).when(impl).execute(eq(vmInfoDao),
+                              eq(agentInfoDao),
+                              eq(agentId),
+                              eq(vmId),
+                              eq(queue),
+                              any(Runnable.class),
+                              errorHandler.capture());
+
+        command.setVmInfoDAO(vmInfoDao);
+        command.setAgentInfoDAO(agentInfoDao);
+        command.setRequestQueue(queue);
+
         TestCommandContextFactory factory = new TestCommandContextFactory();
 
         SimpleArguments args = new SimpleArguments();
-        args.addArgument("hostId", HOST_ID);
         args.addArgument("vmId", VM_ID);
 
-        doAnswer(new Answer<Object>() {
-
-            @Override
-            public Object answer(InvocationOnMock invocation) throws Throwable {
-                Runnable failRunnable = (Runnable) invocation.getArguments()[5];
-                failRunnable.run();
-                return null;
-            }
-        }).when(impl).execute(any(VmInfoDAO.class), any(AgentInfoDAO.class), any(VmRef.class), 
-                any(RequestQueue.class), any(Runnable.class), any(Runnable.class));
-
         try {
             command.run(factory.createContext(args));
             fail("CommandException expected");
         } catch (CommandException e) {
             assertEquals(TRANSLATOR.localize(LocaleResources.HEAP_DUMP_ERROR,
-                    HOST_ID, VM_ID).getContents(), e.getMessage());
+                    AGENT_ID, VM_ID).getContents(), e.getMessage());
         }
     }
 
--- a/vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/DumpHeapHelperTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/vm-heap-analysis/command/src/test/java/com/redhat/thermostat/vm/heap/analysis/command/internal/DumpHeapHelperTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -56,8 +56,8 @@
 import com.redhat.thermostat.common.command.RequestResponseListener;
 import com.redhat.thermostat.common.command.Response;
 import com.redhat.thermostat.common.command.Response.ResponseType;
-import com.redhat.thermostat.storage.core.HostRef;
-import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.core.AgentId;
+import com.redhat.thermostat.storage.core.VmId;
 import com.redhat.thermostat.storage.dao.AgentInfoDAO;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
 import com.redhat.thermostat.storage.model.AgentInformation;
@@ -68,7 +68,9 @@
     private VmInfoDAO vmInfoDAO;
     private AgentInfoDAO agentInfoDao;
     private DumpHeapHelper cmd;
-    private VmRef vmRef;
+    private VmId vmId;
+    private AgentId agentId;
+    private AgentInformation agentInfo;
     private RequestQueue reqQueue;
     private Runnable heapDumpCompleteAction;
     private Runnable heapDumpFailedAction;
@@ -77,23 +79,24 @@
     public void setUp() {
         reqQueue = mock(RequestQueue.class);
 
-        HostRef host = mock(HostRef.class);
-
-        AgentInformation agentInfo = mock(AgentInformation.class);
-        when(agentInfo.getRequestQueueAddress()).thenReturn(new InetSocketAddress("test", 123));
-
         agentInfoDao = mock(AgentInfoDAO.class);
-        when(agentInfoDao.getAgentInformation(host)).thenReturn(agentInfo);
 
         cmd = new DumpHeapHelper();
-        vmRef = mock(VmRef.class);
-        when(vmRef.getVmId()).thenReturn("vmId");
-        when(vmRef.getHostRef()).thenReturn(host);
-        
+
+        agentInfo = mock(AgentInformation.class);
+        when(agentInfo.getRequestQueueAddress()).thenReturn(new InetSocketAddress("test", 123));
+
+        agentId = mock(AgentId.class);
+        when(agentInfoDao.getAgentInformation(agentId)).thenReturn(agentInfo);
+
+        vmId = mock(VmId.class);
+        when(vmId.get()).thenReturn("vmId");
+
         VmInfo vmInfo = mock(VmInfo.class);
         when(vmInfo.getVmPid()).thenReturn(123);
+
         vmInfoDAO = mock(VmInfoDAO.class);
-        when(vmInfoDAO.getVmInfo(vmRef)).thenReturn(vmInfo);
+        when(vmInfoDAO.getVmInfo(vmId)).thenReturn(vmInfo);
         
         heapDumpCompleteAction = mock(Runnable.class);
         heapDumpFailedAction = mock(Runnable.class);
@@ -102,15 +105,14 @@
     @After
     public void tearDown() {
         heapDumpCompleteAction = null;
-        vmRef = null;
+        vmId = null;
         cmd = null;
         reqQueue = null;
     }
 
     @Test
     public void testExecute() {
-
-        cmd.execute(vmInfoDAO, agentInfoDao, vmRef, reqQueue, heapDumpCompleteAction, heapDumpFailedAction);
+        cmd.execute(vmInfoDAO, agentInfoDao, agentId, vmId, reqQueue, heapDumpCompleteAction, heapDumpFailedAction);
 
         ArgumentCaptor<Request> reqArg = ArgumentCaptor.forClass(Request.class);
         verify(reqQueue).putRequest(reqArg.capture());
@@ -133,7 +135,7 @@
     @Test
     public void testExecuteFailure() {
 
-        cmd.execute(vmInfoDAO, agentInfoDao, vmRef, reqQueue, heapDumpCompleteAction, heapDumpFailedAction);
+        cmd.execute(vmInfoDAO, agentInfoDao, agentId, vmId, reqQueue, heapDumpCompleteAction, heapDumpFailedAction);
 
         ArgumentCaptor<Request> reqArg = ArgumentCaptor.forClass(Request.class);
         verify(reqQueue).putRequest(reqArg.capture());
--- a/vm-heap-analysis/distribution/thermostat-plugin.xml	Thu Jun 04 01:14:43 2015 -0500
+++ b/vm-heap-analysis/distribution/thermostat-plugin.xml	Tue Jun 23 10:16:17 2015 -0600
@@ -46,13 +46,6 @@
       <description>Trigger a heap dump on the VM.</description>
       <options>
         <option>
-          <long>hostId</long>
-          <short>a</short>
-          <argument>host</argument>
-          <required>true</required>
-          <description>the ID of the host to monitor</description>
-        </option>
-        <option>
           <long>vmId</long>
           <short>v</short>
           <argument>vm</argument>
--- a/vm-jmx/client-swing/src/test/java/com/redhat/thermostat/vm/jmx/client/swing/internal/JmxNotificationsSwingViewProviderTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/vm-jmx/client-swing/src/test/java/com/redhat/thermostat/vm/jmx/client/swing/internal/JmxNotificationsSwingViewProviderTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -39,7 +39,11 @@
 import static org.junit.Assert.assertTrue;
 
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
+
+@Category(CacioTest.class)
 public class JmxNotificationsSwingViewProviderTest {
 
     @Test
--- a/vm-memory/client-swing/src/test/java/com/redhat/thermostat/vm/memory/client/swing/internal/MemoryStatsViewImplTest.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/vm-memory/client-swing/src/test/java/com/redhat/thermostat/vm/memory/client/swing/internal/MemoryStatsViewImplTest.java	Tue Jun 23 10:16:17 2015 -0600
@@ -54,10 +54,12 @@
 import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import com.redhat.thermostat.annotations.internal.CacioTest;
 import com.redhat.thermostat.vm.memory.client.core.MemoryStatsView;
 
 import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
 
+@Category(CacioTest.class)
 @RunWith(CacioFESTRunner.class)
 public class MemoryStatsViewImplTest {
 
--- a/vm-profiler/jvm-agent/pom.xml	Thu Jun 04 01:14:43 2015 -0500
+++ b/vm-profiler/jvm-agent/pom.xml	Tue Jun 23 10:16:17 2015 -0600
@@ -96,5 +96,11 @@
       <artifactId>asm-all</artifactId>
       <version>${asm.version}</version>
     </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-annotations</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>
--- a/web/client/src/main/java/com/redhat/thermostat/web/client/internal/WebStorageProvider.java	Thu Jun 04 01:14:43 2015 -0500
+++ b/web/client/src/main/java/com/redhat/thermostat/web/client/internal/WebStorageProvider.java	Tue Jun 23 10:16:17 2015 -0600
@@ -56,7 +56,7 @@
     @Override
     public Storage createStorage() {
         WebStorage storage = new WebStorage(url, creds, sslConf);
-        if (LoggingUtils.getEffectiveLogLevel(LoggingUtils.getLogger(WebStorageProvider.class)).intValue() <= LoggingUtils.PERFLOG.intValue()) {
+        if (LoggingUtils.getEffectiveLogLevel(LoggingUtils.getLogger(WebStorageProvider.class)).intValue() <= LoggingUtils.LogLevel.PERFLOG.getLevel().intValue()) {
             PerformanceLogFormatterBuilder builder = PerformanceLogFormatterBuilder.create();
             PerformanceLogFormatter lf = builder.setLoggedTimeUnit(TimeUnit.MICROSECONDS)
                                               .build();