changeset 717:01f4973a06dc

Move Swing-dependent code into separate bundles: heapdumper This commit separates the heapdumper bundle into core and swing bundles. The swing bundle contains code specific to the Swing GUI, and the core bundle is to be used by any Thermostat client. This splits the former activator into two: the core bundle's activator registers commands, and the swing bundle's activator registers ViewProviders. This has also changed an assertion on the number of services registered in the ServicesAvailableActionTest test case. Reviewed-by: omajid Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-October/003812.html
author Elliott Baron <ebaron@redhat.com>
date Tue, 23 Oct 2012 11:21:06 -0400
parents f1a4570624dd
children 2f6384fbe64a
files client/heapdumper/core/pom.xml client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/HeapDumpController.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/HeapDumpDetailsView.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/HeapDumpDetailsViewProvider.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/HeapDumperService.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/HeapHistogramView.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/HeapHistogramViewProvider.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/HeapObjectUI.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/HeapView.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/HeapViewProvider.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/LocaleResources.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/ObjectDetailsView.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/ObjectDetailsViewProvider.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/ObjectRootsView.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/ObjectRootsViewProvider.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/chart/OverviewChart.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/DumpHeapCommand.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/FindObjectsCommand.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/FindRoot.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/FindRootCommand.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/HeapDumperCommand.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/HeapNotFoundException.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/HeapPath.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/ListHeapDumpsCommand.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/ObjectCommandHelper.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/ObjectInfoCommand.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/ObjectNotFoundException.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/SaveHeapDumpToFileCommand.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/ShowHeapHistogramCommand.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/internal/Activator.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/internal/HeapDumpDetailsController.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/internal/Histogram.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/internal/ObjectDetailsController.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/internal/ObjectRootsController.java client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/internal/PrintObjectUtils.java client/heapdumper/core/src/main/resources/META-INF/services/com.redhat.thermostat.common.cli.Command client/heapdumper/core/src/main/resources/com/redhat/thermostat/client/heap/strings.properties client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/HeapDumpControllerTest.java client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/HeapDumpDetailsControllerTest.java client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/LocaleResourcesTest.java client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/ObjectDetailsControllerTest.java client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/ObjectRootsControllerTest.java client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/cli/DumpHeapCommandTest.java client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/cli/FindObjectsCommandTest.java client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/cli/FindRootCommandTest.java client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/cli/HeapDumperCommandTest.java client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/cli/ListHeapDumpsCommandTest.java client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/cli/ObjectInfoCommandTest.java client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/cli/SaveHeapDumpToFileCommandTest.java client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/cli/ShowHeapHistogramCommandTest.java client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/internal/ActivatorTest.java client/heapdumper/pom.xml client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/Activator.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumpController.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumpDetailsController.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumpDetailsView.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumpDetailsViewProvider.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumperService.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapHistogramView.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapHistogramViewProvider.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapObjectUI.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapView.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapViewProvider.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/Histogram.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/LocaleResources.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/ObjectDetailsController.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/ObjectDetailsView.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/ObjectDetailsViewProvider.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/ObjectRootsController.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/ObjectRootsView.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/ObjectRootsViewProvider.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/PrintObjectUtils.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/chart/OverviewChart.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/DumpHeapCommand.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/FindObjectsCommand.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/FindRoot.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/FindRootCommand.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/HeapDumperCommand.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/HeapNotFoundException.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/HeapPath.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/ListHeapDumpsCommand.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/ObjectCommandHelper.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/ObjectInfoCommand.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/ObjectNotFoundException.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/SaveHeapDumpToFileCommand.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/ShowHeapHistogramCommand.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/HeapDetailsSwing.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/HeapPanel.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/HeapSwingView.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/HistogramPanel.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/LazyMutableTreeNode.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/ObjectDetailsPanel.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/ObjectRootsFrame.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/StatsPanel.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/SwingHeapDumpDetailsViewProvider.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/SwingHeapHistogramViewProvider.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/SwingHeapViewProvider.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/SwingObjectDetailsViewProvider.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/SwingObjectRootsViewProvider.java client/heapdumper/src/main/resources/META-INF/services/com.redhat.thermostat.common.cli.Command client/heapdumper/src/main/resources/com/redhat/thermostat/client/heap/strings.properties client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/HeapDumpControllerTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/HeapDumpDetailsControllerTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/LocaleResourcesTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/ObjectDetailsControllerTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/ObjectRootsControllerTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/ServicesAvailableActionTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/cli/DumpHeapCommandTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/cli/FindObjectsCommandTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/cli/FindRootCommandTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/cli/HeapDumperCommandTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/cli/ListHeapDumpsCommandTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/cli/ObjectInfoCommandTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/cli/SaveHeapDumpToFileCommandTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/cli/ShowHeapHistogramCommandTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/swing/HeapDetailsSwingTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/swing/HeapSwingViewTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/swing/ObjectDetailsPanelTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/swing/ObjectRootsFrameTest.java client/heapdumper/swing/pom.xml client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/Activator.java client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/HeapDetailsSwing.java client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/HeapPanel.java client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/HeapSwingView.java client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/HistogramPanel.java client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/LazyMutableTreeNode.java client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/ObjectDetailsPanel.java client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/ObjectRootsFrame.java client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/StatsPanel.java client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/SwingHeapDumpDetailsViewProvider.java client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/SwingHeapHistogramViewProvider.java client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/SwingHeapViewProvider.java client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/SwingObjectDetailsViewProvider.java client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/SwingObjectRootsViewProvider.java client/heapdumper/swing/src/test/java/com/redhat/thermostat/client/heap/swing/HeapDetailsSwingTest.java client/heapdumper/swing/src/test/java/com/redhat/thermostat/client/heap/swing/HeapSwingViewTest.java client/heapdumper/swing/src/test/java/com/redhat/thermostat/client/heap/swing/ObjectDetailsPanelTest.java client/heapdumper/swing/src/test/java/com/redhat/thermostat/client/heap/swing/ObjectRootsFrameTest.java client/heapdumper/swing/src/test/java/com/redhat/thermostat/client/heap/swing/ServicesAvailableActionTest.java
diffstat 139 files changed, 8996 insertions(+), 8675 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/pom.xml	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+
+ Copyright 2012 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-client-heapdumper</artifactId>
+    <groupId>com.redhat.thermostat</groupId>
+    <version>0.5.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>thermostat-client-heapdumper-core</artifactId>
+  <packaging>bundle</packaging>
+  <name>Thermostat Client Heap Dumper Core plugin</name>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
+            <Bundle-SymbolicName>com.redhat.thermostat.client.heapdumper.core</Bundle-SymbolicName>
+            <Export-Package>
+               com.redhat.thermostat.client.heap,
+               com.redhat.thermostat.client.heap.chart
+            </Export-Package>
+            <Private-Package>
+               com.redhat.thermostat.client.heap.internal,
+               com.redhat.thermostat.client.heap.cli
+            </Private-Package>
+            <!-- Do not autogenerate uses clauses in Manifests -->
+            <_nouses>true</_nouses>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <scope>provided</scope>
+    </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-client-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-tools</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-agent-heapdumper</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.jfree</groupId>
+      <artifactId>jfreechart</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.sun</groupId>
+      <artifactId>tools</artifactId>
+      <scope>system</scope>
+      <systemPath>${java.home}/../lib/tools.jar</systemPath>
+    </dependency>
+    
+  </dependencies>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/HeapDumpController.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import com.redhat.thermostat.client.core.controllers.VmInformationServiceController;
+import com.redhat.thermostat.client.core.views.BasicView.Action;
+import com.redhat.thermostat.client.core.views.UIComponent;
+import com.redhat.thermostat.client.heap.HeapView.HeapDumperAction;
+import com.redhat.thermostat.client.heap.chart.OverviewChart;
+import com.redhat.thermostat.client.heap.cli.HeapDumperCommand;
+import com.redhat.thermostat.client.heap.internal.HeapDumpDetailsController;
+import com.redhat.thermostat.client.osgi.service.ApplicationService;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.NotImplementedException;
+import com.redhat.thermostat.common.Timer;
+import com.redhat.thermostat.common.Timer.SchedulingType;
+import com.redhat.thermostat.common.appctx.ApplicationContext;
+import com.redhat.thermostat.common.dao.AgentInfoDAO;
+import com.redhat.thermostat.common.dao.HeapDAO;
+import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
+import com.redhat.thermostat.common.dao.VmRef;
+import com.redhat.thermostat.common.heap.HeapDump;
+import com.redhat.thermostat.common.locale.Translate;
+import com.redhat.thermostat.common.model.HeapInfo;
+import com.redhat.thermostat.common.model.VmMemoryStat;
+import com.redhat.thermostat.common.model.VmMemoryStat.Generation;
+import com.redhat.thermostat.common.model.VmMemoryStat.Space;
+import com.redhat.thermostat.common.utils.DisplayableValues.Scale;
+
+public class HeapDumpController implements VmInformationServiceController {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private final VmMemoryStatDAO vmDao;
+    private final VmRef ref;
+    
+    private final HeapDAO heapDAO;
+        
+    private HeapView view;
+    private final Timer timer;
+    
+    private OverviewChart model;
+    private ApplicationService appService;
+    private HeapDumpDetailsViewProvider detailsViewProvider;
+    private HeapHistogramViewProvider histogramViewProvider;
+    private ObjectDetailsViewProvider objectDetailsViewProvider;
+    private ObjectRootsViewProvider objectRootsViewProvider;
+
+    public HeapDumpController(final AgentInfoDAO agentInfoDao, final VmMemoryStatDAO vmMemoryStatDao, final HeapDAO heapDao, final VmRef ref, final ApplicationService appService, HeapViewProvider viewProvider, HeapDumpDetailsViewProvider detailsViewProvider, HeapHistogramViewProvider histogramProvider, ObjectDetailsViewProvider objectDetailsProvider, ObjectRootsViewProvider objectRootsProvider) {
+        this(agentInfoDao, vmMemoryStatDao, heapDao, ref, appService, new HeapDumperCommand(), viewProvider, detailsViewProvider, histogramProvider, objectDetailsProvider, objectRootsProvider);
+    }
+
+    HeapDumpController(final AgentInfoDAO agentInfoDao, final VmMemoryStatDAO vmMemoryStatDao, final HeapDAO heapDao, final VmRef ref, final ApplicationService appService, final HeapDumperCommand command, HeapViewProvider viewProvider, HeapDumpDetailsViewProvider detailsViewProvider, HeapHistogramViewProvider histogramProvider, ObjectDetailsViewProvider objectDetailsProvider, ObjectRootsViewProvider objectRootsProvider) {
+        
+        this.objectDetailsViewProvider = objectDetailsProvider;
+        this.objectRootsViewProvider = objectRootsProvider;
+        this.histogramViewProvider = histogramProvider;
+        this.detailsViewProvider = detailsViewProvider;
+        this.appService = appService;
+        this.ref = ref;
+        this.vmDao = vmMemoryStatDao;
+        this.heapDAO = heapDao;
+        
+        model = new OverviewChart(
+                    translator.localize(LocaleResources.HEAP_CHART_TITLE),
+                    translator.localize(LocaleResources.HEAP_CHART_TIME_AXIS),
+                    translator.localize(LocaleResources.HEAP_CHART_HEAP_AXIS),
+                    translator.localize(LocaleResources.HEAP_CHART_CAPACITY),
+                    translator.localize(LocaleResources.HEAP_CHART_USED));
+        
+        timer = ApplicationContext.getInstance().getTimerFactory().createTimer();
+        timer.setAction(new HeapOverviewDataCollector());
+        
+        timer.setInitialDelay(0);
+        timer.setDelay(1000);
+        model.setRange(3600);
+        timer.setTimeUnit(TimeUnit.MILLISECONDS);
+        timer.setSchedulingType(SchedulingType.FIXED_RATE);
+        
+        view = viewProvider.createView();
+        view.setModel(model);
+        
+        HeapDump dump = null;
+        view.clearHeapDumpList();
+        Collection<HeapInfo> infos = heapDAO.getAllHeapInfo(ref);
+        for (HeapInfo info : infos) {
+            dump = new HeapDump(info, heapDAO);
+            view.addHeapDump(dump);
+        }
+        
+        // check if we were reading some of the dumps
+        dump = (HeapDump) appService.getApplicationCache().getAttribute(ref);
+        if (dump != null && infos.contains(dump.getInfo())) {
+            showHeapDumpDetails(dump);
+        }
+        
+        view.addActionListener(new ActionListener<Action>() {            
+            @Override
+            public void actionPerformed(ActionEvent<Action> actionEvent) {
+                switch (actionEvent.getActionId()) {
+                case HIDDEN:
+                    timer.stop();
+                    break;
+                
+                case VISIBLE:                    
+                    timer.start();
+                    break;
+
+                default:
+                    throw new NotImplementedException("unknown event: " + actionEvent.getActionId());
+                }
+            }
+        });
+
+        view.addDumperListener(new ActionListener<HeapView.HeapDumperAction>() {
+            @Override
+            public void actionPerformed(ActionEvent<HeapDumperAction> actionEvent) {
+                HeapDump dump = null;
+                switch (actionEvent.getActionId()) {
+                case DUMP_REQUESTED:
+                    command.execute(agentInfoDao, ref, new Runnable() {
+                        public void run() {
+                            view.notifyHeapDumpComplete();
+                        }
+                    });
+                    
+                    break;
+                
+                case ANALYSE:
+                    dump = (HeapDump) actionEvent.getPayload();
+                    analyseDump(dump);
+                    break;
+                }
+            }
+        });
+    }
+
+    
+    private void analyseDump(final HeapDump dump) {
+        appService.getApplicationExecutor().execute(new Runnable() {
+            
+            @Override
+            public void run() {
+                showHeapDumpDetails(dump);
+                appService.getApplicationCache().addAttribute(ref, dump);
+            }
+        });
+    }
+
+    private void showHeapDumpDetails(HeapDump dump) {
+        HeapDumpDetailsController controller = new HeapDumpDetailsController(appService, detailsViewProvider, histogramViewProvider, objectDetailsViewProvider, objectRootsViewProvider);
+        controller.setDump(dump);
+        view.setChildView(controller.getView());
+        view.openDumpView();
+    }
+
+    @Override
+    public UIComponent getView() {
+        return (UIComponent) view;
+    }
+
+    @Override
+    public String getLocalizedName() {
+        return translator.localize(LocaleResources.HEAP_SECTION_TITLE);
+    }
+
+    class HeapOverviewDataCollector implements Runnable {
+
+        private long desiredUpdateTimeStamp = System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1);
+
+        @Override
+        public void run() {
+            checkForHeapDumps();
+            updateMemoryChartAndDisplay();
+        }
+
+        private void checkForHeapDumps() {
+            Collection<HeapInfo> heapInfos = heapDAO.getAllHeapInfo(ref);
+            List<HeapDump> heapDumps = new ArrayList<HeapDump>(heapInfos.size());
+            for (HeapInfo heapInfo : heapInfos) {
+                heapDumps.add(new HeapDump(heapInfo, heapDAO));
+            }
+            view.updateHeapDumpList(heapDumps);
+        }
+
+        private void updateMemoryChartAndDisplay() {
+            List<VmMemoryStat> vmInfo = null;
+            vmInfo = vmDao.getLatestVmMemoryStats(ref, desiredUpdateTimeStamp);
+
+            for (VmMemoryStat memoryStats: vmInfo) {
+                long used = 0l;
+                long capacity = 0l;
+                long max = 0l;
+                List<Generation> generations = memoryStats.getGenerations();
+                for (Generation generation : generations) {
+                    
+                    // non heap
+                    if (generation.name.equals("perm")) {
+                        continue;
+                    }
+                    
+                    List<Space> spaces = generation.spaces;
+                    for (Space space: spaces) {
+                        used += space.used;
+                        capacity += space.capacity;
+                        
+                        // TODO
+                        max =+ space.maxCapacity;
+                    }
+                }
+                model.addData(memoryStats.getTimeStamp(), used, capacity);
+                
+                NumberFormat formatter = DecimalFormat.getInstance();
+
+                double res = Scale.convertTo(Scale.B, used);
+                String _used = formatter.format(res) + " " + Scale.B;
+                
+                res = Scale.convertTo(Scale.B, capacity);
+                String _capacity= formatter.format(capacity) + " " + Scale.B;
+                
+                view.updateUsedAndCapacity(_used, _capacity);
+                desiredUpdateTimeStamp = Math.max(desiredUpdateTimeStamp, memoryStats.getTimeStamp());
+            }
+
+            model.notifyListenersOfModelChange();
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/HeapDumpDetailsView.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+import com.redhat.thermostat.client.core.views.BasicView;
+import com.redhat.thermostat.client.core.views.UIComponent;
+
+public abstract class HeapDumpDetailsView extends BasicView implements UIComponent {
+
+    public abstract void addSubView(String title, HeapHistogramView child);
+    public abstract void addSubView(String title, ObjectDetailsView child);
+    public abstract void removeSubView(String title);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/HeapDumpDetailsViewProvider.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+import com.redhat.thermostat.client.core.views.ViewProvider;
+
+public interface HeapDumpDetailsViewProvider extends ViewProvider {
+
+    @Override
+    public HeapDumpDetailsView createView();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/HeapDumperService.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+import com.redhat.thermostat.client.core.VmFilter;
+import com.redhat.thermostat.client.core.VmInformationService;
+import com.redhat.thermostat.client.core.controllers.VmInformationServiceController;
+import com.redhat.thermostat.client.osgi.service.AlwaysMatchFilter;
+import com.redhat.thermostat.client.osgi.service.ApplicationService;
+import com.redhat.thermostat.common.dao.AgentInfoDAO;
+import com.redhat.thermostat.common.dao.HeapDAO;
+import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
+import com.redhat.thermostat.common.dao.VmRef;
+
+public class HeapDumperService implements VmInformationService {
+    
+    private ApplicationService appService;
+    private AgentInfoDAO agentInfoDao;
+    private VmMemoryStatDAO vmMemoryStatDao;
+    private HeapDAO heapDao;
+
+    private VmFilter filter = new AlwaysMatchFilter();
+    private HeapDumpDetailsViewProvider detailsViewProvider;
+    private HeapHistogramViewProvider histogramViewProvider;
+    private HeapViewProvider viewProvider;
+    private ObjectDetailsViewProvider objectDetailsViewProvider;
+    private ObjectRootsViewProvider objectRootsViewProvider;
+
+    public HeapDumperService(ApplicationService appService, AgentInfoDAO agentInfoDao, VmMemoryStatDAO vmMemoryStatDao, HeapDAO heapDao, HeapDumpDetailsViewProvider detailsViewProvider, HeapViewProvider viewProvider, HeapHistogramViewProvider histogramViewProvider, ObjectDetailsViewProvider objectDetailsViewProvider, ObjectRootsViewProvider objectRootsViewProvider) {
+        this.agentInfoDao = agentInfoDao;
+        this.vmMemoryStatDao = vmMemoryStatDao;
+        this.heapDao = heapDao;
+        this.appService = appService;
+        this.viewProvider = viewProvider;
+        this.detailsViewProvider = detailsViewProvider;
+        this.histogramViewProvider = histogramViewProvider;
+        this.objectDetailsViewProvider = objectDetailsViewProvider;
+        this.objectRootsViewProvider = objectRootsViewProvider;
+    }
+
+    @Override
+    public VmInformationServiceController getInformationServiceController(VmRef ref) {
+        return new HeapDumpController(agentInfoDao, vmMemoryStatDao, heapDao, ref, appService, viewProvider, detailsViewProvider, histogramViewProvider, objectDetailsViewProvider, objectRootsViewProvider);
+    }
+
+    @Override
+    public VmFilter getFilter() {
+        return filter;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/HeapHistogramView.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+import com.redhat.thermostat.client.core.views.BasicView;
+import com.redhat.thermostat.client.core.views.UIComponent;
+import com.redhat.thermostat.common.heap.ObjectHistogram;
+
+public abstract class HeapHistogramView extends BasicView implements UIComponent {
+
+    public abstract void display(ObjectHistogram histogram);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/HeapHistogramViewProvider.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+import com.redhat.thermostat.client.core.views.ViewProvider;
+
+public interface HeapHistogramViewProvider extends ViewProvider {
+
+    @Override
+    public HeapHistogramView createView();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/HeapObjectUI.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+public class HeapObjectUI {
+
+    public String objectId;
+    public String text;
+
+    public HeapObjectUI(String objectId, String text) {
+        this.objectId = objectId;
+        this.text = text;
+    }
+
+    @Override
+    public String toString() {
+        return text;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/HeapView.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+import java.util.List;
+
+import com.redhat.thermostat.client.core.views.BasicView;
+import com.redhat.thermostat.client.core.views.UIComponent;
+import com.redhat.thermostat.client.heap.chart.OverviewChart;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ActionNotifier;
+import com.redhat.thermostat.common.heap.HeapDump;
+
+public abstract class HeapView extends BasicView implements UIComponent {
+    
+    public enum HeapDumperAction {
+        DUMP_REQUESTED,
+        ANALYSE,
+        REQUEST_ABORTED
+    }
+   
+    protected final ActionNotifier<HeapDumperAction> heapDumperNotifier;
+    protected HeapView() {
+        heapDumperNotifier = new ActionNotifier<HeapDumperAction>(this);
+    }
+    
+    public void addDumperListener(ActionListener<HeapDumperAction> listener) {
+        heapDumperNotifier.addActionListener(listener);
+    }
+    
+    public void removeDumperListener(ActionListener<HeapDumperAction> listener) {
+        heapDumperNotifier.removeActionListener(listener);
+    }
+
+    abstract public void updateUsedAndCapacity(String used, String capacity);
+    /** View updates automatically based on the model */
+    abstract public void setModel(OverviewChart model);
+    abstract public void addHeapDump(HeapDump dump);
+    abstract public void clearHeapDumpList();
+    
+    abstract public void openDumpView();
+    abstract public void setChildView(BasicView childView);
+    public abstract void notifyHeapDumpComplete();
+
+    public abstract void updateHeapDumpList(List<HeapDump> heapDumps);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/HeapViewProvider.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+import com.redhat.thermostat.client.core.views.ViewProvider;
+
+public interface HeapViewProvider extends ViewProvider {
+
+    @Override
+    public HeapView createView();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/LocaleResources.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+import com.redhat.thermostat.common.locale.Translate;
+
+public enum LocaleResources {
+
+    MISSING_INFO,
+    HOST_SERVICE_UNAVAILABLE,
+    VM_SERVICE_UNAVAILABLE,
+    HEAP_SERVICE_UNAVAILABLE,
+
+    HEADER_TIMESTAMP,
+    HEADER_HOST_ID,
+    HEADER_VM_ID,
+    HEADER_HEAP_ID,
+    HEADER_OBJECT_ID,
+    HEADER_OBJECT_TYPE,
+
+    FILE_REQUIRED,
+    INVALID_LIMIT,
+    HEAP_ID_NOT_FOUND,
+    HEAP_ID_REQUIRED,
+    SEARCH_TERM_REQUIRED,
+
+    COMMAND_HEAP_DUMP_DONE,
+
+    COMMAND_FIND_ROOT_NO_ROOT_FOUND,
+
+    COMMAND_OBJECT_INFO_OBJECT_ID,
+    COMMAND_OBJECT_INFO_TYPE,
+    COMMAND_OBJECT_INFO_SIZE,
+    COMMAND_OBJECT_INFO_HEAP_ALLOCATED,
+    COMMAND_OBJECT_INFO_REFERENCES,
+    COMMAND_OBJECT_INFO_REFERRERS,
+
+    COMMAND_SAVE_HEAP_DUMP_SAVED_TO_FILE,
+    COMMAND_SAVE_HEAP_DUMP_ERROR_SAVING,
+    COMMAND_SAVE_HEAP_DUMP_ERROR_CLOSING_STREAM,
+
+    HEAP_SECTION_TITLE,
+    HEAP_OVERVIEW_TITLE,
+    HEAP_CHART_TITLE,
+    HEAP_CHART_TIME_AXIS,
+    HEAP_CHART_HEAP_AXIS,
+    HEAP_CHART_CAPACITY,
+    HEAP_CHART_USED,
+
+    HEAP_DUMP_SECTION_HISTOGRAM,
+    HEAP_DUMP_SECTION_OBJECT_BROWSER,
+
+    HEAP_DUMP_CLASS_USAGE,
+    HEAP_DUMP_HISTOGRAM_COLUMN_CLASS,
+    HEAP_DUMP_HISTOGRAM_COLUMN_INSTANCES,
+    HEAP_DUMP_HISTOGRAM_COLUMN_SIZE,
+
+    HEAP_DUMP_OBJECT_BROWSE_SEARCH_HINT,
+    HEAP_DUMP_OBJECT_BROWSE_SEARCH_PATTERN_HELP,
+    HEAP_DUMP_OBJECT_BROWSE_SEARCH_LABEL,
+    HEAP_DUMP_OBJECT_BROWSE_REFERRERS,
+    HEAP_DUMP_OBJECT_BROWSE_REFERENCES,
+    HEAP_DUMP_OBJECT_FIND_ROOT,
+
+    OBJECT_ROOTS_VIEW_TITLE,
+    ;
+
+    static final String RESOURCE_BUNDLE = "com.redhat.thermostat.client.heap.strings";
+
+    public static Translate<LocaleResources> createLocalizer() {
+        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/ObjectDetailsView.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+import java.util.Collection;
+
+import com.redhat.thermostat.client.core.views.BasicView;
+import com.redhat.thermostat.client.core.views.UIComponent;
+import com.redhat.thermostat.common.ActionListener;
+import com.sun.tools.hat.internal.model.JavaHeapObject;
+
+public abstract class ObjectDetailsView extends BasicView implements UIComponent {
+
+    // TODO this should be some sort of aggregate view
+    // showing users 1000 instances of a class is not very useful unless we
+    // allow the user some aggregate results or allow additional sorting or
+    // filtering
+
+    public enum ObjectAction {
+        SEARCH,
+        GET_OBJECT_DETAIL,
+        SHOW_ROOT_TO_GC,
+    }
+
+    public static interface ObjectReferenceCallback {
+        /** get a list of objects that refers to this object */
+        Collection<HeapObjectUI> getReferrers(HeapObjectUI obj);
+
+        /** get a list of objects that this object refers to */
+        Collection<HeapObjectUI> getReferences(HeapObjectUI obj);
+    }
+
+    public abstract void addObjectActionListener(ActionListener<ObjectAction> listener);
+    public abstract void removeObjectActionListnener(ActionListener<ObjectAction> listener);
+
+    public abstract void addObjectReferenceCallback(ObjectReferenceCallback callback);
+    public abstract void removeObjectReferenceCallback(ObjectReferenceCallback callback);
+
+    public abstract String getSearchText();
+
+    public abstract void setMatchingObjects(Collection<HeapObjectUI> objects);
+
+    public abstract HeapObjectUI getSelectedMatchingObject();
+
+    public abstract void setObjectDetails(JavaHeapObject object);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/ObjectDetailsViewProvider.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+import com.redhat.thermostat.client.core.views.ViewProvider;
+
+public interface ObjectDetailsViewProvider extends ViewProvider {
+
+    @Override
+    public ObjectDetailsView createView();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/ObjectRootsView.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+import java.util.List;
+
+import com.redhat.thermostat.client.core.views.UIComponent;
+import com.redhat.thermostat.client.core.views.View;
+import com.redhat.thermostat.common.ActionListener;
+
+public interface ObjectRootsView extends View, UIComponent {
+
+    enum Action {
+        VISIBLE,
+        HIDDEN,
+        OBJECT_SELECTED,
+    }
+
+    void addActionListener(ActionListener<Action> listener);
+    void removeActionListener(ActionListener<Action> listener);
+
+    void showView();
+    void hideView();
+
+    void setPathToRoot(List<HeapObjectUI> pathToRoot);
+    void setObjectDetails(String information);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/ObjectRootsViewProvider.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+import com.redhat.thermostat.client.core.views.ViewProvider;
+
+public interface ObjectRootsViewProvider extends ViewProvider {
+
+    @Override
+    public ObjectRootsView createView();
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/chart/OverviewChart.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2012 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.client.heap.chart;
+
+import java.awt.Color;
+import java.awt.GradientPaint;
+import java.awt.Paint;
+import java.util.Date;
+
+import javax.swing.plaf.ColorUIResource;
+
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.axis.DateAxis;
+import org.jfree.chart.axis.NumberAxis;
+import org.jfree.chart.axis.TickUnits;
+import org.jfree.chart.axis.ValueAxis;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.chart.renderer.xy.XYDifferenceRenderer;
+import org.jfree.data.RangeType;
+import org.jfree.data.time.Millisecond;
+import org.jfree.data.time.TimeSeries;
+import org.jfree.data.time.TimeSeriesCollection;
+
+import com.redhat.thermostat.client.ui.BytesTickUnit;
+
+public class OverviewChart {
+        
+    private static final ColorUIResource MAIN_BAR_BASE_COLOR = new ColorUIResource(0x4A90D9);
+
+    private static final String lock = new String("chartLock");
+
+    private TimeSeries total;
+    private TimeSeries used;
+    private String title;
+    private String xAxis;
+    private String yAxis;
+    
+    public OverviewChart(String title, String xAxis, String yAxis, String mainSeries, String secondarySeries) {
+        
+        this.title = title;
+        this.xAxis = xAxis;
+        this.yAxis = yAxis;
+        
+        total = new TimeSeries(mainSeries);
+        total.setDescription(mainSeries);
+        
+        used = new TimeSeries(secondarySeries);
+        used.setDescription(secondarySeries);
+    }
+    
+    public JFreeChart createChart(int height, Color bgColor) {
+
+        TimeSeriesCollection dataset = new TimeSeriesCollection();
+        
+        synchronized (lock) {
+            dataset.addSeries(total);
+            dataset.addSeries(used);
+        }
+        
+        JFreeChart chart = ChartFactory.createTimeSeriesChart(
+                title,
+                xAxis,
+                yAxis,
+                dataset,
+                true,  // legend
+                false,  // tool tips
+                false   // URLs
+        );
+
+        Paint paint = new GradientPaint(0, 0, MAIN_BAR_BASE_COLOR, 0, height, bgColor);
+        Paint paint2 = new GradientPaint(0, 0, Color.GREEN, 0, height, bgColor);
+
+        XYPlot plot = (XYPlot) chart.getPlot();
+        plot.setDomainPannable(true);
+        XYDifferenceRenderer r = new XYDifferenceRenderer(paint, paint2, false);
+        r.setRoundXCoordinates(true);
+        plot.setDomainCrosshairLockedOnData(true);
+        plot.setRangeCrosshairLockedOnData(true);
+        plot.setDomainCrosshairVisible(true);
+        plot.setRangeCrosshairVisible(true);
+        plot.setRenderer(r);
+
+        ValueAxis domainAxis = new DateAxis(xAxis);
+        domainAxis.setLowerMargin(0.0);
+        domainAxis.setUpperMargin(0.0);
+        plot.setDomainAxis(domainAxis);
+        plot.setForegroundAlpha(0.5f);
+        TickUnits tickUnits = new TickUnits();
+        tickUnits.add(new BytesTickUnit(1.));
+        tickUnits.add(new BytesTickUnit(10.));
+        tickUnits.add(new BytesTickUnit(100.));
+        tickUnits.add(new BytesTickUnit(1000.));
+        tickUnits.add(new BytesTickUnit(10000.));
+        tickUnits.add(new BytesTickUnit(100000.));
+        tickUnits.add(new BytesTickUnit(1000000.));
+        tickUnits.add(new BytesTickUnit(10000000.));
+        tickUnits.add(new BytesTickUnit(100000000.));
+        tickUnits.add(new BytesTickUnit(1000000000.));
+        tickUnits.add(new BytesTickUnit(10000000000.));
+        tickUnits.add(new BytesTickUnit(100000000000.));
+        tickUnits.add(new BytesTickUnit(1000000000000.));
+        NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
+        yAxis.setStandardTickUnits(tickUnits);
+        yAxis.setRangeType(RangeType.POSITIVE);
+        yAxis.setAutoRangeMinimumSize(10);
+        yAxis.setAutoRange(true);
+        return chart;
+    }
+
+    public void addData(long timeStamp, long used, long total) {
+        
+        Millisecond millisecond = new Millisecond(new Date(timeStamp));
+        synchronized (lock) {            
+            if (this.total.getValue(millisecond) == null) {
+                this.total.add(millisecond, total, false);
+                this.total.removeAgedItems(true);
+            }
+            
+            if (this.used.getValue(millisecond) == null) {
+                this.used.add(millisecond, used, false);
+                this.used.removeAgedItems(true);
+            }
+        }
+        
+    }
+
+    public void notifyListenersOfModelChange() {
+        synchronized (lock) {
+            this.total.fireSeriesChanged();
+            this.used.fireSeriesChanged();
+        }
+    }
+
+    public void setRange(int seconds) {
+        total.setMaximumItemCount(seconds);
+        used.setMaximumItemCount(seconds);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/DumpHeapCommand.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import java.util.concurrent.Semaphore;
+
+import com.redhat.thermostat.client.heap.LocaleResources;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.HostVMArguments;
+import com.redhat.thermostat.common.cli.SimpleCommand;
+import com.redhat.thermostat.common.dao.AgentInfoDAO;
+import com.redhat.thermostat.common.locale.Translate;
+import com.redhat.thermostat.common.utils.OSGIUtils;
+
+
+public class DumpHeapCommand extends SimpleCommand {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+    private static final String NAME = "dump-heap";
+
+    private final OSGIUtils serviceProvider;
+    private final HeapDumperCommand implementation;
+
+    public DumpHeapCommand() {
+        this(OSGIUtils.getInstance(), new HeapDumperCommand());
+    }
+
+    DumpHeapCommand(OSGIUtils serviceProvider, HeapDumperCommand impl) {
+        this.serviceProvider = serviceProvider;
+        this.implementation = impl;
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public void run(CommandContext ctx) throws CommandException {
+        HostVMArguments args = new HostVMArguments(ctx.getArguments());
+
+        final Semaphore s = new Semaphore(0);
+        Runnable r = new Runnable() {
+            
+            @Override
+            public void run() {
+                s.release();
+            }
+        };
+        AgentInfoDAO service = serviceProvider.getService(AgentInfoDAO.class);
+        if (service == null) {
+            throw new CommandException("Unable to access agent information");
+        }
+        implementation.execute(service, args.getVM(), r);
+        serviceProvider.ungetService(AgentInfoDAO.class, service);
+
+        try {
+            s.acquire();
+            ctx.getConsole().getOutput().print(translator.localize(LocaleResources.COMMAND_HEAP_DUMP_DONE));
+            ctx.getConsole().getOutput().print("\n");
+        } catch (InterruptedException ex) {
+            // Nothing to do here, just return ASAP.
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/FindObjectsCommand.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import java.util.Collection;
+import java.util.List;
+
+import com.redhat.thermostat.client.heap.LocaleResources;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.SimpleCommand;
+import com.redhat.thermostat.common.cli.TableRenderer;
+import com.redhat.thermostat.common.dao.HeapDAO;
+import com.redhat.thermostat.common.heap.HeapDump;
+import com.redhat.thermostat.common.locale.Translate;
+import com.redhat.thermostat.common.model.HeapInfo;
+import com.redhat.thermostat.common.utils.OSGIUtils;
+import com.sun.tools.hat.internal.model.JavaHeapObject;
+
+public class FindObjectsCommand extends SimpleCommand {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private static final String HEAP_ID_ARG = "heapId";
+    private static final String LIMIT_ARG = "limit";
+    private static final String NAME = "find-objects";
+    private static final String HEADER_OBJECT_ID = translator.localize(LocaleResources.HEADER_OBJECT_ID);
+    private static final String HEADER_TYPE = translator.localize(LocaleResources.HEADER_OBJECT_TYPE);
+    private static final int DEFAULT_LIMIT = 10;
+
+    private OSGIUtils serviceProvider;
+
+    public FindObjectsCommand() {
+        this(OSGIUtils.getInstance());
+    }
+
+    FindObjectsCommand(OSGIUtils serviceProvider) {
+        this.serviceProvider = serviceProvider;
+    }
+
+    @Override
+    public void run(CommandContext ctx) throws CommandException {
+
+        HeapDAO heapDAO = serviceProvider.getServiceAllowNull(HeapDAO.class);
+        if (heapDAO == null) {
+            throw new CommandException(translator.localize(LocaleResources.HEAP_SERVICE_UNAVAILABLE));
+        }
+        try {
+            run(ctx, heapDAO);
+        } finally {
+            serviceProvider.ungetService(HeapDAO.class, heapDAO);
+            heapDAO = null;
+        }
+    }
+
+    private void run(CommandContext ctx, HeapDAO heapDAO) throws CommandException {
+        String heapId = ctx.getArguments().getArgument(HEAP_ID_ARG);
+        HeapInfo heapInfo = heapDAO.getHeapInfo(heapId);
+        if (heapInfo == null) {
+            ctx.getConsole().getOutput().println(translator.localize(LocaleResources.HEAP_ID_NOT_FOUND, heapId));
+            return;
+        }
+        HeapDump heapDump = heapDAO.getHeapDump(heapInfo);
+        if (heapDump == null) {
+            ctx.getConsole().getOutput().println(translator.localize(LocaleResources.HEAP_ID_NOT_FOUND, heapId));
+            return;
+        }
+
+        List<String> terms = ctx.getArguments().getNonOptionArguments();
+        if (terms.size() == 0) {
+            ctx.getConsole().getOutput().println(translator.localize(LocaleResources.SEARCH_TERM_REQUIRED));
+            return;
+        }
+        String searchTerm = terms.get(0);
+        if (searchTerm.trim().length() == 0) {
+            ctx.getConsole().getOutput().println(translator.localize(LocaleResources.SEARCH_TERM_REQUIRED));
+            return;
+        }
+
+        String limitArg = ctx.getArguments().getArgument(LIMIT_ARG);
+        int limit = parseLimit(limitArg);
+        Collection<String> results = heapDump.searchObjects(searchTerm, limit);
+        TableRenderer table = new TableRenderer(2);
+        table.printLine(HEADER_OBJECT_ID, HEADER_TYPE);
+        for (String objectId : results) {
+            JavaHeapObject obj = heapDump.findObject(objectId);
+            String id = obj.getIdString();
+            String className = obj.getClazz().getName();
+            table.printLine(id, className);
+        }
+        table.render(ctx.getConsole().getOutput());
+    }
+
+    private int parseLimit(String limitArg) throws CommandException {
+        int limit = DEFAULT_LIMIT;
+        if (limitArg != null) {
+            try {
+                limit = Integer.parseInt(limitArg);
+            } catch (NumberFormatException ex) {
+                throw new CommandException(translator.localize(LocaleResources.INVALID_LIMIT, limitArg));
+            }
+        }
+        return limit;
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/FindRoot.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import com.sun.tools.hat.internal.model.JavaHeapObject;
+
+public class FindRoot {
+
+    private Set<JavaHeapObject> visitedObjects;
+
+    public Collection<HeapPath<JavaHeapObject>> findShortestPathsToRoot(JavaHeapObject obj, boolean findAll) {
+        HeapPath<JavaHeapObject> path = new HeapPath<>(obj);
+        List<HeapPath<JavaHeapObject>> pathsSoFar = new LinkedList<>();
+        pathsSoFar.add(path);
+        visitedObjects = new HashSet<>();
+        return findShortestPathToRoot(pathsSoFar, findAll);
+    }
+
+    private Collection<HeapPath<JavaHeapObject>> findShortestPathToRoot(List<HeapPath<JavaHeapObject>> pathsSoFar, boolean findAll) {
+        List<HeapPath<JavaHeapObject>> newPaths = new LinkedList<>();
+        Collection<HeapPath<JavaHeapObject>> roots = new ArrayList<>();
+        for (HeapPath<JavaHeapObject> path : pathsSoFar) {
+            JavaHeapObject last = path.getNode();
+            if (visitedObjects.contains(last)) {
+                continue;
+            }
+            @SuppressWarnings("rawtypes")
+            Enumeration referrers = last.getReferers();
+            while (referrers.hasMoreElements()) {
+                JavaHeapObject referrer = (JavaHeapObject) referrers.nextElement();
+                HeapPath<JavaHeapObject> newPath = new HeapPath<>(referrer, path);
+                newPaths.add(newPath);
+                if (referrer.getRoot() != null) {
+                    roots.add(newPath);
+                    if (! findAll) {
+                        return roots;
+                    }
+                }
+            }
+            visitedObjects.add(last);
+        }
+        if (newPaths.isEmpty()) {
+            return roots;
+        } else {
+            Collection<HeapPath<JavaHeapObject>> foundRoots = findShortestPathToRoot(newPaths, findAll);
+            roots.addAll(foundRoots);
+            return roots;
+        }
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/FindRootCommand.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import java.io.PrintStream;
+import java.util.Collection;
+import java.util.Iterator;
+
+import com.redhat.thermostat.client.heap.LocaleResources;
+import com.redhat.thermostat.client.heap.internal.PrintObjectUtils;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.SimpleCommand;
+import com.redhat.thermostat.common.dao.HeapDAO;
+import com.redhat.thermostat.common.heap.HeapDump;
+import com.redhat.thermostat.common.locale.Translate;
+import com.redhat.thermostat.common.utils.OSGIUtils;
+import com.sun.tools.hat.internal.model.JavaHeapObject;
+import com.sun.tools.hat.internal.model.Root;
+import com.sun.tools.hat.internal.model.Snapshot;
+
+public class FindRootCommand extends SimpleCommand {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private static final String ALL_ARG = "all";
+    private static final String NAME = "find-root";
+
+    private OSGIUtils serviceProvider;
+
+    public FindRootCommand() {
+        this(OSGIUtils.getInstance());
+    }
+
+    FindRootCommand(OSGIUtils serviceProvider) {
+        this.serviceProvider = serviceProvider;
+    }
+
+    @Override
+    public void run(CommandContext ctx) throws CommandException {
+        HeapDAO heapDao = serviceProvider.getServiceAllowNull(HeapDAO.class);
+        if (heapDao == null) {
+            throw new CommandException(translator.localize(LocaleResources.HEAP_SERVICE_UNAVAILABLE));
+        }
+
+        try {
+            run(ctx, heapDao);
+        } finally {
+            serviceProvider.ungetService(HeapDAO.class, heapDao);
+        }
+    }
+
+    private void run(CommandContext ctx, HeapDAO heapDao) throws CommandException {
+        ObjectCommandHelper objCmdHelper = new ObjectCommandHelper(ctx, heapDao);
+        HeapDump heapDump = objCmdHelper.getHeapDump();
+        Snapshot snapshot = heapDump.getSnapshot();
+        JavaHeapObject obj = objCmdHelper.getJavaHeapObject();
+        boolean findAll = ctx.getArguments().hasArgument(ALL_ARG);
+        FindRoot findRoot = new FindRoot();
+        Collection<HeapPath<JavaHeapObject>> pathsToRoot = findRoot.findShortestPathsToRoot(obj, findAll);
+        PrintStream out = ctx.getConsole().getOutput();
+        if (pathsToRoot.isEmpty()) {
+            out.println(translator.localize(LocaleResources.COMMAND_FIND_ROOT_NO_ROOT_FOUND, PrintObjectUtils.objectToString(obj)));
+        } else {
+            printPathsToRoot(snapshot, pathsToRoot, out);
+        }
+    }
+
+    private void printPathsToRoot(Snapshot snapshot, Collection<HeapPath<JavaHeapObject>> pathsToRoot, PrintStream out) {
+        for (HeapPath<JavaHeapObject> path : pathsToRoot) {
+            printPathToRoot(snapshot, path, out);
+            out.println();
+        }
+    }
+
+    private void printPathToRoot(Snapshot snapshot, HeapPath<JavaHeapObject> pathToRoot, PrintStream out) {
+        // Print root.
+        Iterator<JavaHeapObject> i = pathToRoot.iterator();
+        JavaHeapObject last = i.next();
+        Root root = last.getRoot();
+        out.println(root.getDescription() + " -> " + PrintObjectUtils.objectToString(last));
+        // Print reference 'tree'.
+        int indentation = 0;
+        while (i.hasNext()) {
+            JavaHeapObject next = i.next();
+            printIndentation(out, indentation);
+            out.print("\u2514");
+            out.print(last.describeReferenceTo(next, snapshot));
+            out.print(" in ");
+            out.print(PrintObjectUtils.objectToString(last));
+            out.print(" -> ");
+            out.println(PrintObjectUtils.objectToString(next));
+            last = next;
+            indentation++;
+        }
+    }
+
+    private void printIndentation(PrintStream out, int indentation) {
+        for (int i = 0; i < indentation; i++) {
+            out.print(" ");
+        }
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/HeapDumperCommand.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import java.net.InetSocketAddress;
+
+import com.redhat.thermostat.client.command.RequestQueue;
+import com.redhat.thermostat.common.command.Request;
+import com.redhat.thermostat.common.command.Request.RequestType;
+import com.redhat.thermostat.common.command.RequestResponseListener;
+import com.redhat.thermostat.common.command.Response;
+import com.redhat.thermostat.common.dao.AgentInfoDAO;
+import com.redhat.thermostat.common.dao.HostRef;
+import com.redhat.thermostat.common.dao.VmRef;
+import com.redhat.thermostat.common.utils.OSGIUtils;
+
+public class HeapDumperCommand {
+    
+    private static final String RECEIVER_CLASS_NAME = "com.redhat.thermostat.agent.heapdumper.internal.HeapDumpReceiver";
+    private static final String VM_ID_PARAM = "vmId";
+
+    private class HeapDumpListener implements RequestResponseListener {
+
+        private Runnable heapDumpCompleteAction;
+
+        private HeapDumpListener(Runnable heapDumpCompleteAction) {
+            this.heapDumpCompleteAction = heapDumpCompleteAction;
+        }
+
+        @Override
+        public void fireComplete(Request request, Response response) {
+            heapDumpCompleteAction.run();
+        }
+        
+    }
+
+    public void execute(AgentInfoDAO agentInfoDAO, VmRef reference, Runnable heapDumpCompleteAction) {
+
+        HostRef targetHostRef = reference.getAgent();
+        String address = agentInfoDAO.getAgentInformation(targetHostRef).getConfigListenAddress();
+        
+        String [] host = address.split(":");
+        InetSocketAddress target = new InetSocketAddress(host[0], Integer.parseInt(host[1]));
+        Request req = new Request(RequestType.RESPONSE_EXPECTED, target);
+        req.setReceiver(RECEIVER_CLASS_NAME);
+        req.setParameter(VM_ID_PARAM, reference.getIdString());
+        req.addListener(new HeapDumpListener(heapDumpCompleteAction));
+
+        RequestQueue queue = OSGIUtils.getInstance().getService(RequestQueue.class);
+        queue.putRequest(req);
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/HeapNotFoundException.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import com.redhat.thermostat.common.cli.CommandException;
+
+@SuppressWarnings("serial")
+class HeapNotFoundException extends CommandException {
+
+    private static final String MESSAGE_TEMPLATE = "Heap ID not found: ";
+
+    HeapNotFoundException(String heapId) {
+        super(MESSAGE_TEMPLATE + heapId);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/HeapPath.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import java.util.Iterator;
+
+public class HeapPath<T> implements Iterable<T> {
+
+    private static class HeapPathIterator<T> implements Iterator<T> {
+
+        private HeapPath<T> path;
+
+        HeapPathIterator(HeapPath<T> path) {
+            this.path = path;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return path != null;
+        }
+
+        @Override
+        public T next() {
+            T next = path.node;
+            path = path.path;
+            return next;
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+    }
+
+    private HeapPath<T> path;
+    private T node;
+    private int length;
+
+    HeapPath(T head) {
+        this(head, null);
+    }
+
+    HeapPath(T node, HeapPath<T> path) {
+        this.node = node;
+        this.path = path;
+        if (path != null) {
+            length = path.length + 1;
+        } else {
+            length = 1;
+        }
+    }
+
+    @Override
+    public Iterator<T> iterator() {
+        return new HeapPathIterator<T>(this);
+    }
+
+    T getNode() {
+        return node;
+    }
+
+    int getLength() {
+        return length;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/ListHeapDumpsCommand.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+
+import com.redhat.thermostat.client.heap.LocaleResources;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.HostVMArguments;
+import com.redhat.thermostat.common.cli.SimpleCommand;
+import com.redhat.thermostat.common.cli.TableRenderer;
+import com.redhat.thermostat.common.dao.HeapDAO;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.common.dao.HostRef;
+import com.redhat.thermostat.common.dao.VmInfoDAO;
+import com.redhat.thermostat.common.dao.VmRef;
+import com.redhat.thermostat.common.locale.Translate;
+import com.redhat.thermostat.common.model.HeapInfo;
+import com.redhat.thermostat.common.utils.OSGIUtils;
+
+public class ListHeapDumpsCommand extends SimpleCommand {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private static final String NAME = "list-heap-dumps";
+
+    private static final String[] COLUMN_NAMES = {
+        translator.localize(LocaleResources.HEADER_HOST_ID),
+        translator.localize(LocaleResources.HEADER_VM_ID),
+        translator.localize(LocaleResources.HEADER_HEAP_ID),
+        translator.localize(LocaleResources.HEADER_TIMESTAMP),
+    };
+
+    private final OSGIUtils serviceProvider;
+
+    public ListHeapDumpsCommand() {
+        this(OSGIUtils.getInstance());
+    }
+
+    /** For tests only */
+    ListHeapDumpsCommand(OSGIUtils serviceProvider) {
+        this.serviceProvider = serviceProvider;
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public void run(CommandContext ctx) throws CommandException {
+        HostVMArguments args = new HostVMArguments(ctx.getArguments(), false, false);
+
+        TableRenderer renderer = new TableRenderer(4);
+
+        renderer.printLine(COLUMN_NAMES);
+
+        HostInfoDAO hostDAO = serviceProvider.getServiceAllowNull(HostInfoDAO.class);
+        if (hostDAO == null) {
+            throw new CommandException(translator.localize(LocaleResources.HOST_SERVICE_UNAVAILABLE));
+        }
+
+        VmInfoDAO vmDAO = serviceProvider.getServiceAllowNull(VmInfoDAO.class);
+        if (vmDAO == null) {
+            throw new CommandException(translator.localize(LocaleResources.VM_SERVICE_UNAVAILABLE));
+        }
+
+        HeapDAO heapDAO = serviceProvider.getServiceAllowNull(HeapDAO.class);
+        if (heapDAO == null) {
+            throw new CommandException(translator.localize(LocaleResources.HEAP_SERVICE_UNAVAILABLE));
+        }
+
+        Collection<HostRef> hosts = args.getHost() != null ? Arrays.asList(args.getHost()) : hostDAO.getHosts();
+        for (HostRef hostRef : hosts) {
+            Collection<VmRef> vms = args.getVM() != null ? Arrays.asList(args.getVM()) : vmDAO.getVMs(hostRef);
+            for (VmRef vmRef : vms) {
+                printDumpsForVm(heapDAO, hostRef, vmRef, renderer);
+            }
+        }
+
+        serviceProvider.ungetService(HeapDAO.class, heapDAO);
+        serviceProvider.ungetService(VmInfoDAO.class, vmDAO);
+        serviceProvider.ungetService(HostInfoDAO.class, hostDAO);
+
+        renderer.render(ctx.getConsole().getOutput());
+    }
+
+    private void printDumpsForVm(HeapDAO heapDAO, HostRef hostRef, VmRef vmRef, TableRenderer renderer) {
+        Collection<HeapInfo> infos = heapDAO.getAllHeapInfo(vmRef);
+        for (HeapInfo info : infos) {
+            renderer.printLine(hostRef.getStringID(),
+                               vmRef.getStringID(),
+                               info.getHeapId(),
+                               new Date(info.getTimeStamp()).toString());
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/ObjectCommandHelper.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import com.redhat.thermostat.client.heap.LocaleResources;
+import com.redhat.thermostat.common.cli.Arguments;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.dao.HeapDAO;
+import com.redhat.thermostat.common.heap.HeapDump;
+import com.redhat.thermostat.common.locale.Translate;
+import com.redhat.thermostat.common.model.HeapInfo;
+import com.sun.tools.hat.internal.model.JavaHeapObject;
+
+class ObjectCommandHelper {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private static final String OBJECT_ID_ARG = "objectId";
+    private static final String HEAP_ID_ARG = "heapId";
+
+    private CommandContext ctx;
+    private HeapDAO dao;
+    private HeapDump heapDump;
+
+    ObjectCommandHelper(CommandContext ctx, HeapDAO dao) {
+        this.ctx = ctx;
+        this.dao = dao;
+    }
+
+    HeapDump getHeapDump() throws CommandException {
+        if (heapDump == null) {
+            loadHeapDump();
+        }
+        return heapDump;
+    }
+
+    private void loadHeapDump() throws CommandException {
+        Arguments args = ctx.getArguments();
+        String heapId = args.getArgument(HEAP_ID_ARG);
+        HeapInfo heapInfo = dao.getHeapInfo(heapId);
+        if (heapInfo == null) {
+            throw new CommandException(translator.localize(LocaleResources.HEAP_ID_NOT_FOUND, heapId));
+        }
+        heapDump = dao.getHeapDump(heapInfo);
+    }
+
+    JavaHeapObject getJavaHeapObject() throws CommandException {
+        HeapDump heapDump = getHeapDump();
+        Arguments args = ctx.getArguments();
+        String objectId = args.getArgument(OBJECT_ID_ARG);
+        JavaHeapObject obj = heapDump.findObject(objectId);
+        if (obj == null) {
+            throw new HeapNotFoundException(objectId);
+        }
+        return obj;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/ObjectInfoCommand.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import java.io.PrintStream;
+import java.util.Enumeration;
+
+import com.redhat.thermostat.client.heap.LocaleResources;
+import com.redhat.thermostat.client.heap.internal.PrintObjectUtils;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.SimpleCommand;
+import com.redhat.thermostat.common.cli.TableRenderer;
+import com.redhat.thermostat.common.dao.HeapDAO;
+import com.redhat.thermostat.common.heap.HeapDump;
+import com.redhat.thermostat.common.locale.Translate;
+import com.redhat.thermostat.common.utils.OSGIUtils;
+import com.sun.tools.hat.internal.model.JavaClass;
+import com.sun.tools.hat.internal.model.JavaField;
+import com.sun.tools.hat.internal.model.JavaHeapObject;
+import com.sun.tools.hat.internal.model.JavaHeapObjectVisitor;
+import com.sun.tools.hat.internal.model.Snapshot;
+
+public class ObjectInfoCommand extends SimpleCommand {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private static final String NAME = "object-info";
+
+    private OSGIUtils serviceProvider;
+    private Snapshot snapshot;
+
+    public ObjectInfoCommand() {
+        this(OSGIUtils.getInstance());
+    }
+
+    ObjectInfoCommand(OSGIUtils serviceProvider) {
+        this.serviceProvider = serviceProvider;
+    }
+
+    @Override
+    public void run(CommandContext ctx) throws CommandException {
+        HeapDAO heapDao = serviceProvider.getServiceAllowNull(HeapDAO.class);
+        if (heapDao == null) {
+            throw new CommandException(translator.localize(LocaleResources.HEAP_SERVICE_UNAVAILABLE));
+        }
+
+        try {
+            run(ctx, heapDao);
+        } finally {
+            serviceProvider.ungetService(HeapDAO.class, heapDao);
+        }
+    }
+
+    private void run(CommandContext ctx, HeapDAO heapDao) throws CommandException {
+        ObjectCommandHelper objCmdHelper = new ObjectCommandHelper(ctx, heapDao);
+        HeapDump heapDump = objCmdHelper.getHeapDump();
+        snapshot = heapDump.getSnapshot();
+        JavaHeapObject obj = objCmdHelper.getJavaHeapObject();
+        TableRenderer table = new TableRenderer(2);
+        table.printLine(translator.localize(LocaleResources.COMMAND_OBJECT_INFO_OBJECT_ID), obj.getIdString());
+        table.printLine(translator.localize(LocaleResources.COMMAND_OBJECT_INFO_TYPE), obj.getClazz().getName());
+        table.printLine(translator.localize(LocaleResources.COMMAND_OBJECT_INFO_SIZE), String.valueOf(obj.getSize()) + " bytes");
+        table.printLine(translator.localize(LocaleResources.COMMAND_OBJECT_INFO_HEAP_ALLOCATED), String.valueOf(obj.isHeapAllocated()));
+        table.printLine(translator.localize(LocaleResources.COMMAND_OBJECT_INFO_REFERENCES), "");
+        printReferences(table, obj);
+        table.printLine(translator.localize(LocaleResources.COMMAND_OBJECT_INFO_REFERRERS), "");
+        printReferrers(table, obj);
+
+        PrintStream out = ctx.getConsole().getOutput();
+        table.render(out);
+
+    }
+
+    private void printReferences(final TableRenderer table, final JavaHeapObject obj) {
+        JavaHeapObjectVisitor v = new JavaHeapObjectVisitor() {
+            
+            @Override
+            public void visit(JavaHeapObject ref) {
+                table.printLine("", describeReference(obj, ref) + " -> " + PrintObjectUtils.objectToString(ref));
+            }
+            
+            @Override
+            public boolean mightExclude() {
+                return false;
+            }
+            
+            @Override
+            public boolean exclude(JavaClass arg0, JavaField arg1) {
+                return false;
+            }
+        };
+        obj.visitReferencedObjects(v);
+    }
+
+    private void printReferrers(TableRenderer table, JavaHeapObject obj) {
+        Enumeration<?> referrers = obj.getReferers();
+        while (referrers.hasMoreElements()) {
+            JavaHeapObject ref = (JavaHeapObject) referrers.nextElement();
+            table.printLine("", PrintObjectUtils.objectToString(ref) + " -> " + describeReference(ref, obj));
+        }
+    }
+
+    private String describeReference(JavaHeapObject from, JavaHeapObject to) {
+        return "[" + from.describeReferenceTo(to, snapshot) + "]";
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/ObjectNotFoundException.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import com.redhat.thermostat.common.cli.CommandException;
+
+@SuppressWarnings("serial")
+class ObjectNotFoundException extends CommandException {
+
+    private static final String MESSAGE_TEMPLATE = "Object not found: ";
+
+    ObjectNotFoundException(String objectId) {
+        super(MESSAGE_TEMPLATE + objectId);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/SaveHeapDumpToFileCommand.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import com.redhat.thermostat.client.heap.LocaleResources;
+import com.redhat.thermostat.common.cli.Arguments;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.SimpleCommand;
+import com.redhat.thermostat.common.dao.HeapDAO;
+import com.redhat.thermostat.common.locale.Translate;
+import com.redhat.thermostat.common.model.HeapInfo;
+import com.redhat.thermostat.common.utils.OSGIUtils;
+import com.redhat.thermostat.common.utils.StreamUtils;
+
+public class SaveHeapDumpToFileCommand extends SimpleCommand {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private static final String NAME = "save-heap-dump-to-file";
+
+    private static final String HEAP_ID_ARGUMENT = "heapId";
+    private static final String FILE_NAME_ARGUMENT = "file";
+
+    private final FileStreamCreator creator;
+    private final OSGIUtils serviceProvider;
+
+    public SaveHeapDumpToFileCommand() {
+        this(OSGIUtils.getInstance(), new FileStreamCreator());
+    }
+
+    SaveHeapDumpToFileCommand(OSGIUtils serviceProvider, FileStreamCreator creator) {
+        this.serviceProvider = serviceProvider;
+        this.creator = creator;
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+
+    public void run(CommandContext ctx) throws CommandException {
+        HeapDAO heapDAO = serviceProvider.getServiceAllowNull(HeapDAO.class);
+        try {
+            run(ctx, heapDAO);
+        } finally {
+            serviceProvider.ungetService(HeapDAO.class, heapDAO);
+            heapDAO = null;
+        }
+    }
+
+    private void run(CommandContext ctx, HeapDAO heapDAO) throws CommandException {
+        Arguments args = ctx.getArguments();
+        String heapId = args.getArgument(HEAP_ID_ARGUMENT);
+        if (heapId == null) {
+            throw new CommandException(translator.localize(LocaleResources.HEAP_ID_REQUIRED));
+        }
+        String filename = args.getArgument(FILE_NAME_ARGUMENT);
+        if (filename == null) {
+            throw new CommandException(translator.localize(LocaleResources.FILE_REQUIRED));
+        }
+
+        HeapInfo heapInfo = heapDAO.getHeapInfo(heapId);
+        try (InputStream heapStream = heapDAO.getHeapDumpData(heapInfo)) {
+            if (heapStream != null) {
+                try {
+                    saveHeapDump(heapStream, filename);
+                    ctx.getConsole().getOutput().println(translator.localize(LocaleResources.COMMAND_SAVE_HEAP_DUMP_SAVED_TO_FILE, filename));
+                } catch (IOException e) {
+                    ctx.getConsole().getOutput().println(translator.localize(LocaleResources.COMMAND_SAVE_HEAP_DUMP_ERROR_SAVING, e.getMessage()));
+                }
+            } else {
+                ctx.getConsole().getOutput().println(translator.localize(LocaleResources.HEAP_ID_NOT_FOUND, heapId));
+            }
+        } catch (IOException e) {
+            throw new CommandException(translator.localize(LocaleResources.COMMAND_SAVE_HEAP_DUMP_ERROR_CLOSING_STREAM, e.getMessage()));
+        }
+    }
+
+    private void saveHeapDump(InputStream heapStream, String filename) throws FileNotFoundException, IOException {
+        try (BufferedInputStream bis = new BufferedInputStream(heapStream);
+             BufferedOutputStream bout = new BufferedOutputStream(creator.createOutputStream(filename))) {
+            StreamUtils.copyStream(bis, bout);
+        }
+    }
+
+    static class FileStreamCreator {
+        public OutputStream createOutputStream(String filename) throws FileNotFoundException {
+            return new FileOutputStream(filename);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/cli/ShowHeapHistogramCommand.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import java.io.PrintStream;
+
+import com.redhat.thermostat.client.heap.LocaleResources;
+import com.redhat.thermostat.common.cli.Arguments;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.SimpleCommand;
+import com.redhat.thermostat.common.cli.TableRenderer;
+import com.redhat.thermostat.common.dao.HeapDAO;
+import com.redhat.thermostat.common.heap.HistogramRecord;
+import com.redhat.thermostat.common.heap.ObjectHistogram;
+import com.redhat.thermostat.common.locale.Translate;
+import com.redhat.thermostat.common.model.HeapInfo;
+import com.redhat.thermostat.common.utils.OSGIUtils;
+
+public class ShowHeapHistogramCommand extends SimpleCommand {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private static final String NAME = "show-heap-histogram";
+
+    private OSGIUtils serviceProvider;
+
+    public ShowHeapHistogramCommand() {
+        this(OSGIUtils.getInstance());
+    }
+
+    ShowHeapHistogramCommand(OSGIUtils serviceProvider) {
+        this.serviceProvider = serviceProvider;
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public void run(CommandContext ctx) throws CommandException {
+        HeapDAO heapDAO = serviceProvider.getServiceAllowNull(HeapDAO.class);
+        if (heapDAO == null) {
+            throw new CommandException(translator.localize(LocaleResources.HEAP_SERVICE_UNAVAILABLE));
+        }
+
+        try {
+            run(ctx, heapDAO);
+        } finally {
+            serviceProvider.ungetService(HeapDAO.class, heapDAO);
+        }
+    }
+
+    private void run(CommandContext ctx, HeapDAO heapDAO) throws CommandException {
+        Arguments args = ctx.getArguments();
+        String heapId = args.getArgument("heapId");
+
+        HeapInfo heapInfo = heapDAO.getHeapInfo(heapId);
+        if (heapInfo == null) {
+            ctx.getConsole().getOutput().println(translator.localize(LocaleResources.HEAP_ID_NOT_FOUND, heapId));
+            return;
+        }
+
+        ObjectHistogram histogram = heapDAO.getHistogram(heapInfo);
+        if (histogram == null) {
+            ctx.getConsole().getOutput().println(translator.localize(LocaleResources.HEAP_ID_NOT_FOUND, heapId));
+            return;
+        } else {
+            printHeapHistogram(histogram, ctx.getConsole().getOutput());
+        }
+    }
+
+    private void printHeapHistogram(ObjectHistogram histogram, PrintStream out) {
+        TableRenderer table = new TableRenderer(3);
+        for (HistogramRecord rec : histogram.getHistogram()) {
+            table.printLine(rec.getClassname(), String.valueOf(rec.getNumberOf()), String.valueOf(rec.getTotalSize()));
+        }
+        table.render(out);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/internal/Activator.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2012 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.client.heap.internal;
+
+import java.util.ServiceLoader;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+import com.redhat.thermostat.common.cli.Command;
+import com.redhat.thermostat.common.cli.CommandRegistry;
+import com.redhat.thermostat.common.cli.CommandRegistryImpl;
+
+public class Activator implements BundleActivator {
+
+    private CommandRegistry reg;
+
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        reg = new CommandRegistryImpl(context);
+        ServiceLoader<Command> cmds = ServiceLoader.load(Command.class,
+                getClass().getClassLoader());
+        reg.registerCommands(cmds);
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        reg.unregisterCommands();
+    }
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/internal/HeapDumpDetailsController.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2012 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.client.heap.internal;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.redhat.thermostat.client.core.views.BasicView;
+import com.redhat.thermostat.client.heap.HeapDumpDetailsView;
+import com.redhat.thermostat.client.heap.HeapDumpDetailsViewProvider;
+import com.redhat.thermostat.client.heap.HeapHistogramView;
+import com.redhat.thermostat.client.heap.HeapHistogramViewProvider;
+import com.redhat.thermostat.client.heap.LocaleResources;
+import com.redhat.thermostat.client.heap.ObjectDetailsView;
+import com.redhat.thermostat.client.heap.ObjectDetailsViewProvider;
+import com.redhat.thermostat.client.heap.ObjectRootsViewProvider;
+import com.redhat.thermostat.client.osgi.service.ApplicationService;
+import com.redhat.thermostat.common.heap.HeapDump;
+import com.redhat.thermostat.common.locale.Translate;
+import com.redhat.thermostat.common.utils.LoggingUtils;
+
+public class HeapDumpDetailsController {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private static final Logger log = LoggingUtils.getLogger(HeapDumpDetailsController.class);
+
+    private final ApplicationService appService;
+
+    private HeapDumpDetailsView view;
+    private HeapDump heapDump;
+    private HeapHistogramViewProvider histogramViewProvider;
+    private ObjectDetailsViewProvider objectDetailsViewProvider;
+    private ObjectRootsViewProvider objectRootsViewProvider;
+
+    public HeapDumpDetailsController(ApplicationService appService, HeapDumpDetailsViewProvider viewProvider, HeapHistogramViewProvider histogramProvider, ObjectDetailsViewProvider objectDetailsProvider, ObjectRootsViewProvider objectRootsProvider) {
+        this.appService = appService;
+        this.histogramViewProvider = histogramProvider;
+        this.objectDetailsViewProvider = objectDetailsProvider;
+        this.objectRootsViewProvider = objectRootsProvider;
+        view = viewProvider.createView();
+    }
+
+    public void setDump(HeapDump dump) {
+        this.heapDump = dump;
+        try {
+            HeapHistogramView heapHistogramView = histogramViewProvider.createView();
+            heapHistogramView.display(heapDump.getHistogram());
+            String title = translator.localize(LocaleResources.HEAP_DUMP_SECTION_HISTOGRAM);
+            view.addSubView(title, heapHistogramView);
+        } catch (IOException e) {
+            log.log(Level.SEVERE, "unexpected error while reading heap dump", e);
+        }
+
+        ObjectDetailsController controller = new ObjectDetailsController(appService, dump, objectDetailsViewProvider, objectRootsViewProvider);
+        ObjectDetailsView detailsView = controller.getView();
+        view.addSubView(translator.localize(LocaleResources.HEAP_DUMP_SECTION_OBJECT_BROWSER), detailsView);
+
+        // do a dummy search right now to prep the index
+        heapDump.searchObjects("A_RANDOM_PATTERN", 1);
+    }
+
+    public BasicView getView() {
+        return view;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/internal/Histogram.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012 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.client.heap.internal;
+
+import java.util.List;
+
+public class Histogram {
+
+    private String[] header;
+    
+    private List<Object[]> data;
+    
+    Histogram(String[] header) {
+        this.header = header;
+    }
+    
+    public String[] getHistogramColums() {
+        return header;
+    }
+
+    void setData(List<Object[]> data) {
+        this.data = data;
+    }
+
+   public List<Object[]> getData() {
+    return data;
+   }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/internal/ObjectDetailsController.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2012 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.client.heap.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+
+import com.redhat.thermostat.client.heap.HeapObjectUI;
+import com.redhat.thermostat.client.heap.ObjectDetailsView;
+import com.redhat.thermostat.client.heap.ObjectDetailsViewProvider;
+import com.redhat.thermostat.client.heap.ObjectRootsViewProvider;
+import com.redhat.thermostat.client.heap.ObjectDetailsView.ObjectAction;
+import com.redhat.thermostat.client.heap.ObjectDetailsView.ObjectReferenceCallback;
+import com.redhat.thermostat.client.osgi.service.ApplicationService;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.NotImplementedException;
+import com.redhat.thermostat.common.heap.HeapDump;
+import com.sun.tools.hat.internal.model.JavaClass;
+import com.sun.tools.hat.internal.model.JavaField;
+import com.sun.tools.hat.internal.model.JavaHeapObject;
+import com.sun.tools.hat.internal.model.JavaHeapObjectVisitor;
+
+public class ObjectDetailsController {
+
+    private ApplicationService appService;
+    private HeapDump heapDump;
+    private ObjectDetailsView view;
+    private ObjectRootsViewProvider viewProvider;
+
+    public ObjectDetailsController(ApplicationService appService, HeapDump heapDump, ObjectDetailsViewProvider viewProvider, ObjectRootsViewProvider rootsViewProvider) {
+        this.appService = appService;
+        this.heapDump = heapDump;
+        this.viewProvider = rootsViewProvider;
+
+        view = viewProvider.createView();
+        addListenersToView();
+    }
+
+    private void addListenersToView() {
+
+        view.addObjectActionListener(new ActionListener<ObjectAction>() {
+            @Override
+            public void actionPerformed(ActionEvent<ObjectAction> actionEvent) {
+                switch (actionEvent.getActionId()) {
+                case SEARCH:
+                    searchForObject();
+                    break;
+                case GET_OBJECT_DETAIL:
+                    showObjectInfo();
+                    break;
+                case SHOW_ROOT_TO_GC:
+                    HeapObjectUI heapObj = (HeapObjectUI) actionEvent.getPayload();
+                    showPathToGC(heapObj);
+                    break;
+                default:
+                    throw new NotImplementedException("unknown action fired by " + actionEvent.getSource());
+                }
+
+            }
+        });
+
+        view.addObjectReferenceCallback(new ObjectReferenceCallback() {
+            @Override
+            public Collection<HeapObjectUI> getReferrers(HeapObjectUI obj) {
+                JavaHeapObject heapObject = heapDump.findObject(obj.objectId);
+
+                @SuppressWarnings("unchecked")
+                Enumeration<JavaHeapObject> referrers = heapObject.getReferers();
+
+                List<HeapObjectUI> objects = new ArrayList<>();
+                while (referrers.hasMoreElements()) {
+                    heapObject = referrers.nextElement();
+                    objects.add(new HeapObjectUI(heapObject.getIdString(), PrintObjectUtils.objectToString(heapObject)));
+                }
+                return objects;
+            }
+
+            @Override
+            public Collection<HeapObjectUI> getReferences(HeapObjectUI obj) {
+                final JavaHeapObject heapObject = heapDump.findObject(obj.objectId);
+
+                final List<JavaHeapObject> references = new ArrayList<>();
+
+                JavaHeapObjectVisitor v = new JavaHeapObjectVisitor() {
+
+                    @Override
+                    public void visit(JavaHeapObject other) {
+                        references.add(other);
+                    }
+
+                    @Override
+                    public boolean mightExclude() {
+                        /* we never return true in exclude */
+                        return false;
+                    }
+
+                    @Override
+                    public boolean exclude(JavaClass clazz, JavaField f) {
+                        /* visit every field in every java class */
+                        return false;
+                    }
+                };
+
+                heapObject.visitReferencedObjects(v);
+
+                List<HeapObjectUI> objects = new ArrayList<>();
+                for (JavaHeapObject ref: references) {
+                    objects.add(new HeapObjectUI(ref.getIdString(), PrintObjectUtils.objectToString(ref)));
+                }
+                return objects;
+            }
+        });
+    }
+
+    private void searchForObject() {
+        String searchText = view.getSearchText();
+        if (searchText == null || searchText.trim().isEmpty()) {
+            return;
+        }
+
+        final int maxResults = computeResultLimit(searchText);
+
+        if (!searchText.contains("*") && !searchText.contains("?")) {
+            searchText = "*" + searchText + "*";
+        }
+
+        final String wildcardQuery = searchText;
+
+        appService.getApplicationExecutor().execute(new Runnable() {
+
+            @Override
+            public void run() {
+                Collection<String> objectIds = heapDump.searchObjects(wildcardQuery, maxResults);
+
+                List<HeapObjectUI> toDisplay = new ArrayList<>();
+                for (String id: objectIds) {
+                    JavaHeapObject heapObject = heapDump.findObject(id);
+                    toDisplay.add(new HeapObjectUI(id, PrintObjectUtils.objectToString(heapObject)));
+                }
+                view.setMatchingObjects(toDisplay);
+            }
+        });
+
+    }
+
+    private int computeResultLimit(String searchText) {
+        return Math.min(1000, searchText.length() * 100);
+    }
+
+    private void showObjectInfo() {
+        HeapObjectUI matchingObject = view.getSelectedMatchingObject();
+        if (matchingObject == null) {
+            return;
+        }
+        String objectId = matchingObject.objectId;
+        JavaHeapObject object = heapDump.findObject(objectId);
+        view.setObjectDetails(object);
+    }
+
+    private void showPathToGC(HeapObjectUI targetObject) {
+        JavaHeapObject heapObject = heapDump.findObject(targetObject.objectId);
+
+        ObjectRootsController controller = new ObjectRootsController(heapDump, heapObject, viewProvider);
+        controller.show();
+    }
+
+    public ObjectDetailsView getView() {
+        return view;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/internal/ObjectRootsController.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2012 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.client.heap.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import com.redhat.thermostat.client.heap.HeapObjectUI;
+import com.redhat.thermostat.client.heap.LocaleResources;
+import com.redhat.thermostat.client.heap.ObjectRootsView;
+import com.redhat.thermostat.client.heap.ObjectRootsViewProvider;
+import com.redhat.thermostat.client.heap.ObjectRootsView.Action;
+import com.redhat.thermostat.client.heap.cli.FindRoot;
+import com.redhat.thermostat.client.heap.cli.HeapPath;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.NotImplementedException;
+import com.redhat.thermostat.common.heap.HeapDump;
+import com.redhat.thermostat.common.locale.Translate;
+import com.sun.tools.hat.internal.model.JavaHeapObject;
+
+public class ObjectRootsController {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private final ObjectRootsView view;
+
+    private final HeapDump heapDump;
+    private final JavaHeapObject heapObject;
+    private final FindRoot rootFinder;
+
+    public ObjectRootsController(HeapDump dump, JavaHeapObject heapObject, ObjectRootsViewProvider viewProvider) {
+        this(dump, heapObject, new FindRoot(), viewProvider);
+    }
+
+    public ObjectRootsController(HeapDump dump, JavaHeapObject heapObject, FindRoot findRoot, ObjectRootsViewProvider viewProvider) {
+        this.heapDump = dump;
+        this.heapObject = heapObject;
+        this.rootFinder = findRoot;
+
+        view = viewProvider.createView();
+
+        view.addActionListener(new ActionListener<ObjectRootsView.Action>() {
+
+            @Override
+            public void actionPerformed(ActionEvent<Action> actionEvent) {
+                switch (actionEvent.getActionId()) {
+                case VISIBLE:
+                    view.showView();
+                    break;
+                case HIDDEN:
+                    view.hideView();
+                    break;
+                case OBJECT_SELECTED:
+                    HeapObjectUI obj = (HeapObjectUI) actionEvent.getPayload();
+                    showObjectDetails(obj);
+                    break;
+                default:
+                    throw new NotImplementedException("unexpected action " +
+                            actionEvent.getActionId() + " recieved by " + ObjectRootsController.this.getClass().getName());
+                }
+
+            }
+        });
+    }
+
+    private void showObjectDetails(HeapObjectUI uiObject) {
+        JavaHeapObject obj = heapDump.findObject(uiObject.objectId);
+        String text = translator.localize(LocaleResources.COMMAND_OBJECT_INFO_OBJECT_ID) + " " + obj.getIdString() + "\n" +
+                translator.localize(LocaleResources.COMMAND_OBJECT_INFO_TYPE) + " " + obj.getClazz().getName() + "\n" +
+                translator.localize(LocaleResources.COMMAND_OBJECT_INFO_SIZE) + " " + String.valueOf(obj.getSize()) + " bytes" + "\n" +
+                translator.localize(LocaleResources.COMMAND_OBJECT_INFO_HEAP_ALLOCATED) + " " + String.valueOf(obj.isHeapAllocated()) + "\n";
+
+        if (obj.getRoot() != null) {
+            text = text + obj.getRoot().getDescription();
+        }
+        view.setObjectDetails(text);
+    }
+
+
+    public void show() {
+        Collection<HeapPath<JavaHeapObject>> paths = rootFinder.findShortestPathsToRoot(heapObject, false);
+        Iterator<HeapPath<JavaHeapObject>> iter = paths.iterator();
+        if (iter.hasNext()) {
+            HeapPath<JavaHeapObject> pathToRoot = iter.next();
+
+            List<HeapObjectUI> path = new ArrayList<>();
+            for (JavaHeapObject heapObj : pathToRoot) {
+                path.add(new HeapObjectUI(heapObj.getIdString(), PrintObjectUtils.objectToString(heapObj)));
+            }
+            view.setPathToRoot(path);
+        }
+        view.showView();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/java/com/redhat/thermostat/client/heap/internal/PrintObjectUtils.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012 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.client.heap.internal;
+
+import com.sun.tools.hat.internal.model.JavaHeapObject;
+
+public class PrintObjectUtils {
+
+    public static String objectToString(JavaHeapObject obj) {
+        return obj.getClazz().getName() + "@" + obj.getIdString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/resources/META-INF/services/com.redhat.thermostat.common.cli.Command	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,7 @@
+com.redhat.thermostat.client.heap.cli.DumpHeapCommand
+com.redhat.thermostat.client.heap.cli.ListHeapDumpsCommand
+com.redhat.thermostat.client.heap.cli.SaveHeapDumpToFileCommand
+com.redhat.thermostat.client.heap.cli.ShowHeapHistogramCommand
+com.redhat.thermostat.client.heap.cli.FindObjectsCommand
+com.redhat.thermostat.client.heap.cli.ObjectInfoCommand
+com.redhat.thermostat.client.heap.cli.FindRootCommand
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/main/resources/com/redhat/thermostat/client/heap/strings.properties	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,58 @@
+MISSING_INFO = Missing Information
+HOST_SERVICE_UNAVAILABLE = Unable to access host information (HostInfoDAO unavailable)
+VM_SERVICE_UNAVAILABLE = Unable to access vm information (VmInfoDAO unavailable)
+HEAP_SERVICE_UNAVAILABLE = Unable to access heap informatio (HeapDAO unavailable)
+
+HEADER_TIMESTAMP = TIMESTAMP
+HEADER_HOST_ID = HOST ID
+HEADER_VM_ID = VM ID
+HEADER_HEAP_ID = HEAP ID
+HEADER_OBJECT_ID = ID
+HEADER_OBJECT_TYPE = TYPE
+
+FILE_REQUIRED = A file name is required
+INVALID_LIMIT = Invalid limit {0}
+HEAP_ID_NOT_FOUND = Heap ID not found: {0}
+HEAP_ID_REQUIRED = Heap ID required
+SEARCH_TERM_REQUIRED = A search term is required
+
+
+COMMAND_HEAP_DUMP_DONE = Done
+
+COMMAND_FIND_ROOT_NO_ROOT_FOUND = No root found for: {0}
+
+COMMAND_OBJECT_INFO_OBJECT_ID = Object ID:
+COMMAND_OBJECT_INFO_TYPE = Type:
+COMMAND_OBJECT_INFO_SIZE = Size:
+COMMAND_OBJECT_INFO_HEAP_ALLOCATED = Heap allocated:
+COMMAND_OBJECT_INFO_REFERENCES = References:
+COMMAND_OBJECT_INFO_REFERRERS = Referrers:
+
+COMMAND_SAVE_HEAP_DUMP_SAVED_TO_FILE = Saved heap dump to {0}
+COMMAND_SAVE_HEAP_DUMP_ERROR_SAVING = error saving heap to file: {0}
+COMMAND_SAVE_HEAP_DUMP_ERROR_CLOSING_STREAM = error closing heap stream: {0}
+
+HEAP_SECTION_TITLE = Memory Analyzer
+HEAP_OVERVIEW_TITLE = Heap Usage Overview
+HEAP_CHART_TITLE = Used Heap vs. Heap Capacity
+HEAP_CHART_TIME_AXIS = Time
+HEAP_CHART_HEAP_AXIS = Heap
+HEAP_CHART_CAPACITY = Heap Capacity
+HEAP_CHART_USED = Used Heap
+
+HEAP_DUMP_SECTION_HISTOGRAM = Histogram
+HEAP_DUMP_SECTION_OBJECT_BROWSER = Object Browser
+
+HEAP_DUMP_CLASS_USAGE = Classes Usage
+HEAP_DUMP_HISTOGRAM_COLUMN_CLASS = Class
+HEAP_DUMP_HISTOGRAM_COLUMN_INSTANCES = Instances
+HEAP_DUMP_HISTOGRAM_COLUMN_SIZE = Size (in bytes)
+
+HEAP_DUMP_OBJECT_BROWSE_SEARCH_HINT = Search for objects by class name (either a partial class name or a wildcard pattern)
+HEAP_DUMP_OBJECT_BROWSE_SEARCH_PATTERN_HELP = Either a partial class name ("Button" will find "javax.swing.JButton") or a wildcard pattern ("*JButton*" will find "javax.swing.JButtonBeanInfo")
+HEAP_DUMP_OBJECT_BROWSE_SEARCH_LABEL = Search for Object
+HEAP_DUMP_OBJECT_BROWSE_REFERRERS = Referrers
+HEAP_DUMP_OBJECT_BROWSE_REFERENCES = References
+HEAP_DUMP_OBJECT_FIND_ROOT = Find Root
+
+OBJECT_ROOTS_VIEW_TITLE = Object Roots
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/HeapDumpControllerTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,405 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Matchers.same;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.client.heap.HeapView.HeapDumperAction;
+import com.redhat.thermostat.client.heap.cli.HeapDumperCommand;
+import com.redhat.thermostat.client.osgi.service.ApplicationCache;
+import com.redhat.thermostat.client.osgi.service.ApplicationService;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.Timer;
+import com.redhat.thermostat.common.TimerFactory;
+import com.redhat.thermostat.common.appctx.ApplicationContext;
+import com.redhat.thermostat.common.appctx.ApplicationContextUtil;
+import com.redhat.thermostat.common.dao.AgentInfoDAO;
+import com.redhat.thermostat.common.dao.HeapDAO;
+import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
+import com.redhat.thermostat.common.dao.VmRef;
+import com.redhat.thermostat.common.heap.HeapDump;
+import com.redhat.thermostat.common.model.HeapInfo;
+import com.redhat.thermostat.common.model.VmMemoryStat;
+import com.redhat.thermostat.common.model.VmMemoryStat.Generation;
+import com.redhat.thermostat.common.model.VmMemoryStat.Space;
+
+public class HeapDumpControllerTest {
+
+    private ActionListener<HeapView.Action> actionListener;
+    private ActionListener<HeapView.HeapDumperAction> heapDumperListener;
+    
+    private Timer timer;
+    
+    private AgentInfoDAO agentDao;
+    private HeapDAO heapDao;
+    private VmMemoryStatDAO vmDao;
+    private HeapView view;
+    private HeapDumpDetailsView detailsView;
+    
+    @SuppressWarnings("unused")
+    private HeapDumpController controller;
+    private HeapDumperCommand heapDumperCommand;
+    private ApplicationService appService;
+    private ArgumentCaptor<Runnable> timerActionCaptor;
+    
+    private HeapViewProvider viewProvider;
+    private HeapDumpDetailsViewProvider detailsViewProvider;
+    private HeapHistogramViewProvider histogramProvider;
+    private ObjectDetailsViewProvider objectDetailsProvider;
+    private ObjectRootsViewProvider objectRootsProvider;
+
+    @Before
+    public void setUp() {
+        ApplicationContextUtil.resetApplicationContext();
+
+        agentDao = mock(AgentInfoDAO.class);
+        heapDao = mock(HeapDAO.class);
+        vmDao = mock(VmMemoryStatDAO.class);
+
+        setUpTimers();
+        setUpView();
+    }
+    
+    private void setUpTimers() {
+        timer = mock(Timer.class);
+        timerActionCaptor = ArgumentCaptor.forClass(Runnable.class);
+        doNothing().when(timer).setAction(timerActionCaptor.capture());
+
+        TimerFactory timerFactory = mock(TimerFactory.class);
+        when(timerFactory.createTimer()).thenReturn(timer);
+        ApplicationContext.getInstance().setTimerFactory(timerFactory);
+    }
+    
+    private void setUpView() {
+        view = mock(HeapView.class);
+        viewProvider = mock(HeapViewProvider.class);
+        when(viewProvider.createView()).thenReturn(view);
+        
+        detailsViewProvider = mock(HeapDumpDetailsViewProvider.class);
+        detailsView = mock(HeapDumpDetailsView.class);
+        when(detailsViewProvider.createView()).thenReturn(detailsView);
+
+        HeapHistogramView histogramView = mock(HeapHistogramView.class);
+        histogramProvider = mock(HeapHistogramViewProvider.class);
+        when(histogramProvider.createView()).thenReturn(histogramView);
+
+        ObjectDetailsView objectView = mock(ObjectDetailsView.class);
+        objectDetailsProvider = mock(ObjectDetailsViewProvider.class);
+        when(objectDetailsProvider.createView()).thenReturn(objectView);
+
+        ObjectRootsView objectRootsView = mock(ObjectRootsView.class);
+        objectRootsProvider = mock(ObjectRootsViewProvider.class);
+        when(objectRootsProvider.createView()).thenReturn(objectRootsView);
+    }
+    
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private void setUpListeners() {        
+        ArgumentCaptor<ActionListener> viewArgumentCaptor1 = ArgumentCaptor.forClass(ActionListener.class);
+        doNothing().when(view).addActionListener(viewArgumentCaptor1.capture());
+        
+        ArgumentCaptor<ActionListener> viewArgumentCaptor2 = ArgumentCaptor.forClass(ActionListener.class);
+        doNothing().when(view).addDumperListener(viewArgumentCaptor2.capture());
+        
+        createController();
+        
+        actionListener = viewArgumentCaptor1.getValue();
+        heapDumperListener = viewArgumentCaptor2.getValue();
+    }
+    
+    private void createController() {
+        ApplicationCache cache = mock(ApplicationCache.class);
+        appService = mock(ApplicationService.class);
+        when(appService.getApplicationCache()).thenReturn(cache);
+        VmRef ref = mock(VmRef.class);
+        heapDumperCommand = mock(HeapDumperCommand.class);
+        controller = new HeapDumpController(agentDao, vmDao, heapDao, ref, appService,
+                heapDumperCommand, viewProvider, detailsViewProvider,
+                histogramProvider, objectDetailsProvider, objectRootsProvider);
+    }
+    
+    @After
+    public void tearDown() {
+    	controller = null;
+    	vmDao = null;
+    	heapDao = null;
+    	viewProvider = null;
+        detailsViewProvider = null;
+        histogramProvider = null;
+        objectDetailsProvider = null;
+        objectRootsProvider = null;
+        ApplicationContextUtil.resetApplicationContext();
+    }
+
+    @Test
+    public void testTimerStartOnViewVisible() {
+        
+        setUpListeners();
+
+        actionListener.actionPerformed(new ActionEvent<>(view, HeapView.Action.VISIBLE));
+        verify(timer).start();
+    }
+
+    @Test
+    public void testTimerStopsOnViewHidden() {
+        
+        setUpListeners();
+        
+        actionListener.actionPerformed(new ActionEvent<>(view, HeapView.Action.HIDDEN));
+        verify(timer).stop();
+    }
+    
+    @Test
+    public void testNotAddHeapDumpsAtStartupWhenNoDumps() {
+                
+        when(heapDao.getAllHeapInfo(any(VmRef.class))).thenReturn(new ArrayList<HeapInfo>());
+        
+        createController();
+        
+        verify(view, times(0)).addHeapDump(any(HeapDump.class));
+    }
+    
+    @Test
+    public void testAddHeapDumpsAtStartupWhenDumpsAreThere() {
+        HeapInfo info1 = mock(HeapInfo.class);
+        HeapInfo info2 = mock(HeapInfo.class);
+        Collection<HeapInfo> infos = new ArrayList<HeapInfo>();
+        infos.add(info1);
+        infos.add(info2);
+        
+        when(heapDao.getAllHeapInfo(any(VmRef.class))).thenReturn(infos);
+
+        createController();
+        
+        verify(view, times(2)).addHeapDump(any(HeapDump.class));
+    }
+    
+    @Test
+    public void testOpenDumpCalledWhenPreviousDump() {
+        
+        HeapDump dump = mock(HeapDump.class);
+        
+        HeapInfo info1 = mock(HeapInfo.class);
+        when(dump.getInfo()).thenReturn(info1);
+        
+        HeapInfo info2 = mock(HeapInfo.class);
+        Collection<HeapInfo> infos = new ArrayList<HeapInfo>();
+        infos.add(info1);
+        infos.add(info2);
+        
+        when(heapDao.getAllHeapInfo(any(VmRef.class))).thenReturn(infos);
+        
+        ApplicationCache cache = mock(ApplicationCache.class);
+        when(cache.getAttribute(any(VmRef.class))).thenReturn(dump);
+        
+        appService = mock(ApplicationService.class);
+        when(appService.getApplicationCache()).thenReturn(cache);
+        VmRef ref = mock(VmRef.class);
+        controller = new HeapDumpController(agentDao, vmDao, heapDao, ref, appService,
+                heapDumperCommand, viewProvider, detailsViewProvider,
+                histogramProvider, objectDetailsProvider, objectRootsProvider);
+        
+        verify(view, times(1)).setChildView(any(HeapView.class));
+        verify(view, times(1)).openDumpView();
+    }
+    
+    @Test
+    public void testNotOpenDumpCalledWhenNoPreviousDump() {
+
+        HeapInfo info1 = mock(HeapInfo.class);        
+        HeapInfo info2 = mock(HeapInfo.class);
+        Collection<HeapInfo> infos = new ArrayList<HeapInfo>();
+        infos.add(info1);
+        infos.add(info2);
+        
+        when(heapDao.getAllHeapInfo(any(VmRef.class))).thenReturn(infos);
+        
+        ApplicationCache cache = mock(ApplicationCache.class);
+        when(cache.getAttribute(any(VmRef.class))).thenReturn(null);
+        
+        appService = mock(ApplicationService.class);
+        when(appService.getApplicationCache()).thenReturn(cache);
+        VmRef ref = mock(VmRef.class);
+        controller = new HeapDumpController(agentDao, vmDao, heapDao, ref, appService,
+                heapDumperCommand, viewProvider, detailsViewProvider,
+                histogramProvider, objectDetailsProvider, objectRootsProvider);
+        
+        verify(view, times(0)).openDumpView();
+    }
+
+    @Test
+    public void testRequestHeapDump() {
+
+        setUpListeners();
+
+        heapDumperListener.actionPerformed(new ActionEvent<HeapDumperAction>(view, HeapDumperAction.DUMP_REQUESTED));
+
+        ArgumentCaptor<Runnable> heapDumpCompleteAction = ArgumentCaptor.forClass(Runnable.class);
+        verify(heapDumperCommand).execute(same(agentDao), any(VmRef.class), heapDumpCompleteAction.capture());
+        heapDumpCompleteAction.getValue().run();
+        verify(view).notifyHeapDumpComplete();
+
+    }
+ 
+    @SuppressWarnings("unchecked")
+	@Test
+    public void testTimerChecksForNewHeapDumps() {
+
+        HeapInfo info1 = mock(HeapInfo.class);
+        HeapInfo info2 = mock(HeapInfo.class);
+        Collection<HeapInfo> infos = new ArrayList<HeapInfo>();
+        infos.add(info1);
+        infos.add(info2);
+        
+        when(heapDao.getAllHeapInfo(any(VmRef.class))).thenReturn(infos);
+
+        createController();
+
+        timerActionCaptor.getValue().run();
+
+        @SuppressWarnings("rawtypes")
+		ArgumentCaptor<List> heapDumps = ArgumentCaptor.forClass(List.class);
+        verify(view).updateHeapDumpList(heapDumps.capture());
+        assertTrue(heapDumps.getValue().contains(new HeapDump(info1, heapDao)));
+        assertTrue(heapDumps.getValue().contains(new HeapDump(info2, heapDao)));
+    }
+
+    @Test
+    public void testTimerFetchesMemoryDataAndUpdatesView() {
+        createController();
+        Runnable timerAction = timerActionCaptor.getValue();
+
+        final long CAPACITY = 10;
+        final long USED = 5;
+        Space space = new Space();
+        space.capacity = CAPACITY;
+        space.maxCapacity = 20;
+        space.used = USED;
+        Generation gen = new Generation();
+        gen.name = "foobar";
+        gen.spaces = Arrays.asList(space);
+        VmMemoryStat stat = new VmMemoryStat();
+        stat.setGenerations(Arrays.asList(gen));
+
+        when(vmDao.getLatestVmMemoryStats(isA(VmRef.class), anyLong())).thenReturn(Arrays.asList(stat));
+
+        timerAction.run();
+
+        ArgumentCaptor<Long> timeStampCaptor = ArgumentCaptor.forClass(Long.class);
+        verify(vmDao).getLatestVmMemoryStats(isA(VmRef.class), timeStampCaptor.capture());
+        assertTimeStampIsAround(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1), timeStampCaptor.getValue());
+        verify(view).updateUsedAndCapacity(USED + " B", CAPACITY + " B");
+    }
+
+    @Test
+    public void testTimerFetchesMemoryDataDeltaOnly() {
+        ArgumentCaptor<Long> timeStampCaptor = ArgumentCaptor.forClass(Long.class);
+
+        final long DATA_TIMESTAMP = System.currentTimeMillis() + 1000000000;
+        Space space = new Space();
+        space.capacity = 10;
+        space.maxCapacity = 20;
+        space.used = 5;
+        Generation gen = new Generation();
+        gen.name = "foobar";
+        gen.spaces = Arrays.asList(space);
+        VmMemoryStat stat = new VmMemoryStat();
+        stat.setTimeStamp(DATA_TIMESTAMP);
+        stat.setGenerations(Arrays.asList(gen));
+
+        when(vmDao.getLatestVmMemoryStats(isA(VmRef.class), anyLong())).thenReturn(Arrays.asList(stat));
+
+        createController();
+        Runnable timerAction = timerActionCaptor.getValue();
+
+        timerAction.run();
+        timerAction.run();
+
+        verify(vmDao, times(2)).getLatestVmMemoryStats(isA(VmRef.class), timeStampCaptor.capture());
+
+        long timeStamp1 = timeStampCaptor.getAllValues().get(0);
+        assertTimeStampIsAround(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1), timeStamp1);
+
+        long timeStamp2 = timeStampCaptor.getAllValues().get(1);
+        assertTimeStampIsAround(DATA_TIMESTAMP, timeStamp2);
+    }
+
+    @Test
+    public void testTimerFetchesMemoryDataDeltaOnlyEvenWithNoData() {
+        ArgumentCaptor<Long> timeStampCaptor = ArgumentCaptor.forClass(Long.class);
+
+        createController();
+        Runnable timerAction = timerActionCaptor.getValue();
+
+        timerAction.run();
+        timerAction.run();
+
+        verify(vmDao, times(2)).getLatestVmMemoryStats(isA(VmRef.class), timeStampCaptor.capture());
+
+        long timeStamp1 = timeStampCaptor.getAllValues().get(0);
+        assertTimeStampIsAround(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1), timeStamp1);
+
+        long timeStamp2 = timeStampCaptor.getAllValues().get(1);
+        assertTimeStampIsAround(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1), timeStamp2);
+    }
+
+    private void assertTimeStampIsAround(long expected, long actual) {
+        assertTrue(actual <= expected + 1000);
+        assertTrue(actual >= expected - 1000);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/HeapDumpDetailsControllerTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.client.heap.internal.HeapDumpDetailsController;
+import com.redhat.thermostat.client.osgi.service.ApplicationService;
+import com.redhat.thermostat.common.appctx.ApplicationContextUtil;
+import com.redhat.thermostat.common.heap.HeapDump;
+import com.redhat.thermostat.common.heap.ObjectHistogram;
+
+public class HeapDumpDetailsControllerTest {
+
+    private HeapDumpDetailsView view;
+    private HeapDumpDetailsViewProvider viewProvider;
+    private HeapHistogramViewProvider histogramProvider;
+    private ObjectDetailsViewProvider objectDetailsProvider;
+    private ObjectRootsViewProvider objectRootsProvider;
+
+    @Before
+    public void setUp() {
+        ApplicationContextUtil.resetApplicationContext();
+
+        viewProvider = mock(HeapDumpDetailsViewProvider.class);
+        view = mock(HeapDumpDetailsView.class);
+        when(viewProvider.createView()).thenReturn(view);
+
+        HeapHistogramView histogramView = mock(HeapHistogramView.class);
+        histogramProvider = mock(HeapHistogramViewProvider.class);
+        when(histogramProvider.createView()).thenReturn(histogramView);
+
+        ObjectDetailsView objectView = mock(ObjectDetailsView.class);
+        objectDetailsProvider = mock(ObjectDetailsViewProvider.class);
+        when(objectDetailsProvider.createView()).thenReturn(objectView);
+
+        ObjectRootsView objectRootsView = mock(ObjectRootsView.class);
+        objectRootsProvider = mock(ObjectRootsViewProvider.class);
+        when(objectRootsProvider.createView()).thenReturn(objectRootsView);
+    }
+
+    @After
+    public void tearDown() {
+        viewProvider = null;
+        histogramProvider = null;
+        objectDetailsProvider = null;
+        objectRootsProvider = null;
+        ApplicationContextUtil.resetApplicationContext();
+    }
+
+    @Test
+    public void verifyInitialize() throws IOException {
+        ApplicationService appService = mock(ApplicationService.class);
+
+        ObjectHistogram histogram = mock(ObjectHistogram.class);
+
+        HeapDump dump = mock(HeapDump.class);
+        when(dump.getHistogram()).thenReturn(histogram);
+
+        HeapDumpDetailsController controller = new HeapDumpDetailsController(
+                appService, viewProvider, histogramProvider,
+                objectDetailsProvider, objectRootsProvider);
+        controller.setDump(dump);
+
+        verify(dump).searchObjects(isA(String.class), anyInt());
+        verify(view)
+                .addSubView(isA(String.class), isA(HeapHistogramView.class));
+        verify(view)
+                .addSubView(isA(String.class), isA(ObjectDetailsView.class));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/LocaleResourcesTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+import java.io.IOException;
+import java.util.Properties;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+
+public class LocaleResourcesTest {
+
+    @Test
+    public void testLocalizedStringsArePresent() throws IOException {
+
+        String stringsResource = "/" + LocaleResources.RESOURCE_BUNDLE.replace(".", "/") + ".properties";
+
+        Properties props = new Properties();
+        props.load(getClass().getResourceAsStream(stringsResource));
+
+        Assert.assertEquals(LocaleResources.values().length, props.values().size());
+        for (LocaleResources resource : LocaleResources.values()) {
+            Assert.assertTrue("missing property from resource bound file: " + resource,
+                              props.containsKey(resource.name()));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/ObjectDetailsControllerTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,289 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.contains;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
+import org.mockito.stubbing.OngoingStubbing;
+
+import com.redhat.thermostat.client.heap.ObjectDetailsView.ObjectAction;
+import com.redhat.thermostat.client.heap.internal.ObjectDetailsController;
+import com.redhat.thermostat.client.osgi.service.ApplicationService;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.appctx.ApplicationContextUtil;
+import com.redhat.thermostat.common.heap.HeapDump;
+import com.sun.tools.hat.internal.model.JavaClass;
+import com.sun.tools.hat.internal.model.JavaHeapObject;
+
+public class ObjectDetailsControllerTest {
+
+    private ObjectDetailsView view;
+    private ApplicationService appService;
+    private ObjectRootsViewProvider objectRootsProvider;
+    private ObjectDetailsViewProvider objectDetailsProvider;
+
+    private ArgumentCaptor<Runnable> runnableCaptor;
+
+    @Before
+    public void setUp() {
+        ApplicationContextUtil.resetApplicationContext();
+
+        view = mock(ObjectDetailsView.class);
+        objectDetailsProvider = mock(ObjectDetailsViewProvider.class);
+        when(objectDetailsProvider.createView()).thenReturn(view);
+        
+        objectRootsProvider = mock(ObjectRootsViewProvider.class);
+        when(objectRootsProvider.createView()).thenReturn(mock(ObjectRootsView.class));
+        runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+        ExecutorService executorService = mock(ExecutorService.class);
+        doNothing().when(executorService).execute(runnableCaptor.capture());
+
+        appService = mock(ApplicationService.class);
+        when(appService.getApplicationExecutor()).thenReturn(executorService);
+    }
+
+    @After
+    public void tearDown() {
+        view = null;
+        objectDetailsProvider = null;
+        objectRootsProvider = null;
+        ApplicationContextUtil.resetApplicationContext();
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Test
+    public void verifySearchWorks() {
+        final String SEARCH_TEXT = "Test";
+        final String OBJECT_ID = "0xcafebabe";
+        final String OBJECT_CLASS_NAME = "FOO";
+
+        when(view.getSearchText()).thenReturn(SEARCH_TEXT);
+
+        JavaClass heapObjectClass = mock(JavaClass.class);
+        when(heapObjectClass.getName()).thenReturn(OBJECT_CLASS_NAME);
+
+        JavaHeapObject heapObject = mock(JavaHeapObject.class);
+        when(heapObject.getIdString()).thenReturn(OBJECT_ID);
+        when(heapObject.getClazz()).thenReturn(heapObjectClass);
+
+        HeapDump dump = mock(HeapDump.class);
+        when(dump.searchObjects(contains(SEARCH_TEXT), anyInt())).thenReturn(Arrays.asList(OBJECT_ID));
+        when(dump.findObject(eq(OBJECT_ID))).thenReturn(heapObject);
+
+        ArgumentCaptor<ActionListener> viewArgumentCaptor1 = ArgumentCaptor.forClass(ActionListener.class);
+        doNothing().when(view).addObjectActionListener(viewArgumentCaptor1.capture());
+
+        @SuppressWarnings("unused")
+        ObjectDetailsController controller = new ObjectDetailsController(appService, dump, this.objectDetailsProvider, this.objectRootsProvider);
+
+        ActionListener<ObjectAction> actionListener = viewArgumentCaptor1.getValue();
+        assertNotNull(actionListener);
+        actionListener.actionPerformed(new ActionEvent<ObjectAction>(view, ObjectAction.SEARCH));
+
+        runnableCaptor.getValue().run();
+
+        ArgumentCaptor<Collection> matchingObjectsCaptor = ArgumentCaptor.forClass(Collection.class);
+        verify(view).setMatchingObjects(matchingObjectsCaptor.capture());
+
+        List<HeapObjectUI> matchingObjects = new ArrayList<HeapObjectUI>(matchingObjectsCaptor.getValue());
+        assertEquals(1, matchingObjects.size());
+        assertEquals(OBJECT_ID, matchingObjects.get(0).objectId);
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Test
+    public void verifyInputConvertedIntoWildcardsIfNeeded() {
+        HeapDump heap = mock(HeapDump.class);
+        when(view.getSearchText()).thenReturn("a");
+
+        ArgumentCaptor<ActionListener> objectActionListenerCaptor = ArgumentCaptor.forClass(ActionListener.class);
+        doNothing().when(view).addObjectActionListener(objectActionListenerCaptor.capture());
+
+        @SuppressWarnings("unused")
+        ObjectDetailsController controller = new ObjectDetailsController(appService, heap, this.objectDetailsProvider, this.objectRootsProvider);
+
+        ActionListener<ObjectAction> actionListener = objectActionListenerCaptor.getValue();
+        assertNotNull(actionListener);
+        actionListener.actionPerformed(new ActionEvent<ObjectAction>(view, ObjectAction.SEARCH));
+
+        runnableCaptor.getValue().run();
+
+        verify(heap).searchObjects("*a*", 100);
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Test
+    public void verifyWildcardInputNotConvertedIntoWildcards() {
+        HeapDump heap = mock(HeapDump.class);
+        when(view.getSearchText()).thenReturn("*a?");
+
+        ArgumentCaptor<ActionListener> objectActionListenerCaptor = ArgumentCaptor.forClass(ActionListener.class);
+        doNothing().when(view).addObjectActionListener(objectActionListenerCaptor.capture());
+
+        @SuppressWarnings("unused")
+        ObjectDetailsController controller = new ObjectDetailsController(appService, heap, this.objectDetailsProvider, this.objectRootsProvider);
+
+        ActionListener<ObjectAction> actionListener = objectActionListenerCaptor.getValue();
+        assertNotNull(actionListener);
+        actionListener.actionPerformed(new ActionEvent<ObjectAction>(view, ObjectAction.SEARCH));
+
+        runnableCaptor.getValue().run();
+
+        verify(heap).searchObjects("*a?", 300);
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Test
+    public void verifySearchLimits() {
+
+        Object[][] limits = new Object[][] {
+            { "a",       100 },
+            { "ab",      200 },
+            { "abc",     300 },
+            { "abcd",    400 },
+            { "abcde",   500 },
+            { "abcdef",  600},
+            { "abcdefg", 700},
+            { "java.lang.Class", 1000 },
+        };
+
+        HeapDump heap = mock(HeapDump.class);
+
+        OngoingStubbing<String> ongoing = when(view.getSearchText());
+        for (int i = 0; i < limits.length; i++) {
+            ongoing = ongoing.thenReturn((String)limits[i][0]);
+        }
+
+        ArgumentCaptor<ActionListener> objectActionListenerCaptor = ArgumentCaptor.forClass(ActionListener.class);
+        doNothing().when(view).addObjectActionListener(objectActionListenerCaptor.capture());
+
+        @SuppressWarnings("unused")
+        ObjectDetailsController controller = new ObjectDetailsController(appService, heap, this.objectDetailsProvider, this.objectRootsProvider);
+
+        ActionListener<ObjectAction> actionListener = objectActionListenerCaptor.getValue();
+        assertNotNull(actionListener);
+
+        for (int i = 0; i < limits.length; i++) {
+            actionListener.actionPerformed(new ActionEvent<ObjectAction>(view, ObjectAction.SEARCH));
+            runnableCaptor.getValue().run();
+        }
+
+        InOrder inOrder = inOrder(heap);
+        for (int i = 0; i < limits.length; i++) {
+            String text = (String) limits[i][0];
+            int times = (Integer) limits[i][1];
+            inOrder.verify(heap).searchObjects("*" + text + "*", times);
+        }
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Test
+    public void verifyGettingDetailsWorks() {
+        final String OBJECT_ID = "0xcafebabe";
+        final String OBJECT_ID_VISIBLE = "FOO BAR";
+
+        JavaHeapObject heapObject = mock(JavaHeapObject.class);
+
+        HeapObjectUI heapObjectRepresentation = new HeapObjectUI(OBJECT_ID, OBJECT_ID_VISIBLE);
+
+        HeapDump dump = mock(HeapDump.class);
+        when(dump.findObject(OBJECT_ID)).thenReturn(heapObject);
+
+        ArgumentCaptor<ActionListener> viewArgumentCaptor1 = ArgumentCaptor.forClass(ActionListener.class);
+        doNothing().when(view).addObjectActionListener(viewArgumentCaptor1.capture());
+
+        when(view.getSelectedMatchingObject()).thenReturn(heapObjectRepresentation);
+
+        @SuppressWarnings("unused")
+        ObjectDetailsController controller = new ObjectDetailsController(appService, dump, this.objectDetailsProvider, this.objectRootsProvider);
+
+        ActionListener<ObjectAction> actionListener = viewArgumentCaptor1.getValue();
+        assertNotNull(actionListener);
+        actionListener.actionPerformed(new ActionEvent<ObjectAction>(view, ObjectAction.GET_OBJECT_DETAIL));
+
+        verify(view).setObjectDetails(heapObject);
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Test
+    public void verifyFindRoot() {
+        final String OBJECT_ID = "0xcafebabe";
+        final String OBJECT_ID_VISIBLE = "FOO BAR";
+
+        JavaHeapObject heapObject = mock(JavaHeapObject.class);
+
+        HeapObjectUI heapObjectRepresentation = new HeapObjectUI(OBJECT_ID, OBJECT_ID_VISIBLE);
+
+        HeapDump dump = mock(HeapDump.class);
+        when(dump.findObject(OBJECT_ID)).thenReturn(heapObject);
+
+        ArgumentCaptor<ActionListener> viewArgumentCaptor1 = ArgumentCaptor.forClass(ActionListener.class);
+        doNothing().when(view).addObjectActionListener(viewArgumentCaptor1.capture());
+
+        when(view.getSelectedMatchingObject()).thenReturn(heapObjectRepresentation);
+
+        @SuppressWarnings("unused")
+        ObjectDetailsController controller = new ObjectDetailsController(appService, dump, this.objectDetailsProvider, this.objectRootsProvider);
+
+        ActionListener<ObjectAction> actionListener = viewArgumentCaptor1.getValue();
+        assertNotNull(actionListener);
+        actionListener.actionPerformed(new ActionEvent<ObjectAction>(view, ObjectAction.GET_OBJECT_DETAIL));
+
+        verify(view).setObjectDetails(heapObject);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/ObjectRootsControllerTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2012 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.client.heap;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.client.heap.ObjectRootsView.Action;
+import com.redhat.thermostat.client.heap.cli.FindRoot;
+import com.redhat.thermostat.client.heap.cli.HeapPath;
+import com.redhat.thermostat.client.heap.internal.ObjectRootsController;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.appctx.ApplicationContextUtil;
+import com.redhat.thermostat.common.heap.HeapDump;
+import com.sun.tools.hat.internal.model.JavaClass;
+import com.sun.tools.hat.internal.model.JavaHeapObject;
+
+public class ObjectRootsControllerTest {
+
+    ObjectRootsController controller;
+
+    HeapDump heapDump;
+    JavaHeapObject heapObject;
+    JavaClass clazz;
+    FindRoot rootFinder;
+
+    ObjectRootsView view;
+    ActionListener<Action> listener;
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Before
+    public void setUp() {
+        ApplicationContextUtil.resetApplicationContext();
+
+        // Set up views
+        view = mock(ObjectRootsView.class);
+
+        ObjectRootsViewProvider viewProvider = mock(ObjectRootsViewProvider.class);
+        when(viewProvider.createView()).thenReturn(view);
+        
+        // set up models
+        heapObject = mock(JavaHeapObject.class);
+        when(heapObject.getIdString()).thenReturn("id-string");
+
+        clazz = mock(JavaClass.class);
+        when(clazz.getName()).thenReturn("class");
+        when(heapObject.getClazz()).thenReturn(clazz);
+
+        heapDump = mock(HeapDump.class);
+        when(heapDump.findObject("test")).thenReturn(heapObject);
+
+        rootFinder = mock(FindRoot.class);
+
+        // create controller
+        controller = new ObjectRootsController(heapDump, heapObject, rootFinder, viewProvider);
+
+        ArgumentCaptor<ActionListener> listenerCaptor = ArgumentCaptor.forClass(ActionListener.class);
+        verify(view).addActionListener(listenerCaptor.capture());
+
+        listener = listenerCaptor.getValue();
+    }
+
+    @After
+    public void tearDown() {
+        ApplicationContextUtil.resetApplicationContext();
+    }
+
+
+    @Test
+    public void verifyAddListenersToView() {
+        assertNotNull(listener);
+    }
+
+    @Test
+    public void verifySetObjectDetailsInView() {
+        when(heapObject.getIdString()).thenReturn("object-id");
+        when(heapObject.isHeapAllocated()).thenReturn(true);
+        when(heapObject.getSize()).thenReturn(10);
+
+        when(clazz.getName()).thenReturn("object-class");
+
+        HeapObjectUI heapObj = new HeapObjectUI("test", "test");
+        ActionEvent<Action> event = new ActionEvent<Action>(view, Action.OBJECT_SELECTED);
+        event.setPayload(heapObj);
+        listener.actionPerformed(event);
+
+        verify(view).setObjectDetails("Object ID: object-id\n" +
+                "Type: object-class\n" +
+                "Size: 10 bytes\n" +
+                "Heap allocated: true\n");
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @Test
+    public void testShow() {
+
+        HeapPath<JavaHeapObject> path = mock(HeapPath.class);
+        when(path.iterator()).thenReturn(Arrays.asList(heapObject).iterator());
+
+        when(rootFinder.findShortestPathsToRoot(heapObject, false)).thenReturn(Arrays.asList(path));
+
+        controller.show();
+
+        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
+
+        verify(view).setPathToRoot(captor.capture());
+
+        HeapObjectUI heapObj = (HeapObjectUI) captor.getValue().get(0);
+        assertEquals("id-string", heapObj.objectId);
+        assertEquals("class@id-string", heapObj.text);
+
+        verify(view).showView();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/cli/DumpHeapCommandTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isA;
+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;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import com.redhat.thermostat.common.cli.Command;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.dao.AgentInfoDAO;
+import com.redhat.thermostat.common.dao.VmRef;
+import com.redhat.thermostat.common.utils.OSGIUtils;
+import com.redhat.thermostat.test.TestCommandContextFactory;
+
+public class DumpHeapCommandTest {
+
+    @Test
+    public void testBasics() {
+        Command command = new DumpHeapCommand();
+        assertEquals("dump-heap", command.getName());
+        assertNotNull(command.getDescription());
+        assertNotNull(command.getUsage());
+    }
+
+    @Test
+    public void verifyAcuallyCallsWorker() throws CommandException {
+        AgentInfoDAO agentInfoDao = mock(AgentInfoDAO.class);
+        OSGIUtils osgi = mock(OSGIUtils.class);
+        when(osgi.getService(AgentInfoDAO.class)).thenReturn(agentInfoDao);
+
+        HeapDumperCommand impl = mock(HeapDumperCommand.class);
+        final ArgumentCaptor<Runnable> arg = ArgumentCaptor.forClass(Runnable.class);
+        doAnswer(new Answer<Void>() {
+
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                arg.getValue().run();
+                return null;
+            }
+        }).when(impl).execute(eq(agentInfoDao), any(VmRef.class), arg.capture());
+
+        DumpHeapCommand command = new DumpHeapCommand(osgi, impl);
+
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("hostId", "foo");
+        args.addArgument("vmId", "0");
+
+        command.run(factory.createContext(args));
+
+        verify(impl).execute(eq(agentInfoDao), isA(VmRef.class), any(Runnable.class));
+        assertEquals("Done\n", factory.getOutput());
+    }
+
+    @Test
+    public void verifyNeedsHostAndVmId() throws CommandException {
+        AgentInfoDAO agentInfoDao = mock(AgentInfoDAO.class);
+        OSGIUtils osgi = mock(OSGIUtils.class);
+        when(osgi.getService(AgentInfoDAO.class)).thenReturn(agentInfoDao);
+
+        HeapDumperCommand impl = mock(HeapDumperCommand.class);
+        DumpHeapCommand command = new DumpHeapCommand(osgi, impl);
+
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+
+        SimpleArguments args = new SimpleArguments();
+
+        try {
+            command.run(factory.createContext(args));
+            assertTrue("should not reach here", false);
+        } catch (CommandException ce) {
+            assertEquals("a hostId is required", ce.getMessage());
+        }
+    }
+
+    @Test
+    public void verifyFailsIfAgentDaoIsNotAvailable() {
+        OSGIUtils osgi = mock(OSGIUtils.class);
+
+        HeapDumperCommand impl = mock(HeapDumperCommand.class);
+        DumpHeapCommand command = new DumpHeapCommand(osgi, impl);
+
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("hostId", "foo");
+        args.addArgument("vmId", "0");
+
+        try {
+            command.run(factory.createContext(args));
+            assertTrue("should not reach here", false);
+        } catch (CommandException ce) {
+            assertEquals("Unable to access agent information", ce.getMessage());
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/cli/FindObjectsCommandTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.isA;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.redhat.thermostat.client.heap.cli.FindObjectsCommand;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.dao.HeapDAO;
+import com.redhat.thermostat.common.heap.HeapDump;
+import com.redhat.thermostat.common.model.HeapInfo;
+import com.redhat.thermostat.common.utils.OSGIUtils;
+import com.redhat.thermostat.test.TestCommandContextFactory;
+import com.sun.tools.hat.internal.model.JavaClass;
+import com.sun.tools.hat.internal.model.JavaHeapObject;
+
+public class FindObjectsCommandTest {
+
+    private static final String HEAP_ID = "TEST_HEAP_ID";
+
+    private FindObjectsCommand cmd;
+
+    private HeapDump heapDump;
+
+    private HeapDAO dao;
+
+    @Before
+    public void setUp() {
+        setupHeapDump();
+
+        setupDAO();
+
+        OSGIUtils serviceProvider = mock(OSGIUtils.class);
+        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(dao);
+
+        cmd = new FindObjectsCommand(serviceProvider);
+
+    }
+
+    private void setupHeapDump() {
+        heapDump = mock(HeapDump.class);
+        JavaClass fooCls = mock(JavaClass.class);
+        when(fooCls.getName()).thenReturn("FooType");
+        JavaHeapObject fooObj = mock(JavaHeapObject.class);
+        when(fooObj.getIdString()).thenReturn("123");
+        when(fooObj.getClazz()).thenReturn(fooCls);
+        JavaClass barCls = mock(JavaClass.class);
+        when(barCls.getName()).thenReturn("BarType");
+        JavaHeapObject barObj = mock(JavaHeapObject.class);
+        when(barObj.getIdString()).thenReturn("456");
+        when(barObj.getClazz()).thenReturn(barCls);
+        JavaClass bazCls = mock(JavaClass.class);
+        when(bazCls.getName()).thenReturn("BazType");
+        JavaHeapObject bazObj = mock(JavaHeapObject.class);
+        when(bazObj.getIdString()).thenReturn("789");
+        when(bazObj.getClazz()).thenReturn(bazCls);
+
+        when(heapDump.searchObjects("fluff", 10)).thenReturn(Arrays.asList("foo", "bar", "baz"));
+        when(heapDump.searchObjects("fluff", 2)).thenReturn(Arrays.asList("foo", "bar"));
+        when(heapDump.findObject("foo")).thenReturn(fooObj);
+        when(heapDump.findObject("bar")).thenReturn(barObj);
+        when(heapDump.findObject("baz")).thenReturn(bazObj);
+    }
+
+    private void setupDAO() {
+        HeapInfo heapInfo = mock(HeapInfo.class);
+
+        dao = mock(HeapDAO.class);
+        when(dao.getHeapInfo(HEAP_ID)).thenReturn(heapInfo);
+        when(dao.getHeapDump(heapInfo)).thenReturn(heapDump);
+    }
+
+    @Test
+    public void testName() {
+        assertEquals("find-objects", cmd.getName());
+    }
+
+    @Test
+    public void testDescAndUsage() {
+        assertNotNull(cmd.getDescription());
+        assertNotNull(cmd.getUsage());
+    }
+
+    @Ignore
+    @Test
+    public void testOptions() {
+        Options options = cmd.getOptions();
+        assertEquals(2, options.getOptions().size());
+
+        assertTrue(options.hasOption("heapId"));
+        Option heapOption = options.getOption("heapId");
+        assertEquals("the ID of the heapdump to analyze", heapOption.getDescription());
+        assertTrue(heapOption.isRequired());
+        assertTrue(heapOption.hasArg());
+
+        assertTrue(options.hasOption("limit"));
+        Option limitOption = options.getOption("limit");
+        assertEquals("limit search to top N results, defaults to 10", limitOption.getDescription());
+        assertFalse(limitOption.isRequired());
+        assertTrue(limitOption.hasArg());
+    }
+
+    @Test
+    public void testStorageRequired() {
+        assertTrue(cmd.isStorageRequired());
+    }
+
+    @Test
+    public void testSimpleSearch() throws CommandException {
+
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("heapId", HEAP_ID);
+        args.addNonOptionArgument("fluff");
+
+        cmd.run(factory.createContext(args));
+
+        String expected = "ID  TYPE\n" +
+                          "123 FooType\n" +
+                          "456 BarType\n" +
+                          "789 BazType\n";
+
+        assertEquals(expected, factory.getOutput());
+
+    }
+
+    @Test
+    public void testSearchWithLimit() throws CommandException {
+
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("heapId", HEAP_ID);
+        args.addArgument("limit", "2");
+        args.addNonOptionArgument("fluff");
+
+        cmd.run(factory.createContext(args));
+
+        String expected = "ID  TYPE\n" +
+                          "123 FooType\n" +
+                          "456 BarType\n";
+
+        assertEquals(expected, factory.getOutput());
+
+    }
+
+    @Test(expected=CommandException.class)
+    public void testSearchWithInvalidLimit() throws CommandException {
+
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("heapId", HEAP_ID);
+        args.addArgument("limit", "urgs");
+        args.addNonOptionArgument("fluff");
+
+        cmd.run(factory.createContext(args));
+
+
+    }
+
+    @Test
+    public void testSearchWithBadHeapId() throws CommandException {
+        final String INVALID_HEAP_ID = "foobarbaz";
+
+        HeapDAO dao = mock(HeapDAO.class);
+        when(dao.getHeapInfo(INVALID_HEAP_ID)).thenReturn(null);
+        when(dao.getHeapDump(isA(HeapInfo.class))).thenReturn(null);
+
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("heapId", INVALID_HEAP_ID);
+
+        cmd.run(factory.createContext(args));
+
+        assertEquals("Heap ID not found: " + INVALID_HEAP_ID + "\n", factory.getOutput());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/cli/FindRootCommandTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,345 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.same;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Collection;
+import java.util.Enumeration;
+
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockito.stubbing.OngoingStubbing;
+
+import com.redhat.thermostat.client.heap.cli.ObjectNotFoundException;
+import com.redhat.thermostat.client.heap.cli.FindRootCommand;
+import com.redhat.thermostat.client.heap.cli.HeapNotFoundException;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.dao.HeapDAO;
+import com.redhat.thermostat.common.heap.HeapDump;
+import com.redhat.thermostat.common.model.HeapInfo;
+import com.redhat.thermostat.common.utils.OSGIUtils;
+import com.redhat.thermostat.test.TestCommandContextFactory;
+import com.sun.tools.hat.internal.model.JavaClass;
+import com.sun.tools.hat.internal.model.JavaHeapObject;
+import com.sun.tools.hat.internal.model.Root;
+import com.sun.tools.hat.internal.model.Snapshot;
+
+public class FindRootCommandTest {
+
+    private static final String HEAP_ID = "TEST_HEAP_ID";
+
+    private FindRootCommand cmd;
+
+    private JavaHeapObject fooObj;
+
+    private JavaHeapObject barObj;
+
+    private JavaHeapObject bazObj;
+
+    private JavaHeapObject bumObj;
+
+    private JavaHeapObject beeObj;
+
+    private HeapDAO dao;
+
+    @Before
+    public void setUp() {
+        HeapDump heapDump = setupHeapDump();
+        setupDAO(heapDump);
+
+        OSGIUtils serviceProvider = mock(OSGIUtils.class);
+        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(dao);
+
+        cmd = new FindRootCommand(serviceProvider);
+    }
+
+    @After
+    public void tearDown() {
+        fooObj = null;
+        barObj = null;
+        bazObj = null;
+        bumObj = null;
+        beeObj = null;
+        cmd = null;
+    }
+
+    @SuppressWarnings("rawtypes")
+    private HeapDump setupHeapDump() {
+        fooObj = createMockObject("FooType", "123");
+        barObj = createMockObject("BarType", "456");
+        bazObj = createMockObject("BazType", "789");
+        bumObj = createMockObject("BumType", "987");
+        beeObj = createMockObject("BeeType", "654");
+        // Setup referrer network.
+        Enumeration fooRefs = createReferrerEnum(barObj);
+        // The exception is thrown in circle-tests when we visit the foo object again.
+        when(fooObj.getReferers()).thenReturn(fooRefs).thenThrow(new RuntimeException());
+        Enumeration barRefs = createReferrerEnum(bazObj, bumObj);
+        when(barObj.getReferers()).thenReturn(barRefs);
+        Enumeration bumRefs = createReferrerEnum(beeObj);
+        when(bumObj.getReferers()).thenReturn(bumRefs);
+        Enumeration emptyRefs = createReferrerEnum();
+        when(bazObj.getReferers()).thenReturn(emptyRefs);
+        when(beeObj.getReferers()).thenReturn(emptyRefs);
+
+        // Setup referrer descriptions.
+        when(barObj.describeReferenceTo(same(fooObj), any(Snapshot.class))).thenReturn("field foo");
+        when(bazObj.describeReferenceTo(same(barObj), any(Snapshot.class))).thenReturn("field bar");
+        when(bumObj.describeReferenceTo(same(barObj), any(Snapshot.class))).thenReturn("field bar");
+        when(beeObj.describeReferenceTo(same(bumObj), any(Snapshot.class))).thenReturn("field bum");
+
+        // Setup roots.
+        Root bazRoot = mock(Root.class);
+        when(bazRoot.getDescription()).thenReturn("baz root");
+        when(bazObj.getRoot()).thenReturn(bazRoot);
+        Root beeRoot = mock(Root.class);
+        when(beeRoot.getDescription()).thenReturn("bee root");
+        when(beeObj.getRoot()).thenReturn(beeRoot);
+
+        // Setup heap dump.
+        HeapDump heapDump = mock(HeapDump.class);
+        when(heapDump.findObject("foo")).thenReturn(fooObj);
+        return heapDump;
+    }
+
+    private void setupDAO(HeapDump heapDump) {
+
+        HeapInfo heapInfo = mock(HeapInfo.class);
+
+        dao = mock(HeapDAO.class);
+        when(dao.getHeapInfo(HEAP_ID)).thenReturn(heapInfo);
+        when(dao.getHeapDump(heapInfo)).thenReturn(heapDump);
+
+    }
+
+    private JavaHeapObject createMockObject(String className, String id) {
+        JavaClass cls = mock(JavaClass.class);
+        when(cls.getName()).thenReturn(className);
+        JavaHeapObject obj = mock(JavaHeapObject.class);
+        when(obj.getIdString()).thenReturn(id);
+        when(obj.getClazz()).thenReturn(cls);
+        return obj;
+    }
+
+    @SuppressWarnings("rawtypes")
+    private Enumeration createReferrerEnum(JavaHeapObject... objs) {
+        Enumeration refs = mock(Enumeration.class);
+        OngoingStubbing<Boolean> hasMoreElements = when(refs.hasMoreElements());
+        for (int i = 0; i < objs.length; i++) {
+            hasMoreElements = hasMoreElements.thenReturn(true);
+        }
+        hasMoreElements.thenReturn(false);
+        OngoingStubbing<Object> nextElement = when(refs.nextElement());
+        for (JavaHeapObject obj : objs) {
+            nextElement = nextElement.thenReturn(obj);
+        }
+        nextElement.thenReturn(null);
+        return refs;
+    }
+
+    @Test
+    public void testName() {
+        assertEquals("find-root", cmd.getName());
+    }
+
+    @Test
+    public void testDescAndUsage() {
+        assertNotNull(cmd.getDescription());
+        assertNotNull(cmd.getUsage());
+    }
+
+    @Ignore
+    @Test
+    public void testOptions() {
+        String heapIdOption = "heapId";
+        String objectIdOption = "objectId";
+        String allOption = "all";
+        Options options = cmd.getOptions();
+        @SuppressWarnings("unchecked")
+        Collection<Options> theOptions = options.getOptions();
+        assertEquals(3, theOptions.size());
+
+        assertTrue(options.hasOption(heapIdOption));
+        Option heapOption = options.getOption(heapIdOption);
+        assertEquals("the ID of the heapdump to analyze", heapOption.getDescription());
+        assertTrue(heapOption.isRequired());
+        assertTrue(heapOption.hasArg());
+
+        assertTrue(options.hasOption(objectIdOption));
+        Option objectOption = options.getOption(objectIdOption);
+        assertEquals("the ID of the object to query", objectOption.getDescription());
+        assertTrue(heapOption.isRequired());
+        assertTrue(heapOption.hasArg());
+
+        assertTrue(options.hasOption(allOption));
+        Option all = options.getOption(allOption);
+        assertEquals("finds all paths to GC roots", all.getDescription());
+        assertFalse(all.isRequired());
+        assertFalse(all.hasArg());
+    }
+
+    @Test
+    public void testStorageRequired() {
+        assertTrue(cmd.isStorageRequired());
+    }
+
+    @Test
+    public void testSimpleAllRootsSearch() throws CommandException {
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("heapId", HEAP_ID);
+        args.addArgument("objectId", "foo");
+        args.addArgument("all", "true");
+
+        cmd.run(factory.createContext(args));
+
+        String expected = "baz root -> BazType@789\n" +
+                          "\u2514field bar in BazType@789 -> BarType@456\n" +
+                          " \u2514field foo in BarType@456 -> FooType@123\n" +
+                          "\n" +
+                          "bee root -> BeeType@654\n" +
+                          "\u2514field bum in BeeType@654 -> BumType@987\n" +
+                          " \u2514field bar in BumType@987 -> BarType@456\n" +
+                          "  \u2514field foo in BarType@456 -> FooType@123\n" +
+                          "\n";
+
+        assertEquals(expected, factory.getOutput());
+
+    }
+
+    @Test
+    public void testSimpleRootSearch() throws CommandException {
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("heapId", HEAP_ID);
+        args.addArgument("objectId", "foo");
+
+        cmd.run(factory.createContext(args));
+
+        String expected = "baz root -> BazType@789\n" +
+                          "\u2514field bar in BazType@789 -> BarType@456\n" +
+                          " \u2514field foo in BarType@456 -> FooType@123\n" +
+                          "\n";
+
+        assertEquals(expected, factory.getOutput());
+
+    }
+
+    @Test
+    public void testSearchWithoutRoot() throws CommandException {
+        when(bazObj.getRoot()).thenReturn(null);
+        when(beeObj.getRoot()).thenReturn(null);
+
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("heapId", HEAP_ID);
+        args.addArgument("objectId", "foo");
+
+        cmd.run(factory.createContext(args));
+
+        String expected = "No root found for: FooType@123\n";
+
+        assertEquals(expected, factory.getOutput());
+
+    }
+
+    @Test
+    public void testSearchWithoutRootWithCircle() throws CommandException {
+        when(bazObj.getRoot()).thenReturn(null);
+        @SuppressWarnings("rawtypes")
+        Enumeration bazReferrers = createReferrerEnum(fooObj);
+        when(bazObj.getReferers()).thenReturn(bazReferrers);
+        when(beeObj.getRoot()).thenReturn(null);
+        @SuppressWarnings("rawtypes")
+        Enumeration beeReferrers = createReferrerEnum(fooObj);
+        when(beeObj.getReferers()).thenReturn(beeReferrers);
+
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("heapId", HEAP_ID);
+        args.addArgument("objectId", "foo");
+
+        cmd.run(factory.createContext(args));
+
+        String expected = "No root found for: FooType@123\n";
+
+        assertEquals(expected, factory.getOutput());
+
+    }
+
+    public void testHeapNotFound() throws CommandException {
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("heapId", "fluff");
+        args.addArgument("objectId", "foo");
+
+        try {
+            cmd.run(factory.createContext(args));
+            fail();
+        } catch (HeapNotFoundException ex) {
+           assertEquals("Heap ID not found: fluff", ex.getMessage());
+        }
+    }
+
+    public void testObjectNotFound() throws CommandException {
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("heapId", HEAP_ID);
+        args.addArgument("objectId", "fluff");
+
+        try {
+            cmd.run(factory.createContext(args));
+            fail();
+        } catch (ObjectNotFoundException ex) {
+            assertEquals("Object not found: fluff", ex.getMessage());
+         }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/cli/HeapDumperCommandTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.net.InetSocketAddress;
+import java.util.Collection;
+
+import junit.framework.AssertionFailedError;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.client.command.RequestQueue;
+import com.redhat.thermostat.common.appctx.ApplicationContextUtil;
+import com.redhat.thermostat.common.command.Request;
+import com.redhat.thermostat.common.command.Request.RequestType;
+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.common.dao.AgentInfoDAO;
+import com.redhat.thermostat.common.dao.HostRef;
+import com.redhat.thermostat.common.dao.VmRef;
+import com.redhat.thermostat.common.model.AgentInformation;
+import com.redhat.thermostat.common.utils.OSGIUtils;
+
+public class HeapDumperCommandTest {
+
+    private AgentInfoDAO agentInfoDao;
+    private HeapDumperCommand cmd;
+    private VmRef vmRef;
+    private RequestQueue reqQueue;
+    private Runnable heapDumpCompleteAction;
+
+    @Before
+    public void setUp() {
+        ApplicationContextUtil.resetApplicationContext();
+
+        reqQueue = mock(RequestQueue.class);
+        OSGIUtils osgiUtils = mock(OSGIUtils.class);
+        when(osgiUtils.getService(RequestQueue.class)).thenReturn(reqQueue);
+        OSGIUtils.setInstance(osgiUtils);
+
+        HostRef host = mock(HostRef.class);
+
+        AgentInformation agentInfo = mock(AgentInformation.class);
+        when(agentInfo.getConfigListenAddress()).thenReturn("test:123");
+
+        agentInfoDao = mock(AgentInfoDAO.class);
+        when(agentInfoDao.getAgentInformation(host)).thenReturn(agentInfo);
+
+        cmd = new HeapDumperCommand();
+        vmRef = mock(VmRef.class);
+        when(vmRef.getIdString()).thenReturn("123");
+        when(vmRef.getAgent()).thenReturn(host);
+        heapDumpCompleteAction = mock(Runnable.class);
+
+    }
+
+    @After
+    public void tearDown() {
+        heapDumpCompleteAction = null;
+        vmRef = null;
+        cmd = null;
+        reqQueue = null;
+        ApplicationContextUtil.resetApplicationContext();
+    }
+
+    @Test
+	public void testExecute() {
+
+        cmd.execute(agentInfoDao, vmRef, heapDumpCompleteAction);
+
+		ArgumentCaptor<Request> reqArg = ArgumentCaptor.forClass(Request.class);
+		verify(reqQueue).putRequest(reqArg.capture());
+		Request req = reqArg.getValue();
+		assertEquals("com.redhat.thermostat.agent.heapdumper.internal.HeapDumpReceiver", req.getReceiver());
+		verifyClassExists(req.getReceiver());
+		assertEquals(RequestType.RESPONSE_EXPECTED, req.getType());
+		assertEquals("123", req.getParameter("vmId"));
+		assertEquals(new InetSocketAddress("test", 123), req.getTarget());
+
+		Collection<RequestResponseListener> ls = req.getListeners();
+		for (RequestResponseListener l : ls) {
+		    l.fireComplete(req, new Response(ResponseType.OK));
+		}
+		verify(heapDumpCompleteAction).run();
+    }
+
+    private void verifyClassExists(String receiver) {
+        try {
+            Class.forName(receiver);
+        } catch (ClassNotFoundException e) {
+            throw new AssertionFailedError();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/cli/ListHeapDumpsCommandTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+import org.apache.commons.cli.Options;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.appctx.ApplicationContextUtil;
+import com.redhat.thermostat.common.cli.Command;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.dao.HeapDAO;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.common.dao.HostRef;
+import com.redhat.thermostat.common.dao.VmInfoDAO;
+import com.redhat.thermostat.common.dao.VmRef;
+import com.redhat.thermostat.common.model.HeapInfo;
+import com.redhat.thermostat.common.utils.OSGIUtils;
+import com.redhat.thermostat.test.TestCommandContextFactory;
+
+public class ListHeapDumpsCommandTest {
+
+    private static TimeZone defaultTimezone;
+
+    @BeforeClass
+    public static void setUpClass() {
+        defaultTimezone = TimeZone.getDefault();
+        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+    }
+
+    @AfterClass
+    public static void tearDownClass() {
+        TimeZone.setDefault(defaultTimezone);
+    }
+
+    @Before
+    public void setUp() {
+        ApplicationContextUtil.resetApplicationContext();
+    }
+
+    @After
+    public void tearDown() {
+        ApplicationContextUtil.resetApplicationContext();
+
+    }
+
+    @Test
+    public void verifyBasics() {
+        Command command = new ListHeapDumpsCommand();
+        assertEquals("list-heap-dumps", command.getName());
+        assertNotNull(command.getDescription());
+        assertNotNull(command.getUsage());
+    }
+
+    @Ignore
+    @Test
+    public void verifyOptions() {
+        Command command = new ListHeapDumpsCommand();
+        Options options = command.getOptions();
+        assertNotNull(options);
+        assertEquals(2, options.getOptions().size());
+    }
+
+    @Test
+    public void verifyFailsWithoutHostDao() throws Exception {
+        OSGIUtils serviceProvider = mock(OSGIUtils.class);
+
+        Command command = new ListHeapDumpsCommand(serviceProvider);
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+        try {
+            command.run(factory.createContext(new SimpleArguments()));
+        } catch (CommandException hostDaoNotAvailableException) {
+            assertEquals("Unable to access host information (HostInfoDAO unavailable)",
+                    hostDaoNotAvailableException.getMessage());
+        }
+    }
+
+    @Test
+    public void verifyWorksWithoutAnyInformation() throws CommandException {
+        HostInfoDAO hostInfo = mock(HostInfoDAO.class);
+        VmInfoDAO vmInfo = mock(VmInfoDAO.class);
+        HeapDAO heapDao = mock(HeapDAO.class);
+
+        OSGIUtils serviceProvider = mock(OSGIUtils.class);
+        when(serviceProvider.getServiceAllowNull(HostInfoDAO.class)).thenReturn(hostInfo);
+        when(serviceProvider.getServiceAllowNull(VmInfoDAO.class)).thenReturn(vmInfo);
+        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(heapDao);
+
+        Command command = new ListHeapDumpsCommand(serviceProvider);
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+        command.run(factory.createContext(new SimpleArguments()));
+        assertEquals("HOST ID VM ID HEAP ID TIMESTAMP\n", factory.getOutput());
+    }
+
+    @Test
+    public void verifyWorks() throws CommandException {
+        HostRef hostRef = mock(HostRef.class);
+        when(hostRef.getStringID()).thenReturn("host-id");
+        VmRef vmRef = mock(VmRef.class);
+        when(vmRef.getStringID()).thenReturn("1");
+
+        HeapInfo heapInfo = mock(HeapInfo.class);
+        Calendar timestamp = Calendar.getInstance();
+        timestamp.set(2012, 5, 7, 15, 32, 0);
+        when(heapInfo.getTimeStamp()).thenReturn(timestamp.getTimeInMillis());
+        when(heapInfo.getHeapId()).thenReturn("0001");
+
+        HeapDAO heapDao = mock(HeapDAO.class);
+
+        VmInfoDAO vmInfo = mock(VmInfoDAO.class);
+        when(vmInfo.getVMs(hostRef)).thenReturn(Arrays.asList(vmRef));
+
+        HostInfoDAO hostInfo = mock(HostInfoDAO.class);
+        when(hostInfo.getHosts()).thenReturn(Arrays.asList(hostRef));
+
+        when(heapDao.getAllHeapInfo(vmRef)).thenReturn(Arrays.asList(heapInfo));
+
+        OSGIUtils serviceProvider = mock(OSGIUtils.class);
+        when(serviceProvider.getServiceAllowNull(HostInfoDAO.class)).thenReturn(hostInfo);
+        when(serviceProvider.getServiceAllowNull(VmInfoDAO.class)).thenReturn(vmInfo);
+        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(heapDao);
+
+        Command command = new ListHeapDumpsCommand(serviceProvider);
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+        command.run(factory.createContext(new SimpleArguments()));
+
+        String expected = "HOST ID VM ID HEAP ID TIMESTAMP\n" +
+                          "host-id 1     0001    Thu Jun 07 15:32:00 UTC 2012\n";
+
+        assertEquals(expected, factory.getOutput());
+    }
+
+    @Test
+    public void verifyWorksWithFilterOnHost() throws CommandException {
+        HostRef hostRef1 = mock(HostRef.class);
+        when(hostRef1.getStringID()).thenReturn("host1");
+        VmRef vmRef1 = mock(VmRef.class);
+        when(vmRef1.getStringID()).thenReturn("1");
+
+        HostRef hostRef2 = mock(HostRef.class);
+        when(hostRef2.getStringID()).thenReturn("host2");
+        VmRef vmRef2 = mock(VmRef.class);
+        when(vmRef2.getStringID()).thenReturn("2");
+
+        HeapInfo heapInfo = mock(HeapInfo.class);
+        Calendar timestamp = Calendar.getInstance();
+        timestamp.set(2012, 5, 7, 15, 32, 0);
+        when(heapInfo.getTimeStamp()).thenReturn(timestamp.getTimeInMillis());
+        when(heapInfo.getHeapId()).thenReturn("0001");
+
+        HeapDAO heapDao = mock(HeapDAO.class);
+
+        VmInfoDAO vmInfo = mock(VmInfoDAO.class);
+        when(vmInfo.getVMs(isA(HostRef.class))).thenReturn(Arrays.asList(vmRef1)).thenReturn(Arrays.asList(vmRef2));
+
+        HostInfoDAO hostInfo = mock(HostInfoDAO.class);
+        when(hostInfo.getHosts()).thenReturn(Arrays.asList(hostRef1, hostRef2));
+
+        when(heapDao.getAllHeapInfo(vmRef1)).thenReturn(Arrays.asList(heapInfo));
+        when(heapDao.getAllHeapInfo(vmRef2)).thenReturn(Arrays.asList(heapInfo));
+
+        OSGIUtils serviceProvider = mock(OSGIUtils.class);
+        when(serviceProvider.getServiceAllowNull(HostInfoDAO.class)).thenReturn(hostInfo);
+        when(serviceProvider.getServiceAllowNull(VmInfoDAO.class)).thenReturn(vmInfo);
+        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(heapDao);
+
+        Command command = new ListHeapDumpsCommand(serviceProvider);
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("hostId", "host1");
+
+        command.run(factory.createContext(args));
+
+        String expected = "HOST ID VM ID HEAP ID TIMESTAMP\n" +
+                          "host1   1     0001    Thu Jun 07 15:32:00 UTC 2012\n";
+
+        assertEquals(expected, factory.getOutput());
+    }
+
+    @Test
+    public void verifyWorksWithFilterOnHostAndVM() throws CommandException {
+        HostRef hostRef1 = mock(HostRef.class);
+        when(hostRef1.getStringID()).thenReturn("host1");
+        when(hostRef1.getAgentId()).thenReturn("host1");
+        VmRef vmRef1 = mock(VmRef.class);
+        when(vmRef1.getStringID()).thenReturn("1");
+
+        HostRef hostRef2 = mock(HostRef.class);
+        when(hostRef2.getStringID()).thenReturn("host2");
+        VmRef vmRef2 = mock(VmRef.class);
+        when(vmRef2.getStringID()).thenReturn("2");
+
+        HeapInfo heapInfo = mock(HeapInfo.class);
+        Calendar timestamp = Calendar.getInstance();
+        timestamp.set(2012, 5, 7, 15, 32, 0);
+        when(heapInfo.getTimeStamp()).thenReturn(timestamp.getTimeInMillis());
+        when(heapInfo.getHeapDumpId()).thenReturn("0001");
+
+        HeapDAO heapDao = mock(HeapDAO.class);
+
+        VmInfoDAO vmInfo = mock(VmInfoDAO.class);
+        when(vmInfo.getVMs(isA(HostRef.class))).thenReturn(Arrays.asList(vmRef1)).thenReturn(Arrays.asList(vmRef2));
+
+        HostInfoDAO hostInfo = mock(HostInfoDAO.class);
+        when(hostInfo.getHosts()).thenReturn(Arrays.asList(hostRef1, hostRef2));
+
+        when(heapDao.getAllHeapInfo(vmRef1)).thenReturn(Arrays.asList(heapInfo));
+        when(heapDao.getAllHeapInfo(vmRef2)).thenReturn(Arrays.asList(heapInfo));
+
+        OSGIUtils serviceProvider = mock(OSGIUtils.class);
+        when(serviceProvider.getServiceAllowNull(HostInfoDAO.class)).thenReturn(hostInfo);
+        when(serviceProvider.getServiceAllowNull(VmInfoDAO.class)).thenReturn(vmInfo);
+        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(heapDao);
+
+        Command command = new ListHeapDumpsCommand(serviceProvider);
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("hostId", "host1");
+        args.addArgument("vmId", "1"); // vm id must be an int for the arg parser to work
+
+        command.run(factory.createContext(args));
+
+        String expected = "HOST ID VM ID HEAP ID TIMESTAMP\n";
+
+        assertEquals(expected, factory.getOutput());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/cli/ObjectInfoCommandTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.same;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Enumeration;
+
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import com.redhat.thermostat.client.heap.cli.HeapNotFoundException;
+import com.redhat.thermostat.client.heap.cli.ObjectInfoCommand;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.dao.HeapDAO;
+import com.redhat.thermostat.common.heap.HeapDump;
+import com.redhat.thermostat.common.model.HeapInfo;
+import com.redhat.thermostat.common.utils.OSGIUtils;
+import com.redhat.thermostat.test.TestCommandContextFactory;
+import com.sun.tools.hat.internal.model.JavaClass;
+import com.sun.tools.hat.internal.model.JavaHeapObject;
+import com.sun.tools.hat.internal.model.JavaHeapObjectVisitor;
+import com.sun.tools.hat.internal.model.Snapshot;
+
+public class ObjectInfoCommandTest {
+
+    private static final String HEAP_ID = "TEST_HEAP_ID";
+
+    private ObjectInfoCommand cmd;
+    private HeapDump heapDump;
+
+    private HeapDAO dao;
+
+    @Before
+    public void setUp() {
+        setupHeapDump();
+        setupDAO();
+
+        OSGIUtils serviceProvider = mock(OSGIUtils.class);
+        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(dao);
+
+        cmd = new ObjectInfoCommand(serviceProvider);
+    }
+
+    @After
+    public void tearDown() {
+        heapDump = null;
+        cmd = null;
+    }
+
+    private void setupHeapDump() {
+        heapDump = mock(HeapDump.class);
+        JavaClass barCls = mock(JavaClass.class);
+        when(barCls.getName()).thenReturn("BarType");
+        final JavaHeapObject barObj = mock(JavaHeapObject.class);
+        when(barObj.getIdString()).thenReturn("456");
+        when(barObj.getClazz()).thenReturn(barCls);
+        JavaClass bazCls = mock(JavaClass.class);
+        when(bazCls.getName()).thenReturn("BazType");
+        final JavaHeapObject bazObj = mock(JavaHeapObject.class);
+        when(bazObj.getIdString()).thenReturn("789");
+        when(bazObj.getClazz()).thenReturn(bazCls);
+
+        JavaClass fooCls = mock(JavaClass.class);
+        when(fooCls.getName()).thenReturn("FooType");
+        JavaHeapObject fooObj = mock(JavaHeapObject.class);
+        when(fooObj.getIdString()).thenReturn("123");
+        when(fooObj.getClazz()).thenReturn(fooCls);
+        doAnswer(new Answer<Void>() {
+
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                JavaHeapObjectVisitor v = (JavaHeapObjectVisitor) invocation.getArguments()[0];
+                v.visit(barObj);
+                v.visit(bazObj);
+                return null;
+            }
+            
+        }).when(fooObj).visitReferencedObjects(any(JavaHeapObjectVisitor.class));
+        when(fooObj.describeReferenceTo(same(barObj), any(Snapshot.class))).thenReturn("field bar");
+        when(fooObj.describeReferenceTo(same(bazObj), any(Snapshot.class))).thenReturn("field baz");
+        @SuppressWarnings("rawtypes")
+        Enumeration referrerEnum = mock(Enumeration.class);
+        when(referrerEnum.hasMoreElements()).thenReturn(true).thenReturn(true).thenReturn(false);
+        when(referrerEnum.nextElement()).thenReturn(barObj).thenReturn(bazObj);
+        when(fooObj.getReferers()).thenReturn(referrerEnum);
+        when(barObj.describeReferenceTo(same(fooObj), any(Snapshot.class))).thenReturn("field foo");
+        when(bazObj.describeReferenceTo(same(fooObj), any(Snapshot.class))).thenReturn("field foo");
+        when(fooObj.isNew()).thenReturn(true);
+        when(fooObj.isHeapAllocated()).thenReturn(false);
+        when(fooObj.getSize()).thenReturn(128);
+        when(heapDump.findObject("foo")).thenReturn(fooObj);
+    }
+
+    private void setupDAO() {
+
+        HeapInfo heapInfo = mock(HeapInfo.class);
+
+        dao = mock(HeapDAO.class);
+        when(dao.getHeapInfo(HEAP_ID)).thenReturn(heapInfo);
+        when(dao.getHeapDump(heapInfo)).thenReturn(heapDump);
+    }
+
+    @Test
+    public void testName() {
+        assertEquals("object-info", cmd.getName());
+    }
+
+    @Test
+    public void testDescAndUsage() {
+        assertNotNull(cmd.getDescription());
+        assertNotNull(cmd.getUsage());
+    }
+
+    @Ignore
+    @Test
+    public void testOptions() {
+        Options options = cmd.getOptions();
+        assertEquals(2, options.getOptions().size());
+
+        assertTrue(options.hasOption("heapId"));
+        Option heapOption = options.getOption("heapId");
+        assertEquals("the ID of the heapdump to analyze", heapOption.getDescription());
+        assertTrue(heapOption.isRequired());
+        assertTrue(heapOption.hasArg());
+
+        assertTrue(options.hasOption("objectId"));
+        Option objOption = options.getOption("objectId");
+        assertEquals("the ID of the object to query", objOption.getDescription());
+        assertTrue(objOption.isRequired());
+        assertTrue(objOption.hasArg());
+    }
+
+    @Test
+    public void testStorageRequired() {
+        assertTrue(cmd.isStorageRequired());
+    }
+
+    @Test
+    public void testSimpleObject() throws CommandException {
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("heapId", HEAP_ID);
+        args.addArgument("objectId", "foo");
+
+        cmd.run(factory.createContext(args));
+
+        String expected = "Object ID:      123\n" +
+                          "Type:           FooType\n" +
+                          "Size:           128 bytes\n" +
+                          "Heap allocated: false\n" +
+                          "References:     \n" +
+                          "                [field bar] -> BarType@456\n" +
+                          "                [field baz] -> BazType@789\n" +
+                          "Referrers:      \n" +
+                          "                BarType@456 -> [field foo]\n" +
+                          "                BazType@789 -> [field foo]\n";
+
+        assertEquals(expected, factory.getOutput());
+
+    }
+
+    @Test(expected=CommandException.class)
+    public void testHeapNotFound() throws CommandException {
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("heapId", "fluff");
+        args.addArgument("objectId", "foo");
+
+        try {
+            cmd.run(factory.createContext(args));
+            fail();
+        } catch (HeapNotFoundException ex) {
+            assertEquals("Heap not found: fluff", ex.getMessage());
+        }
+    }
+
+    public void testObjectNotFound() throws CommandException {
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("heapId", HEAP_ID);
+        args.addArgument("objectId", "fluff");
+
+        try {
+            cmd.run(factory.createContext(args));
+            fail();
+        } catch (ObjectNotFoundException ex) {
+            assertEquals("Object not found: fluff", ex.getMessage());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/cli/SaveHeapDumpToFileCommandTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.nio.charset.Charset;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.client.heap.cli.SaveHeapDumpToFileCommand;
+import com.redhat.thermostat.client.heap.cli.SaveHeapDumpToFileCommand.FileStreamCreator;
+import com.redhat.thermostat.common.cli.Command;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.dao.HeapDAO;
+import com.redhat.thermostat.common.model.HeapInfo;
+import com.redhat.thermostat.common.utils.OSGIUtils;
+import com.redhat.thermostat.test.TestCommandContextFactory;
+
+public class SaveHeapDumpToFileCommandTest {
+
+    @Test
+    public void verifyBasicInformation() {
+        Command command = new SaveHeapDumpToFileCommand();
+        assertEquals("save-heap-dump-to-file", command.getName());
+        assertNotNull(command.getDescription());
+        assertNotNull(command.getUsage());
+    }
+
+    @Test (expected=CommandException.class)
+    public void verifyMissingHeapIdThrowsException() throws CommandException {
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("hostId", "host-id");
+        args.addArgument("vmId", "1");
+        args.addArgument("file", "heap-id-1");
+
+        OSGIUtils serviceProvider = mock(OSGIUtils.class);
+        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(mock(HeapDAO.class));
+
+        Command command = new SaveHeapDumpToFileCommand(serviceProvider, mock(FileStreamCreator.class));
+        command.run(factory.createContext(args));
+    }
+
+    @Test (expected=CommandException.class)
+    public void verifyMissingFileNameThrowsException() throws CommandException {
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("hostId", "host-id");
+        args.addArgument("vmId", "1");
+        args.addArgument("heapId", "heap-id-1");
+
+        OSGIUtils serviceProvider = mock(OSGIUtils.class);
+        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(mock(HeapDAO.class));
+
+        Command command = new SaveHeapDumpToFileCommand(serviceProvider, mock(FileStreamCreator.class));
+        command.run(factory.createContext(args));
+    }
+
+    @Test
+    public void verifyCommandWorks() throws CommandException, FileNotFoundException {
+        final String HEAP_ID = "heap-id-1";
+        final String FILE_NAME = "some-file-name";
+        final String HEAP_CONTENTS = "0xCAFEBABE";
+        final byte[] HEAP_CONTENT_BYTES = HEAP_CONTENTS.getBytes(Charset.forName("UTF-8"));
+
+        ByteArrayOutputStream heapDumpStream = new ByteArrayOutputStream();
+
+        HeapDAO heapDao = mock(HeapDAO.class);
+
+        HeapInfo info = mock(HeapInfo.class);
+        when(heapDao.getHeapInfo(HEAP_ID)).thenReturn(info);
+        when(heapDao.getHeapDumpData(info)).thenReturn(new ByteArrayInputStream(HEAP_CONTENT_BYTES));
+
+        OSGIUtils serviceProvider = mock(OSGIUtils.class);
+        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(heapDao);
+
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("heapId", HEAP_ID);
+        args.addArgument("file", FILE_NAME);
+
+        FileStreamCreator creator = mock(FileStreamCreator.class);
+        when(creator.createOutputStream(FILE_NAME)).thenReturn(heapDumpStream);
+
+        Command command = new SaveHeapDumpToFileCommand(serviceProvider, creator);
+        command.run(factory.createContext(args));
+
+        assertArrayEquals(HEAP_CONTENT_BYTES, heapDumpStream.toByteArray());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/cli/ShowHeapHistogramCommandTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2012 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.client.heap.cli;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.common.cli.Command;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.common.dao.HeapDAO;
+import com.redhat.thermostat.common.heap.ObjectHistogram;
+import com.redhat.thermostat.common.model.HeapInfo;
+import com.redhat.thermostat.common.utils.OSGIUtils;
+import com.redhat.thermostat.test.TestCommandContextFactory;
+import com.sun.tools.hat.internal.model.JavaClass;
+import com.sun.tools.hat.internal.model.JavaHeapObject;
+
+public class ShowHeapHistogramCommandTest {
+
+    @Test
+    public void verifyBasics() {
+        Command command = new ShowHeapHistogramCommand();
+
+        assertEquals("show-heap-histogram", command.getName());
+        assertNotNull(command.getDescription());
+        assertNotNull(command.getUsage());
+    }
+
+    @Test
+    public void verifyWorks() throws CommandException {
+        ObjectHistogram histo = new ObjectHistogram();
+
+        JavaClass cls1 = mock(JavaClass.class);
+        JavaHeapObject obj1 = mock(JavaHeapObject.class);
+        when(cls1.getName()).thenReturn("class1");
+        when(obj1.getClazz()).thenReturn(cls1);
+        when(obj1.getSize()).thenReturn(5);
+        JavaHeapObject obj2 = mock(JavaHeapObject.class);
+        when(obj2.getClazz()).thenReturn(cls1);
+        when(obj2.getSize()).thenReturn(3);
+        JavaClass cls2 = mock(JavaClass.class);
+        JavaHeapObject obj3 = mock(JavaHeapObject.class);
+        when(cls2.getName()).thenReturn("verylongclassnameclass2");
+        when(obj3.getClazz()).thenReturn(cls2);
+        when(obj3.getSize()).thenReturn(10);
+
+        histo.addThing(obj1);
+        histo.addThing(obj2);
+        histo.addThing(obj3);
+
+        final String HEAP_ID = "heap-id-1";
+
+        HeapDAO heapDao = mock(HeapDAO.class);
+
+        HeapInfo heapInfo = mock(HeapInfo.class);
+        when(heapDao.getHeapInfo(HEAP_ID)).thenReturn(heapInfo);
+        when(heapDao.getHistogram(heapInfo)).thenReturn(histo);
+
+        OSGIUtils serviceProvider = mock(OSGIUtils.class);
+        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(heapDao);
+
+        Command command = new ShowHeapHistogramCommand(serviceProvider);
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("heapId", HEAP_ID);
+
+        command.run(factory.createContext(args));
+
+        assertEquals("class1                  2 8\n" +
+        		     "verylongclassnameclass2 1 10\n", factory.getOutput());
+        verify(serviceProvider).ungetService(HeapDAO.class, heapDao);
+    }
+
+    @Test
+    public void verifyWorkWithBadHeapId() throws CommandException {
+        final String BAD_HEAP_ID = "invalid-heap-id";
+
+        HeapDAO heapDao = mock(HeapDAO.class);
+
+        HeapInfo heapInfo = mock(HeapInfo.class);
+        when(heapDao.getHeapInfo(BAD_HEAP_ID)).thenReturn(null);
+        when(heapDao.getHistogram(any(HeapInfo.class))).thenReturn(null);
+
+        OSGIUtils serviceProvider = mock(OSGIUtils.class);
+        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(heapDao);
+
+        Command command = new ShowHeapHistogramCommand(serviceProvider);
+        TestCommandContextFactory factory = new TestCommandContextFactory();
+
+        SimpleArguments args = new SimpleArguments();
+        args.addArgument("heapId", BAD_HEAP_ID);
+
+        command.run(factory.createContext(args));
+
+        assertEquals("Heap ID not found: " + BAD_HEAP_ID + "\n", factory.getOutput());
+        verify(serviceProvider).ungetService(HeapDAO.class, heapDao);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/core/src/test/java/com/redhat/thermostat/client/heap/internal/ActivatorTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2012 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.client.heap.internal;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.client.heap.cli.DumpHeapCommand;
+import com.redhat.thermostat.client.heap.cli.FindObjectsCommand;
+import com.redhat.thermostat.client.heap.cli.FindRootCommand;
+import com.redhat.thermostat.client.heap.cli.ListHeapDumpsCommand;
+import com.redhat.thermostat.client.heap.cli.ObjectInfoCommand;
+import com.redhat.thermostat.client.heap.cli.SaveHeapDumpToFileCommand;
+import com.redhat.thermostat.client.heap.cli.ShowHeapHistogramCommand;
+import com.redhat.thermostat.common.cli.Command;
+import com.redhat.thermostat.test.StubBundleContext;
+
+public class ActivatorTest {
+
+    @Test
+    public void testCommandsRegistered() throws Exception {
+        StubBundleContext ctx = new StubBundleContext();
+        Activator activator = new Activator();
+        
+        activator.start(ctx);
+        
+        assertTrue(ctx.isServiceRegistered(Command.class.getName(), DumpHeapCommand.class));
+        assertTrue(ctx.isServiceRegistered(Command.class.getName(), FindObjectsCommand.class));
+        assertTrue(ctx.isServiceRegistered(Command.class.getName(), FindRootCommand.class));
+        assertTrue(ctx.isServiceRegistered(Command.class.getName(), ListHeapDumpsCommand.class));
+        assertTrue(ctx.isServiceRegistered(Command.class.getName(), ObjectInfoCommand.class));
+        assertTrue(ctx.isServiceRegistered(Command.class.getName(), SaveHeapDumpToFileCommand.class));
+        assertTrue(ctx.isServiceRegistered(Command.class.getName(), ShowHeapHistogramCommand.class));
+    }
+}
--- a/client/heapdumper/pom.xml	Tue Oct 23 11:19:24 2012 -0400
+++ b/client/heapdumper/pom.xml	Tue Oct 23 11:21:06 2012 -0400
@@ -38,116 +38,21 @@
 -->
 <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>
+    <groupId>com.redhat.thermostat</groupId>
     <artifactId>thermostat-client</artifactId>
-    <groupId>com.redhat.thermostat</groupId>
     <version>0.5.0-SNAPSHOT</version>
   </parent>
+
   <artifactId>thermostat-client-heapdumper</artifactId>
-  <packaging>bundle</packaging>
+  <packaging>pom</packaging>
+
   <name>Thermostat Client Heap Dumper plugin</name>
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
-            <Bundle-Activator>com.redhat.thermostat.client.heap.Activator</Bundle-Activator>
-            <Bundle-SymbolicName>com.redhat.thermostat.client.heapdumper</Bundle-SymbolicName>
-            <Private-Package>
-               com.redhat.thermostat.client.heap,
-               com.redhat.thermostat.client.heap.cli,
-               com.redhat.thermostat.client.heap.swing,
-               com.redhat.thermostat.client.heap.chart
-            </Private-Package>
-            <!-- Do not autogenerate uses clauses in Manifests -->
-            <_nouses>true</_nouses>
-          </instructions>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-  <dependencies>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.mockito</groupId>
-      <artifactId>mockito-core</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.easytesting</groupId>
-      <artifactId>fest-swing</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>net.java.openjdk.cacio</groupId>
-      <artifactId>cacio-tta</artifactId>
-      <scope>test</scope>
-    </dependency>
-    
-    <dependency>
-      <groupId>org.osgi</groupId>
-      <artifactId>org.osgi.core</artifactId>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.osgi</groupId>
-      <artifactId>org.osgi.compendium</artifactId>
-      <scope>provided</scope>
-    </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-client-core</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-tools</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-agent-heapdumper</artifactId>
-      <version>${project.version}</version>
-      <scope>test</scope>
-    </dependency>
+  <modules>
+    <module>core</module>
+    <module>swing</module>
+  </modules>
 
-    <dependency>
-      <groupId>org.jfree</groupId>
-      <artifactId>jfreechart</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>com.sun</groupId>
-      <artifactId>tools</artifactId>
-      <scope>system</scope>
-      <systemPath>${java.home}/../lib/tools.jar</systemPath>
-    </dependency>
-    
-  </dependencies>
 </project>
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/Activator.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import java.util.Map;
-import java.util.Objects;
-import java.util.ServiceLoader;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-
-import com.redhat.thermostat.client.core.VmInformationService;
-import com.redhat.thermostat.client.heap.swing.SwingHeapDumpDetailsViewProvider;
-import com.redhat.thermostat.client.heap.swing.SwingHeapHistogramViewProvider;
-import com.redhat.thermostat.client.heap.swing.SwingHeapViewProvider;
-import com.redhat.thermostat.client.heap.swing.SwingObjectDetailsViewProvider;
-import com.redhat.thermostat.client.heap.swing.SwingObjectRootsViewProvider;
-import com.redhat.thermostat.client.osgi.service.ApplicationService;
-import com.redhat.thermostat.common.MultipleServiceTracker;
-import com.redhat.thermostat.common.MultipleServiceTracker.Action;
-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.common.dao.AgentInfoDAO;
-import com.redhat.thermostat.common.dao.HeapDAO;
-import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
-
-public class Activator implements BundleActivator {
-
-    private CommandRegistry reg;
-    private MultipleServiceTracker heapDumperServiceTracker;
-    private ServiceRegistration heapDumperServiceRegistration;
-    private BundleContext context;
-
-    @Override
-    public void start(final BundleContext context) throws Exception {
-
-        this.context = context;
-        Class<?>[] deps = new Class<?>[] {
-                ApplicationService.class,
-                AgentInfoDAO.class,
-                VmMemoryStatDAO.class,
-                HeapDAO.class,
-        };
-
-        heapDumperServiceTracker = new MultipleServiceTracker(context, deps,
-                getServiceAvailableAction());
-        heapDumperServiceTracker.open();
-
-        reg = new CommandRegistryImpl(context);
-        ServiceLoader<Command> cmds = ServiceLoader.load(Command.class,
-                getClass().getClassLoader());
-        reg.registerCommands(cmds);
-    }
-
-    @Override
-    public void stop(BundleContext context) throws Exception {
-        heapDumperServiceTracker.close();
-        reg.unregisterCommands();
-    }
-    
-    // package private for testing
-    ServicesAvailableAction getServiceAvailableAction() {
-        return new ServicesAvailableAction();
-    }
-    
-    class ServicesAvailableAction implements Action {
-
-        @Override
-        public void dependenciesAvailable(Map<String, Object> services) {
-            ApplicationService appService = (ApplicationService) services
-                    .get(ApplicationService.class.getName());
-            Objects.requireNonNull(appService);
-            AgentInfoDAO agentDao = (AgentInfoDAO) services
-                    .get(AgentInfoDAO.class.getName());
-            Objects.requireNonNull(agentDao);
-            VmMemoryStatDAO vmMemoryStatDao = (VmMemoryStatDAO) services
-                    .get(VmMemoryStatDAO.class.getName());
-            Objects.requireNonNull(vmMemoryStatDao);
-            HeapDAO heapDao = (HeapDAO) services.get(HeapDAO.class.getName());
-            Objects.requireNonNull(heapDao);
-            heapDumperServiceRegistration = context
-                    .registerService(VmInformationService.class
-                            .getName(), new HeapDumperService(
-                            appService, agentDao, vmMemoryStatDao, heapDao,
-                            new SwingHeapDumpDetailsViewProvider(),
-                            new SwingHeapViewProvider(),
-                            new SwingHeapHistogramViewProvider(),
-                            new SwingObjectDetailsViewProvider(),
-                            new SwingObjectRootsViewProvider()),
-                            null);
-            
-        }
-
-        @Override
-        public void dependenciesUnavailable() {
-            heapDumperServiceRegistration.unregister();
-        }
-        
-    }
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumpController.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,270 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import java.text.DecimalFormat;
-import java.text.NumberFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import com.redhat.thermostat.client.core.controllers.VmInformationServiceController;
-import com.redhat.thermostat.client.core.views.BasicView.Action;
-import com.redhat.thermostat.client.core.views.UIComponent;
-import com.redhat.thermostat.client.heap.HeapView.HeapDumperAction;
-import com.redhat.thermostat.client.heap.chart.OverviewChart;
-import com.redhat.thermostat.client.heap.cli.HeapDumperCommand;
-import com.redhat.thermostat.client.osgi.service.ApplicationService;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.NotImplementedException;
-import com.redhat.thermostat.common.Timer;
-import com.redhat.thermostat.common.Timer.SchedulingType;
-import com.redhat.thermostat.common.appctx.ApplicationContext;
-import com.redhat.thermostat.common.dao.AgentInfoDAO;
-import com.redhat.thermostat.common.dao.HeapDAO;
-import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
-import com.redhat.thermostat.common.dao.VmRef;
-import com.redhat.thermostat.common.heap.HeapDump;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.common.model.HeapInfo;
-import com.redhat.thermostat.common.model.VmMemoryStat;
-import com.redhat.thermostat.common.model.VmMemoryStat.Generation;
-import com.redhat.thermostat.common.model.VmMemoryStat.Space;
-import com.redhat.thermostat.common.utils.DisplayableValues.Scale;
-
-public class HeapDumpController implements VmInformationServiceController {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private final VmMemoryStatDAO vmDao;
-    private final VmRef ref;
-    
-    private final HeapDAO heapDAO;
-        
-    private HeapView view;
-    private final Timer timer;
-    
-    private OverviewChart model;
-    private ApplicationService appService;
-    private HeapDumpDetailsViewProvider detailsViewProvider;
-    private HeapHistogramViewProvider histogramViewProvider;
-    private ObjectDetailsViewProvider objectDetailsViewProvider;
-    private ObjectRootsViewProvider objectRootsViewProvider;
-
-    public HeapDumpController(final AgentInfoDAO agentInfoDao, final VmMemoryStatDAO vmMemoryStatDao, final HeapDAO heapDao, final VmRef ref, final ApplicationService appService, HeapViewProvider viewProvider, HeapDumpDetailsViewProvider detailsViewProvider, HeapHistogramViewProvider histogramProvider, ObjectDetailsViewProvider objectDetailsProvider, ObjectRootsViewProvider objectRootsProvider) {
-        this(agentInfoDao, vmMemoryStatDao, heapDao, ref, appService, new HeapDumperCommand(), viewProvider, detailsViewProvider, histogramProvider, objectDetailsProvider, objectRootsProvider);
-    }
-
-    HeapDumpController(final AgentInfoDAO agentInfoDao, final VmMemoryStatDAO vmMemoryStatDao, final HeapDAO heapDao, final VmRef ref, final ApplicationService appService, final HeapDumperCommand command, HeapViewProvider viewProvider, HeapDumpDetailsViewProvider detailsViewProvider, HeapHistogramViewProvider histogramProvider, ObjectDetailsViewProvider objectDetailsProvider, ObjectRootsViewProvider objectRootsProvider) {
-        
-        this.objectDetailsViewProvider = objectDetailsProvider;
-        this.objectRootsViewProvider = objectRootsProvider;
-        this.histogramViewProvider = histogramProvider;
-        this.detailsViewProvider = detailsViewProvider;
-        this.appService = appService;
-        this.ref = ref;
-        this.vmDao = vmMemoryStatDao;
-        this.heapDAO = heapDao;
-        
-        model = new OverviewChart(
-                    translator.localize(LocaleResources.HEAP_CHART_TITLE),
-                    translator.localize(LocaleResources.HEAP_CHART_TIME_AXIS),
-                    translator.localize(LocaleResources.HEAP_CHART_HEAP_AXIS),
-                    translator.localize(LocaleResources.HEAP_CHART_CAPACITY),
-                    translator.localize(LocaleResources.HEAP_CHART_USED));
-        
-        timer = ApplicationContext.getInstance().getTimerFactory().createTimer();
-        timer.setAction(new HeapOverviewDataCollector());
-        
-        timer.setInitialDelay(0);
-        timer.setDelay(1000);
-        model.setRange(3600);
-        timer.setTimeUnit(TimeUnit.MILLISECONDS);
-        timer.setSchedulingType(SchedulingType.FIXED_RATE);
-        
-        view = viewProvider.createView();
-        view.setModel(model);
-        
-        HeapDump dump = null;
-        view.clearHeapDumpList();
-        Collection<HeapInfo> infos = heapDAO.getAllHeapInfo(ref);
-        for (HeapInfo info : infos) {
-            dump = new HeapDump(info, heapDAO);
-            view.addHeapDump(dump);
-        }
-        
-        // check if we were reading some of the dumps
-        dump = (HeapDump) appService.getApplicationCache().getAttribute(ref);
-        if (dump != null && infos.contains(dump.getInfo())) {
-            showHeapDumpDetails(dump);
-        }
-        
-        view.addActionListener(new ActionListener<Action>() {            
-            @Override
-            public void actionPerformed(ActionEvent<Action> actionEvent) {
-                switch (actionEvent.getActionId()) {
-                case HIDDEN:
-                    timer.stop();
-                    break;
-                
-                case VISIBLE:                    
-                    timer.start();
-                    break;
-
-                default:
-                    throw new NotImplementedException("unknown event: " + actionEvent.getActionId());
-                }
-            }
-        });
-
-        view.addDumperListener(new ActionListener<HeapView.HeapDumperAction>() {
-            @Override
-            public void actionPerformed(ActionEvent<HeapDumperAction> actionEvent) {
-                HeapDump dump = null;
-                switch (actionEvent.getActionId()) {
-                case DUMP_REQUESTED:
-                    command.execute(agentInfoDao, ref, new Runnable() {
-                        public void run() {
-                            view.notifyHeapDumpComplete();
-                        }
-                    });
-                    
-                    break;
-                
-                case ANALYSE:
-                    dump = (HeapDump) actionEvent.getPayload();
-                    analyseDump(dump);
-                    break;
-                }
-            }
-        });
-    }
-
-    
-    private void analyseDump(final HeapDump dump) {
-        appService.getApplicationExecutor().execute(new Runnable() {
-            
-            @Override
-            public void run() {
-                showHeapDumpDetails(dump);
-                appService.getApplicationCache().addAttribute(ref, dump);
-            }
-        });
-    }
-
-    private void showHeapDumpDetails(HeapDump dump) {
-        HeapDumpDetailsController controller = new HeapDumpDetailsController(appService, detailsViewProvider, histogramViewProvider, objectDetailsViewProvider, objectRootsViewProvider);
-        controller.setDump(dump);
-        view.setChildView(controller.getView());
-        view.openDumpView();
-    }
-
-    @Override
-    public UIComponent getView() {
-        return (UIComponent) view;
-    }
-
-    @Override
-    public String getLocalizedName() {
-        return translator.localize(LocaleResources.HEAP_SECTION_TITLE);
-    }
-
-    class HeapOverviewDataCollector implements Runnable {
-
-        private long desiredUpdateTimeStamp = System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1);
-
-        @Override
-        public void run() {
-            checkForHeapDumps();
-            updateMemoryChartAndDisplay();
-        }
-
-        private void checkForHeapDumps() {
-            Collection<HeapInfo> heapInfos = heapDAO.getAllHeapInfo(ref);
-            List<HeapDump> heapDumps = new ArrayList<HeapDump>(heapInfos.size());
-            for (HeapInfo heapInfo : heapInfos) {
-                heapDumps.add(new HeapDump(heapInfo, heapDAO));
-            }
-            view.updateHeapDumpList(heapDumps);
-        }
-
-        private void updateMemoryChartAndDisplay() {
-            List<VmMemoryStat> vmInfo = null;
-            vmInfo = vmDao.getLatestVmMemoryStats(ref, desiredUpdateTimeStamp);
-
-            for (VmMemoryStat memoryStats: vmInfo) {
-                long used = 0l;
-                long capacity = 0l;
-                long max = 0l;
-                List<Generation> generations = memoryStats.getGenerations();
-                for (Generation generation : generations) {
-                    
-                    // non heap
-                    if (generation.name.equals("perm")) {
-                        continue;
-                    }
-                    
-                    List<Space> spaces = generation.spaces;
-                    for (Space space: spaces) {
-                        used += space.used;
-                        capacity += space.capacity;
-                        
-                        // TODO
-                        max =+ space.maxCapacity;
-                    }
-                }
-                model.addData(memoryStats.getTimeStamp(), used, capacity);
-                
-                NumberFormat formatter = DecimalFormat.getInstance();
-
-                double res = Scale.convertTo(Scale.B, used);
-                String _used = formatter.format(res) + " " + Scale.B;
-                
-                res = Scale.convertTo(Scale.B, capacity);
-                String _capacity= formatter.format(capacity) + " " + Scale.B;
-                
-                view.updateUsedAndCapacity(_used, _capacity);
-                desiredUpdateTimeStamp = Math.max(desiredUpdateTimeStamp, memoryStats.getTimeStamp());
-            }
-
-            model.notifyListenersOfModelChange();
-        }
-
-    }
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumpDetailsController.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.client.core.views.BasicView;
-import com.redhat.thermostat.client.osgi.service.ApplicationService;
-import com.redhat.thermostat.common.heap.HeapDump;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-
-public class HeapDumpDetailsController {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private static final Logger log = LoggingUtils.getLogger(HeapDumpDetailsController.class);
-
-    private final ApplicationService appService;
-
-    private HeapDumpDetailsView view;
-    private HeapDump heapDump;
-    private HeapHistogramViewProvider histogramViewProvider;
-    private ObjectDetailsViewProvider objectDetailsViewProvider;
-    private ObjectRootsViewProvider objectRootsViewProvider;
-
-    public HeapDumpDetailsController(ApplicationService appService, HeapDumpDetailsViewProvider viewProvider, HeapHistogramViewProvider histogramProvider, ObjectDetailsViewProvider objectDetailsProvider, ObjectRootsViewProvider objectRootsProvider) {
-        this.appService = appService;
-        this.histogramViewProvider = histogramProvider;
-        this.objectDetailsViewProvider = objectDetailsProvider;
-        this.objectRootsViewProvider = objectRootsProvider;
-        view = viewProvider.createView();
-    }
-
-    public void setDump(HeapDump dump) {
-        this.heapDump = dump;
-        try {
-            HeapHistogramView heapHistogramView = histogramViewProvider.createView();
-            heapHistogramView.display(heapDump.getHistogram());
-            String title = translator.localize(LocaleResources.HEAP_DUMP_SECTION_HISTOGRAM);
-            view.addSubView(title, heapHistogramView);
-        } catch (IOException e) {
-            log.log(Level.SEVERE, "unexpected error while reading heap dump", e);
-        }
-
-        ObjectDetailsController controller = new ObjectDetailsController(appService, dump, objectDetailsViewProvider, objectRootsViewProvider);
-        ObjectDetailsView detailsView = controller.getView();
-        view.addSubView(translator.localize(LocaleResources.HEAP_DUMP_SECTION_OBJECT_BROWSER), detailsView);
-
-        // do a dummy search right now to prep the index
-        heapDump.searchObjects("A_RANDOM_PATTERN", 1);
-    }
-
-    public BasicView getView() {
-        return view;
-    }
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumpDetailsView.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import com.redhat.thermostat.client.core.views.BasicView;
-import com.redhat.thermostat.client.core.views.UIComponent;
-
-public abstract class HeapDumpDetailsView extends BasicView implements UIComponent {
-
-    public abstract void addSubView(String title, HeapHistogramView child);
-    public abstract void addSubView(String title, ObjectDetailsView child);
-    public abstract void removeSubView(String title);
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumpDetailsViewProvider.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import com.redhat.thermostat.client.core.views.ViewProvider;
-
-public interface HeapDumpDetailsViewProvider extends ViewProvider {
-
-    @Override
-    public HeapDumpDetailsView createView();
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumperService.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import com.redhat.thermostat.client.core.VmFilter;
-import com.redhat.thermostat.client.core.VmInformationService;
-import com.redhat.thermostat.client.core.controllers.VmInformationServiceController;
-import com.redhat.thermostat.client.osgi.service.AlwaysMatchFilter;
-import com.redhat.thermostat.client.osgi.service.ApplicationService;
-import com.redhat.thermostat.common.dao.AgentInfoDAO;
-import com.redhat.thermostat.common.dao.HeapDAO;
-import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
-import com.redhat.thermostat.common.dao.VmRef;
-
-public class HeapDumperService implements VmInformationService {
-    
-    private ApplicationService appService;
-    private AgentInfoDAO agentInfoDao;
-    private VmMemoryStatDAO vmMemoryStatDao;
-    private HeapDAO heapDao;
-
-    private VmFilter filter = new AlwaysMatchFilter();
-    private HeapDumpDetailsViewProvider detailsViewProvider;
-    private HeapHistogramViewProvider histogramViewProvider;
-    private HeapViewProvider viewProvider;
-    private ObjectDetailsViewProvider objectDetailsViewProvider;
-    private ObjectRootsViewProvider objectRootsViewProvider;
-
-    public HeapDumperService(ApplicationService appService, AgentInfoDAO agentInfoDao, VmMemoryStatDAO vmMemoryStatDao, HeapDAO heapDao, HeapDumpDetailsViewProvider detailsViewProvider, HeapViewProvider viewProvider, HeapHistogramViewProvider histogramViewProvider, ObjectDetailsViewProvider objectDetailsViewProvider, ObjectRootsViewProvider objectRootsViewProvider) {
-        this.agentInfoDao = agentInfoDao;
-        this.vmMemoryStatDao = vmMemoryStatDao;
-        this.heapDao = heapDao;
-        this.appService = appService;
-        this.viewProvider = viewProvider;
-        this.detailsViewProvider = detailsViewProvider;
-        this.histogramViewProvider = histogramViewProvider;
-        this.objectDetailsViewProvider = objectDetailsViewProvider;
-        this.objectRootsViewProvider = objectRootsViewProvider;
-    }
-
-    @Override
-    public VmInformationServiceController getInformationServiceController(VmRef ref) {
-        return new HeapDumpController(agentInfoDao, vmMemoryStatDao, heapDao, ref, appService, viewProvider, detailsViewProvider, histogramViewProvider, objectDetailsViewProvider, objectRootsViewProvider);
-    }
-
-    @Override
-    public VmFilter getFilter() {
-        return filter;
-    }
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapHistogramView.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import com.redhat.thermostat.client.core.views.BasicView;
-import com.redhat.thermostat.client.core.views.UIComponent;
-import com.redhat.thermostat.common.heap.ObjectHistogram;
-
-public abstract class HeapHistogramView extends BasicView implements UIComponent {
-
-    public abstract void display(ObjectHistogram histogram);
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapHistogramViewProvider.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import com.redhat.thermostat.client.core.views.ViewProvider;
-
-public interface HeapHistogramViewProvider extends ViewProvider {
-
-    @Override
-    public HeapHistogramView createView();
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapObjectUI.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-public class HeapObjectUI {
-
-    public String objectId;
-    public String text;
-
-    public HeapObjectUI(String objectId, String text) {
-        this.objectId = objectId;
-        this.text = text;
-    }
-
-    @Override
-    public String toString() {
-        return text;
-    }
-}
\ No newline at end of file
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapView.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import java.util.List;
-
-import com.redhat.thermostat.client.core.views.BasicView;
-import com.redhat.thermostat.client.core.views.UIComponent;
-import com.redhat.thermostat.client.heap.chart.OverviewChart;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ActionNotifier;
-import com.redhat.thermostat.common.heap.HeapDump;
-
-public abstract class HeapView extends BasicView implements UIComponent {
-    
-    public enum HeapDumperAction {
-        DUMP_REQUESTED,
-        ANALYSE,
-        REQUEST_ABORTED
-    }
-   
-    protected final ActionNotifier<HeapDumperAction> heapDumperNotifier;
-    protected HeapView() {
-        heapDumperNotifier = new ActionNotifier<HeapDumperAction>(this);
-    }
-    
-    public void addDumperListener(ActionListener<HeapDumperAction> listener) {
-        heapDumperNotifier.addActionListener(listener);
-    }
-    
-    public void removeDumperListener(ActionListener<HeapDumperAction> listener) {
-        heapDumperNotifier.removeActionListener(listener);
-    }
-
-    abstract public void updateUsedAndCapacity(String used, String capacity);
-    /** View updates automatically based on the model */
-    abstract public void setModel(OverviewChart model);
-    abstract public void addHeapDump(HeapDump dump);
-    abstract public void clearHeapDumpList();
-    
-    abstract public void openDumpView();
-    abstract public void setChildView(BasicView childView);
-    public abstract void notifyHeapDumpComplete();
-
-    public abstract void updateHeapDumpList(List<HeapDump> heapDumps);
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapViewProvider.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import com.redhat.thermostat.client.core.views.ViewProvider;
-
-public interface HeapViewProvider extends ViewProvider {
-
-    @Override
-    public HeapView createView();
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/Histogram.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import java.util.List;
-
-public class Histogram {
-
-    private String[] header;
-    
-    private List<Object[]> data;
-    
-    Histogram(String[] header) {
-        this.header = header;
-    }
-    
-    public String[] getHistogramColums() {
-        return header;
-    }
-
-    void setData(List<Object[]> data) {
-        this.data = data;
-    }
-
-   public List<Object[]> getData() {
-    return data;
-   }
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/LocaleResources.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import com.redhat.thermostat.common.locale.Translate;
-
-public enum LocaleResources {
-
-    MISSING_INFO,
-    HOST_SERVICE_UNAVAILABLE,
-    VM_SERVICE_UNAVAILABLE,
-    HEAP_SERVICE_UNAVAILABLE,
-
-    HEADER_TIMESTAMP,
-    HEADER_HOST_ID,
-    HEADER_VM_ID,
-    HEADER_HEAP_ID,
-    HEADER_OBJECT_ID,
-    HEADER_OBJECT_TYPE,
-
-    FILE_REQUIRED,
-    INVALID_LIMIT,
-    HEAP_ID_NOT_FOUND,
-    HEAP_ID_REQUIRED,
-    SEARCH_TERM_REQUIRED,
-
-    COMMAND_HEAP_DUMP_DONE,
-
-    COMMAND_FIND_ROOT_NO_ROOT_FOUND,
-
-    COMMAND_OBJECT_INFO_OBJECT_ID,
-    COMMAND_OBJECT_INFO_TYPE,
-    COMMAND_OBJECT_INFO_SIZE,
-    COMMAND_OBJECT_INFO_HEAP_ALLOCATED,
-    COMMAND_OBJECT_INFO_REFERENCES,
-    COMMAND_OBJECT_INFO_REFERRERS,
-
-    COMMAND_SAVE_HEAP_DUMP_SAVED_TO_FILE,
-    COMMAND_SAVE_HEAP_DUMP_ERROR_SAVING,
-    COMMAND_SAVE_HEAP_DUMP_ERROR_CLOSING_STREAM,
-
-    HEAP_SECTION_TITLE,
-    HEAP_OVERVIEW_TITLE,
-    HEAP_CHART_TITLE,
-    HEAP_CHART_TIME_AXIS,
-    HEAP_CHART_HEAP_AXIS,
-    HEAP_CHART_CAPACITY,
-    HEAP_CHART_USED,
-
-    HEAP_DUMP_SECTION_HISTOGRAM,
-    HEAP_DUMP_SECTION_OBJECT_BROWSER,
-
-    HEAP_DUMP_CLASS_USAGE,
-    HEAP_DUMP_HISTOGRAM_COLUMN_CLASS,
-    HEAP_DUMP_HISTOGRAM_COLUMN_INSTANCES,
-    HEAP_DUMP_HISTOGRAM_COLUMN_SIZE,
-
-    HEAP_DUMP_OBJECT_BROWSE_SEARCH_HINT,
-    HEAP_DUMP_OBJECT_BROWSE_SEARCH_PATTERN_HELP,
-    HEAP_DUMP_OBJECT_BROWSE_SEARCH_LABEL,
-    HEAP_DUMP_OBJECT_BROWSE_REFERRERS,
-    HEAP_DUMP_OBJECT_BROWSE_REFERENCES,
-    HEAP_DUMP_OBJECT_FIND_ROOT,
-
-    OBJECT_ROOTS_VIEW_TITLE,
-    ;
-
-    static final String RESOURCE_BUNDLE = "com.redhat.thermostat.client.heap.strings";
-
-    public static Translate<LocaleResources> createLocalizer() {
-        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
-    }
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/ObjectDetailsController.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,203 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.List;
-
-import com.redhat.thermostat.client.heap.ObjectDetailsView.ObjectAction;
-import com.redhat.thermostat.client.heap.ObjectDetailsView.ObjectReferenceCallback;
-import com.redhat.thermostat.client.osgi.service.ApplicationService;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.NotImplementedException;
-import com.redhat.thermostat.common.heap.HeapDump;
-import com.sun.tools.hat.internal.model.JavaClass;
-import com.sun.tools.hat.internal.model.JavaField;
-import com.sun.tools.hat.internal.model.JavaHeapObject;
-import com.sun.tools.hat.internal.model.JavaHeapObjectVisitor;
-
-public class ObjectDetailsController {
-
-    private ApplicationService appService;
-    private HeapDump heapDump;
-    private ObjectDetailsView view;
-    private ObjectRootsViewProvider viewProvider;
-
-    public ObjectDetailsController(ApplicationService appService, HeapDump heapDump, ObjectDetailsViewProvider viewProvider, ObjectRootsViewProvider rootsViewProvider) {
-        this.appService = appService;
-        this.heapDump = heapDump;
-        this.viewProvider = rootsViewProvider;
-
-        view = viewProvider.createView();
-        addListenersToView();
-    }
-
-    private void addListenersToView() {
-
-        view.addObjectActionListener(new ActionListener<ObjectAction>() {
-            @Override
-            public void actionPerformed(ActionEvent<ObjectAction> actionEvent) {
-                switch (actionEvent.getActionId()) {
-                case SEARCH:
-                    searchForObject();
-                    break;
-                case GET_OBJECT_DETAIL:
-                    showObjectInfo();
-                    break;
-                case SHOW_ROOT_TO_GC:
-                    HeapObjectUI heapObj = (HeapObjectUI) actionEvent.getPayload();
-                    showPathToGC(heapObj);
-                    break;
-                default:
-                    throw new NotImplementedException("unknown action fired by " + actionEvent.getSource());
-                }
-
-            }
-        });
-
-        view.addObjectReferenceCallback(new ObjectReferenceCallback() {
-            @Override
-            public Collection<HeapObjectUI> getReferrers(HeapObjectUI obj) {
-                JavaHeapObject heapObject = heapDump.findObject(obj.objectId);
-
-                @SuppressWarnings("unchecked")
-                Enumeration<JavaHeapObject> referrers = heapObject.getReferers();
-
-                List<HeapObjectUI> objects = new ArrayList<>();
-                while (referrers.hasMoreElements()) {
-                    heapObject = referrers.nextElement();
-                    objects.add(new HeapObjectUI(heapObject.getIdString(), PrintObjectUtils.objectToString(heapObject)));
-                }
-                return objects;
-            }
-
-            @Override
-            public Collection<HeapObjectUI> getReferences(HeapObjectUI obj) {
-                final JavaHeapObject heapObject = heapDump.findObject(obj.objectId);
-
-                final List<JavaHeapObject> references = new ArrayList<>();
-
-                JavaHeapObjectVisitor v = new JavaHeapObjectVisitor() {
-
-                    @Override
-                    public void visit(JavaHeapObject other) {
-                        references.add(other);
-                    }
-
-                    @Override
-                    public boolean mightExclude() {
-                        /* we never return true in exclude */
-                        return false;
-                    }
-
-                    @Override
-                    public boolean exclude(JavaClass clazz, JavaField f) {
-                        /* visit every field in every java class */
-                        return false;
-                    }
-                };
-
-                heapObject.visitReferencedObjects(v);
-
-                List<HeapObjectUI> objects = new ArrayList<>();
-                for (JavaHeapObject ref: references) {
-                    objects.add(new HeapObjectUI(ref.getIdString(), PrintObjectUtils.objectToString(ref)));
-                }
-                return objects;
-            }
-        });
-    }
-
-    private void searchForObject() {
-        String searchText = view.getSearchText();
-        if (searchText == null || searchText.trim().isEmpty()) {
-            return;
-        }
-
-        final int maxResults = computeResultLimit(searchText);
-
-        if (!searchText.contains("*") && !searchText.contains("?")) {
-            searchText = "*" + searchText + "*";
-        }
-
-        final String wildcardQuery = searchText;
-
-        appService.getApplicationExecutor().execute(new Runnable() {
-
-            @Override
-            public void run() {
-                Collection<String> objectIds = heapDump.searchObjects(wildcardQuery, maxResults);
-
-                List<HeapObjectUI> toDisplay = new ArrayList<>();
-                for (String id: objectIds) {
-                    JavaHeapObject heapObject = heapDump.findObject(id);
-                    toDisplay.add(new HeapObjectUI(id, PrintObjectUtils.objectToString(heapObject)));
-                }
-                view.setMatchingObjects(toDisplay);
-            }
-        });
-
-    }
-
-    private int computeResultLimit(String searchText) {
-        return Math.min(1000, searchText.length() * 100);
-    }
-
-    private void showObjectInfo() {
-        HeapObjectUI matchingObject = view.getSelectedMatchingObject();
-        if (matchingObject == null) {
-            return;
-        }
-        String objectId = matchingObject.objectId;
-        JavaHeapObject object = heapDump.findObject(objectId);
-        view.setObjectDetails(object);
-    }
-
-    private void showPathToGC(HeapObjectUI targetObject) {
-        JavaHeapObject heapObject = heapDump.findObject(targetObject.objectId);
-
-        ObjectRootsController controller = new ObjectRootsController(heapDump, heapObject, viewProvider);
-        controller.show();
-    }
-
-    public ObjectDetailsView getView() {
-        return view;
-    }
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/ObjectDetailsView.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import java.util.Collection;
-
-import com.redhat.thermostat.client.core.views.BasicView;
-import com.redhat.thermostat.client.core.views.UIComponent;
-import com.redhat.thermostat.common.ActionListener;
-import com.sun.tools.hat.internal.model.JavaHeapObject;
-
-public abstract class ObjectDetailsView extends BasicView implements UIComponent {
-
-    // TODO this should be some sort of aggregate view
-    // showing users 1000 instances of a class is not very useful unless we
-    // allow the user some aggregate results or allow additional sorting or
-    // filtering
-
-    public enum ObjectAction {
-        SEARCH,
-        GET_OBJECT_DETAIL,
-        SHOW_ROOT_TO_GC,
-    }
-
-    public static interface ObjectReferenceCallback {
-        /** get a list of objects that refers to this object */
-        Collection<HeapObjectUI> getReferrers(HeapObjectUI obj);
-
-        /** get a list of objects that this object refers to */
-        Collection<HeapObjectUI> getReferences(HeapObjectUI obj);
-    }
-
-    public abstract void addObjectActionListener(ActionListener<ObjectAction> listener);
-    public abstract void removeObjectActionListnener(ActionListener<ObjectAction> listener);
-
-    public abstract void addObjectReferenceCallback(ObjectReferenceCallback callback);
-    public abstract void removeObjectReferenceCallback(ObjectReferenceCallback callback);
-
-    public abstract String getSearchText();
-
-    public abstract void setMatchingObjects(Collection<HeapObjectUI> objects);
-
-    public abstract HeapObjectUI getSelectedMatchingObject();
-
-    public abstract void setObjectDetails(JavaHeapObject object);
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/ObjectDetailsViewProvider.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import com.redhat.thermostat.client.core.views.ViewProvider;
-
-public interface ObjectDetailsViewProvider extends ViewProvider {
-
-    @Override
-    public ObjectDetailsView createView();
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/ObjectRootsController.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-import com.redhat.thermostat.client.heap.ObjectRootsView.Action;
-import com.redhat.thermostat.client.heap.cli.FindRoot;
-import com.redhat.thermostat.client.heap.cli.HeapPath;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.NotImplementedException;
-import com.redhat.thermostat.common.heap.HeapDump;
-import com.redhat.thermostat.common.locale.Translate;
-import com.sun.tools.hat.internal.model.JavaHeapObject;
-
-public class ObjectRootsController {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private final ObjectRootsView view;
-
-    private final HeapDump heapDump;
-    private final JavaHeapObject heapObject;
-    private final FindRoot rootFinder;
-
-    public ObjectRootsController(HeapDump dump, JavaHeapObject heapObject, ObjectRootsViewProvider viewProvider) {
-        this(dump, heapObject, new FindRoot(), viewProvider);
-    }
-
-    public ObjectRootsController(HeapDump dump, JavaHeapObject heapObject, FindRoot findRoot, ObjectRootsViewProvider viewProvider) {
-        this.heapDump = dump;
-        this.heapObject = heapObject;
-        this.rootFinder = findRoot;
-
-        view = viewProvider.createView();
-
-        view.addActionListener(new ActionListener<ObjectRootsView.Action>() {
-
-            @Override
-            public void actionPerformed(ActionEvent<Action> actionEvent) {
-                switch (actionEvent.getActionId()) {
-                case VISIBLE:
-                    view.showView();
-                    break;
-                case HIDDEN:
-                    view.hideView();
-                    break;
-                case OBJECT_SELECTED:
-                    HeapObjectUI obj = (HeapObjectUI) actionEvent.getPayload();
-                    showObjectDetails(obj);
-                    break;
-                default:
-                    throw new NotImplementedException("unexpected action " +
-                            actionEvent.getActionId() + " recieved by " + ObjectRootsController.this.getClass().getName());
-                }
-
-            }
-        });
-    }
-
-    private void showObjectDetails(HeapObjectUI uiObject) {
-        JavaHeapObject obj = heapDump.findObject(uiObject.objectId);
-        String text = translator.localize(LocaleResources.COMMAND_OBJECT_INFO_OBJECT_ID) + " " + obj.getIdString() + "\n" +
-                translator.localize(LocaleResources.COMMAND_OBJECT_INFO_TYPE) + " " + obj.getClazz().getName() + "\n" +
-                translator.localize(LocaleResources.COMMAND_OBJECT_INFO_SIZE) + " " + String.valueOf(obj.getSize()) + " bytes" + "\n" +
-                translator.localize(LocaleResources.COMMAND_OBJECT_INFO_HEAP_ALLOCATED) + " " + String.valueOf(obj.isHeapAllocated()) + "\n";
-
-        if (obj.getRoot() != null) {
-            text = text + obj.getRoot().getDescription();
-        }
-        view.setObjectDetails(text);
-    }
-
-
-    public void show() {
-        Collection<HeapPath<JavaHeapObject>> paths = rootFinder.findShortestPathsToRoot(heapObject, false);
-        Iterator<HeapPath<JavaHeapObject>> iter = paths.iterator();
-        if (iter.hasNext()) {
-            HeapPath<JavaHeapObject> pathToRoot = iter.next();
-
-            List<HeapObjectUI> path = new ArrayList<>();
-            for (JavaHeapObject heapObj : pathToRoot) {
-                path.add(new HeapObjectUI(heapObj.getIdString(), PrintObjectUtils.objectToString(heapObj)));
-            }
-            view.setPathToRoot(path);
-        }
-        view.showView();
-    }
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/ObjectRootsView.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import java.util.List;
-
-import com.redhat.thermostat.client.core.views.UIComponent;
-import com.redhat.thermostat.client.core.views.View;
-import com.redhat.thermostat.common.ActionListener;
-
-public interface ObjectRootsView extends View, UIComponent {
-
-    enum Action {
-        VISIBLE,
-        HIDDEN,
-        OBJECT_SELECTED,
-    }
-
-    void addActionListener(ActionListener<Action> listener);
-    void removeActionListener(ActionListener<Action> listener);
-
-    void showView();
-    void hideView();
-
-    void setPathToRoot(List<HeapObjectUI> pathToRoot);
-    void setObjectDetails(String information);
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/ObjectRootsViewProvider.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import com.redhat.thermostat.client.core.views.ViewProvider;
-
-public interface ObjectRootsViewProvider extends ViewProvider {
-
-    @Override
-    public ObjectRootsView createView();
-    
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/PrintObjectUtils.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import com.sun.tools.hat.internal.model.JavaHeapObject;
-
-public class PrintObjectUtils {
-
-    public static String objectToString(JavaHeapObject obj) {
-        return obj.getClazz().getName() + "@" + obj.getIdString();
-    }
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/chart/OverviewChart.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,173 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.chart;
-
-import java.awt.Color;
-import java.awt.GradientPaint;
-import java.awt.Paint;
-import java.util.Date;
-
-import javax.swing.plaf.ColorUIResource;
-
-import org.jfree.chart.ChartFactory;
-import org.jfree.chart.JFreeChart;
-import org.jfree.chart.axis.DateAxis;
-import org.jfree.chart.axis.NumberAxis;
-import org.jfree.chart.axis.TickUnits;
-import org.jfree.chart.axis.ValueAxis;
-import org.jfree.chart.plot.XYPlot;
-import org.jfree.chart.renderer.xy.XYDifferenceRenderer;
-import org.jfree.data.RangeType;
-import org.jfree.data.time.Millisecond;
-import org.jfree.data.time.TimeSeries;
-import org.jfree.data.time.TimeSeriesCollection;
-
-import com.redhat.thermostat.charts.BytesTickUnit;
-
-public class OverviewChart {
-        
-    private static final ColorUIResource MAIN_BAR_BASE_COLOR = new ColorUIResource(0x4A90D9);
-
-    private static final String lock = new String("chartLock");
-
-    private TimeSeries total;
-    private TimeSeries used;
-    private String title;
-    private String xAxis;
-    private String yAxis;
-    
-    public OverviewChart(String title, String xAxis, String yAxis, String mainSeries, String secondarySeries) {
-        
-        this.title = title;
-        this.xAxis = xAxis;
-        this.yAxis = yAxis;
-        
-        total = new TimeSeries(mainSeries);
-        total.setDescription(mainSeries);
-        
-        used = new TimeSeries(secondarySeries);
-        used.setDescription(secondarySeries);
-    }
-    
-    public JFreeChart createChart(int height, Color bgColor) {
-
-        TimeSeriesCollection dataset = new TimeSeriesCollection();
-        
-        synchronized (lock) {
-            dataset.addSeries(total);
-            dataset.addSeries(used);
-        }
-        
-        JFreeChart chart = ChartFactory.createTimeSeriesChart(
-                title,
-                xAxis,
-                yAxis,
-                dataset,
-                true,  // legend
-                false,  // tool tips
-                false   // URLs
-        );
-
-        Paint paint = new GradientPaint(0, 0, MAIN_BAR_BASE_COLOR, 0, height, bgColor);
-        Paint paint2 = new GradientPaint(0, 0, Color.GREEN, 0, height, bgColor);
-
-        XYPlot plot = (XYPlot) chart.getPlot();
-        plot.setDomainPannable(true);
-        XYDifferenceRenderer r = new XYDifferenceRenderer(paint, paint2, false);
-        r.setRoundXCoordinates(true);
-        plot.setDomainCrosshairLockedOnData(true);
-        plot.setRangeCrosshairLockedOnData(true);
-        plot.setDomainCrosshairVisible(true);
-        plot.setRangeCrosshairVisible(true);
-        plot.setRenderer(r);
-
-        ValueAxis domainAxis = new DateAxis(xAxis);
-        domainAxis.setLowerMargin(0.0);
-        domainAxis.setUpperMargin(0.0);
-        plot.setDomainAxis(domainAxis);
-        plot.setForegroundAlpha(0.5f);
-        TickUnits tickUnits = new TickUnits();
-        tickUnits.add(new BytesTickUnit(1.));
-        tickUnits.add(new BytesTickUnit(10.));
-        tickUnits.add(new BytesTickUnit(100.));
-        tickUnits.add(new BytesTickUnit(1000.));
-        tickUnits.add(new BytesTickUnit(10000.));
-        tickUnits.add(new BytesTickUnit(100000.));
-        tickUnits.add(new BytesTickUnit(1000000.));
-        tickUnits.add(new BytesTickUnit(10000000.));
-        tickUnits.add(new BytesTickUnit(100000000.));
-        tickUnits.add(new BytesTickUnit(1000000000.));
-        tickUnits.add(new BytesTickUnit(10000000000.));
-        tickUnits.add(new BytesTickUnit(100000000000.));
-        tickUnits.add(new BytesTickUnit(1000000000000.));
-        NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
-        yAxis.setStandardTickUnits(tickUnits);
-        yAxis.setRangeType(RangeType.POSITIVE);
-        yAxis.setAutoRangeMinimumSize(10);
-        yAxis.setAutoRange(true);
-        return chart;
-    }
-
-    public void addData(long timeStamp, long used, long total) {
-        
-        Millisecond millisecond = new Millisecond(new Date(timeStamp));
-        synchronized (lock) {            
-            if (this.total.getValue(millisecond) == null) {
-                this.total.add(millisecond, total, false);
-                this.total.removeAgedItems(true);
-            }
-            
-            if (this.used.getValue(millisecond) == null) {
-                this.used.add(millisecond, used, false);
-                this.used.removeAgedItems(true);
-            }
-        }
-        
-    }
-
-    public void notifyListenersOfModelChange() {
-        synchronized (lock) {
-            this.total.fireSeriesChanged();
-            this.used.fireSeriesChanged();
-        }
-    }
-
-    public void setRange(int seconds) {
-        total.setMaximumItemCount(seconds);
-        used.setMaximumItemCount(seconds);
-    }
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/DumpHeapCommand.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import java.util.concurrent.Semaphore;
-
-import com.redhat.thermostat.client.heap.LocaleResources;
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.HostVMArguments;
-import com.redhat.thermostat.common.cli.SimpleCommand;
-import com.redhat.thermostat.common.dao.AgentInfoDAO;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.common.utils.OSGIUtils;
-
-
-public class DumpHeapCommand extends SimpleCommand {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-    private static final String NAME = "dump-heap";
-
-    private final OSGIUtils serviceProvider;
-    private final HeapDumperCommand implementation;
-
-    public DumpHeapCommand() {
-        this(OSGIUtils.getInstance(), new HeapDumperCommand());
-    }
-
-    DumpHeapCommand(OSGIUtils serviceProvider, HeapDumperCommand impl) {
-        this.serviceProvider = serviceProvider;
-        this.implementation = impl;
-    }
-
-    @Override
-    public String getName() {
-        return NAME;
-    }
-
-    @Override
-    public void run(CommandContext ctx) throws CommandException {
-        HostVMArguments args = new HostVMArguments(ctx.getArguments());
-
-        final Semaphore s = new Semaphore(0);
-        Runnable r = new Runnable() {
-            
-            @Override
-            public void run() {
-                s.release();
-            }
-        };
-        AgentInfoDAO service = serviceProvider.getService(AgentInfoDAO.class);
-        if (service == null) {
-            throw new CommandException("Unable to access agent information");
-        }
-        implementation.execute(service, args.getVM(), r);
-        serviceProvider.ungetService(AgentInfoDAO.class, service);
-
-        try {
-            s.acquire();
-            ctx.getConsole().getOutput().print(translator.localize(LocaleResources.COMMAND_HEAP_DUMP_DONE));
-            ctx.getConsole().getOutput().print("\n");
-        } catch (InterruptedException ex) {
-            // Nothing to do here, just return ASAP.
-        }
-    }
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/FindObjectsCommand.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import java.util.Collection;
-import java.util.List;
-
-import com.redhat.thermostat.client.heap.LocaleResources;
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.SimpleCommand;
-import com.redhat.thermostat.common.cli.TableRenderer;
-import com.redhat.thermostat.common.dao.HeapDAO;
-import com.redhat.thermostat.common.heap.HeapDump;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.common.model.HeapInfo;
-import com.redhat.thermostat.common.utils.OSGIUtils;
-import com.sun.tools.hat.internal.model.JavaHeapObject;
-
-public class FindObjectsCommand extends SimpleCommand {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private static final String HEAP_ID_ARG = "heapId";
-    private static final String LIMIT_ARG = "limit";
-    private static final String NAME = "find-objects";
-    private static final String HEADER_OBJECT_ID = translator.localize(LocaleResources.HEADER_OBJECT_ID);
-    private static final String HEADER_TYPE = translator.localize(LocaleResources.HEADER_OBJECT_TYPE);
-    private static final int DEFAULT_LIMIT = 10;
-
-    private OSGIUtils serviceProvider;
-
-    public FindObjectsCommand() {
-        this(OSGIUtils.getInstance());
-    }
-
-    FindObjectsCommand(OSGIUtils serviceProvider) {
-        this.serviceProvider = serviceProvider;
-    }
-
-    @Override
-    public void run(CommandContext ctx) throws CommandException {
-
-        HeapDAO heapDAO = serviceProvider.getServiceAllowNull(HeapDAO.class);
-        if (heapDAO == null) {
-            throw new CommandException(translator.localize(LocaleResources.HEAP_SERVICE_UNAVAILABLE));
-        }
-        try {
-            run(ctx, heapDAO);
-        } finally {
-            serviceProvider.ungetService(HeapDAO.class, heapDAO);
-            heapDAO = null;
-        }
-    }
-
-    private void run(CommandContext ctx, HeapDAO heapDAO) throws CommandException {
-        String heapId = ctx.getArguments().getArgument(HEAP_ID_ARG);
-        HeapInfo heapInfo = heapDAO.getHeapInfo(heapId);
-        if (heapInfo == null) {
-            ctx.getConsole().getOutput().println(translator.localize(LocaleResources.HEAP_ID_NOT_FOUND, heapId));
-            return;
-        }
-        HeapDump heapDump = heapDAO.getHeapDump(heapInfo);
-        if (heapDump == null) {
-            ctx.getConsole().getOutput().println(translator.localize(LocaleResources.HEAP_ID_NOT_FOUND, heapId));
-            return;
-        }
-
-        List<String> terms = ctx.getArguments().getNonOptionArguments();
-        if (terms.size() == 0) {
-            ctx.getConsole().getOutput().println(translator.localize(LocaleResources.SEARCH_TERM_REQUIRED));
-            return;
-        }
-        String searchTerm = terms.get(0);
-        if (searchTerm.trim().length() == 0) {
-            ctx.getConsole().getOutput().println(translator.localize(LocaleResources.SEARCH_TERM_REQUIRED));
-            return;
-        }
-
-        String limitArg = ctx.getArguments().getArgument(LIMIT_ARG);
-        int limit = parseLimit(limitArg);
-        Collection<String> results = heapDump.searchObjects(searchTerm, limit);
-        TableRenderer table = new TableRenderer(2);
-        table.printLine(HEADER_OBJECT_ID, HEADER_TYPE);
-        for (String objectId : results) {
-            JavaHeapObject obj = heapDump.findObject(objectId);
-            String id = obj.getIdString();
-            String className = obj.getClazz().getName();
-            table.printLine(id, className);
-        }
-        table.render(ctx.getConsole().getOutput());
-    }
-
-    private int parseLimit(String limitArg) throws CommandException {
-        int limit = DEFAULT_LIMIT;
-        if (limitArg != null) {
-            try {
-                limit = Integer.parseInt(limitArg);
-            } catch (NumberFormatException ex) {
-                throw new CommandException(translator.localize(LocaleResources.INVALID_LIMIT, limitArg));
-            }
-        }
-        return limit;
-    }
-
-    @Override
-    public String getName() {
-        return NAME;
-    }
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/FindRoot.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
-import com.sun.tools.hat.internal.model.JavaHeapObject;
-
-public class FindRoot {
-
-    private Set<JavaHeapObject> visitedObjects;
-
-    public Collection<HeapPath<JavaHeapObject>> findShortestPathsToRoot(JavaHeapObject obj, boolean findAll) {
-        HeapPath<JavaHeapObject> path = new HeapPath<>(obj);
-        List<HeapPath<JavaHeapObject>> pathsSoFar = new LinkedList<>();
-        pathsSoFar.add(path);
-        visitedObjects = new HashSet<>();
-        return findShortestPathToRoot(pathsSoFar, findAll);
-    }
-
-    private Collection<HeapPath<JavaHeapObject>> findShortestPathToRoot(List<HeapPath<JavaHeapObject>> pathsSoFar, boolean findAll) {
-        List<HeapPath<JavaHeapObject>> newPaths = new LinkedList<>();
-        Collection<HeapPath<JavaHeapObject>> roots = new ArrayList<>();
-        for (HeapPath<JavaHeapObject> path : pathsSoFar) {
-            JavaHeapObject last = path.getNode();
-            if (visitedObjects.contains(last)) {
-                continue;
-            }
-            @SuppressWarnings("rawtypes")
-            Enumeration referrers = last.getReferers();
-            while (referrers.hasMoreElements()) {
-                JavaHeapObject referrer = (JavaHeapObject) referrers.nextElement();
-                HeapPath<JavaHeapObject> newPath = new HeapPath<>(referrer, path);
-                newPaths.add(newPath);
-                if (referrer.getRoot() != null) {
-                    roots.add(newPath);
-                    if (! findAll) {
-                        return roots;
-                    }
-                }
-            }
-            visitedObjects.add(last);
-        }
-        if (newPaths.isEmpty()) {
-            return roots;
-        } else {
-            Collection<HeapPath<JavaHeapObject>> foundRoots = findShortestPathToRoot(newPaths, findAll);
-            roots.addAll(foundRoots);
-            return roots;
-        }
-    }
-
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/FindRootCommand.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import java.io.PrintStream;
-import java.util.Collection;
-import java.util.Iterator;
-
-import com.redhat.thermostat.client.heap.LocaleResources;
-import com.redhat.thermostat.client.heap.PrintObjectUtils;
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.SimpleCommand;
-import com.redhat.thermostat.common.dao.HeapDAO;
-import com.redhat.thermostat.common.heap.HeapDump;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.common.utils.OSGIUtils;
-import com.sun.tools.hat.internal.model.JavaHeapObject;
-import com.sun.tools.hat.internal.model.Root;
-import com.sun.tools.hat.internal.model.Snapshot;
-
-public class FindRootCommand extends SimpleCommand {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private static final String ALL_ARG = "all";
-    private static final String NAME = "find-root";
-
-    private OSGIUtils serviceProvider;
-
-    public FindRootCommand() {
-        this(OSGIUtils.getInstance());
-    }
-
-    FindRootCommand(OSGIUtils serviceProvider) {
-        this.serviceProvider = serviceProvider;
-    }
-
-    @Override
-    public void run(CommandContext ctx) throws CommandException {
-        HeapDAO heapDao = serviceProvider.getServiceAllowNull(HeapDAO.class);
-        if (heapDao == null) {
-            throw new CommandException(translator.localize(LocaleResources.HEAP_SERVICE_UNAVAILABLE));
-        }
-
-        try {
-            run(ctx, heapDao);
-        } finally {
-            serviceProvider.ungetService(HeapDAO.class, heapDao);
-        }
-    }
-
-    private void run(CommandContext ctx, HeapDAO heapDao) throws CommandException {
-        ObjectCommandHelper objCmdHelper = new ObjectCommandHelper(ctx, heapDao);
-        HeapDump heapDump = objCmdHelper.getHeapDump();
-        Snapshot snapshot = heapDump.getSnapshot();
-        JavaHeapObject obj = objCmdHelper.getJavaHeapObject();
-        boolean findAll = ctx.getArguments().hasArgument(ALL_ARG);
-        FindRoot findRoot = new FindRoot();
-        Collection<HeapPath<JavaHeapObject>> pathsToRoot = findRoot.findShortestPathsToRoot(obj, findAll);
-        PrintStream out = ctx.getConsole().getOutput();
-        if (pathsToRoot.isEmpty()) {
-            out.println(translator.localize(LocaleResources.COMMAND_FIND_ROOT_NO_ROOT_FOUND, PrintObjectUtils.objectToString(obj)));
-        } else {
-            printPathsToRoot(snapshot, pathsToRoot, out);
-        }
-    }
-
-    private void printPathsToRoot(Snapshot snapshot, Collection<HeapPath<JavaHeapObject>> pathsToRoot, PrintStream out) {
-        for (HeapPath<JavaHeapObject> path : pathsToRoot) {
-            printPathToRoot(snapshot, path, out);
-            out.println();
-        }
-    }
-
-    private void printPathToRoot(Snapshot snapshot, HeapPath<JavaHeapObject> pathToRoot, PrintStream out) {
-        // Print root.
-        Iterator<JavaHeapObject> i = pathToRoot.iterator();
-        JavaHeapObject last = i.next();
-        Root root = last.getRoot();
-        out.println(root.getDescription() + " -> " + PrintObjectUtils.objectToString(last));
-        // Print reference 'tree'.
-        int indentation = 0;
-        while (i.hasNext()) {
-            JavaHeapObject next = i.next();
-            printIndentation(out, indentation);
-            out.print("\u2514");
-            out.print(last.describeReferenceTo(next, snapshot));
-            out.print(" in ");
-            out.print(PrintObjectUtils.objectToString(last));
-            out.print(" -> ");
-            out.println(PrintObjectUtils.objectToString(next));
-            last = next;
-            indentation++;
-        }
-    }
-
-    private void printIndentation(PrintStream out, int indentation) {
-        for (int i = 0; i < indentation; i++) {
-            out.print(" ");
-        }
-    }
-
-    @Override
-    public String getName() {
-        return NAME;
-    }
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/HeapDumperCommand.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import java.net.InetSocketAddress;
-
-import com.redhat.thermostat.client.command.RequestQueue;
-import com.redhat.thermostat.common.command.Request;
-import com.redhat.thermostat.common.command.Request.RequestType;
-import com.redhat.thermostat.common.command.RequestResponseListener;
-import com.redhat.thermostat.common.command.Response;
-import com.redhat.thermostat.common.dao.AgentInfoDAO;
-import com.redhat.thermostat.common.dao.HostRef;
-import com.redhat.thermostat.common.dao.VmRef;
-import com.redhat.thermostat.common.utils.OSGIUtils;
-
-public class HeapDumperCommand {
-    
-    private static final String RECEIVER_CLASS_NAME = "com.redhat.thermostat.agent.heapdumper.internal.HeapDumpReceiver";
-    private static final String VM_ID_PARAM = "vmId";
-
-    private class HeapDumpListener implements RequestResponseListener {
-
-        private Runnable heapDumpCompleteAction;
-
-        private HeapDumpListener(Runnable heapDumpCompleteAction) {
-            this.heapDumpCompleteAction = heapDumpCompleteAction;
-        }
-
-        @Override
-        public void fireComplete(Request request, Response response) {
-            heapDumpCompleteAction.run();
-        }
-        
-    }
-
-    public void execute(AgentInfoDAO agentInfoDAO, VmRef reference, Runnable heapDumpCompleteAction) {
-
-        HostRef targetHostRef = reference.getAgent();
-        String address = agentInfoDAO.getAgentInformation(targetHostRef).getConfigListenAddress();
-        
-        String [] host = address.split(":");
-        InetSocketAddress target = new InetSocketAddress(host[0], Integer.parseInt(host[1]));
-        Request req = new Request(RequestType.RESPONSE_EXPECTED, target);
-        req.setReceiver(RECEIVER_CLASS_NAME);
-        req.setParameter(VM_ID_PARAM, reference.getIdString());
-        req.addListener(new HeapDumpListener(heapDumpCompleteAction));
-
-        RequestQueue queue = OSGIUtils.getInstance().getService(RequestQueue.class);
-        queue.putRequest(req);
-
-    }
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/HeapNotFoundException.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import com.redhat.thermostat.common.cli.CommandException;
-
-@SuppressWarnings("serial")
-class HeapNotFoundException extends CommandException {
-
-    private static final String MESSAGE_TEMPLATE = "Heap ID not found: ";
-
-    HeapNotFoundException(String heapId) {
-        super(MESSAGE_TEMPLATE + heapId);
-    }
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/HeapPath.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import java.util.Iterator;
-
-public class HeapPath<T> implements Iterable<T> {
-
-    private static class HeapPathIterator<T> implements Iterator<T> {
-
-        private HeapPath<T> path;
-
-        HeapPathIterator(HeapPath<T> path) {
-            this.path = path;
-        }
-
-        @Override
-        public boolean hasNext() {
-            return path != null;
-        }
-
-        @Override
-        public T next() {
-            T next = path.node;
-            path = path.path;
-            return next;
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-
-    }
-
-    private HeapPath<T> path;
-    private T node;
-    private int length;
-
-    HeapPath(T head) {
-        this(head, null);
-    }
-
-    HeapPath(T node, HeapPath<T> path) {
-        this.node = node;
-        this.path = path;
-        if (path != null) {
-            length = path.length + 1;
-        } else {
-            length = 1;
-        }
-    }
-
-    @Override
-    public Iterator<T> iterator() {
-        return new HeapPathIterator<T>(this);
-    }
-
-    T getNode() {
-        return node;
-    }
-
-    int getLength() {
-        return length;
-    }
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/ListHeapDumpsCommand.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Date;
-
-import com.redhat.thermostat.client.heap.LocaleResources;
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.HostVMArguments;
-import com.redhat.thermostat.common.cli.SimpleCommand;
-import com.redhat.thermostat.common.cli.TableRenderer;
-import com.redhat.thermostat.common.dao.HeapDAO;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
-import com.redhat.thermostat.common.dao.HostRef;
-import com.redhat.thermostat.common.dao.VmInfoDAO;
-import com.redhat.thermostat.common.dao.VmRef;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.common.model.HeapInfo;
-import com.redhat.thermostat.common.utils.OSGIUtils;
-
-public class ListHeapDumpsCommand extends SimpleCommand {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private static final String NAME = "list-heap-dumps";
-
-    private static final String[] COLUMN_NAMES = {
-        translator.localize(LocaleResources.HEADER_HOST_ID),
-        translator.localize(LocaleResources.HEADER_VM_ID),
-        translator.localize(LocaleResources.HEADER_HEAP_ID),
-        translator.localize(LocaleResources.HEADER_TIMESTAMP),
-    };
-
-    private final OSGIUtils serviceProvider;
-
-    public ListHeapDumpsCommand() {
-        this(OSGIUtils.getInstance());
-    }
-
-    /** For tests only */
-    ListHeapDumpsCommand(OSGIUtils serviceProvider) {
-        this.serviceProvider = serviceProvider;
-    }
-
-    @Override
-    public String getName() {
-        return NAME;
-    }
-
-    @Override
-    public void run(CommandContext ctx) throws CommandException {
-        HostVMArguments args = new HostVMArguments(ctx.getArguments(), false, false);
-
-        TableRenderer renderer = new TableRenderer(4);
-
-        renderer.printLine(COLUMN_NAMES);
-
-        HostInfoDAO hostDAO = serviceProvider.getServiceAllowNull(HostInfoDAO.class);
-        if (hostDAO == null) {
-            throw new CommandException(translator.localize(LocaleResources.HOST_SERVICE_UNAVAILABLE));
-        }
-
-        VmInfoDAO vmDAO = serviceProvider.getServiceAllowNull(VmInfoDAO.class);
-        if (vmDAO == null) {
-            throw new CommandException(translator.localize(LocaleResources.VM_SERVICE_UNAVAILABLE));
-        }
-
-        HeapDAO heapDAO = serviceProvider.getServiceAllowNull(HeapDAO.class);
-        if (heapDAO == null) {
-            throw new CommandException(translator.localize(LocaleResources.HEAP_SERVICE_UNAVAILABLE));
-        }
-
-        Collection<HostRef> hosts = args.getHost() != null ? Arrays.asList(args.getHost()) : hostDAO.getHosts();
-        for (HostRef hostRef : hosts) {
-            Collection<VmRef> vms = args.getVM() != null ? Arrays.asList(args.getVM()) : vmDAO.getVMs(hostRef);
-            for (VmRef vmRef : vms) {
-                printDumpsForVm(heapDAO, hostRef, vmRef, renderer);
-            }
-        }
-
-        serviceProvider.ungetService(HeapDAO.class, heapDAO);
-        serviceProvider.ungetService(VmInfoDAO.class, vmDAO);
-        serviceProvider.ungetService(HostInfoDAO.class, hostDAO);
-
-        renderer.render(ctx.getConsole().getOutput());
-    }
-
-    private void printDumpsForVm(HeapDAO heapDAO, HostRef hostRef, VmRef vmRef, TableRenderer renderer) {
-        Collection<HeapInfo> infos = heapDAO.getAllHeapInfo(vmRef);
-        for (HeapInfo info : infos) {
-            renderer.printLine(hostRef.getStringID(),
-                               vmRef.getStringID(),
-                               info.getHeapId(),
-                               new Date(info.getTimeStamp()).toString());
-        }
-    }
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/ObjectCommandHelper.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import com.redhat.thermostat.client.heap.LocaleResources;
-import com.redhat.thermostat.common.cli.Arguments;
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.dao.HeapDAO;
-import com.redhat.thermostat.common.heap.HeapDump;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.common.model.HeapInfo;
-import com.sun.tools.hat.internal.model.JavaHeapObject;
-
-class ObjectCommandHelper {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private static final String OBJECT_ID_ARG = "objectId";
-    private static final String HEAP_ID_ARG = "heapId";
-
-    private CommandContext ctx;
-    private HeapDAO dao;
-    private HeapDump heapDump;
-
-    ObjectCommandHelper(CommandContext ctx, HeapDAO dao) {
-        this.ctx = ctx;
-        this.dao = dao;
-    }
-
-    HeapDump getHeapDump() throws CommandException {
-        if (heapDump == null) {
-            loadHeapDump();
-        }
-        return heapDump;
-    }
-
-    private void loadHeapDump() throws CommandException {
-        Arguments args = ctx.getArguments();
-        String heapId = args.getArgument(HEAP_ID_ARG);
-        HeapInfo heapInfo = dao.getHeapInfo(heapId);
-        if (heapInfo == null) {
-            throw new CommandException(translator.localize(LocaleResources.HEAP_ID_NOT_FOUND, heapId));
-        }
-        heapDump = dao.getHeapDump(heapInfo);
-    }
-
-    JavaHeapObject getJavaHeapObject() throws CommandException {
-        HeapDump heapDump = getHeapDump();
-        Arguments args = ctx.getArguments();
-        String objectId = args.getArgument(OBJECT_ID_ARG);
-        JavaHeapObject obj = heapDump.findObject(objectId);
-        if (obj == null) {
-            throw new HeapNotFoundException(objectId);
-        }
-        return obj;
-    }
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/ObjectInfoCommand.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,147 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import java.io.PrintStream;
-import java.util.Enumeration;
-
-import com.redhat.thermostat.client.heap.LocaleResources;
-import com.redhat.thermostat.client.heap.PrintObjectUtils;
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.SimpleCommand;
-import com.redhat.thermostat.common.cli.TableRenderer;
-import com.redhat.thermostat.common.dao.HeapDAO;
-import com.redhat.thermostat.common.heap.HeapDump;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.common.utils.OSGIUtils;
-import com.sun.tools.hat.internal.model.JavaClass;
-import com.sun.tools.hat.internal.model.JavaField;
-import com.sun.tools.hat.internal.model.JavaHeapObject;
-import com.sun.tools.hat.internal.model.JavaHeapObjectVisitor;
-import com.sun.tools.hat.internal.model.Snapshot;
-
-public class ObjectInfoCommand extends SimpleCommand {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private static final String NAME = "object-info";
-
-    private OSGIUtils serviceProvider;
-    private Snapshot snapshot;
-
-    public ObjectInfoCommand() {
-        this(OSGIUtils.getInstance());
-    }
-
-    ObjectInfoCommand(OSGIUtils serviceProvider) {
-        this.serviceProvider = serviceProvider;
-    }
-
-    @Override
-    public void run(CommandContext ctx) throws CommandException {
-        HeapDAO heapDao = serviceProvider.getServiceAllowNull(HeapDAO.class);
-        if (heapDao == null) {
-            throw new CommandException(translator.localize(LocaleResources.HEAP_SERVICE_UNAVAILABLE));
-        }
-
-        try {
-            run(ctx, heapDao);
-        } finally {
-            serviceProvider.ungetService(HeapDAO.class, heapDao);
-        }
-    }
-
-    private void run(CommandContext ctx, HeapDAO heapDao) throws CommandException {
-        ObjectCommandHelper objCmdHelper = new ObjectCommandHelper(ctx, heapDao);
-        HeapDump heapDump = objCmdHelper.getHeapDump();
-        snapshot = heapDump.getSnapshot();
-        JavaHeapObject obj = objCmdHelper.getJavaHeapObject();
-        TableRenderer table = new TableRenderer(2);
-        table.printLine(translator.localize(LocaleResources.COMMAND_OBJECT_INFO_OBJECT_ID), obj.getIdString());
-        table.printLine(translator.localize(LocaleResources.COMMAND_OBJECT_INFO_TYPE), obj.getClazz().getName());
-        table.printLine(translator.localize(LocaleResources.COMMAND_OBJECT_INFO_SIZE), String.valueOf(obj.getSize()) + " bytes");
-        table.printLine(translator.localize(LocaleResources.COMMAND_OBJECT_INFO_HEAP_ALLOCATED), String.valueOf(obj.isHeapAllocated()));
-        table.printLine(translator.localize(LocaleResources.COMMAND_OBJECT_INFO_REFERENCES), "");
-        printReferences(table, obj);
-        table.printLine(translator.localize(LocaleResources.COMMAND_OBJECT_INFO_REFERRERS), "");
-        printReferrers(table, obj);
-
-        PrintStream out = ctx.getConsole().getOutput();
-        table.render(out);
-
-    }
-
-    private void printReferences(final TableRenderer table, final JavaHeapObject obj) {
-        JavaHeapObjectVisitor v = new JavaHeapObjectVisitor() {
-            
-            @Override
-            public void visit(JavaHeapObject ref) {
-                table.printLine("", describeReference(obj, ref) + " -> " + PrintObjectUtils.objectToString(ref));
-            }
-            
-            @Override
-            public boolean mightExclude() {
-                return false;
-            }
-            
-            @Override
-            public boolean exclude(JavaClass arg0, JavaField arg1) {
-                return false;
-            }
-        };
-        obj.visitReferencedObjects(v);
-    }
-
-    private void printReferrers(TableRenderer table, JavaHeapObject obj) {
-        Enumeration<?> referrers = obj.getReferers();
-        while (referrers.hasMoreElements()) {
-            JavaHeapObject ref = (JavaHeapObject) referrers.nextElement();
-            table.printLine("", PrintObjectUtils.objectToString(ref) + " -> " + describeReference(ref, obj));
-        }
-    }
-
-    private String describeReference(JavaHeapObject from, JavaHeapObject to) {
-        return "[" + from.describeReferenceTo(to, snapshot) + "]";
-    }
-
-    @Override
-    public String getName() {
-        return NAME;
-    }
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/ObjectNotFoundException.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import com.redhat.thermostat.common.cli.CommandException;
-
-@SuppressWarnings("serial")
-class ObjectNotFoundException extends CommandException {
-
-    private static final String MESSAGE_TEMPLATE = "Object not found: ";
-
-    ObjectNotFoundException(String objectId) {
-        super(MESSAGE_TEMPLATE + objectId);
-    }
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/SaveHeapDumpToFileCommand.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import com.redhat.thermostat.client.heap.LocaleResources;
-import com.redhat.thermostat.common.cli.Arguments;
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.SimpleCommand;
-import com.redhat.thermostat.common.dao.HeapDAO;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.common.model.HeapInfo;
-import com.redhat.thermostat.common.utils.OSGIUtils;
-import com.redhat.thermostat.common.utils.StreamUtils;
-
-public class SaveHeapDumpToFileCommand extends SimpleCommand {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private static final String NAME = "save-heap-dump-to-file";
-
-    private static final String HEAP_ID_ARGUMENT = "heapId";
-    private static final String FILE_NAME_ARGUMENT = "file";
-
-    private final FileStreamCreator creator;
-    private final OSGIUtils serviceProvider;
-
-    public SaveHeapDumpToFileCommand() {
-        this(OSGIUtils.getInstance(), new FileStreamCreator());
-    }
-
-    SaveHeapDumpToFileCommand(OSGIUtils serviceProvider, FileStreamCreator creator) {
-        this.serviceProvider = serviceProvider;
-        this.creator = creator;
-    }
-
-    @Override
-    public String getName() {
-        return NAME;
-    }
-
-    @Override
-
-    public void run(CommandContext ctx) throws CommandException {
-        HeapDAO heapDAO = serviceProvider.getServiceAllowNull(HeapDAO.class);
-        try {
-            run(ctx, heapDAO);
-        } finally {
-            serviceProvider.ungetService(HeapDAO.class, heapDAO);
-            heapDAO = null;
-        }
-    }
-
-    private void run(CommandContext ctx, HeapDAO heapDAO) throws CommandException {
-        Arguments args = ctx.getArguments();
-        String heapId = args.getArgument(HEAP_ID_ARGUMENT);
-        if (heapId == null) {
-            throw new CommandException(translator.localize(LocaleResources.HEAP_ID_REQUIRED));
-        }
-        String filename = args.getArgument(FILE_NAME_ARGUMENT);
-        if (filename == null) {
-            throw new CommandException(translator.localize(LocaleResources.FILE_REQUIRED));
-        }
-
-        HeapInfo heapInfo = heapDAO.getHeapInfo(heapId);
-        try (InputStream heapStream = heapDAO.getHeapDumpData(heapInfo)) {
-            if (heapStream != null) {
-                try {
-                    saveHeapDump(heapStream, filename);
-                    ctx.getConsole().getOutput().println(translator.localize(LocaleResources.COMMAND_SAVE_HEAP_DUMP_SAVED_TO_FILE, filename));
-                } catch (IOException e) {
-                    ctx.getConsole().getOutput().println(translator.localize(LocaleResources.COMMAND_SAVE_HEAP_DUMP_ERROR_SAVING, e.getMessage()));
-                }
-            } else {
-                ctx.getConsole().getOutput().println(translator.localize(LocaleResources.HEAP_ID_NOT_FOUND, heapId));
-            }
-        } catch (IOException e) {
-            throw new CommandException(translator.localize(LocaleResources.COMMAND_SAVE_HEAP_DUMP_ERROR_CLOSING_STREAM, e.getMessage()));
-        }
-    }
-
-    private void saveHeapDump(InputStream heapStream, String filename) throws FileNotFoundException, IOException {
-        try (BufferedInputStream bis = new BufferedInputStream(heapStream);
-             BufferedOutputStream bout = new BufferedOutputStream(creator.createOutputStream(filename))) {
-            StreamUtils.copyStream(bis, bout);
-        }
-    }
-
-    static class FileStreamCreator {
-        public OutputStream createOutputStream(String filename) throws FileNotFoundException {
-            return new FileOutputStream(filename);
-        }
-    }
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/cli/ShowHeapHistogramCommand.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import java.io.PrintStream;
-
-import com.redhat.thermostat.client.heap.LocaleResources;
-import com.redhat.thermostat.common.cli.Arguments;
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.SimpleCommand;
-import com.redhat.thermostat.common.cli.TableRenderer;
-import com.redhat.thermostat.common.dao.HeapDAO;
-import com.redhat.thermostat.common.heap.HistogramRecord;
-import com.redhat.thermostat.common.heap.ObjectHistogram;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.common.model.HeapInfo;
-import com.redhat.thermostat.common.utils.OSGIUtils;
-
-public class ShowHeapHistogramCommand extends SimpleCommand {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private static final String NAME = "show-heap-histogram";
-
-    private OSGIUtils serviceProvider;
-
-    public ShowHeapHistogramCommand() {
-        this(OSGIUtils.getInstance());
-    }
-
-    ShowHeapHistogramCommand(OSGIUtils serviceProvider) {
-        this.serviceProvider = serviceProvider;
-    }
-
-    @Override
-    public String getName() {
-        return NAME;
-    }
-
-    @Override
-    public void run(CommandContext ctx) throws CommandException {
-        HeapDAO heapDAO = serviceProvider.getServiceAllowNull(HeapDAO.class);
-        if (heapDAO == null) {
-            throw new CommandException(translator.localize(LocaleResources.HEAP_SERVICE_UNAVAILABLE));
-        }
-
-        try {
-            run(ctx, heapDAO);
-        } finally {
-            serviceProvider.ungetService(HeapDAO.class, heapDAO);
-        }
-    }
-
-    private void run(CommandContext ctx, HeapDAO heapDAO) throws CommandException {
-        Arguments args = ctx.getArguments();
-        String heapId = args.getArgument("heapId");
-
-        HeapInfo heapInfo = heapDAO.getHeapInfo(heapId);
-        if (heapInfo == null) {
-            ctx.getConsole().getOutput().println(translator.localize(LocaleResources.HEAP_ID_NOT_FOUND, heapId));
-            return;
-        }
-
-        ObjectHistogram histogram = heapDAO.getHistogram(heapInfo);
-        if (histogram == null) {
-            ctx.getConsole().getOutput().println(translator.localize(LocaleResources.HEAP_ID_NOT_FOUND, heapId));
-            return;
-        } else {
-            printHeapHistogram(histogram, ctx.getConsole().getOutput());
-        }
-    }
-
-    private void printHeapHistogram(ObjectHistogram histogram, PrintStream out) {
-        TableRenderer table = new TableRenderer(3);
-        for (HistogramRecord rec : histogram.getHistogram()) {
-            table.printLine(rec.getClassname(), String.valueOf(rec.getNumberOf()), String.valueOf(rec.getTotalSize()));
-        }
-        table.render(out);
-    }
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/HeapDetailsSwing.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.swing;
-
-import java.awt.BorderLayout;
-
-import javax.swing.JPanel;
-import javax.swing.JTabbedPane;
-import javax.swing.SwingUtilities;
-
-import com.redhat.thermostat.client.heap.HeapDumpDetailsView;
-import com.redhat.thermostat.client.heap.HeapHistogramView;
-import com.redhat.thermostat.client.heap.ObjectDetailsView;
-import com.redhat.thermostat.client.ui.SwingComponent;
-
-public class HeapDetailsSwing extends HeapDumpDetailsView implements SwingComponent {
-
-    /** For TESTING only! */
-    static final String TAB_NAME = "tabs";
-
-    private JPanel visiblePane;
-
-    private JTabbedPane tabPane = new JTabbedPane();
-
-    public HeapDetailsSwing() {
-        visiblePane = new JPanel();
-        visiblePane.setLayout(new BorderLayout());
-        visiblePane.add(tabPane, BorderLayout.CENTER);
-
-        tabPane.setName(TAB_NAME);
-    }
-
-    @Override
-    public void addSubView(final String title, final HeapHistogramView view) {
-        verifyIsSwingComponent(view);
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                tabPane.insertTab(title, null, ((SwingComponent)view).getUiComponent(), null, 0);
-            }
-        });
-    }
-
-    @Override
-    public void addSubView(final String title, final ObjectDetailsView view) {
-        verifyIsSwingComponent(view);
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                tabPane.insertTab(title, null, ((SwingComponent)view).getUiComponent(), null, 1);
-            }
-        });
-    }
-
-    @Override
-    public void removeSubView(final String title) {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                int tabCount = tabPane.getTabCount();
-                for (int i = 0; i < tabCount; i++) {
-                    String tabTitle = tabPane.getTitleAt(i);
-                    if (tabTitle.equals(title)) {
-                        tabPane.removeTabAt(i);
-                        return;
-                    }
-                }
-            }
-        });
-    }
-
-    @Override
-    public JPanel getUiComponent() {
-        return visiblePane;
-    }
-
-    private void verifyIsSwingComponent(Object obj) {
-        if (!(obj instanceof SwingComponent)) {
-            throw new IllegalArgumentException("component is not swing");
-        }
-    }
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/HeapPanel.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.swing;
-
-import java.awt.Dimension;
-
-import javax.swing.JPanel;
-import javax.swing.JSplitPane;
-import javax.swing.GroupLayout;
-import javax.swing.GroupLayout.Alignment;
-
-@SuppressWarnings("serial")
-public class HeapPanel extends JPanel {
-
-    private JSplitPane splitPane;
-    
-    public HeapPanel() {
-        
-        splitPane = new JSplitPane();
-        splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
-        GroupLayout groupLayout = new GroupLayout(this);
-        groupLayout.setHorizontalGroup(
-            groupLayout.createParallelGroup(Alignment.LEADING)
-                .addComponent(splitPane, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE)
-        );
-        groupLayout.setVerticalGroup(
-            groupLayout.createParallelGroup(Alignment.LEADING)
-                .addGroup(groupLayout.createSequentialGroup()
-                    .addGap(5)
-                    .addComponent(splitPane, GroupLayout.DEFAULT_SIZE, 295, Short.MAX_VALUE))
-        );
-
-        splitPane.setOneTouchExpandable(true);
-        setLayout(groupLayout);
-    }
-
-    void divideView() {
-        splitPane.setDividerLocation(.5d);
-    }
-    
-    void hideBottom() {
-        splitPane.getBottomComponent().setMinimumSize(new Dimension(0, 0));
-        splitPane.setDividerLocation(1.0d);
-    }
-    
-    void hideTop() {
-        splitPane.getTopComponent().setMinimumSize(new Dimension(0, 0));
-        splitPane.setDividerLocation(0.0d);
-    }
-    
-    void setTop(JPanel panel) {
-        splitPane.setTopComponent(panel);
-    }
-    
-    void setBottom(JPanel panel) {
-        splitPane.setBottomComponent(panel);
-    }
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/HeapSwingView.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,230 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.swing;
-
-import java.awt.Component;
-import java.awt.EventQueue;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.List;
-
-import javax.swing.BoxLayout;
-import javax.swing.JPanel;
-import javax.swing.SwingUtilities;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-
-import org.jfree.chart.ChartPanel;
-
-import com.redhat.thermostat.client.core.views.BasicView;
-import com.redhat.thermostat.client.heap.HeapView;
-import com.redhat.thermostat.client.heap.LocaleResources;
-import com.redhat.thermostat.client.heap.chart.OverviewChart;
-import com.redhat.thermostat.client.ui.ComponentVisibleListener;
-import com.redhat.thermostat.client.ui.SwingComponent;
-import com.redhat.thermostat.common.heap.HeapDump;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.swing.HeaderPanel;
-
-public class HeapSwingView extends HeapView implements SwingComponent {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private StatsPanel stats;
-
-    private HeapPanel heapDetailPanel;
-    private HeaderPanel overview;
-    
-    private JPanel visiblePane;
-    
-    public HeapSwingView() {
-        stats = new StatsPanel();
-        stats.addHeapDumperListener(new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                
-                stats.disableHeapDumperControl();
-                
-                heapDumperNotifier.fireAction(HeapDumperAction.DUMP_REQUESTED);
-            }
-        });
-        
-        stats.addDumpListListener(new ListSelectionListener() {
-            @Override
-            public void valueChanged(ListSelectionEvent arg0) {
-                HeapDump dump = stats.getSelectedHeapDump();
-                heapDumperNotifier.fireAction(HeapDumperAction.ANALYSE, dump);
-            }
-        });
-        
-        visiblePane = new JPanel();
-        visiblePane.setLayout(new BoxLayout(visiblePane, BoxLayout.X_AXIS));
-        
-        heapDetailPanel = new HeapPanel();
-        
-        overview = new HeaderPanel(translator.localize(LocaleResources.HEAP_OVERVIEW_TITLE));
-        overview.setContent(stats);
-        overview.addHierarchyListener(new ViewVisibleListener());
-
-        // at the beginning, only the overview is visible
-        visiblePane.add(overview);
-    }
-    
-    private class ViewVisibleListener extends ComponentVisibleListener {
-        @Override
-        public void componentShown(Component component) {
-            HeapSwingView.this.notify(Action.VISIBLE);
-        }
-
-        @Override
-        public void componentHidden(Component component) {
-            HeapSwingView.this.notify(Action.HIDDEN);
-        }
-    }
-
-    @Override
-    public void setModel(final OverviewChart model) {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                ChartPanel charts = new ChartPanel(model.createChart(stats.getWidth(), stats.getBackground()));
-                /*
-                 * By default, ChartPanel scales itself instead of redrawing things when
-                 * it's resized. To have it resize automatically, we need to set minimum
-                 * and maximum sizes. Lets constrain the minimum, but not the maximum
-                 * size.
-                 */
-                final int MINIMUM_DRAW_SIZE = 100;
-
-                charts.setMinimumDrawHeight(MINIMUM_DRAW_SIZE);
-                charts.setMinimumDrawWidth(MINIMUM_DRAW_SIZE);
-
-                charts.setMaximumDrawHeight(Integer.MAX_VALUE);
-                charts.setMaximumDrawWidth(Integer.MAX_VALUE);
-
-                stats.setChartPanel(charts);
-            }
-        });
-    }
-
-    @Override
-    public void updateUsedAndCapacity(final String used, final String capacity) {
-        
-        SwingUtilities.invokeLater(new Runnable() {
-            
-            @Override
-            public void run() {
-                stats.setMax(capacity);
-                stats.setUsed(used);
-            }
-        });
-    }
-
-    @Override
-    public void addHeapDump(final HeapDump dump) {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                stats.addDump(dump);
-            }
-        });
-    }
-    
-    @Override
-    public void clearHeapDumpList() {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                stats.clearDumpList();
-            }
-        });
-    }
-    
-    @Override
-    public void openDumpView() {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                visiblePane.removeAll();
-                heapDetailPanel.divideView();
-                heapDetailPanel.setTop(overview);
-
-                visiblePane.add(heapDetailPanel);
-                visiblePane.revalidate();
-            }
-        });
-    }
-
-    @Override
-    public void setChildView(BasicView childView) {
-        if (childView instanceof HeapDetailsSwing) {
-            final HeapDetailsSwing view = (HeapDetailsSwing)childView;
-            SwingUtilities.invokeLater(new Runnable() {
-                @Override
-                public void run() {
-                    heapDetailPanel.setBottom(view.getUiComponent());
-                    visiblePane.revalidate();
-                }
-            });
-        }
-    }
-    
-    @Override
-    public Component getUiComponent() {
-        return visiblePane;
-    }
-
-    @Override
-    public void notifyHeapDumpComplete() {
-        EventQueue.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                stats.enableHeapDumperControl();
-            }
-        });
-    }
-
-    @Override
-    public void updateHeapDumpList(final List<HeapDump> heapDumps) {
-        EventQueue.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                stats.updateHeapDumpList(heapDumps);
-            }
-        });
-    }
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/HistogramPanel.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.swing;
-
-import java.awt.Component;
-import java.text.DecimalFormat;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.swing.BoxLayout;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.table.DefaultTableModel;
-
-import com.redhat.thermostat.client.heap.HeapHistogramView;
-import com.redhat.thermostat.client.heap.LocaleResources;
-import com.redhat.thermostat.client.ui.SwingComponent;
-import com.redhat.thermostat.common.heap.HistogramRecord;
-import com.redhat.thermostat.common.heap.ObjectHistogram;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.common.utils.DescriptorConverter;
-import com.redhat.thermostat.swing.HeaderPanel;
-import com.redhat.thermostat.swing.ThermostatTable;
-import com.redhat.thermostat.swing.ThermostatTableRenderer;
-
-@SuppressWarnings("serial")
-public class HistogramPanel extends HeapHistogramView implements SwingComponent {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private final JPanel panel;
-
-    private HeaderPanel headerPanel;
-
-    public HistogramPanel() {
-        panel = new JPanel();
-        panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
-
-        headerPanel = new HeaderPanel(translator.localize(LocaleResources.HEAP_DUMP_CLASS_USAGE));
-        panel.add(headerPanel);
-    }
-
-    @Override
-    public void display(ObjectHistogram histogram) {
-        ThermostatTable table = new ThermostatTable(new HistogramTableModel(histogram));
-        table.setDefaultRenderer(Long.class, new NiceNumberFormatter());
-        headerPanel.setContent(table.wrap());
-    }
-
-    private final class NiceNumberFormatter extends ThermostatTableRenderer {
-
-        private final DecimalFormat formatter = new DecimalFormat("###,###.###");
-
-        private NiceNumberFormatter() {
-            setHorizontalAlignment(JLabel.RIGHT);
-        }
-
-        @Override
-        protected void setValue(Object v) {
-            String formatted = formatter.format(v);
-            setText(formatted);
-        }
-    }
-
-    private class HistogramTableModel extends DefaultTableModel {
-
-        private final String[] columnNames = new String[] {
-            translator.localize(LocaleResources.HEAP_DUMP_HISTOGRAM_COLUMN_CLASS),
-            translator.localize(LocaleResources.HEAP_DUMP_HISTOGRAM_COLUMN_INSTANCES),
-            translator.localize(LocaleResources.HEAP_DUMP_HISTOGRAM_COLUMN_SIZE),
-        };
-
-        private List<HistogramRecord> histogram;
-
-        public HistogramTableModel(ObjectHistogram objHistogram) {
-            histogram = new ArrayList<>();
-            histogram.addAll(objHistogram.getHistogram());
-        }
-
-        @Override
-        public String getColumnName(int column) {
-            return columnNames[column];
-        }
-
-        @Override
-        public Class<?> getColumnClass(int column) {
-            if (column == 0) {
-                return String.class;
-            } else {
-                return Long.class;
-            }
-        }
-
-        @Override
-        public Object getValueAt(int row, int column) {
-            Object result = null;
-            if (row >= histogram.size()) {
-                throw new ArrayIndexOutOfBoundsException();
-            }
-            if (histogram != null) {
-                HistogramRecord record = histogram.get(row);
-                switch (column) {
-                case 0:
-                    result = DescriptorConverter.toJavaType(record.getClassname());
-                    break;
-                case 1:
-                    result = Long.valueOf(record.getNumberOf());
-                    break;
-                case 2:
-                    result = Long.valueOf(record.getTotalSize());
-                    break;
-                default:
-                    throw new ArrayIndexOutOfBoundsException();
-                }
-            }
-            return result;
-        }
-
-        @Override
-        public int getColumnCount() {
-            return 3;
-        }
-
-        @Override
-        public int getRowCount() {
-            if (histogram != null) {
-                return histogram.size();
-            }
-            return 0;
-        }
-
-        @Override
-        public boolean isCellEditable(int row, int column) {
-            return false;
-        }
-    }
-
-    @Override
-    public Component getUiComponent() {
-        return panel;
-    }
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/LazyMutableTreeNode.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.swing;
-
-import com.redhat.thermostat.client.heap.HeapObjectUI;
-
-class LazyMutableTreeNode extends javax.swing.tree.DefaultMutableTreeNode {
-
-    public LazyMutableTreeNode() {
-        super();
-    }
-
-    public LazyMutableTreeNode(HeapObjectUI heapObjectUI) {
-        super(heapObjectUI);
-    }
-
-    @Override
-    public boolean isLeaf() {
-        return !getAllowsChildren();
-    }
-}
\ No newline at end of file
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/ObjectDetailsPanel.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,435 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.swing;
-
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import javax.swing.ButtonGroup;
-import javax.swing.JMenuItem;
-import javax.swing.JPanel;
-import javax.swing.GroupLayout;
-import javax.swing.JPopupMenu;
-import javax.swing.JToggleButton;
-import javax.swing.JTree;
-import javax.swing.SwingUtilities;
-import javax.swing.GroupLayout.Alignment;
-import javax.swing.JLabel;
-
-import com.redhat.thermostat.client.heap.HeapObjectUI;
-import com.redhat.thermostat.client.heap.LocaleResources;
-import com.redhat.thermostat.client.heap.ObjectDetailsView;
-import com.redhat.thermostat.client.ui.SearchFieldSwingView;
-import com.redhat.thermostat.client.ui.SearchFieldView.SearchAction;
-import com.redhat.thermostat.client.ui.SwingComponent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionNotifier;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.swing.EdtHelper;
-import com.sun.tools.hat.internal.model.JavaHeapObject;
-
-import javax.swing.LayoutStyle.ComponentPlacement;
-import javax.swing.JScrollPane;
-import javax.swing.JTextPane;
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-
-import javax.swing.JSplitPane;
-import javax.swing.event.TreeExpansionEvent;
-import javax.swing.event.TreeSelectionEvent;
-import javax.swing.event.TreeSelectionListener;
-import javax.swing.event.TreeWillExpandListener;
-import javax.swing.tree.DefaultTreeCellRenderer;
-import javax.swing.tree.DefaultTreeModel;
-import javax.swing.tree.ExpandVetoException;
-import javax.swing.tree.MutableTreeNode;
-import javax.swing.tree.TreePath;
-import javax.swing.tree.TreeSelectionModel;
-
-/**
- * A Panel that displays JavaHeapObjects and referrers and references.
- */
-public class ObjectDetailsPanel extends ObjectDetailsView implements SwingComponent {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    /** For TESTING ONLY! */
-    static final String TREE_NAME = "ref-tree";
-    /** For TESTING ONLY! */
-    static final String DETAILS_NAME = "object-details";
-
-    private final ActionNotifier<ObjectAction> notifier = new ActionNotifier<>(this);
-
-    private final JPanel panel;
-
-    private final SearchFieldSwingView searchField;
-
-    private final LazyMutableTreeNode ROOT = new LazyMutableTreeNode(null);
-    /** all the nodes in this model must be {@link LazyMutableTreeNode}s */
-    private final DefaultTreeModel model = new DefaultTreeModel(ROOT);
-    private final JTree objectTree = new JTree(model);
-
-    private final JTextPane objectDetailsPane;
-
-    private final ButtonGroup refGroup = new ButtonGroup();
-    private final JToggleButton toggleReferrersButton;
-    private final JToggleButton toggleReferencesButton;
-
-    private final List<ObjectReferenceCallback> callbacks = new CopyOnWriteArrayList<>();
-
-    public ObjectDetailsPanel() {
-
-        panel = new JPanel();
-
-        JLabel searchLabel = new JLabel(translator.localize(LocaleResources.HEAP_DUMP_OBJECT_BROWSE_SEARCH_LABEL));
-
-        searchField = new SearchFieldSwingView();
-        searchField.setTooltip(translator.localize(LocaleResources.HEAP_DUMP_OBJECT_BROWSE_SEARCH_PATTERN_HELP));
-
-        JSplitPane splitPane = new JSplitPane();
-        splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
-        splitPane.setDividerLocation(0.8 /* 80% */);
-
-        toggleReferrersButton = new JToggleButton(translator.localize(LocaleResources.HEAP_DUMP_OBJECT_BROWSE_REFERRERS));
-        refGroup.add(toggleReferrersButton);
-
-        toggleReferencesButton = new JToggleButton(translator.localize(LocaleResources.HEAP_DUMP_OBJECT_BROWSE_REFERENCES));
-        refGroup.add(toggleReferencesButton);
-
-        toggleReferrersButton.setSelected(true);
-
-        GroupLayout groupLayout = new GroupLayout(panel);
-        groupLayout.setHorizontalGroup(
-            groupLayout.createParallelGroup(Alignment.LEADING)
-                .addGroup(groupLayout.createSequentialGroup()
-                    .addContainerGap()
-                    .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
-                        .addGroup(groupLayout.createSequentialGroup()
-                            .addComponent(searchLabel)
-                            .addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                            .addComponent(toggleReferencesButton)
-                            .addPreferredGap(ComponentPlacement.RELATED)
-                            .addComponent(toggleReferrersButton))
-                        .addGroup(groupLayout.createSequentialGroup()
-                            .addGap(12)
-                            .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
-                                .addComponent(splitPane, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 447, Short.MAX_VALUE)
-                                .addComponent(searchField, GroupLayout.DEFAULT_SIZE, 447, Short.MAX_VALUE))))
-                    .addContainerGap())
-        );
-        groupLayout.setVerticalGroup(
-            groupLayout.createParallelGroup(Alignment.LEADING)
-                .addGroup(groupLayout.createSequentialGroup()
-                    .addContainerGap()
-                    .addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
-                        .addComponent(searchLabel)
-                        .addComponent(toggleReferrersButton)
-                        .addComponent(toggleReferencesButton))
-                    .addPreferredGap(ComponentPlacement.RELATED)
-                    .addComponent(searchField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
-                    .addPreferredGap(ComponentPlacement.RELATED)
-                    .addComponent(splitPane, GroupLayout.DEFAULT_SIZE, 314, Short.MAX_VALUE)
-                    .addContainerGap())
-        );
-
-        searchField.addActionListener(new ActionListener<SearchAction>() {
-            @Override
-            public void actionPerformed(ActionEvent<SearchAction> actionEvent) {
-                switch (actionEvent.getActionId()) {
-                case TEXT_CHANGED:
-                    notifier.fireAction(ObjectAction.SEARCH);
-                    break;
-                }
-            }
-        });
-        searchField.setLabel(translator.localize(LocaleResources.HEAP_DUMP_OBJECT_BROWSE_SEARCH_HINT));
-
-        java.awt.event.ActionListener treeToggleListener = new java.awt.event.ActionListener() {
-            @Override
-            public void actionPerformed(java.awt.event.ActionEvent e) {
-                notifier.fireAction(ObjectAction.SEARCH);
-            }
-        };
-
-        JToggleButton[] buttons = getTreeModeButtons();
-        for (JToggleButton button: buttons) {
-            button.addActionListener(treeToggleListener);
-        }
-
-        JScrollPane scrollPane = new JScrollPane();
-        scrollPane.setViewportView(objectTree);
-
-        splitPane.setLeftComponent(scrollPane);
-
-        JPanel panel = new JPanel();
-        splitPane.setRightComponent(panel);
-
-        panel.setLayout(new BorderLayout(0, 0));
-
-        objectDetailsPane = new JTextPane();
-        objectDetailsPane.setName(DETAILS_NAME);
-        objectDetailsPane.setEditable(false);
-        panel.add(objectDetailsPane);
-        this.panel.setLayout(groupLayout);
-
-        initializeTree();
-        clearTree();
-    }
-
-    private void initializeTree() {
-        objectTree.setName(TREE_NAME);
-        objectTree.setRootVisible(false);
-        objectTree.setShowsRootHandles(true);
-        objectTree.setEditable(false);
-
-        objectTree.addTreeSelectionListener(new TreeSelectionListener() {
-            @Override
-            public void valueChanged(TreeSelectionEvent e) {
-                notifier.fireAction(ObjectAction.GET_OBJECT_DETAIL);
-            }
-        });
-
-        if (objectTree.getCellRenderer() instanceof DefaultTreeCellRenderer) {
-            DefaultTreeCellRenderer cellRenderer = (DefaultTreeCellRenderer) objectTree.getCellRenderer();
-            cellRenderer.setClosedIcon(null);
-            cellRenderer.setOpenIcon(null);
-            cellRenderer.setLeafIcon(null);
-        }
-
-        objectTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
-        objectTree.expandPath(new TreePath(ROOT.getPath()));
-
-        objectTree.addTreeWillExpandListener(new TreeWillExpandListener() {
-
-            @Override
-            public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException {
-                if (new TreePath(ROOT.getPath()).equals(event.getPath())) {
-                    return;
-                }
-
-                lazyLoadChildren(event.getPath());
-            }
-
-            @Override
-            public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException {
-                if (new TreePath(ROOT.getPath()).equals(event.getPath())) {
-                    throw new ExpandVetoException(event, "root cant be collapsed");
-                }
-            }
-        });
-
-        objectTree.addMouseListener(new MouseAdapter() {
-            @Override
-            public void mousePressed(MouseEvent e) {
-                if (e.isPopupTrigger()) {
-                    int row = objectTree.getRowForLocation(e.getX(), e.getY());
-                    if (row == -1) {
-                        return;
-                    }
-
-                    TreePath path = objectTree.getPathForRow(row);
-                    final HeapObjectUI heapObject = (HeapObjectUI) ((LazyMutableTreeNode)path.getLastPathComponent()).getUserObject();
-                    JPopupMenu popup = new JPopupMenu();
-                    JMenuItem findRootItem = new JMenuItem(translator.localize(LocaleResources.HEAP_DUMP_OBJECT_FIND_ROOT));
-                    findRootItem.addActionListener(new java.awt.event.ActionListener() {
-                        @Override
-                        public void actionPerformed(java.awt.event.ActionEvent e) {
-                            notifier.fireAction(ObjectAction.SHOW_ROOT_TO_GC, heapObject);
-                        }
-                    });
-                    popup.add(findRootItem);
-                    popup.show(e.getComponent(), e.getX(), e.getY());
-                }
-            }
-        });
-    }
-
-    private void clearTree() {
-        // clear children from model
-        int childrenCount = ROOT.getChildCount();
-        for (int i = 0; i < childrenCount; i++) {
-            MutableTreeNode child = (MutableTreeNode) ROOT.getChildAt(0);
-            model.removeNodeFromParent(child);
-        }
-    }
-
-    private void lazyLoadChildren(TreePath path) {
-        LazyMutableTreeNode node = (LazyMutableTreeNode) path.getLastPathComponent();
-        if (node.getChildCount() > 0) {
-            // already processed
-            return;
-        }
-
-        if (toggleReferencesButton.isSelected()) {
-            addReferences(node);
-        } else if (toggleReferrersButton.isSelected()) {
-            addReferrers(node);
-        }
-    }
-
-    private void addReferrers(LazyMutableTreeNode node) {
-        HeapObjectUI data = (HeapObjectUI) node.getUserObject();
-
-        List<HeapObjectUI> referrers = new ArrayList<>();
-        for (ObjectReferenceCallback callback : callbacks) {
-            referrers.addAll(callback.getReferrers(data));
-        }
-
-        for (HeapObjectUI obj: referrers) {
-            model.insertNodeInto(new LazyMutableTreeNode(obj), node, node.getChildCount());
-        }
-    }
-
-    private void addReferences(LazyMutableTreeNode node) {
-        HeapObjectUI data = (HeapObjectUI) node.getUserObject();
-
-        List<HeapObjectUI> referrers = new ArrayList<>();
-        for (ObjectReferenceCallback callback : callbacks) {
-            referrers.addAll(callback.getReferences(data));
-        }
-
-        for (HeapObjectUI obj: referrers) {
-            model.insertNodeInto(new LazyMutableTreeNode(obj), node, node.getChildCount());
-        }
-    }
-
-    private JToggleButton[] getTreeModeButtons() {
-        return new JToggleButton[] { toggleReferencesButton, toggleReferrersButton };
-    }
-
-    @Override
-    public void addObjectActionListener(ActionListener<ObjectAction> listener) {
-        notifier.addActionListener(listener);
-    }
-
-    @Override
-    public void removeObjectActionListnener(ActionListener<ObjectAction> listener) {
-        notifier.removeActionListener(listener);
-    }
-
-    @Override
-    public void addObjectReferenceCallback(ObjectReferenceCallback callback) {
-        callbacks.add(callback);
-    }
-
-    @Override
-    public void removeObjectReferenceCallback(ObjectReferenceCallback callback) {
-        callbacks.remove(callback);
-    }
-
-    @Override
-    public String getSearchText() {
-        try {
-            return new EdtHelper().callAndWait(new Callable<String>() {
-                @Override
-                public String call() throws Exception {
-                    return searchField.getSearchText();
-                }
-            });
-        } catch (InvocationTargetException | InterruptedException e) {
-            e.printStackTrace();
-            return null;
-        }
-    }
-
-    @Override
-    public void setMatchingObjects(final Collection<HeapObjectUI> objects) {
-        try {
-            new EdtHelper().callAndWait(new Runnable() {
-                @Override
-                public void run() {
-                    // clear children
-                    clearTree();
-
-                    // add new children
-                    for (HeapObjectUI object: objects) {
-                        MutableTreeNode node = new LazyMutableTreeNode(object);
-                        model.insertNodeInto(node, ROOT, ROOT.getChildCount());
-                    }
-                    objectTree.expandPath(new TreePath(ROOT.getPath()));
-                }
-            });
-        } catch (InvocationTargetException | InterruptedException e) {
-            e.printStackTrace();
-        }
-    }
-
-    @Override
-    public void setObjectDetails(final JavaHeapObject obj) {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                // TODO use some other gui control for this rather than a plain text box
-                String text = translator.localize(LocaleResources.COMMAND_OBJECT_INFO_OBJECT_ID) + obj.getIdString() + "\n" +
-                              translator.localize(LocaleResources.COMMAND_OBJECT_INFO_TYPE) + obj.getClazz().getName() + "\n" +
-                              translator.localize(LocaleResources.COMMAND_OBJECT_INFO_SIZE) + String.valueOf(obj.getSize()) + " bytes" + "\n" +
-                              translator.localize(LocaleResources.COMMAND_OBJECT_INFO_HEAP_ALLOCATED) + String.valueOf(obj.isHeapAllocated()) + "\n";
-                objectDetailsPane.setText(text);
-            }
-        });
-    }
-
-    /**
-     * @return null if no selected object
-     */
-    @Override
-    public HeapObjectUI getSelectedMatchingObject() {
-        try {
-            return new EdtHelper().callAndWait(new Callable<HeapObjectUI>() {
-                @Override
-                public HeapObjectUI call() throws Exception {
-                    LazyMutableTreeNode node = (LazyMutableTreeNode) objectTree.getSelectionPath().getLastPathComponent();
-                    return (HeapObjectUI) node.getUserObject();
-                }
-            });
-        } catch (InvocationTargetException | InterruptedException e) {
-            return null;
-        }
-    }
-
-    @Override
-    public Component getUiComponent() {
-        return panel;
-    }
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/ObjectRootsFrame.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.swing;
-
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
-
-import javax.swing.GroupLayout;
-import javax.swing.GroupLayout.Alignment;
-import javax.swing.JFrame;
-import javax.swing.JLabel;
-import javax.swing.JScrollPane;
-import javax.swing.JTextPane;
-import javax.swing.JTree;
-import javax.swing.LayoutStyle.ComponentPlacement;
-import javax.swing.SwingUtilities;
-import javax.swing.event.TreeSelectionEvent;
-import javax.swing.event.TreeSelectionListener;
-import javax.swing.tree.DefaultTreeModel;
-import javax.swing.tree.MutableTreeNode;
-import javax.swing.tree.TreePath;
-
-import com.redhat.thermostat.client.heap.HeapObjectUI;
-import com.redhat.thermostat.client.heap.LocaleResources;
-import com.redhat.thermostat.client.heap.ObjectRootsView;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ActionNotifier;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.swing.EdtHelper;
-
-@SuppressWarnings("serial")
-public class ObjectRootsFrame extends JFrame implements ObjectRootsView {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    /** For TESTING ONLY! */
-    static final String TREE_NAME = "roots-tree";
-
-    static final String DETAILS_NAME = "object-details";
-
-    private final ActionNotifier<Action> notifier = new ActionNotifier<>(this);
-
-    private final LazyMutableTreeNode ROOT = new LazyMutableTreeNode();
-    private final DefaultTreeModel dataModel;
-    private final JTree pathToRootTree;
-
-    private final JTextPane objectDetails;
-
-    public ObjectRootsFrame() {
-        setTitle(translator.localize(LocaleResources.OBJECT_ROOTS_VIEW_TITLE));
-
-        dataModel = new DefaultTreeModel(ROOT);
-        pathToRootTree = new JTree(dataModel);
-        pathToRootTree.setName(TREE_NAME);
-
-        JLabel lblNewLabel = new JLabel(translator.localize(LocaleResources.OBJECT_ROOTS_VIEW_TITLE));
-
-        JScrollPane scrollPane = new JScrollPane(pathToRootTree);
-
-        objectDetails = new JTextPane();
-        objectDetails.setName(DETAILS_NAME);
-
-        GroupLayout groupLayout = new GroupLayout(getContentPane());
-        groupLayout.setHorizontalGroup(
-            groupLayout.createParallelGroup(Alignment.TRAILING)
-                .addGroup(groupLayout.createSequentialGroup()
-                    .addContainerGap()
-                    .addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
-                        .addComponent(scrollPane, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 416, Short.MAX_VALUE)
-                        .addComponent(objectDetails, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 416, Short.MAX_VALUE)
-                        .addComponent(lblNewLabel, Alignment.LEADING))
-                    .addContainerGap())
-        );
-        groupLayout.setVerticalGroup(
-            groupLayout.createParallelGroup(Alignment.LEADING)
-                .addGroup(groupLayout.createSequentialGroup()
-                    .addContainerGap()
-                    .addComponent(lblNewLabel)
-                    .addPreferredGap(ComponentPlacement.RELATED)
-                    .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 126, Short.MAX_VALUE)
-                    .addPreferredGap(ComponentPlacement.RELATED)
-                    .addComponent(objectDetails, GroupLayout.PREFERRED_SIZE, 93, GroupLayout.PREFERRED_SIZE)
-                    .addContainerGap())
-        );
-        getContentPane().setLayout(groupLayout);
-
-        addWindowListener(new WindowAdapter() {
-            @Override
-            public void windowOpened(WindowEvent e) {
-                notifier.fireAction(Action.VISIBLE);
-            }
-
-            @Override
-            public void windowClosing(WindowEvent e) {
-                notifier.fireAction(Action.HIDDEN);
-            }
-        });
-
-        pathToRootTree.addTreeSelectionListener(new TreeSelectionListener() {
-            @Override
-            public void valueChanged(TreeSelectionEvent e) {
-                HeapObjectUI obj = (HeapObjectUI) ((LazyMutableTreeNode)e.getPath().getLastPathComponent()).getUserObject();
-                notifier.fireAction(Action.OBJECT_SELECTED, obj);
-            }
-        });
-
-
-    }
-
-    @Override
-    public void addActionListener(ActionListener<Action> listener) {
-        notifier.addActionListener(listener);
-    }
-
-    @Override
-    public void removeActionListener(ActionListener<Action> listener) {
-        notifier.removeActionListener(listener);
-    }
-
-    @Override
-    public void showView() {
-        Callable<Boolean> hideViewRunnable = new Callable<Boolean>() {
-            @Override
-            public Boolean call() {
-                pack();
-                setVisible(true);
-                return new Boolean(true);
-            }
-        };
-        try {
-            new EdtHelper().callAndWait(hideViewRunnable);
-        } catch (InvocationTargetException | InterruptedException e) {
-            InternalError error = new InternalError();
-            error.initCause(e);
-            throw error;
-        }
-    }
-
-    @Override
-    public void hideView() {
-        Callable<Boolean> hideViewRunnable = new Callable<Boolean>() {
-            @Override
-            public Boolean call() {
-                setVisible(false);
-                dispose();
-                return new Boolean(true);
-            }
-        };
-        try {
-            new EdtHelper().callAndWait(hideViewRunnable);
-        } catch (InvocationTargetException | InterruptedException e) {
-            InternalError error = new InternalError();
-            error.initCause(e);
-            throw error;
-        }
-    }
-
-    @Override
-    public void setPathToRoot(List<HeapObjectUI> pathToRoot) {
-        final List<HeapObjectUI> path = new ArrayList<>(pathToRoot);
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                clearTree();
-
-                LazyMutableTreeNode node = ROOT;
-                node.setUserObject(path.get(0));
-                TreePath treePath = new TreePath(node);
-                LazyMutableTreeNode parent = ROOT;
-                for (int i = 1; i < path.size(); i++) {
-                    HeapObjectUI obj = path.get(i);
-                    node = new LazyMutableTreeNode(obj);
-                    dataModel.insertNodeInto(node, parent, node.getChildCount());
-                    parent = node;
-                    treePath = treePath.pathByAddingChild(node);
-                }
-
-                pathToRootTree.expandPath(treePath);
-                pathToRootTree.setSelectionPath(treePath);
-            }
-        });
-    }
-
-    private void clearTree() {
-        // clear children from model
-        int childrenCount = ROOT.getChildCount();
-        for (int i = 0; i < childrenCount; i++) {
-            MutableTreeNode child = (MutableTreeNode) ROOT.getChildAt(0);
-            dataModel.removeNodeFromParent(child);
-        }
-    }
-
-    @Override
-    public void setObjectDetails(final String information) {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                objectDetails.setText(information);
-            }
-        });
-    }
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/StatsPanel.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,210 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.swing;
-
-import java.awt.event.ActionListener;
-import java.util.List;
-
-import javax.swing.BoxLayout;
-import javax.swing.DefaultListModel;
-import javax.swing.GroupLayout;
-import javax.swing.GroupLayout.Alignment;
-import javax.swing.JButton;
-import javax.swing.JLabel;
-import javax.swing.JList;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.LayoutStyle.ComponentPlacement;
-import javax.swing.ListSelectionModel;
-import javax.swing.SwingConstants;
-import javax.swing.event.ListSelectionListener;
-
-import com.redhat.thermostat.common.heap.HeapDump;
-
-@SuppressWarnings("serial")
-public class StatsPanel extends JPanel {
-    
-    private JPanel leftPanel;
-    
-    private JButton heapDumpButton;
-    private JList<HeapDump> dumpList;
-    private DefaultListModel<HeapDump> listModel;
-    
-    private JLabel max;
-    private JLabel current;
-    
-    public StatsPanel() {
-        
-        leftPanel = new JPanel();
-        leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.X_AXIS));
-        
-        JPanel rightPanel = new JPanel();
-        GroupLayout groupLayout = new GroupLayout(this);
-        groupLayout.setHorizontalGroup(
-            groupLayout.createParallelGroup(Alignment.LEADING)
-                .addGroup(Alignment.TRAILING, groupLayout.createSequentialGroup()
-                    .addComponent(leftPanel, GroupLayout.DEFAULT_SIZE, 343, Short.MAX_VALUE)
-                    .addPreferredGap(ComponentPlacement.UNRELATED)
-                    .addComponent(rightPanel, GroupLayout.PREFERRED_SIZE, 252, GroupLayout.PREFERRED_SIZE))
-        );
-        groupLayout.setVerticalGroup(
-            groupLayout.createParallelGroup(Alignment.LEADING)
-                .addComponent(rightPanel, GroupLayout.DEFAULT_SIZE, 293, Short.MAX_VALUE)
-                .addComponent(leftPanel, GroupLayout.DEFAULT_SIZE, 293, Short.MAX_VALUE)
-        );
-        
-        JLabel currentLabel = new JLabel("used:");
-        currentLabel.setHorizontalAlignment(SwingConstants.LEFT);
-        
-        JLabel maxLabel = new JLabel("capacity:");
-        maxLabel.setHorizontalAlignment(SwingConstants.LEFT);
-        
-        current = new JLabel("-");
-        current.setHorizontalAlignment(SwingConstants.RIGHT);
-        
-        max = new JLabel("-");
-        max.setHorizontalAlignment(SwingConstants.RIGHT);
-        
-        heapDumpButton = new JButton("Heap Dump");
-        heapDumpButton.setName("heapDumpButton");
-
-        JScrollPane dumpListScrollPane = new JScrollPane();
-        dumpList = new JList<>();
-        dumpList.setName("heapDumpList");
-        listModel = new DefaultListModel<>();
-        dumpList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-        dumpList.setModel(listModel);
-        
-        GroupLayout gl_rightPanel = new GroupLayout(rightPanel);
-        gl_rightPanel.setHorizontalGroup(
-            gl_rightPanel.createParallelGroup(Alignment.TRAILING)
-                .addGroup(gl_rightPanel.createSequentialGroup()
-                    .addContainerGap()
-                    .addGroup(gl_rightPanel.createParallelGroup(Alignment.TRAILING)
-                        .addComponent(dumpListScrollPane, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 173, Short.MAX_VALUE)
-                        .addComponent(heapDumpButton, GroupLayout.DEFAULT_SIZE, 173, Short.MAX_VALUE)
-                        .addGroup(gl_rightPanel.createSequentialGroup()
-                            .addGroup(gl_rightPanel.createParallelGroup(Alignment.TRAILING, false)
-                                .addComponent(maxLabel, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                                .addComponent(currentLabel, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 48, Short.MAX_VALUE))
-                            .addPreferredGap(ComponentPlacement.RELATED)
-                            .addGroup(gl_rightPanel.createParallelGroup(Alignment.TRAILING)
-                                .addComponent(current, GroupLayout.DEFAULT_SIZE, 119, Short.MAX_VALUE)
-                                .addComponent(max, GroupLayout.PREFERRED_SIZE, 119, GroupLayout.PREFERRED_SIZE))))
-                    .addContainerGap())
-        );
-        gl_rightPanel.setVerticalGroup(
-            gl_rightPanel.createParallelGroup(Alignment.LEADING)
-                .addGroup(gl_rightPanel.createSequentialGroup()
-                    .addContainerGap()
-                    .addGroup(gl_rightPanel.createParallelGroup(Alignment.BASELINE)
-                        .addComponent(currentLabel, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE)
-                        .addComponent(current))
-                    .addPreferredGap(ComponentPlacement.RELATED)
-                    .addGroup(gl_rightPanel.createParallelGroup(Alignment.BASELINE)
-                        .addComponent(maxLabel)
-                        .addComponent(max))
-                    .addGap(18)
-                    .addComponent(heapDumpButton)
-                    .addGap(18)
-                    .addComponent(dumpListScrollPane, GroupLayout.DEFAULT_SIZE, 172, Short.MAX_VALUE)
-                    .addContainerGap())
-        );
-        rightPanel.setLayout(gl_rightPanel);
-        setLayout(groupLayout);
-
-        dumpListScrollPane.setViewportView(dumpList);
-    }
-    
-    void setChartPanel(JPanel panel) {
-        leftPanel.removeAll();
-        leftPanel.add(panel);
-        leftPanel.revalidate();
-        repaint();
-    }
-
-    public void setMax(String capacity) {
-        max.setText(capacity);
-    }
-
-    public void setUsed(String used) {
-        current.setText(used);
-    }
-    
-    void addHeapDumperListener(ActionListener listener) {
-        heapDumpButton.addActionListener(listener);
-    }
-
-    void addDumpListListener(ListSelectionListener listener) {
-        dumpList.addListSelectionListener(listener);
-    }
-    
-    public void disableHeapDumperControl() {
-        heapDumpButton.setText("dumping...");
-        heapDumpButton.setEnabled(false);
-    }
-
-    public void enableHeapDumperControl() {
-        heapDumpButton.setText("Heap Dump");
-        heapDumpButton.setEnabled(true);
-    }
-
-    public void addDump(HeapDump dump) {
-        
-        listModel.addElement(dump);
-    }
-
-    public void clearDumpList() {
-        listModel.clear();
-    }
-    
-    public HeapDump getSelectedHeapDump() {
-        return dumpList.getSelectedValue();
-    }
-
-    public void updateHeapDumpList(List<HeapDump> heapDumps) {
-        int numItemsBefore = listModel.getSize();
-        for (HeapDump heapDump : heapDumps) {
-            if (! listModel.contains(heapDump)) {
-                listModel.addElement(heapDump);
-            }
-        }
-        if (numItemsBefore == 0 && listModel.getSize() > 0) {
-            dumpList.repaint();
-        }
-    }
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/SwingHeapDumpDetailsViewProvider.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.swing;
-
-import com.redhat.thermostat.client.heap.HeapDumpDetailsView;
-import com.redhat.thermostat.client.heap.HeapDumpDetailsViewProvider;
-
-public class SwingHeapDumpDetailsViewProvider implements
-        HeapDumpDetailsViewProvider {
-
-    @Override
-    public HeapDumpDetailsView createView() {
-        return new HeapDetailsSwing();
-    }
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/SwingHeapHistogramViewProvider.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.swing;
-
-import com.redhat.thermostat.client.heap.HeapHistogramView;
-import com.redhat.thermostat.client.heap.HeapHistogramViewProvider;
-
-public class SwingHeapHistogramViewProvider implements
-        HeapHistogramViewProvider {
-
-    @Override
-    public HeapHistogramView createView() {
-        return new HistogramPanel();
-    }
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/SwingHeapViewProvider.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.swing;
-
-import com.redhat.thermostat.client.heap.HeapView;
-import com.redhat.thermostat.client.heap.HeapViewProvider;
-
-public class SwingHeapViewProvider implements HeapViewProvider {
-
-    @Override
-    public HeapView createView() {
-        return new HeapSwingView();
-    }
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/SwingObjectDetailsViewProvider.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.swing;
-
-import com.redhat.thermostat.client.heap.ObjectDetailsView;
-import com.redhat.thermostat.client.heap.ObjectDetailsViewProvider;
-
-public class SwingObjectDetailsViewProvider implements
-        ObjectDetailsViewProvider {
-
-    @Override
-    public ObjectDetailsView createView() {
-        return new ObjectDetailsPanel();
-    }
-
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/SwingObjectRootsViewProvider.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.swing;
-
-import com.redhat.thermostat.client.heap.ObjectRootsView;
-import com.redhat.thermostat.client.heap.ObjectRootsViewProvider;
-
-public class SwingObjectRootsViewProvider implements ObjectRootsViewProvider {
-
-    @Override
-    public ObjectRootsView createView() {
-        return new ObjectRootsFrame();
-    }
-
-}
--- a/client/heapdumper/src/main/resources/META-INF/services/com.redhat.thermostat.common.cli.Command	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-com.redhat.thermostat.client.heap.cli.DumpHeapCommand
-com.redhat.thermostat.client.heap.cli.ListHeapDumpsCommand
-com.redhat.thermostat.client.heap.cli.SaveHeapDumpToFileCommand
-com.redhat.thermostat.client.heap.cli.ShowHeapHistogramCommand
-com.redhat.thermostat.client.heap.cli.FindObjectsCommand
-com.redhat.thermostat.client.heap.cli.ObjectInfoCommand
-com.redhat.thermostat.client.heap.cli.FindRootCommand
\ No newline at end of file
--- a/client/heapdumper/src/main/resources/com/redhat/thermostat/client/heap/strings.properties	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-MISSING_INFO = Missing Information
-HOST_SERVICE_UNAVAILABLE = Unable to access host information (HostInfoDAO unavailable)
-VM_SERVICE_UNAVAILABLE = Unable to access vm information (VmInfoDAO unavailable)
-HEAP_SERVICE_UNAVAILABLE = Unable to access heap informatio (HeapDAO unavailable)
-
-HEADER_TIMESTAMP = TIMESTAMP
-HEADER_HOST_ID = HOST ID
-HEADER_VM_ID = VM ID
-HEADER_HEAP_ID = HEAP ID
-HEADER_OBJECT_ID = ID
-HEADER_OBJECT_TYPE = TYPE
-
-FILE_REQUIRED = A file name is required
-INVALID_LIMIT = Invalid limit {0}
-HEAP_ID_NOT_FOUND = Heap ID not found: {0}
-HEAP_ID_REQUIRED = Heap ID required
-SEARCH_TERM_REQUIRED = A search term is required
-
-
-COMMAND_HEAP_DUMP_DONE = Done
-
-COMMAND_FIND_ROOT_NO_ROOT_FOUND = No root found for: {0}
-
-COMMAND_OBJECT_INFO_OBJECT_ID = Object ID:
-COMMAND_OBJECT_INFO_TYPE = Type:
-COMMAND_OBJECT_INFO_SIZE = Size:
-COMMAND_OBJECT_INFO_HEAP_ALLOCATED = Heap allocated:
-COMMAND_OBJECT_INFO_REFERENCES = References:
-COMMAND_OBJECT_INFO_REFERRERS = Referrers:
-
-COMMAND_SAVE_HEAP_DUMP_SAVED_TO_FILE = Saved heap dump to {0}
-COMMAND_SAVE_HEAP_DUMP_ERROR_SAVING = error saving heap to file: {0}
-COMMAND_SAVE_HEAP_DUMP_ERROR_CLOSING_STREAM = error closing heap stream: {0}
-
-HEAP_SECTION_TITLE = Memory Analyzer
-HEAP_OVERVIEW_TITLE = Heap Usage Overview
-HEAP_CHART_TITLE = Used Heap vs. Heap Capacity
-HEAP_CHART_TIME_AXIS = Time
-HEAP_CHART_HEAP_AXIS = Heap
-HEAP_CHART_CAPACITY = Heap Capacity
-HEAP_CHART_USED = Used Heap
-
-HEAP_DUMP_SECTION_HISTOGRAM = Histogram
-HEAP_DUMP_SECTION_OBJECT_BROWSER = Object Browser
-
-HEAP_DUMP_CLASS_USAGE = Classes Usage
-HEAP_DUMP_HISTOGRAM_COLUMN_CLASS = Class
-HEAP_DUMP_HISTOGRAM_COLUMN_INSTANCES = Instances
-HEAP_DUMP_HISTOGRAM_COLUMN_SIZE = Size (in bytes)
-
-HEAP_DUMP_OBJECT_BROWSE_SEARCH_HINT = Search for objects by class name (either a partial class name or a wildcard pattern)
-HEAP_DUMP_OBJECT_BROWSE_SEARCH_PATTERN_HELP = Either a partial class name ("Button" will find "javax.swing.JButton") or a wildcard pattern ("*JButton*" will find "javax.swing.JButtonBeanInfo")
-HEAP_DUMP_OBJECT_BROWSE_SEARCH_LABEL = Search for Object
-HEAP_DUMP_OBJECT_BROWSE_REFERRERS = Referrers
-HEAP_DUMP_OBJECT_BROWSE_REFERENCES = References
-HEAP_DUMP_OBJECT_FIND_ROOT = Find Root
-
-OBJECT_ROOTS_VIEW_TITLE = Object Roots
\ No newline at end of file
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/HeapDumpControllerTest.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,405 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.isA;
-import static org.mockito.Matchers.same;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.client.heap.HeapView.HeapDumperAction;
-import com.redhat.thermostat.client.heap.cli.HeapDumperCommand;
-import com.redhat.thermostat.client.osgi.service.ApplicationCache;
-import com.redhat.thermostat.client.osgi.service.ApplicationService;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.Timer;
-import com.redhat.thermostat.common.TimerFactory;
-import com.redhat.thermostat.common.appctx.ApplicationContext;
-import com.redhat.thermostat.common.appctx.ApplicationContextUtil;
-import com.redhat.thermostat.common.dao.AgentInfoDAO;
-import com.redhat.thermostat.common.dao.HeapDAO;
-import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
-import com.redhat.thermostat.common.dao.VmRef;
-import com.redhat.thermostat.common.heap.HeapDump;
-import com.redhat.thermostat.common.model.HeapInfo;
-import com.redhat.thermostat.common.model.VmMemoryStat;
-import com.redhat.thermostat.common.model.VmMemoryStat.Generation;
-import com.redhat.thermostat.common.model.VmMemoryStat.Space;
-
-public class HeapDumpControllerTest {
-
-    private ActionListener<HeapView.Action> actionListener;
-    private ActionListener<HeapView.HeapDumperAction> heapDumperListener;
-    
-    private Timer timer;
-    
-    private AgentInfoDAO agentDao;
-    private HeapDAO heapDao;
-    private VmMemoryStatDAO vmDao;
-    private HeapView view;
-    private HeapDumpDetailsView detailsView;
-    
-    @SuppressWarnings("unused")
-    private HeapDumpController controller;
-    private HeapDumperCommand heapDumperCommand;
-    private ApplicationService appService;
-    private ArgumentCaptor<Runnable> timerActionCaptor;
-    
-    private HeapViewProvider viewProvider;
-    private HeapDumpDetailsViewProvider detailsViewProvider;
-    private HeapHistogramViewProvider histogramProvider;
-    private ObjectDetailsViewProvider objectDetailsProvider;
-    private ObjectRootsViewProvider objectRootsProvider;
-
-    @Before
-    public void setUp() {
-        ApplicationContextUtil.resetApplicationContext();
-
-        agentDao = mock(AgentInfoDAO.class);
-        heapDao = mock(HeapDAO.class);
-        vmDao = mock(VmMemoryStatDAO.class);
-
-        setUpTimers();
-        setUpView();
-    }
-    
-    private void setUpTimers() {
-        timer = mock(Timer.class);
-        timerActionCaptor = ArgumentCaptor.forClass(Runnable.class);
-        doNothing().when(timer).setAction(timerActionCaptor.capture());
-
-        TimerFactory timerFactory = mock(TimerFactory.class);
-        when(timerFactory.createTimer()).thenReturn(timer);
-        ApplicationContext.getInstance().setTimerFactory(timerFactory);
-    }
-    
-    private void setUpView() {
-        view = mock(HeapView.class);
-        viewProvider = mock(HeapViewProvider.class);
-        when(viewProvider.createView()).thenReturn(view);
-        
-        detailsViewProvider = mock(HeapDumpDetailsViewProvider.class);
-        detailsView = mock(HeapDumpDetailsView.class);
-        when(detailsViewProvider.createView()).thenReturn(detailsView);
-
-        HeapHistogramView histogramView = mock(HeapHistogramView.class);
-        histogramProvider = mock(HeapHistogramViewProvider.class);
-        when(histogramProvider.createView()).thenReturn(histogramView);
-
-        ObjectDetailsView objectView = mock(ObjectDetailsView.class);
-        objectDetailsProvider = mock(ObjectDetailsViewProvider.class);
-        when(objectDetailsProvider.createView()).thenReturn(objectView);
-
-        ObjectRootsView objectRootsView = mock(ObjectRootsView.class);
-        objectRootsProvider = mock(ObjectRootsViewProvider.class);
-        when(objectRootsProvider.createView()).thenReturn(objectRootsView);
-    }
-    
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    private void setUpListeners() {        
-        ArgumentCaptor<ActionListener> viewArgumentCaptor1 = ArgumentCaptor.forClass(ActionListener.class);
-        doNothing().when(view).addActionListener(viewArgumentCaptor1.capture());
-        
-        ArgumentCaptor<ActionListener> viewArgumentCaptor2 = ArgumentCaptor.forClass(ActionListener.class);
-        doNothing().when(view).addDumperListener(viewArgumentCaptor2.capture());
-        
-        createController();
-        
-        actionListener = viewArgumentCaptor1.getValue();
-        heapDumperListener = viewArgumentCaptor2.getValue();
-    }
-    
-    private void createController() {
-        ApplicationCache cache = mock(ApplicationCache.class);
-        appService = mock(ApplicationService.class);
-        when(appService.getApplicationCache()).thenReturn(cache);
-        VmRef ref = mock(VmRef.class);
-        heapDumperCommand = mock(HeapDumperCommand.class);
-        controller = new HeapDumpController(agentDao, vmDao, heapDao, ref, appService,
-                heapDumperCommand, viewProvider, detailsViewProvider,
-                histogramProvider, objectDetailsProvider, objectRootsProvider);
-    }
-    
-    @After
-    public void tearDown() {
-    	controller = null;
-    	vmDao = null;
-    	heapDao = null;
-    	viewProvider = null;
-        detailsViewProvider = null;
-        histogramProvider = null;
-        objectDetailsProvider = null;
-        objectRootsProvider = null;
-        ApplicationContextUtil.resetApplicationContext();
-    }
-
-    @Test
-    public void testTimerStartOnViewVisible() {
-        
-        setUpListeners();
-
-        actionListener.actionPerformed(new ActionEvent<>(view, HeapView.Action.VISIBLE));
-        verify(timer).start();
-    }
-
-    @Test
-    public void testTimerStopsOnViewHidden() {
-        
-        setUpListeners();
-        
-        actionListener.actionPerformed(new ActionEvent<>(view, HeapView.Action.HIDDEN));
-        verify(timer).stop();
-    }
-    
-    @Test
-    public void testNotAddHeapDumpsAtStartupWhenNoDumps() {
-                
-        when(heapDao.getAllHeapInfo(any(VmRef.class))).thenReturn(new ArrayList<HeapInfo>());
-        
-        createController();
-        
-        verify(view, times(0)).addHeapDump(any(HeapDump.class));
-    }
-    
-    @Test
-    public void testAddHeapDumpsAtStartupWhenDumpsAreThere() {
-        HeapInfo info1 = mock(HeapInfo.class);
-        HeapInfo info2 = mock(HeapInfo.class);
-        Collection<HeapInfo> infos = new ArrayList<HeapInfo>();
-        infos.add(info1);
-        infos.add(info2);
-        
-        when(heapDao.getAllHeapInfo(any(VmRef.class))).thenReturn(infos);
-
-        createController();
-        
-        verify(view, times(2)).addHeapDump(any(HeapDump.class));
-    }
-    
-    @Test
-    public void testOpenDumpCalledWhenPreviousDump() {
-        
-        HeapDump dump = mock(HeapDump.class);
-        
-        HeapInfo info1 = mock(HeapInfo.class);
-        when(dump.getInfo()).thenReturn(info1);
-        
-        HeapInfo info2 = mock(HeapInfo.class);
-        Collection<HeapInfo> infos = new ArrayList<HeapInfo>();
-        infos.add(info1);
-        infos.add(info2);
-        
-        when(heapDao.getAllHeapInfo(any(VmRef.class))).thenReturn(infos);
-        
-        ApplicationCache cache = mock(ApplicationCache.class);
-        when(cache.getAttribute(any(VmRef.class))).thenReturn(dump);
-        
-        appService = mock(ApplicationService.class);
-        when(appService.getApplicationCache()).thenReturn(cache);
-        VmRef ref = mock(VmRef.class);
-        controller = new HeapDumpController(agentDao, vmDao, heapDao, ref, appService,
-                heapDumperCommand, viewProvider, detailsViewProvider,
-                histogramProvider, objectDetailsProvider, objectRootsProvider);
-        
-        verify(view, times(1)).setChildView(any(HeapView.class));
-        verify(view, times(1)).openDumpView();
-    }
-    
-    @Test
-    public void testNotOpenDumpCalledWhenNoPreviousDump() {
-
-        HeapInfo info1 = mock(HeapInfo.class);        
-        HeapInfo info2 = mock(HeapInfo.class);
-        Collection<HeapInfo> infos = new ArrayList<HeapInfo>();
-        infos.add(info1);
-        infos.add(info2);
-        
-        when(heapDao.getAllHeapInfo(any(VmRef.class))).thenReturn(infos);
-        
-        ApplicationCache cache = mock(ApplicationCache.class);
-        when(cache.getAttribute(any(VmRef.class))).thenReturn(null);
-        
-        appService = mock(ApplicationService.class);
-        when(appService.getApplicationCache()).thenReturn(cache);
-        VmRef ref = mock(VmRef.class);
-        controller = new HeapDumpController(agentDao, vmDao, heapDao, ref, appService,
-                heapDumperCommand, viewProvider, detailsViewProvider,
-                histogramProvider, objectDetailsProvider, objectRootsProvider);
-        
-        verify(view, times(0)).openDumpView();
-    }
-
-    @Test
-    public void testRequestHeapDump() {
-
-        setUpListeners();
-
-        heapDumperListener.actionPerformed(new ActionEvent<HeapDumperAction>(view, HeapDumperAction.DUMP_REQUESTED));
-
-        ArgumentCaptor<Runnable> heapDumpCompleteAction = ArgumentCaptor.forClass(Runnable.class);
-        verify(heapDumperCommand).execute(same(agentDao), any(VmRef.class), heapDumpCompleteAction.capture());
-        heapDumpCompleteAction.getValue().run();
-        verify(view).notifyHeapDumpComplete();
-
-    }
- 
-    @SuppressWarnings("unchecked")
-	@Test
-    public void testTimerChecksForNewHeapDumps() {
-
-        HeapInfo info1 = mock(HeapInfo.class);
-        HeapInfo info2 = mock(HeapInfo.class);
-        Collection<HeapInfo> infos = new ArrayList<HeapInfo>();
-        infos.add(info1);
-        infos.add(info2);
-        
-        when(heapDao.getAllHeapInfo(any(VmRef.class))).thenReturn(infos);
-
-        createController();
-
-        timerActionCaptor.getValue().run();
-
-        @SuppressWarnings("rawtypes")
-		ArgumentCaptor<List> heapDumps = ArgumentCaptor.forClass(List.class);
-        verify(view).updateHeapDumpList(heapDumps.capture());
-        assertTrue(heapDumps.getValue().contains(new HeapDump(info1, heapDao)));
-        assertTrue(heapDumps.getValue().contains(new HeapDump(info2, heapDao)));
-    }
-
-    @Test
-    public void testTimerFetchesMemoryDataAndUpdatesView() {
-        createController();
-        Runnable timerAction = timerActionCaptor.getValue();
-
-        final long CAPACITY = 10;
-        final long USED = 5;
-        Space space = new Space();
-        space.capacity = CAPACITY;
-        space.maxCapacity = 20;
-        space.used = USED;
-        Generation gen = new Generation();
-        gen.name = "foobar";
-        gen.spaces = Arrays.asList(space);
-        VmMemoryStat stat = new VmMemoryStat();
-        stat.setGenerations(Arrays.asList(gen));
-
-        when(vmDao.getLatestVmMemoryStats(isA(VmRef.class), anyLong())).thenReturn(Arrays.asList(stat));
-
-        timerAction.run();
-
-        ArgumentCaptor<Long> timeStampCaptor = ArgumentCaptor.forClass(Long.class);
-        verify(vmDao).getLatestVmMemoryStats(isA(VmRef.class), timeStampCaptor.capture());
-        assertTimeStampIsAround(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1), timeStampCaptor.getValue());
-        verify(view).updateUsedAndCapacity(USED + " B", CAPACITY + " B");
-    }
-
-    @Test
-    public void testTimerFetchesMemoryDataDeltaOnly() {
-        ArgumentCaptor<Long> timeStampCaptor = ArgumentCaptor.forClass(Long.class);
-
-        final long DATA_TIMESTAMP = System.currentTimeMillis() + 1000000000;
-        Space space = new Space();
-        space.capacity = 10;
-        space.maxCapacity = 20;
-        space.used = 5;
-        Generation gen = new Generation();
-        gen.name = "foobar";
-        gen.spaces = Arrays.asList(space);
-        VmMemoryStat stat = new VmMemoryStat();
-        stat.setTimeStamp(DATA_TIMESTAMP);
-        stat.setGenerations(Arrays.asList(gen));
-
-        when(vmDao.getLatestVmMemoryStats(isA(VmRef.class), anyLong())).thenReturn(Arrays.asList(stat));
-
-        createController();
-        Runnable timerAction = timerActionCaptor.getValue();
-
-        timerAction.run();
-        timerAction.run();
-
-        verify(vmDao, times(2)).getLatestVmMemoryStats(isA(VmRef.class), timeStampCaptor.capture());
-
-        long timeStamp1 = timeStampCaptor.getAllValues().get(0);
-        assertTimeStampIsAround(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1), timeStamp1);
-
-        long timeStamp2 = timeStampCaptor.getAllValues().get(1);
-        assertTimeStampIsAround(DATA_TIMESTAMP, timeStamp2);
-    }
-
-    @Test
-    public void testTimerFetchesMemoryDataDeltaOnlyEvenWithNoData() {
-        ArgumentCaptor<Long> timeStampCaptor = ArgumentCaptor.forClass(Long.class);
-
-        createController();
-        Runnable timerAction = timerActionCaptor.getValue();
-
-        timerAction.run();
-        timerAction.run();
-
-        verify(vmDao, times(2)).getLatestVmMemoryStats(isA(VmRef.class), timeStampCaptor.capture());
-
-        long timeStamp1 = timeStampCaptor.getAllValues().get(0);
-        assertTimeStampIsAround(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1), timeStamp1);
-
-        long timeStamp2 = timeStampCaptor.getAllValues().get(1);
-        assertTimeStampIsAround(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1), timeStamp2);
-    }
-
-    private void assertTimeStampIsAround(long expected, long actual) {
-        assertTrue(actual <= expected + 1000);
-        assertTrue(actual >= expected - 1000);
-    }
-
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/HeapDumpDetailsControllerTest.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.isA;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.client.osgi.service.ApplicationService;
-import com.redhat.thermostat.common.appctx.ApplicationContextUtil;
-import com.redhat.thermostat.common.heap.HeapDump;
-import com.redhat.thermostat.common.heap.ObjectHistogram;
-
-public class HeapDumpDetailsControllerTest {
-
-    private HeapDumpDetailsView view;
-    private HeapDumpDetailsViewProvider viewProvider;
-    private HeapHistogramViewProvider histogramProvider;
-    private ObjectDetailsViewProvider objectDetailsProvider;
-    private ObjectRootsViewProvider objectRootsProvider;
-
-    @Before
-    public void setUp() {
-        ApplicationContextUtil.resetApplicationContext();
-
-        viewProvider = mock(HeapDumpDetailsViewProvider.class);
-        view = mock(HeapDumpDetailsView.class);
-        when(viewProvider.createView()).thenReturn(view);
-
-        HeapHistogramView histogramView = mock(HeapHistogramView.class);
-        histogramProvider = mock(HeapHistogramViewProvider.class);
-        when(histogramProvider.createView()).thenReturn(histogramView);
-
-        ObjectDetailsView objectView = mock(ObjectDetailsView.class);
-        objectDetailsProvider = mock(ObjectDetailsViewProvider.class);
-        when(objectDetailsProvider.createView()).thenReturn(objectView);
-
-        ObjectRootsView objectRootsView = mock(ObjectRootsView.class);
-        objectRootsProvider = mock(ObjectRootsViewProvider.class);
-        when(objectRootsProvider.createView()).thenReturn(objectRootsView);
-    }
-
-    @After
-    public void tearDown() {
-        viewProvider = null;
-        histogramProvider = null;
-        objectDetailsProvider = null;
-        objectRootsProvider = null;
-        ApplicationContextUtil.resetApplicationContext();
-    }
-
-    @Test
-    public void verifyInitialize() throws IOException {
-        ApplicationService appService = mock(ApplicationService.class);
-
-        ObjectHistogram histogram = mock(ObjectHistogram.class);
-
-        HeapDump dump = mock(HeapDump.class);
-        when(dump.getHistogram()).thenReturn(histogram);
-
-        HeapDumpDetailsController controller = new HeapDumpDetailsController(
-                appService, viewProvider, histogramProvider,
-                objectDetailsProvider, objectRootsProvider);
-        controller.setDump(dump);
-
-        verify(dump).searchObjects(isA(String.class), anyInt());
-        verify(view)
-                .addSubView(isA(String.class), isA(HeapHistogramView.class));
-        verify(view)
-                .addSubView(isA(String.class), isA(ObjectDetailsView.class));
-    }
-
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/LocaleResourcesTest.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import java.io.IOException;
-import java.util.Properties;
-
-import junit.framework.Assert;
-
-import org.junit.Test;
-
-public class LocaleResourcesTest {
-
-    @Test
-    public void testLocalizedStringsArePresent() throws IOException {
-
-        String stringsResource = "/" + LocaleResources.RESOURCE_BUNDLE.replace(".", "/") + ".properties";
-
-        Properties props = new Properties();
-        props.load(getClass().getResourceAsStream(stringsResource));
-
-        Assert.assertEquals(LocaleResources.values().length, props.values().size());
-        for (LocaleResources resource : LocaleResources.values()) {
-            Assert.assertTrue("missing property from resource bound file: " + resource,
-                              props.containsKey(resource.name()));
-        }
-    }
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/ObjectDetailsControllerTest.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,288 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.contains;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.InOrder;
-import org.mockito.stubbing.OngoingStubbing;
-
-import com.redhat.thermostat.client.heap.ObjectDetailsView.ObjectAction;
-import com.redhat.thermostat.client.osgi.service.ApplicationService;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.appctx.ApplicationContextUtil;
-import com.redhat.thermostat.common.heap.HeapDump;
-import com.sun.tools.hat.internal.model.JavaClass;
-import com.sun.tools.hat.internal.model.JavaHeapObject;
-
-public class ObjectDetailsControllerTest {
-
-    private ObjectDetailsView view;
-    private ApplicationService appService;
-    private ObjectRootsViewProvider objectRootsProvider;
-    private ObjectDetailsViewProvider objectDetailsProvider;
-
-    private ArgumentCaptor<Runnable> runnableCaptor;
-
-    @Before
-    public void setUp() {
-        ApplicationContextUtil.resetApplicationContext();
-
-        view = mock(ObjectDetailsView.class);
-        objectDetailsProvider = mock(ObjectDetailsViewProvider.class);
-        when(objectDetailsProvider.createView()).thenReturn(view);
-        
-        objectRootsProvider = mock(ObjectRootsViewProvider.class);
-        when(objectRootsProvider.createView()).thenReturn(mock(ObjectRootsView.class));
-        runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
-        ExecutorService executorService = mock(ExecutorService.class);
-        doNothing().when(executorService).execute(runnableCaptor.capture());
-
-        appService = mock(ApplicationService.class);
-        when(appService.getApplicationExecutor()).thenReturn(executorService);
-    }
-
-    @After
-    public void tearDown() {
-        view = null;
-        objectDetailsProvider = null;
-        objectRootsProvider = null;
-        ApplicationContextUtil.resetApplicationContext();
-    }
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    @Test
-    public void verifySearchWorks() {
-        final String SEARCH_TEXT = "Test";
-        final String OBJECT_ID = "0xcafebabe";
-        final String OBJECT_CLASS_NAME = "FOO";
-
-        when(view.getSearchText()).thenReturn(SEARCH_TEXT);
-
-        JavaClass heapObjectClass = mock(JavaClass.class);
-        when(heapObjectClass.getName()).thenReturn(OBJECT_CLASS_NAME);
-
-        JavaHeapObject heapObject = mock(JavaHeapObject.class);
-        when(heapObject.getIdString()).thenReturn(OBJECT_ID);
-        when(heapObject.getClazz()).thenReturn(heapObjectClass);
-
-        HeapDump dump = mock(HeapDump.class);
-        when(dump.searchObjects(contains(SEARCH_TEXT), anyInt())).thenReturn(Arrays.asList(OBJECT_ID));
-        when(dump.findObject(eq(OBJECT_ID))).thenReturn(heapObject);
-
-        ArgumentCaptor<ActionListener> viewArgumentCaptor1 = ArgumentCaptor.forClass(ActionListener.class);
-        doNothing().when(view).addObjectActionListener(viewArgumentCaptor1.capture());
-
-        @SuppressWarnings("unused")
-        ObjectDetailsController controller = new ObjectDetailsController(appService, dump, this.objectDetailsProvider, this.objectRootsProvider);
-
-        ActionListener<ObjectAction> actionListener = viewArgumentCaptor1.getValue();
-        assertNotNull(actionListener);
-        actionListener.actionPerformed(new ActionEvent<ObjectAction>(view, ObjectAction.SEARCH));
-
-        runnableCaptor.getValue().run();
-
-        ArgumentCaptor<Collection> matchingObjectsCaptor = ArgumentCaptor.forClass(Collection.class);
-        verify(view).setMatchingObjects(matchingObjectsCaptor.capture());
-
-        List<HeapObjectUI> matchingObjects = new ArrayList<HeapObjectUI>(matchingObjectsCaptor.getValue());
-        assertEquals(1, matchingObjects.size());
-        assertEquals(OBJECT_ID, matchingObjects.get(0).objectId);
-    }
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    @Test
-    public void verifyInputConvertedIntoWildcardsIfNeeded() {
-        HeapDump heap = mock(HeapDump.class);
-        when(view.getSearchText()).thenReturn("a");
-
-        ArgumentCaptor<ActionListener> objectActionListenerCaptor = ArgumentCaptor.forClass(ActionListener.class);
-        doNothing().when(view).addObjectActionListener(objectActionListenerCaptor.capture());
-
-        @SuppressWarnings("unused")
-        ObjectDetailsController controller = new ObjectDetailsController(appService, heap, this.objectDetailsProvider, this.objectRootsProvider);
-
-        ActionListener<ObjectAction> actionListener = objectActionListenerCaptor.getValue();
-        assertNotNull(actionListener);
-        actionListener.actionPerformed(new ActionEvent<ObjectAction>(view, ObjectAction.SEARCH));
-
-        runnableCaptor.getValue().run();
-
-        verify(heap).searchObjects("*a*", 100);
-    }
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    @Test
-    public void verifyWildcardInputNotConvertedIntoWildcards() {
-        HeapDump heap = mock(HeapDump.class);
-        when(view.getSearchText()).thenReturn("*a?");
-
-        ArgumentCaptor<ActionListener> objectActionListenerCaptor = ArgumentCaptor.forClass(ActionListener.class);
-        doNothing().when(view).addObjectActionListener(objectActionListenerCaptor.capture());
-
-        @SuppressWarnings("unused")
-        ObjectDetailsController controller = new ObjectDetailsController(appService, heap, this.objectDetailsProvider, this.objectRootsProvider);
-
-        ActionListener<ObjectAction> actionListener = objectActionListenerCaptor.getValue();
-        assertNotNull(actionListener);
-        actionListener.actionPerformed(new ActionEvent<ObjectAction>(view, ObjectAction.SEARCH));
-
-        runnableCaptor.getValue().run();
-
-        verify(heap).searchObjects("*a?", 300);
-    }
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    @Test
-    public void verifySearchLimits() {
-
-        Object[][] limits = new Object[][] {
-            { "a",       100 },
-            { "ab",      200 },
-            { "abc",     300 },
-            { "abcd",    400 },
-            { "abcde",   500 },
-            { "abcdef",  600},
-            { "abcdefg", 700},
-            { "java.lang.Class", 1000 },
-        };
-
-        HeapDump heap = mock(HeapDump.class);
-
-        OngoingStubbing<String> ongoing = when(view.getSearchText());
-        for (int i = 0; i < limits.length; i++) {
-            ongoing = ongoing.thenReturn((String)limits[i][0]);
-        }
-
-        ArgumentCaptor<ActionListener> objectActionListenerCaptor = ArgumentCaptor.forClass(ActionListener.class);
-        doNothing().when(view).addObjectActionListener(objectActionListenerCaptor.capture());
-
-        @SuppressWarnings("unused")
-        ObjectDetailsController controller = new ObjectDetailsController(appService, heap, this.objectDetailsProvider, this.objectRootsProvider);
-
-        ActionListener<ObjectAction> actionListener = objectActionListenerCaptor.getValue();
-        assertNotNull(actionListener);
-
-        for (int i = 0; i < limits.length; i++) {
-            actionListener.actionPerformed(new ActionEvent<ObjectAction>(view, ObjectAction.SEARCH));
-            runnableCaptor.getValue().run();
-        }
-
-        InOrder inOrder = inOrder(heap);
-        for (int i = 0; i < limits.length; i++) {
-            String text = (String) limits[i][0];
-            int times = (Integer) limits[i][1];
-            inOrder.verify(heap).searchObjects("*" + text + "*", times);
-        }
-    }
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    @Test
-    public void verifyGettingDetailsWorks() {
-        final String OBJECT_ID = "0xcafebabe";
-        final String OBJECT_ID_VISIBLE = "FOO BAR";
-
-        JavaHeapObject heapObject = mock(JavaHeapObject.class);
-
-        HeapObjectUI heapObjectRepresentation = new HeapObjectUI(OBJECT_ID, OBJECT_ID_VISIBLE);
-
-        HeapDump dump = mock(HeapDump.class);
-        when(dump.findObject(OBJECT_ID)).thenReturn(heapObject);
-
-        ArgumentCaptor<ActionListener> viewArgumentCaptor1 = ArgumentCaptor.forClass(ActionListener.class);
-        doNothing().when(view).addObjectActionListener(viewArgumentCaptor1.capture());
-
-        when(view.getSelectedMatchingObject()).thenReturn(heapObjectRepresentation);
-
-        @SuppressWarnings("unused")
-        ObjectDetailsController controller = new ObjectDetailsController(appService, dump, this.objectDetailsProvider, this.objectRootsProvider);
-
-        ActionListener<ObjectAction> actionListener = viewArgumentCaptor1.getValue();
-        assertNotNull(actionListener);
-        actionListener.actionPerformed(new ActionEvent<ObjectAction>(view, ObjectAction.GET_OBJECT_DETAIL));
-
-        verify(view).setObjectDetails(heapObject);
-    }
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    @Test
-    public void verifyFindRoot() {
-        final String OBJECT_ID = "0xcafebabe";
-        final String OBJECT_ID_VISIBLE = "FOO BAR";
-
-        JavaHeapObject heapObject = mock(JavaHeapObject.class);
-
-        HeapObjectUI heapObjectRepresentation = new HeapObjectUI(OBJECT_ID, OBJECT_ID_VISIBLE);
-
-        HeapDump dump = mock(HeapDump.class);
-        when(dump.findObject(OBJECT_ID)).thenReturn(heapObject);
-
-        ArgumentCaptor<ActionListener> viewArgumentCaptor1 = ArgumentCaptor.forClass(ActionListener.class);
-        doNothing().when(view).addObjectActionListener(viewArgumentCaptor1.capture());
-
-        when(view.getSelectedMatchingObject()).thenReturn(heapObjectRepresentation);
-
-        @SuppressWarnings("unused")
-        ObjectDetailsController controller = new ObjectDetailsController(appService, dump, this.objectDetailsProvider, this.objectRootsProvider);
-
-        ActionListener<ObjectAction> actionListener = viewArgumentCaptor1.getValue();
-        assertNotNull(actionListener);
-        actionListener.actionPerformed(new ActionEvent<ObjectAction>(view, ObjectAction.GET_OBJECT_DETAIL));
-
-        verify(view).setObjectDetails(heapObject);
-    }
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/ObjectRootsControllerTest.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.client.heap.ObjectRootsView.Action;
-import com.redhat.thermostat.client.heap.cli.FindRoot;
-import com.redhat.thermostat.client.heap.cli.HeapPath;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.appctx.ApplicationContextUtil;
-import com.redhat.thermostat.common.heap.HeapDump;
-import com.sun.tools.hat.internal.model.JavaClass;
-import com.sun.tools.hat.internal.model.JavaHeapObject;
-
-public class ObjectRootsControllerTest {
-
-    ObjectRootsController controller;
-
-    HeapDump heapDump;
-    JavaHeapObject heapObject;
-    JavaClass clazz;
-    FindRoot rootFinder;
-
-    ObjectRootsView view;
-    ActionListener<Action> listener;
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    @Before
-    public void setUp() {
-        ApplicationContextUtil.resetApplicationContext();
-
-        // Set up views
-        view = mock(ObjectRootsView.class);
-
-        ObjectRootsViewProvider viewProvider = mock(ObjectRootsViewProvider.class);
-        when(viewProvider.createView()).thenReturn(view);
-        
-        // set up models
-        heapObject = mock(JavaHeapObject.class);
-        when(heapObject.getIdString()).thenReturn("id-string");
-
-        clazz = mock(JavaClass.class);
-        when(clazz.getName()).thenReturn("class");
-        when(heapObject.getClazz()).thenReturn(clazz);
-
-        heapDump = mock(HeapDump.class);
-        when(heapDump.findObject("test")).thenReturn(heapObject);
-
-        rootFinder = mock(FindRoot.class);
-
-        // create controller
-        controller = new ObjectRootsController(heapDump, heapObject, rootFinder, viewProvider);
-
-        ArgumentCaptor<ActionListener> listenerCaptor = ArgumentCaptor.forClass(ActionListener.class);
-        verify(view).addActionListener(listenerCaptor.capture());
-
-        listener = listenerCaptor.getValue();
-    }
-
-    @After
-    public void tearDown() {
-        ApplicationContextUtil.resetApplicationContext();
-    }
-
-
-    @Test
-    public void verifyAddListenersToView() {
-        assertNotNull(listener);
-    }
-
-    @Test
-    public void verifySetObjectDetailsInView() {
-        when(heapObject.getIdString()).thenReturn("object-id");
-        when(heapObject.isHeapAllocated()).thenReturn(true);
-        when(heapObject.getSize()).thenReturn(10);
-
-        when(clazz.getName()).thenReturn("object-class");
-
-        HeapObjectUI heapObj = new HeapObjectUI("test", "test");
-        ActionEvent<Action> event = new ActionEvent<Action>(view, Action.OBJECT_SELECTED);
-        event.setPayload(heapObj);
-        listener.actionPerformed(event);
-
-        verify(view).setObjectDetails("Object ID: object-id\n" +
-                "Type: object-class\n" +
-                "Size: 10 bytes\n" +
-                "Heap allocated: true\n");
-    }
-
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    @Test
-    public void testShow() {
-
-        HeapPath<JavaHeapObject> path = mock(HeapPath.class);
-        when(path.iterator()).thenReturn(Arrays.asList(heapObject).iterator());
-
-        when(rootFinder.findShortestPathsToRoot(heapObject, false)).thenReturn(Arrays.asList(path));
-
-        controller.show();
-
-        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
-
-        verify(view).setPathToRoot(captor.capture());
-
-        HeapObjectUI heapObj = (HeapObjectUI) captor.getValue().get(0);
-        assertEquals("id-string", heapObj.objectId);
-        assertEquals("class@id-string", heapObj.text);
-
-        verify(view).showView();
-    }
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/ServicesAvailableActionTest.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*
- * Copyright 2012 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.client.heap;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.client.core.VmInformationService;
-import com.redhat.thermostat.client.heap.Activator.ServicesAvailableAction;
-import com.redhat.thermostat.client.osgi.service.ApplicationService;
-import com.redhat.thermostat.common.dao.AgentInfoDAO;
-import com.redhat.thermostat.common.dao.HeapDAO;
-import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
-import com.redhat.thermostat.test.StubBundleContext;
-
-public class ServicesAvailableActionTest {
-
-    @Test
-    public void verifyDepsAvailableRegistersVmInformationService() throws Exception {
-        StubBundleContext ctx = new StubBundleContext();
-        Activator activator = new Activator();
-        
-        activator.start(ctx);
-        
-        
-        
-        ServicesAvailableAction action = activator.getServiceAvailableAction();
-        ApplicationService appService = mock(ApplicationService.class);
-        AgentInfoDAO dao = mock(AgentInfoDAO.class);
-        VmMemoryStatDAO vmMemoryDao = mock(VmMemoryStatDAO.class);
-        HeapDAO heapDao = mock(HeapDAO.class);
-        Map<String, Object> services = new HashMap<>();
-        services.put(AgentInfoDAO.class.getName(), dao);
-        services.put(ApplicationService.class.getName(), appService);
-        services.put(VmMemoryStatDAO.class.getName(), vmMemoryDao);
-        services.put(HeapDAO.class.getName(), heapDao);
-        
-        action.dependenciesAvailable(services);
-        
-        assertTrue(ctx.isServiceRegistered(VmInformationService.class.getName(), HeapDumperService.class));
-        
-        // Interesting enought this comes back with all services listed in
-        // 1.) this bundles commands: META-IN/services/com.redhat.thermostat.common.cli.Command (7 Commands)
-        // 2.) commands provided by tools (6 commands)
-        // 3.) 3 more services, namely applicationService, AgentInfoDAO and the VmInformationService registered
-        //     by this bundle.
-        assertEquals(16, ctx.getAllServices().size());
-    }
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/cli/DumpHeapCommandTest.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isA;
-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;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-import com.redhat.thermostat.common.cli.Command;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.SimpleArguments;
-import com.redhat.thermostat.common.dao.AgentInfoDAO;
-import com.redhat.thermostat.common.dao.VmRef;
-import com.redhat.thermostat.common.utils.OSGIUtils;
-import com.redhat.thermostat.test.TestCommandContextFactory;
-
-public class DumpHeapCommandTest {
-
-    @Test
-    public void testBasics() {
-        Command command = new DumpHeapCommand();
-        assertEquals("dump-heap", command.getName());
-        assertNotNull(command.getDescription());
-        assertNotNull(command.getUsage());
-    }
-
-    @Test
-    public void verifyAcuallyCallsWorker() throws CommandException {
-        AgentInfoDAO agentInfoDao = mock(AgentInfoDAO.class);
-        OSGIUtils osgi = mock(OSGIUtils.class);
-        when(osgi.getService(AgentInfoDAO.class)).thenReturn(agentInfoDao);
-
-        HeapDumperCommand impl = mock(HeapDumperCommand.class);
-        final ArgumentCaptor<Runnable> arg = ArgumentCaptor.forClass(Runnable.class);
-        doAnswer(new Answer<Void>() {
-
-            @Override
-            public Void answer(InvocationOnMock invocation) throws Throwable {
-                arg.getValue().run();
-                return null;
-            }
-        }).when(impl).execute(eq(agentInfoDao), any(VmRef.class), arg.capture());
-
-        DumpHeapCommand command = new DumpHeapCommand(osgi, impl);
-
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("hostId", "foo");
-        args.addArgument("vmId", "0");
-
-        command.run(factory.createContext(args));
-
-        verify(impl).execute(eq(agentInfoDao), isA(VmRef.class), any(Runnable.class));
-        assertEquals("Done\n", factory.getOutput());
-    }
-
-    @Test
-    public void verifyNeedsHostAndVmId() throws CommandException {
-        AgentInfoDAO agentInfoDao = mock(AgentInfoDAO.class);
-        OSGIUtils osgi = mock(OSGIUtils.class);
-        when(osgi.getService(AgentInfoDAO.class)).thenReturn(agentInfoDao);
-
-        HeapDumperCommand impl = mock(HeapDumperCommand.class);
-        DumpHeapCommand command = new DumpHeapCommand(osgi, impl);
-
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-
-        SimpleArguments args = new SimpleArguments();
-
-        try {
-            command.run(factory.createContext(args));
-            assertTrue("should not reach here", false);
-        } catch (CommandException ce) {
-            assertEquals("a hostId is required", ce.getMessage());
-        }
-    }
-
-    @Test
-    public void verifyFailsIfAgentDaoIsNotAvailable() {
-        OSGIUtils osgi = mock(OSGIUtils.class);
-
-        HeapDumperCommand impl = mock(HeapDumperCommand.class);
-        DumpHeapCommand command = new DumpHeapCommand(osgi, impl);
-
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("hostId", "foo");
-        args.addArgument("vmId", "0");
-
-        try {
-            command.run(factory.createContext(args));
-            assertTrue("should not reach here", false);
-        } catch (CommandException ce) {
-            assertEquals("Unable to access agent information", ce.getMessage());
-        }
-    }
-
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/cli/FindObjectsCommandTest.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,225 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.isA;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.Arrays;
-
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.Options;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import com.redhat.thermostat.client.heap.cli.FindObjectsCommand;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.SimpleArguments;
-import com.redhat.thermostat.common.dao.HeapDAO;
-import com.redhat.thermostat.common.heap.HeapDump;
-import com.redhat.thermostat.common.model.HeapInfo;
-import com.redhat.thermostat.common.utils.OSGIUtils;
-import com.redhat.thermostat.test.TestCommandContextFactory;
-import com.sun.tools.hat.internal.model.JavaClass;
-import com.sun.tools.hat.internal.model.JavaHeapObject;
-
-public class FindObjectsCommandTest {
-
-    private static final String HEAP_ID = "TEST_HEAP_ID";
-
-    private FindObjectsCommand cmd;
-
-    private HeapDump heapDump;
-
-    private HeapDAO dao;
-
-    @Before
-    public void setUp() {
-        setupHeapDump();
-
-        setupDAO();
-
-        OSGIUtils serviceProvider = mock(OSGIUtils.class);
-        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(dao);
-
-        cmd = new FindObjectsCommand(serviceProvider);
-
-    }
-
-    private void setupHeapDump() {
-        heapDump = mock(HeapDump.class);
-        JavaClass fooCls = mock(JavaClass.class);
-        when(fooCls.getName()).thenReturn("FooType");
-        JavaHeapObject fooObj = mock(JavaHeapObject.class);
-        when(fooObj.getIdString()).thenReturn("123");
-        when(fooObj.getClazz()).thenReturn(fooCls);
-        JavaClass barCls = mock(JavaClass.class);
-        when(barCls.getName()).thenReturn("BarType");
-        JavaHeapObject barObj = mock(JavaHeapObject.class);
-        when(barObj.getIdString()).thenReturn("456");
-        when(barObj.getClazz()).thenReturn(barCls);
-        JavaClass bazCls = mock(JavaClass.class);
-        when(bazCls.getName()).thenReturn("BazType");
-        JavaHeapObject bazObj = mock(JavaHeapObject.class);
-        when(bazObj.getIdString()).thenReturn("789");
-        when(bazObj.getClazz()).thenReturn(bazCls);
-
-        when(heapDump.searchObjects("fluff", 10)).thenReturn(Arrays.asList("foo", "bar", "baz"));
-        when(heapDump.searchObjects("fluff", 2)).thenReturn(Arrays.asList("foo", "bar"));
-        when(heapDump.findObject("foo")).thenReturn(fooObj);
-        when(heapDump.findObject("bar")).thenReturn(barObj);
-        when(heapDump.findObject("baz")).thenReturn(bazObj);
-    }
-
-    private void setupDAO() {
-        HeapInfo heapInfo = mock(HeapInfo.class);
-
-        dao = mock(HeapDAO.class);
-        when(dao.getHeapInfo(HEAP_ID)).thenReturn(heapInfo);
-        when(dao.getHeapDump(heapInfo)).thenReturn(heapDump);
-    }
-
-    @Test
-    public void testName() {
-        assertEquals("find-objects", cmd.getName());
-    }
-
-    @Test
-    public void testDescAndUsage() {
-        assertNotNull(cmd.getDescription());
-        assertNotNull(cmd.getUsage());
-    }
-
-    @Ignore
-    @Test
-    public void testOptions() {
-        Options options = cmd.getOptions();
-        assertEquals(2, options.getOptions().size());
-
-        assertTrue(options.hasOption("heapId"));
-        Option heapOption = options.getOption("heapId");
-        assertEquals("the ID of the heapdump to analyze", heapOption.getDescription());
-        assertTrue(heapOption.isRequired());
-        assertTrue(heapOption.hasArg());
-
-        assertTrue(options.hasOption("limit"));
-        Option limitOption = options.getOption("limit");
-        assertEquals("limit search to top N results, defaults to 10", limitOption.getDescription());
-        assertFalse(limitOption.isRequired());
-        assertTrue(limitOption.hasArg());
-    }
-
-    @Test
-    public void testStorageRequired() {
-        assertTrue(cmd.isStorageRequired());
-    }
-
-    @Test
-    public void testSimpleSearch() throws CommandException {
-
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("heapId", HEAP_ID);
-        args.addNonOptionArgument("fluff");
-
-        cmd.run(factory.createContext(args));
-
-        String expected = "ID  TYPE\n" +
-                          "123 FooType\n" +
-                          "456 BarType\n" +
-                          "789 BazType\n";
-
-        assertEquals(expected, factory.getOutput());
-
-    }
-
-    @Test
-    public void testSearchWithLimit() throws CommandException {
-
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("heapId", HEAP_ID);
-        args.addArgument("limit", "2");
-        args.addNonOptionArgument("fluff");
-
-        cmd.run(factory.createContext(args));
-
-        String expected = "ID  TYPE\n" +
-                          "123 FooType\n" +
-                          "456 BarType\n";
-
-        assertEquals(expected, factory.getOutput());
-
-    }
-
-    @Test(expected=CommandException.class)
-    public void testSearchWithInvalidLimit() throws CommandException {
-
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("heapId", HEAP_ID);
-        args.addArgument("limit", "urgs");
-        args.addNonOptionArgument("fluff");
-
-        cmd.run(factory.createContext(args));
-
-
-    }
-
-    @Test
-    public void testSearchWithBadHeapId() throws CommandException {
-        final String INVALID_HEAP_ID = "foobarbaz";
-
-        HeapDAO dao = mock(HeapDAO.class);
-        when(dao.getHeapInfo(INVALID_HEAP_ID)).thenReturn(null);
-        when(dao.getHeapDump(isA(HeapInfo.class))).thenReturn(null);
-
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("heapId", INVALID_HEAP_ID);
-
-        cmd.run(factory.createContext(args));
-
-        assertEquals("Heap ID not found: " + INVALID_HEAP_ID + "\n", factory.getOutput());
-    }
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/cli/FindRootCommandTest.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,345 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.same;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.Collection;
-import java.util.Enumeration;
-
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.Options;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.mockito.stubbing.OngoingStubbing;
-
-import com.redhat.thermostat.client.heap.cli.ObjectNotFoundException;
-import com.redhat.thermostat.client.heap.cli.FindRootCommand;
-import com.redhat.thermostat.client.heap.cli.HeapNotFoundException;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.SimpleArguments;
-import com.redhat.thermostat.common.dao.HeapDAO;
-import com.redhat.thermostat.common.heap.HeapDump;
-import com.redhat.thermostat.common.model.HeapInfo;
-import com.redhat.thermostat.common.utils.OSGIUtils;
-import com.redhat.thermostat.test.TestCommandContextFactory;
-import com.sun.tools.hat.internal.model.JavaClass;
-import com.sun.tools.hat.internal.model.JavaHeapObject;
-import com.sun.tools.hat.internal.model.Root;
-import com.sun.tools.hat.internal.model.Snapshot;
-
-public class FindRootCommandTest {
-
-    private static final String HEAP_ID = "TEST_HEAP_ID";
-
-    private FindRootCommand cmd;
-
-    private JavaHeapObject fooObj;
-
-    private JavaHeapObject barObj;
-
-    private JavaHeapObject bazObj;
-
-    private JavaHeapObject bumObj;
-
-    private JavaHeapObject beeObj;
-
-    private HeapDAO dao;
-
-    @Before
-    public void setUp() {
-        HeapDump heapDump = setupHeapDump();
-        setupDAO(heapDump);
-
-        OSGIUtils serviceProvider = mock(OSGIUtils.class);
-        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(dao);
-
-        cmd = new FindRootCommand(serviceProvider);
-    }
-
-    @After
-    public void tearDown() {
-        fooObj = null;
-        barObj = null;
-        bazObj = null;
-        bumObj = null;
-        beeObj = null;
-        cmd = null;
-    }
-
-    @SuppressWarnings("rawtypes")
-    private HeapDump setupHeapDump() {
-        fooObj = createMockObject("FooType", "123");
-        barObj = createMockObject("BarType", "456");
-        bazObj = createMockObject("BazType", "789");
-        bumObj = createMockObject("BumType", "987");
-        beeObj = createMockObject("BeeType", "654");
-        // Setup referrer network.
-        Enumeration fooRefs = createReferrerEnum(barObj);
-        // The exception is thrown in circle-tests when we visit the foo object again.
-        when(fooObj.getReferers()).thenReturn(fooRefs).thenThrow(new RuntimeException());
-        Enumeration barRefs = createReferrerEnum(bazObj, bumObj);
-        when(barObj.getReferers()).thenReturn(barRefs);
-        Enumeration bumRefs = createReferrerEnum(beeObj);
-        when(bumObj.getReferers()).thenReturn(bumRefs);
-        Enumeration emptyRefs = createReferrerEnum();
-        when(bazObj.getReferers()).thenReturn(emptyRefs);
-        when(beeObj.getReferers()).thenReturn(emptyRefs);
-
-        // Setup referrer descriptions.
-        when(barObj.describeReferenceTo(same(fooObj), any(Snapshot.class))).thenReturn("field foo");
-        when(bazObj.describeReferenceTo(same(barObj), any(Snapshot.class))).thenReturn("field bar");
-        when(bumObj.describeReferenceTo(same(barObj), any(Snapshot.class))).thenReturn("field bar");
-        when(beeObj.describeReferenceTo(same(bumObj), any(Snapshot.class))).thenReturn("field bum");
-
-        // Setup roots.
-        Root bazRoot = mock(Root.class);
-        when(bazRoot.getDescription()).thenReturn("baz root");
-        when(bazObj.getRoot()).thenReturn(bazRoot);
-        Root beeRoot = mock(Root.class);
-        when(beeRoot.getDescription()).thenReturn("bee root");
-        when(beeObj.getRoot()).thenReturn(beeRoot);
-
-        // Setup heap dump.
-        HeapDump heapDump = mock(HeapDump.class);
-        when(heapDump.findObject("foo")).thenReturn(fooObj);
-        return heapDump;
-    }
-
-    private void setupDAO(HeapDump heapDump) {
-
-        HeapInfo heapInfo = mock(HeapInfo.class);
-
-        dao = mock(HeapDAO.class);
-        when(dao.getHeapInfo(HEAP_ID)).thenReturn(heapInfo);
-        when(dao.getHeapDump(heapInfo)).thenReturn(heapDump);
-
-    }
-
-    private JavaHeapObject createMockObject(String className, String id) {
-        JavaClass cls = mock(JavaClass.class);
-        when(cls.getName()).thenReturn(className);
-        JavaHeapObject obj = mock(JavaHeapObject.class);
-        when(obj.getIdString()).thenReturn(id);
-        when(obj.getClazz()).thenReturn(cls);
-        return obj;
-    }
-
-    @SuppressWarnings("rawtypes")
-    private Enumeration createReferrerEnum(JavaHeapObject... objs) {
-        Enumeration refs = mock(Enumeration.class);
-        OngoingStubbing<Boolean> hasMoreElements = when(refs.hasMoreElements());
-        for (int i = 0; i < objs.length; i++) {
-            hasMoreElements = hasMoreElements.thenReturn(true);
-        }
-        hasMoreElements.thenReturn(false);
-        OngoingStubbing<Object> nextElement = when(refs.nextElement());
-        for (JavaHeapObject obj : objs) {
-            nextElement = nextElement.thenReturn(obj);
-        }
-        nextElement.thenReturn(null);
-        return refs;
-    }
-
-    @Test
-    public void testName() {
-        assertEquals("find-root", cmd.getName());
-    }
-
-    @Test
-    public void testDescAndUsage() {
-        assertNotNull(cmd.getDescription());
-        assertNotNull(cmd.getUsage());
-    }
-
-    @Ignore
-    @Test
-    public void testOptions() {
-        String heapIdOption = "heapId";
-        String objectIdOption = "objectId";
-        String allOption = "all";
-        Options options = cmd.getOptions();
-        @SuppressWarnings("unchecked")
-        Collection<Options> theOptions = options.getOptions();
-        assertEquals(3, theOptions.size());
-
-        assertTrue(options.hasOption(heapIdOption));
-        Option heapOption = options.getOption(heapIdOption);
-        assertEquals("the ID of the heapdump to analyze", heapOption.getDescription());
-        assertTrue(heapOption.isRequired());
-        assertTrue(heapOption.hasArg());
-
-        assertTrue(options.hasOption(objectIdOption));
-        Option objectOption = options.getOption(objectIdOption);
-        assertEquals("the ID of the object to query", objectOption.getDescription());
-        assertTrue(heapOption.isRequired());
-        assertTrue(heapOption.hasArg());
-
-        assertTrue(options.hasOption(allOption));
-        Option all = options.getOption(allOption);
-        assertEquals("finds all paths to GC roots", all.getDescription());
-        assertFalse(all.isRequired());
-        assertFalse(all.hasArg());
-    }
-
-    @Test
-    public void testStorageRequired() {
-        assertTrue(cmd.isStorageRequired());
-    }
-
-    @Test
-    public void testSimpleAllRootsSearch() throws CommandException {
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("heapId", HEAP_ID);
-        args.addArgument("objectId", "foo");
-        args.addArgument("all", "true");
-
-        cmd.run(factory.createContext(args));
-
-        String expected = "baz root -> BazType@789\n" +
-                          "\u2514field bar in BazType@789 -> BarType@456\n" +
-                          " \u2514field foo in BarType@456 -> FooType@123\n" +
-                          "\n" +
-                          "bee root -> BeeType@654\n" +
-                          "\u2514field bum in BeeType@654 -> BumType@987\n" +
-                          " \u2514field bar in BumType@987 -> BarType@456\n" +
-                          "  \u2514field foo in BarType@456 -> FooType@123\n" +
-                          "\n";
-
-        assertEquals(expected, factory.getOutput());
-
-    }
-
-    @Test
-    public void testSimpleRootSearch() throws CommandException {
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("heapId", HEAP_ID);
-        args.addArgument("objectId", "foo");
-
-        cmd.run(factory.createContext(args));
-
-        String expected = "baz root -> BazType@789\n" +
-                          "\u2514field bar in BazType@789 -> BarType@456\n" +
-                          " \u2514field foo in BarType@456 -> FooType@123\n" +
-                          "\n";
-
-        assertEquals(expected, factory.getOutput());
-
-    }
-
-    @Test
-    public void testSearchWithoutRoot() throws CommandException {
-        when(bazObj.getRoot()).thenReturn(null);
-        when(beeObj.getRoot()).thenReturn(null);
-
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("heapId", HEAP_ID);
-        args.addArgument("objectId", "foo");
-
-        cmd.run(factory.createContext(args));
-
-        String expected = "No root found for: FooType@123\n";
-
-        assertEquals(expected, factory.getOutput());
-
-    }
-
-    @Test
-    public void testSearchWithoutRootWithCircle() throws CommandException {
-        when(bazObj.getRoot()).thenReturn(null);
-        @SuppressWarnings("rawtypes")
-        Enumeration bazReferrers = createReferrerEnum(fooObj);
-        when(bazObj.getReferers()).thenReturn(bazReferrers);
-        when(beeObj.getRoot()).thenReturn(null);
-        @SuppressWarnings("rawtypes")
-        Enumeration beeReferrers = createReferrerEnum(fooObj);
-        when(beeObj.getReferers()).thenReturn(beeReferrers);
-
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("heapId", HEAP_ID);
-        args.addArgument("objectId", "foo");
-
-        cmd.run(factory.createContext(args));
-
-        String expected = "No root found for: FooType@123\n";
-
-        assertEquals(expected, factory.getOutput());
-
-    }
-
-    public void testHeapNotFound() throws CommandException {
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("heapId", "fluff");
-        args.addArgument("objectId", "foo");
-
-        try {
-            cmd.run(factory.createContext(args));
-            fail();
-        } catch (HeapNotFoundException ex) {
-           assertEquals("Heap ID not found: fluff", ex.getMessage());
-        }
-    }
-
-    public void testObjectNotFound() throws CommandException {
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("heapId", HEAP_ID);
-        args.addArgument("objectId", "fluff");
-
-        try {
-            cmd.run(factory.createContext(args));
-            fail();
-        } catch (ObjectNotFoundException ex) {
-            assertEquals("Object not found: fluff", ex.getMessage());
-         }
-    }
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/cli/HeapDumperCommandTest.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,138 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.net.InetSocketAddress;
-import java.util.Collection;
-
-import junit.framework.AssertionFailedError;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.client.command.RequestQueue;
-import com.redhat.thermostat.common.appctx.ApplicationContextUtil;
-import com.redhat.thermostat.common.command.Request;
-import com.redhat.thermostat.common.command.Request.RequestType;
-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.common.dao.AgentInfoDAO;
-import com.redhat.thermostat.common.dao.HostRef;
-import com.redhat.thermostat.common.dao.VmRef;
-import com.redhat.thermostat.common.model.AgentInformation;
-import com.redhat.thermostat.common.utils.OSGIUtils;
-
-public class HeapDumperCommandTest {
-
-    private AgentInfoDAO agentInfoDao;
-    private HeapDumperCommand cmd;
-    private VmRef vmRef;
-    private RequestQueue reqQueue;
-    private Runnable heapDumpCompleteAction;
-
-    @Before
-    public void setUp() {
-        ApplicationContextUtil.resetApplicationContext();
-
-        reqQueue = mock(RequestQueue.class);
-        OSGIUtils osgiUtils = mock(OSGIUtils.class);
-        when(osgiUtils.getService(RequestQueue.class)).thenReturn(reqQueue);
-        OSGIUtils.setInstance(osgiUtils);
-
-        HostRef host = mock(HostRef.class);
-
-        AgentInformation agentInfo = mock(AgentInformation.class);
-        when(agentInfo.getConfigListenAddress()).thenReturn("test:123");
-
-        agentInfoDao = mock(AgentInfoDAO.class);
-        when(agentInfoDao.getAgentInformation(host)).thenReturn(agentInfo);
-
-        cmd = new HeapDumperCommand();
-        vmRef = mock(VmRef.class);
-        when(vmRef.getIdString()).thenReturn("123");
-        when(vmRef.getAgent()).thenReturn(host);
-        heapDumpCompleteAction = mock(Runnable.class);
-
-    }
-
-    @After
-    public void tearDown() {
-        heapDumpCompleteAction = null;
-        vmRef = null;
-        cmd = null;
-        reqQueue = null;
-        ApplicationContextUtil.resetApplicationContext();
-    }
-
-    @Test
-	public void testExecute() {
-
-        cmd.execute(agentInfoDao, vmRef, heapDumpCompleteAction);
-
-		ArgumentCaptor<Request> reqArg = ArgumentCaptor.forClass(Request.class);
-		verify(reqQueue).putRequest(reqArg.capture());
-		Request req = reqArg.getValue();
-		assertEquals("com.redhat.thermostat.agent.heapdumper.internal.HeapDumpReceiver", req.getReceiver());
-		verifyClassExists(req.getReceiver());
-		assertEquals(RequestType.RESPONSE_EXPECTED, req.getType());
-		assertEquals("123", req.getParameter("vmId"));
-		assertEquals(new InetSocketAddress("test", 123), req.getTarget());
-
-		Collection<RequestResponseListener> ls = req.getListeners();
-		for (RequestResponseListener l : ls) {
-		    l.fireComplete(req, new Response(ResponseType.OK));
-		}
-		verify(heapDumpCompleteAction).run();
-    }
-
-    private void verifyClassExists(String receiver) {
-        try {
-            Class.forName(receiver);
-        } catch (ClassNotFoundException e) {
-            throw new AssertionFailedError();
-        }
-    }
-
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/cli/ListHeapDumpsCommandTest.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,278 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Matchers.isA;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.TimeZone;
-
-import org.apache.commons.cli.Options;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.appctx.ApplicationContextUtil;
-import com.redhat.thermostat.common.cli.Command;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.SimpleArguments;
-import com.redhat.thermostat.common.dao.HeapDAO;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
-import com.redhat.thermostat.common.dao.HostRef;
-import com.redhat.thermostat.common.dao.VmInfoDAO;
-import com.redhat.thermostat.common.dao.VmRef;
-import com.redhat.thermostat.common.model.HeapInfo;
-import com.redhat.thermostat.common.utils.OSGIUtils;
-import com.redhat.thermostat.test.TestCommandContextFactory;
-
-public class ListHeapDumpsCommandTest {
-
-    private static TimeZone defaultTimezone;
-
-    @BeforeClass
-    public static void setUpClass() {
-        defaultTimezone = TimeZone.getDefault();
-        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
-    }
-
-    @AfterClass
-    public static void tearDownClass() {
-        TimeZone.setDefault(defaultTimezone);
-    }
-
-    @Before
-    public void setUp() {
-        ApplicationContextUtil.resetApplicationContext();
-    }
-
-    @After
-    public void tearDown() {
-        ApplicationContextUtil.resetApplicationContext();
-
-    }
-
-    @Test
-    public void verifyBasics() {
-        Command command = new ListHeapDumpsCommand();
-        assertEquals("list-heap-dumps", command.getName());
-        assertNotNull(command.getDescription());
-        assertNotNull(command.getUsage());
-    }
-
-    @Ignore
-    @Test
-    public void verifyOptions() {
-        Command command = new ListHeapDumpsCommand();
-        Options options = command.getOptions();
-        assertNotNull(options);
-        assertEquals(2, options.getOptions().size());
-    }
-
-    @Test
-    public void verifyFailsWithoutHostDao() throws Exception {
-        OSGIUtils serviceProvider = mock(OSGIUtils.class);
-
-        Command command = new ListHeapDumpsCommand(serviceProvider);
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-        try {
-            command.run(factory.createContext(new SimpleArguments()));
-        } catch (CommandException hostDaoNotAvailableException) {
-            assertEquals("Unable to access host information (HostInfoDAO unavailable)",
-                    hostDaoNotAvailableException.getMessage());
-        }
-    }
-
-    @Test
-    public void verifyWorksWithoutAnyInformation() throws CommandException {
-        HostInfoDAO hostInfo = mock(HostInfoDAO.class);
-        VmInfoDAO vmInfo = mock(VmInfoDAO.class);
-        HeapDAO heapDao = mock(HeapDAO.class);
-
-        OSGIUtils serviceProvider = mock(OSGIUtils.class);
-        when(serviceProvider.getServiceAllowNull(HostInfoDAO.class)).thenReturn(hostInfo);
-        when(serviceProvider.getServiceAllowNull(VmInfoDAO.class)).thenReturn(vmInfo);
-        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(heapDao);
-
-        Command command = new ListHeapDumpsCommand(serviceProvider);
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-        command.run(factory.createContext(new SimpleArguments()));
-        assertEquals("HOST ID VM ID HEAP ID TIMESTAMP\n", factory.getOutput());
-    }
-
-    @Test
-    public void verifyWorks() throws CommandException {
-        HostRef hostRef = mock(HostRef.class);
-        when(hostRef.getStringID()).thenReturn("host-id");
-        VmRef vmRef = mock(VmRef.class);
-        when(vmRef.getStringID()).thenReturn("1");
-
-        HeapInfo heapInfo = mock(HeapInfo.class);
-        Calendar timestamp = Calendar.getInstance();
-        timestamp.set(2012, 5, 7, 15, 32, 0);
-        when(heapInfo.getTimeStamp()).thenReturn(timestamp.getTimeInMillis());
-        when(heapInfo.getHeapId()).thenReturn("0001");
-
-        HeapDAO heapDao = mock(HeapDAO.class);
-
-        VmInfoDAO vmInfo = mock(VmInfoDAO.class);
-        when(vmInfo.getVMs(hostRef)).thenReturn(Arrays.asList(vmRef));
-
-        HostInfoDAO hostInfo = mock(HostInfoDAO.class);
-        when(hostInfo.getHosts()).thenReturn(Arrays.asList(hostRef));
-
-        when(heapDao.getAllHeapInfo(vmRef)).thenReturn(Arrays.asList(heapInfo));
-
-        OSGIUtils serviceProvider = mock(OSGIUtils.class);
-        when(serviceProvider.getServiceAllowNull(HostInfoDAO.class)).thenReturn(hostInfo);
-        when(serviceProvider.getServiceAllowNull(VmInfoDAO.class)).thenReturn(vmInfo);
-        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(heapDao);
-
-        Command command = new ListHeapDumpsCommand(serviceProvider);
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-        command.run(factory.createContext(new SimpleArguments()));
-
-        String expected = "HOST ID VM ID HEAP ID TIMESTAMP\n" +
-                          "host-id 1     0001    Thu Jun 07 15:32:00 UTC 2012\n";
-
-        assertEquals(expected, factory.getOutput());
-    }
-
-    @Test
-    public void verifyWorksWithFilterOnHost() throws CommandException {
-        HostRef hostRef1 = mock(HostRef.class);
-        when(hostRef1.getStringID()).thenReturn("host1");
-        VmRef vmRef1 = mock(VmRef.class);
-        when(vmRef1.getStringID()).thenReturn("1");
-
-        HostRef hostRef2 = mock(HostRef.class);
-        when(hostRef2.getStringID()).thenReturn("host2");
-        VmRef vmRef2 = mock(VmRef.class);
-        when(vmRef2.getStringID()).thenReturn("2");
-
-        HeapInfo heapInfo = mock(HeapInfo.class);
-        Calendar timestamp = Calendar.getInstance();
-        timestamp.set(2012, 5, 7, 15, 32, 0);
-        when(heapInfo.getTimeStamp()).thenReturn(timestamp.getTimeInMillis());
-        when(heapInfo.getHeapId()).thenReturn("0001");
-
-        HeapDAO heapDao = mock(HeapDAO.class);
-
-        VmInfoDAO vmInfo = mock(VmInfoDAO.class);
-        when(vmInfo.getVMs(isA(HostRef.class))).thenReturn(Arrays.asList(vmRef1)).thenReturn(Arrays.asList(vmRef2));
-
-        HostInfoDAO hostInfo = mock(HostInfoDAO.class);
-        when(hostInfo.getHosts()).thenReturn(Arrays.asList(hostRef1, hostRef2));
-
-        when(heapDao.getAllHeapInfo(vmRef1)).thenReturn(Arrays.asList(heapInfo));
-        when(heapDao.getAllHeapInfo(vmRef2)).thenReturn(Arrays.asList(heapInfo));
-
-        OSGIUtils serviceProvider = mock(OSGIUtils.class);
-        when(serviceProvider.getServiceAllowNull(HostInfoDAO.class)).thenReturn(hostInfo);
-        when(serviceProvider.getServiceAllowNull(VmInfoDAO.class)).thenReturn(vmInfo);
-        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(heapDao);
-
-        Command command = new ListHeapDumpsCommand(serviceProvider);
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("hostId", "host1");
-
-        command.run(factory.createContext(args));
-
-        String expected = "HOST ID VM ID HEAP ID TIMESTAMP\n" +
-                          "host1   1     0001    Thu Jun 07 15:32:00 UTC 2012\n";
-
-        assertEquals(expected, factory.getOutput());
-    }
-
-    @Test
-    public void verifyWorksWithFilterOnHostAndVM() throws CommandException {
-        HostRef hostRef1 = mock(HostRef.class);
-        when(hostRef1.getStringID()).thenReturn("host1");
-        when(hostRef1.getAgentId()).thenReturn("host1");
-        VmRef vmRef1 = mock(VmRef.class);
-        when(vmRef1.getStringID()).thenReturn("1");
-
-        HostRef hostRef2 = mock(HostRef.class);
-        when(hostRef2.getStringID()).thenReturn("host2");
-        VmRef vmRef2 = mock(VmRef.class);
-        when(vmRef2.getStringID()).thenReturn("2");
-
-        HeapInfo heapInfo = mock(HeapInfo.class);
-        Calendar timestamp = Calendar.getInstance();
-        timestamp.set(2012, 5, 7, 15, 32, 0);
-        when(heapInfo.getTimeStamp()).thenReturn(timestamp.getTimeInMillis());
-        when(heapInfo.getHeapDumpId()).thenReturn("0001");
-
-        HeapDAO heapDao = mock(HeapDAO.class);
-
-        VmInfoDAO vmInfo = mock(VmInfoDAO.class);
-        when(vmInfo.getVMs(isA(HostRef.class))).thenReturn(Arrays.asList(vmRef1)).thenReturn(Arrays.asList(vmRef2));
-
-        HostInfoDAO hostInfo = mock(HostInfoDAO.class);
-        when(hostInfo.getHosts()).thenReturn(Arrays.asList(hostRef1, hostRef2));
-
-        when(heapDao.getAllHeapInfo(vmRef1)).thenReturn(Arrays.asList(heapInfo));
-        when(heapDao.getAllHeapInfo(vmRef2)).thenReturn(Arrays.asList(heapInfo));
-
-        OSGIUtils serviceProvider = mock(OSGIUtils.class);
-        when(serviceProvider.getServiceAllowNull(HostInfoDAO.class)).thenReturn(hostInfo);
-        when(serviceProvider.getServiceAllowNull(VmInfoDAO.class)).thenReturn(vmInfo);
-        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(heapDao);
-
-        Command command = new ListHeapDumpsCommand(serviceProvider);
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("hostId", "host1");
-        args.addArgument("vmId", "1"); // vm id must be an int for the arg parser to work
-
-        command.run(factory.createContext(args));
-
-        String expected = "HOST ID VM ID HEAP ID TIMESTAMP\n";
-
-        assertEquals(expected, factory.getOutput());
-    }
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/cli/ObjectInfoCommandTest.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,240 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.same;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.Enumeration;
-
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.Options;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-import com.redhat.thermostat.client.heap.cli.HeapNotFoundException;
-import com.redhat.thermostat.client.heap.cli.ObjectInfoCommand;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.SimpleArguments;
-import com.redhat.thermostat.common.dao.HeapDAO;
-import com.redhat.thermostat.common.heap.HeapDump;
-import com.redhat.thermostat.common.model.HeapInfo;
-import com.redhat.thermostat.common.utils.OSGIUtils;
-import com.redhat.thermostat.test.TestCommandContextFactory;
-import com.sun.tools.hat.internal.model.JavaClass;
-import com.sun.tools.hat.internal.model.JavaHeapObject;
-import com.sun.tools.hat.internal.model.JavaHeapObjectVisitor;
-import com.sun.tools.hat.internal.model.Snapshot;
-
-public class ObjectInfoCommandTest {
-
-    private static final String HEAP_ID = "TEST_HEAP_ID";
-
-    private ObjectInfoCommand cmd;
-    private HeapDump heapDump;
-
-    private HeapDAO dao;
-
-    @Before
-    public void setUp() {
-        setupHeapDump();
-        setupDAO();
-
-        OSGIUtils serviceProvider = mock(OSGIUtils.class);
-        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(dao);
-
-        cmd = new ObjectInfoCommand(serviceProvider);
-    }
-
-    @After
-    public void tearDown() {
-        heapDump = null;
-        cmd = null;
-    }
-
-    private void setupHeapDump() {
-        heapDump = mock(HeapDump.class);
-        JavaClass barCls = mock(JavaClass.class);
-        when(barCls.getName()).thenReturn("BarType");
-        final JavaHeapObject barObj = mock(JavaHeapObject.class);
-        when(barObj.getIdString()).thenReturn("456");
-        when(barObj.getClazz()).thenReturn(barCls);
-        JavaClass bazCls = mock(JavaClass.class);
-        when(bazCls.getName()).thenReturn("BazType");
-        final JavaHeapObject bazObj = mock(JavaHeapObject.class);
-        when(bazObj.getIdString()).thenReturn("789");
-        when(bazObj.getClazz()).thenReturn(bazCls);
-
-        JavaClass fooCls = mock(JavaClass.class);
-        when(fooCls.getName()).thenReturn("FooType");
-        JavaHeapObject fooObj = mock(JavaHeapObject.class);
-        when(fooObj.getIdString()).thenReturn("123");
-        when(fooObj.getClazz()).thenReturn(fooCls);
-        doAnswer(new Answer<Void>() {
-
-            @Override
-            public Void answer(InvocationOnMock invocation) throws Throwable {
-                JavaHeapObjectVisitor v = (JavaHeapObjectVisitor) invocation.getArguments()[0];
-                v.visit(barObj);
-                v.visit(bazObj);
-                return null;
-            }
-            
-        }).when(fooObj).visitReferencedObjects(any(JavaHeapObjectVisitor.class));
-        when(fooObj.describeReferenceTo(same(barObj), any(Snapshot.class))).thenReturn("field bar");
-        when(fooObj.describeReferenceTo(same(bazObj), any(Snapshot.class))).thenReturn("field baz");
-        @SuppressWarnings("rawtypes")
-        Enumeration referrerEnum = mock(Enumeration.class);
-        when(referrerEnum.hasMoreElements()).thenReturn(true).thenReturn(true).thenReturn(false);
-        when(referrerEnum.nextElement()).thenReturn(barObj).thenReturn(bazObj);
-        when(fooObj.getReferers()).thenReturn(referrerEnum);
-        when(barObj.describeReferenceTo(same(fooObj), any(Snapshot.class))).thenReturn("field foo");
-        when(bazObj.describeReferenceTo(same(fooObj), any(Snapshot.class))).thenReturn("field foo");
-        when(fooObj.isNew()).thenReturn(true);
-        when(fooObj.isHeapAllocated()).thenReturn(false);
-        when(fooObj.getSize()).thenReturn(128);
-        when(heapDump.findObject("foo")).thenReturn(fooObj);
-    }
-
-    private void setupDAO() {
-
-        HeapInfo heapInfo = mock(HeapInfo.class);
-
-        dao = mock(HeapDAO.class);
-        when(dao.getHeapInfo(HEAP_ID)).thenReturn(heapInfo);
-        when(dao.getHeapDump(heapInfo)).thenReturn(heapDump);
-    }
-
-    @Test
-    public void testName() {
-        assertEquals("object-info", cmd.getName());
-    }
-
-    @Test
-    public void testDescAndUsage() {
-        assertNotNull(cmd.getDescription());
-        assertNotNull(cmd.getUsage());
-    }
-
-    @Ignore
-    @Test
-    public void testOptions() {
-        Options options = cmd.getOptions();
-        assertEquals(2, options.getOptions().size());
-
-        assertTrue(options.hasOption("heapId"));
-        Option heapOption = options.getOption("heapId");
-        assertEquals("the ID of the heapdump to analyze", heapOption.getDescription());
-        assertTrue(heapOption.isRequired());
-        assertTrue(heapOption.hasArg());
-
-        assertTrue(options.hasOption("objectId"));
-        Option objOption = options.getOption("objectId");
-        assertEquals("the ID of the object to query", objOption.getDescription());
-        assertTrue(objOption.isRequired());
-        assertTrue(objOption.hasArg());
-    }
-
-    @Test
-    public void testStorageRequired() {
-        assertTrue(cmd.isStorageRequired());
-    }
-
-    @Test
-    public void testSimpleObject() throws CommandException {
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("heapId", HEAP_ID);
-        args.addArgument("objectId", "foo");
-
-        cmd.run(factory.createContext(args));
-
-        String expected = "Object ID:      123\n" +
-                          "Type:           FooType\n" +
-                          "Size:           128 bytes\n" +
-                          "Heap allocated: false\n" +
-                          "References:     \n" +
-                          "                [field bar] -> BarType@456\n" +
-                          "                [field baz] -> BazType@789\n" +
-                          "Referrers:      \n" +
-                          "                BarType@456 -> [field foo]\n" +
-                          "                BazType@789 -> [field foo]\n";
-
-        assertEquals(expected, factory.getOutput());
-
-    }
-
-    @Test(expected=CommandException.class)
-    public void testHeapNotFound() throws CommandException {
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("heapId", "fluff");
-        args.addArgument("objectId", "foo");
-
-        try {
-            cmd.run(factory.createContext(args));
-            fail();
-        } catch (HeapNotFoundException ex) {
-            assertEquals("Heap not found: fluff", ex.getMessage());
-        }
-    }
-
-    public void testObjectNotFound() throws CommandException {
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("heapId", HEAP_ID);
-        args.addArgument("objectId", "fluff");
-
-        try {
-            cmd.run(factory.createContext(args));
-            fail();
-        } catch (ObjectNotFoundException ex) {
-            assertEquals("Object not found: fluff", ex.getMessage());
-        }
-    }
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/cli/SaveHeapDumpToFileCommandTest.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.FileNotFoundException;
-import java.nio.charset.Charset;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.client.heap.cli.SaveHeapDumpToFileCommand;
-import com.redhat.thermostat.client.heap.cli.SaveHeapDumpToFileCommand.FileStreamCreator;
-import com.redhat.thermostat.common.cli.Command;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.SimpleArguments;
-import com.redhat.thermostat.common.dao.HeapDAO;
-import com.redhat.thermostat.common.model.HeapInfo;
-import com.redhat.thermostat.common.utils.OSGIUtils;
-import com.redhat.thermostat.test.TestCommandContextFactory;
-
-public class SaveHeapDumpToFileCommandTest {
-
-    @Test
-    public void verifyBasicInformation() {
-        Command command = new SaveHeapDumpToFileCommand();
-        assertEquals("save-heap-dump-to-file", command.getName());
-        assertNotNull(command.getDescription());
-        assertNotNull(command.getUsage());
-    }
-
-    @Test (expected=CommandException.class)
-    public void verifyMissingHeapIdThrowsException() throws CommandException {
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("hostId", "host-id");
-        args.addArgument("vmId", "1");
-        args.addArgument("file", "heap-id-1");
-
-        OSGIUtils serviceProvider = mock(OSGIUtils.class);
-        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(mock(HeapDAO.class));
-
-        Command command = new SaveHeapDumpToFileCommand(serviceProvider, mock(FileStreamCreator.class));
-        command.run(factory.createContext(args));
-    }
-
-    @Test (expected=CommandException.class)
-    public void verifyMissingFileNameThrowsException() throws CommandException {
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("hostId", "host-id");
-        args.addArgument("vmId", "1");
-        args.addArgument("heapId", "heap-id-1");
-
-        OSGIUtils serviceProvider = mock(OSGIUtils.class);
-        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(mock(HeapDAO.class));
-
-        Command command = new SaveHeapDumpToFileCommand(serviceProvider, mock(FileStreamCreator.class));
-        command.run(factory.createContext(args));
-    }
-
-    @Test
-    public void verifyCommandWorks() throws CommandException, FileNotFoundException {
-        final String HEAP_ID = "heap-id-1";
-        final String FILE_NAME = "some-file-name";
-        final String HEAP_CONTENTS = "0xCAFEBABE";
-        final byte[] HEAP_CONTENT_BYTES = HEAP_CONTENTS.getBytes(Charset.forName("UTF-8"));
-
-        ByteArrayOutputStream heapDumpStream = new ByteArrayOutputStream();
-
-        HeapDAO heapDao = mock(HeapDAO.class);
-
-        HeapInfo info = mock(HeapInfo.class);
-        when(heapDao.getHeapInfo(HEAP_ID)).thenReturn(info);
-        when(heapDao.getHeapDumpData(info)).thenReturn(new ByteArrayInputStream(HEAP_CONTENT_BYTES));
-
-        OSGIUtils serviceProvider = mock(OSGIUtils.class);
-        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(heapDao);
-
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("heapId", HEAP_ID);
-        args.addArgument("file", FILE_NAME);
-
-        FileStreamCreator creator = mock(FileStreamCreator.class);
-        when(creator.createOutputStream(FILE_NAME)).thenReturn(heapDumpStream);
-
-        Command command = new SaveHeapDumpToFileCommand(serviceProvider, creator);
-        command.run(factory.createContext(args));
-
-        assertArrayEquals(HEAP_CONTENT_BYTES, heapDumpStream.toByteArray());
-    }
-
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/cli/ShowHeapHistogramCommandTest.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.cli;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.common.cli.Command;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.SimpleArguments;
-import com.redhat.thermostat.common.dao.HeapDAO;
-import com.redhat.thermostat.common.heap.ObjectHistogram;
-import com.redhat.thermostat.common.model.HeapInfo;
-import com.redhat.thermostat.common.utils.OSGIUtils;
-import com.redhat.thermostat.test.TestCommandContextFactory;
-import com.sun.tools.hat.internal.model.JavaClass;
-import com.sun.tools.hat.internal.model.JavaHeapObject;
-
-public class ShowHeapHistogramCommandTest {
-
-    @Test
-    public void verifyBasics() {
-        Command command = new ShowHeapHistogramCommand();
-
-        assertEquals("show-heap-histogram", command.getName());
-        assertNotNull(command.getDescription());
-        assertNotNull(command.getUsage());
-    }
-
-    @Test
-    public void verifyWorks() throws CommandException {
-        ObjectHistogram histo = new ObjectHistogram();
-
-        JavaClass cls1 = mock(JavaClass.class);
-        JavaHeapObject obj1 = mock(JavaHeapObject.class);
-        when(cls1.getName()).thenReturn("class1");
-        when(obj1.getClazz()).thenReturn(cls1);
-        when(obj1.getSize()).thenReturn(5);
-        JavaHeapObject obj2 = mock(JavaHeapObject.class);
-        when(obj2.getClazz()).thenReturn(cls1);
-        when(obj2.getSize()).thenReturn(3);
-        JavaClass cls2 = mock(JavaClass.class);
-        JavaHeapObject obj3 = mock(JavaHeapObject.class);
-        when(cls2.getName()).thenReturn("verylongclassnameclass2");
-        when(obj3.getClazz()).thenReturn(cls2);
-        when(obj3.getSize()).thenReturn(10);
-
-        histo.addThing(obj1);
-        histo.addThing(obj2);
-        histo.addThing(obj3);
-
-        final String HEAP_ID = "heap-id-1";
-
-        HeapDAO heapDao = mock(HeapDAO.class);
-
-        HeapInfo heapInfo = mock(HeapInfo.class);
-        when(heapDao.getHeapInfo(HEAP_ID)).thenReturn(heapInfo);
-        when(heapDao.getHistogram(heapInfo)).thenReturn(histo);
-
-        OSGIUtils serviceProvider = mock(OSGIUtils.class);
-        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(heapDao);
-
-        Command command = new ShowHeapHistogramCommand(serviceProvider);
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("heapId", HEAP_ID);
-
-        command.run(factory.createContext(args));
-
-        assertEquals("class1                  2 8\n" +
-        		     "verylongclassnameclass2 1 10\n", factory.getOutput());
-        verify(serviceProvider).ungetService(HeapDAO.class, heapDao);
-    }
-
-    @Test
-    public void verifyWorkWithBadHeapId() throws CommandException {
-        final String BAD_HEAP_ID = "invalid-heap-id";
-
-        HeapDAO heapDao = mock(HeapDAO.class);
-
-        HeapInfo heapInfo = mock(HeapInfo.class);
-        when(heapDao.getHeapInfo(BAD_HEAP_ID)).thenReturn(null);
-        when(heapDao.getHistogram(any(HeapInfo.class))).thenReturn(null);
-
-        OSGIUtils serviceProvider = mock(OSGIUtils.class);
-        when(serviceProvider.getServiceAllowNull(HeapDAO.class)).thenReturn(heapDao);
-
-        Command command = new ShowHeapHistogramCommand(serviceProvider);
-        TestCommandContextFactory factory = new TestCommandContextFactory();
-
-        SimpleArguments args = new SimpleArguments();
-        args.addArgument("heapId", BAD_HEAP_ID);
-
-        command.run(factory.createContext(args));
-
-        assertEquals("Heap ID not found: " + BAD_HEAP_ID + "\n", factory.getOutput());
-        verify(serviceProvider).ungetService(HeapDAO.class, heapDao);
-    }
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/swing/HeapDetailsSwingTest.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,151 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.swing;
-
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.lang.reflect.InvocationTargetException;
-import java.util.concurrent.Callable;
-
-import javax.swing.JFrame;
-import javax.swing.JPanel;
-
-import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
-
-import org.fest.swing.annotation.GUITest;
-import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
-import org.fest.swing.edt.GuiActionRunner;
-import org.fest.swing.edt.GuiTask;
-import org.fest.swing.fixture.FrameFixture;
-import org.fest.swing.fixture.JTabbedPaneFixture;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import com.redhat.thermostat.swing.EdtHelper;
-
-@RunWith(CacioFESTRunner.class)
-public class HeapDetailsSwingTest {
-
-    private JFrame frame;
-    private FrameFixture frameFixture;
-    private HeapDetailsSwing view;
-
-    @BeforeClass
-    public static void setUpOnce() {
-        FailOnThreadViolationRepaintManager.install();
-    }
-
-    @Before
-    public void setUp() {
-        GuiActionRunner.execute(new GuiTask() {
-            @Override
-            protected void executeInEDT() throws Throwable {
-                view = new HeapDetailsSwing();
-                frame = new JFrame();
-                frame.add(view.getUiComponent());
-
-            }
-        });
-        frameFixture = new FrameFixture(frame);
-    }
-
-    @After
-    public void tearDown() {
-        frameFixture.cleanUp();
-        frameFixture = null;
-    }
-
-    @GUITest
-    @Test
-    public void verifyTabsAdded() throws InvocationTargetException, InterruptedException {
-        frameFixture.show();
-
-        JTabbedPaneFixture tabPane = frameFixture.tabbedPane("tabs");
-        assertNotNull(tabPane);
-
-        HistogramPanel histogramView = mock(HistogramPanel.class);
-        when(histogramView.getUiComponent()).thenReturn(new EdtHelper().callAndWait(new Callable<JPanel>() {
-            @Override
-            public JPanel call() throws Exception {
-                return new JPanel();
-            }
-        }));
-
-        ObjectDetailsPanel objectDetailsView = mock(ObjectDetailsPanel.class);
-        when(objectDetailsView.getUiComponent()).thenReturn(new EdtHelper().callAndWait(new Callable<JPanel>() {
-            @Override
-            public JPanel call() throws Exception {
-                return new JPanel();
-            }
-        }));
-        view.addSubView("test1", histogramView);
-        view.addSubView("test2", objectDetailsView);
-
-        tabPane.requireTabTitles("test1", "test2");
-    }
-
-
-    @GUITest
-    @Test
-    public void verifyAddRemove() throws InvocationTargetException, InterruptedException {
-        frameFixture.show();
-
-        JTabbedPaneFixture tabPane = frameFixture.tabbedPane("tabs");
-        assertNotNull(tabPane);
-
-        HistogramPanel histogramView = mock(HistogramPanel.class);
-        when(histogramView.getUiComponent()).thenReturn(new EdtHelper().callAndWait(new Callable<JPanel>() {
-            @Override
-            public JPanel call() throws Exception {
-                return new JPanel();
-            }
-        }));
-
-        view.addSubView("test1", histogramView);
-
-        tabPane.requireTabTitles("test1");
-
-        view.removeSubView("test1");
-
-        tabPane.requireTabTitles();
-    }
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/swing/HeapSwingViewTest.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-package com.redhat.thermostat.client.heap.swing;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import java.awt.Container;
-import java.util.Arrays;
-import java.util.List;
-
-import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
-
-import org.fest.swing.annotation.GUITest;
-import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
-import org.fest.swing.edt.GuiActionRunner;
-import org.fest.swing.edt.GuiTask;
-import org.fest.swing.fixture.Containers;
-import org.fest.swing.fixture.FrameFixture;
-import org.fest.swing.fixture.JButtonFixture;
-import org.fest.swing.fixture.JListFixture;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import com.redhat.thermostat.client.heap.HeapView.HeapDumperAction;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.heap.HeapDump;
-
-@RunWith(CacioFESTRunner.class)
-public class HeapSwingViewTest {
-
-    private HeapSwingView view;
-
-    private FrameFixture frame;
-
-    @BeforeClass
-    public static void setUpOnce() {
-        FailOnThreadViolationRepaintManager.install();
-    }
-
-
-    @Before
-    public void setUp() throws Exception {
-        GuiActionRunner.execute(new GuiTask() {
-            
-            @Override
-            protected void executeInEDT() throws Throwable {
-                view = new HeapSwingView();
-            }
-        });
-        frame = Containers.showInFrame((Container) view.getUiComponent());
-    }
-
-    @After
-    public void tearDown() {
-        frame.cleanUp();
-        frame = null;
-        view = null;
-    }
-
-    @Test
-    @GUITest
-    public void testActivateHeapDump() {
-        @SuppressWarnings("unchecked")
-        ActionListener<HeapDumperAction> l = mock(ActionListener.class);
-        view.addDumperListener(l);
-        JButtonFixture heapDumpButton = frame.button("heapDumpButton");
-        heapDumpButton.click();
-        verify(l).actionPerformed(new ActionEvent<HeapDumperAction>(view, HeapDumperAction.DUMP_REQUESTED));
-    }
-
-    @Test
-    @GUITest
-    public void testNotifyHeapDumpComplete() {
-        final JButtonFixture heapDumpButton = frame.button("heapDumpButton");
-        GuiActionRunner.execute(new GuiTask() {
-            
-            @Override
-            protected void executeInEDT() throws Throwable {
-                heapDumpButton.component().setEnabled(false);
-            }
-        });
-
-        view.notifyHeapDumpComplete();
-        frame.robot.waitForIdle();
-
-        heapDumpButton.requireEnabled();
-    }
-
-    @Test
-    @GUITest
-    public void testUpdateHeapDumpList() {
-        JListFixture heapDumpList = frame.list("heapDumpList");
-        heapDumpList.requireItemCount(0);
-
-        HeapDump heapDump = mock(HeapDump.class);
-        List<HeapDump> heapDumps = Arrays.asList(heapDump);
-
-        view.updateHeapDumpList(heapDumps);
-        frame.robot.waitForIdle();
-        heapDumpList.requireItemCount(1);
-
-        view.updateHeapDumpList(heapDumps);
-        frame.robot.waitForIdle();
-        heapDumpList.requireItemCount(1);
-
-    }
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/swing/ObjectDetailsPanelTest.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,189 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.swing;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import javax.swing.JFrame;
-import javax.swing.JTree;
-import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.TreePath;
-
-import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
-
-import org.fest.swing.annotation.GUITest;
-import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
-import org.fest.swing.edt.GuiActionRunner;
-import org.fest.swing.edt.GuiTask;
-import org.fest.swing.fixture.FrameFixture;
-import org.fest.swing.fixture.JTextComponentFixture;
-import org.fest.swing.fixture.JTreeFixture;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import com.redhat.thermostat.client.heap.HeapObjectUI;
-import com.redhat.thermostat.client.heap.ObjectDetailsView.ObjectAction;
-import com.redhat.thermostat.client.ui.SearchFieldView;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.sun.tools.hat.internal.model.JavaClass;
-import com.sun.tools.hat.internal.model.JavaHeapObject;
-
-@RunWith(CacioFESTRunner.class)
-public class ObjectDetailsPanelTest {
-
-    private JFrame frame;
-    private FrameFixture frameFixture;
-    private ObjectDetailsPanel view;
-    private ActionListener<ObjectAction> listener;
-
-    @BeforeClass
-    public static void setUpOnce() {
-        FailOnThreadViolationRepaintManager.install();
-    }
-
-    @SuppressWarnings("unchecked")
-    @Before
-    public void setUp() {
-        GuiActionRunner.execute(new GuiTask() {
-            @Override
-            protected void executeInEDT() throws Throwable {
-                view = new ObjectDetailsPanel();
-                frame = new JFrame();
-                frame.add(view.getUiComponent());
-
-            }
-        });
-        frameFixture = new FrameFixture(frame);
-
-        listener = mock(ActionListener.class);
-        view.addObjectActionListener(listener);
-    }
-
-    @After
-    public void tearDown() {
-        frameFixture.cleanUp();
-        frameFixture = null;
-    }
-
-    @GUITest
-    @Test
-    public void verifySearchWorks() {
-        final String SEARCH_TEXT = "test";
-
-        frameFixture.show();
-
-        JTextComponentFixture searchBox = frameFixture.textBox(SearchFieldView.VIEW_NAME);
-        searchBox.enterText(SEARCH_TEXT);
-
-        verify(listener, times(SEARCH_TEXT.length())).actionPerformed(new ActionEvent<ObjectAction>(view, ObjectAction.SEARCH));
-
-        assertEquals(SEARCH_TEXT, view.getSearchText());
-    }
-
-    @GUITest
-    @Test
-    public void verifyMatchingObjectsWork() {
-        frameFixture.show();
-
-        HeapObjectUI obj1 = new HeapObjectUI("obj1", "obj1");
-        HeapObjectUI obj2 = new HeapObjectUI("obj2", "obj2");
-
-        view.setMatchingObjects(Arrays.asList(obj1, obj2));
-
-        JTreeFixture tree = frameFixture.tree(ObjectDetailsPanel.TREE_NAME);
-
-        TreePath[] paths = getRows(tree.component());
-
-        assertEquals(obj1, getUserObject(paths[0]));
-        assertEquals(obj2, getUserObject(paths[1]));
-
-        tree.selectPath("obj1");
-
-        assertEquals(obj1, view.getSelectedMatchingObject());
-    }
-
-    private static Object getUserObject(TreePath path) {
-        return ((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
-    }
-
-    private static TreePath[] getRows(JTree tree) {
-        List<TreePath> paths = new ArrayList<>();
-        for (int i = 0; i < tree.getRowCount(); i++) {
-            paths.add(tree.getPathForRow(i));
-        }
-        return paths.toArray(new TreePath[0]);
-    }
-
-    @GUITest
-    @Test
-    public void verifySettingObjectDetails() {
-        final String OBJECT_ID = "id";
-        final boolean HEAP_ALLOCATED = true;
-        final int OBJECT_SIZE = 10;
-        final String OBJECT_CLASS = "foo.bar.Baz";
-
-        frameFixture.show();
-
-        JavaClass klass = mock(JavaClass.class);
-        when(klass.getName()).thenReturn(OBJECT_CLASS);
-
-        JavaHeapObject heapObj = mock(JavaHeapObject.class);
-        when(heapObj.getIdString()).thenReturn(OBJECT_ID);
-        when(heapObj.isHeapAllocated()).thenReturn(HEAP_ALLOCATED);
-        when(heapObj.getSize()).thenReturn(OBJECT_SIZE);
-        when(heapObj.getClazz()).thenReturn(klass);
-
-        view.setObjectDetails(heapObj);
-
-        JTextComponentFixture textBox = frameFixture.textBox(ObjectDetailsPanel.DETAILS_NAME);
-        String expected = "Object ID:" + OBJECT_ID  + "\nType:" + OBJECT_CLASS + "\nSize:" + OBJECT_SIZE + " bytes\nHeap allocated:" + HEAP_ALLOCATED + "\n";
-        assertEquals(expected, textBox.text());
-    }
-
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/swing/ObjectRootsFrameTest.java	Tue Oct 23 11:19:24 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +0,0 @@
-/*
- * Copyright 2012 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.client.heap.swing;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.swing.JTree;
-import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.TreePath;
-
-import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
-
-import org.fest.swing.annotation.GUITest;
-import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
-import org.fest.swing.edt.GuiActionRunner;
-import org.fest.swing.edt.GuiQuery;
-import org.fest.swing.fixture.FrameFixture;
-import org.fest.swing.fixture.JTextComponentFixture;
-import org.fest.swing.fixture.JTreeFixture;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.client.heap.HeapObjectUI;
-import com.redhat.thermostat.client.heap.ObjectRootsView;
-import com.redhat.thermostat.client.heap.ObjectRootsView.Action;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-
-@RunWith(CacioFESTRunner.class)
-public class ObjectRootsFrameTest {
-
-    private ObjectRootsFrame frame;
-    private FrameFixture frameFixture;
-
-    @BeforeClass
-    public static void setUpOnce() {
-        FailOnThreadViolationRepaintManager.install();
-    }
-
-    @Before
-    public void setUp() {
-        frame = GuiActionRunner.execute(new GuiQuery<ObjectRootsFrame>() {
-            @Override
-            protected ObjectRootsFrame executeInEDT() throws Throwable {
-                return new ObjectRootsFrame();
-            }
-        });
-        frameFixture = new FrameFixture(frame);
-    }
-
-    @After
-    public void tearDown() {
-        frameFixture.cleanUp();
-        frameFixture = null;
-        frame.hideView();
-    }
-
-    @GUITest
-    @Test
-    public void verifyShowHide() {
-        frame.showView();
-
-        frameFixture.requireVisible();
-
-        frame.hideView();
-
-        frameFixture.requireNotVisible();
-    }
-
-    @GUITest
-    @Test
-    public void verifySetPath() {
-        List<HeapObjectUI> path = new ArrayList<>();
-        path.add(new HeapObjectUI("test", "test"));
-        path.add(new HeapObjectUI("test2", "test2"));
-        frame.setPathToRoot(path);
-
-        frame.showView();
-
-        frameFixture.requireVisible();
-
-        JTreeFixture tree = frameFixture.tree(ObjectRootsFrame.TREE_NAME);
-
-        TreePath[] paths = getRows(tree.component());
-
-        assertEquals(path.get(0), getUserObject(paths[0]));
-        assertEquals(path.get(1), getUserObject(paths[1]));
-    }
-
-    private static Object getUserObject(TreePath path) {
-        return ((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
-    }
-
-    private static TreePath[] getRows(JTree tree) {
-        List<TreePath> paths = new ArrayList<>();
-        for (int i = 0; i < tree.getRowCount(); i++) {
-            paths.add(tree.getPathForRow(i));
-        }
-        return paths.toArray(new TreePath[0]);
-    }
-
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    @GUITest
-    @Test
-    public void verifyTreeInteraction() {
-        frame.showView();
-
-        frameFixture.requireVisible();
-
-        ActionListener<ObjectRootsView.Action> listener = mock(ActionListener.class);
-        frame.addActionListener(listener);
-
-        List<HeapObjectUI> path = new ArrayList<>();
-        path.add(new HeapObjectUI("test", "test"));
-        frame.setPathToRoot(path);
-
-        JTreeFixture tree = frameFixture.tree(ObjectRootsFrame.TREE_NAME);
-        tree.selectRow(0);
-
-        ArgumentCaptor<ActionEvent> argCaptor = ArgumentCaptor.forClass(ActionEvent.class);
-        // We really want to verify that there's exactly one actionPerformend() call.
-        // If there are more events (such as VISIBLE events) fired, this may be a recipe
-        // for desaster if visble events trigger other actions, such as spawning a thread or
-        // starting/stopping a timer.
-        verify(listener).actionPerformed(argCaptor.capture());
-
-        assertEquals(frame, argCaptor.getValue().getSource());
-        
-        assertEquals(Action.OBJECT_SELECTED, argCaptor.getValue().getActionId());
-        assertEquals(path.get(0), argCaptor.getValue().getPayload());
-    }
-
-    @GUITest
-    @Test
-    public void verifySetDetails() {
-        String detailsText = "foo-bar";
-        frame.setObjectDetails(detailsText);
-
-        frame.showView();
-
-        frameFixture.requireVisible();
-
-        JTextComponentFixture textBox = frameFixture.textBox(ObjectRootsFrame.DETAILS_NAME);
-        textBox.requireText(detailsText);
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/pom.xml	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+
+ Copyright 2012 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-client-heapdumper</artifactId>
+    <groupId>com.redhat.thermostat</groupId>
+    <version>0.5.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>thermostat-client-heapdumper-swing</artifactId>
+  <packaging>bundle</packaging>
+  <name>Thermostat Client Heap Dumper Swing plugin</name>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
+            <Bundle-Activator>com.redhat.thermostat.client.heap.swing.Activator</Bundle-Activator>
+            <Bundle-SymbolicName>com.redhat.thermostat.client.heapdumper.swing</Bundle-SymbolicName>
+            <Private-Package>
+               com.redhat.thermostat.client.heap.swing
+            </Private-Package>
+            <!-- Do not autogenerate uses clauses in Manifests -->
+            <_nouses>true</_nouses>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.easytesting</groupId>
+      <artifactId>fest-swing</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>net.java.openjdk.cacio</groupId>
+      <artifactId>cacio-tta</artifactId>
+      <scope>test</scope>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <scope>provided</scope>
+    </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-client-swing</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-tools</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-client-heapdumper-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-agent-heapdumper</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.jfree</groupId>
+      <artifactId>jfreechart</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.sun</groupId>
+      <artifactId>tools</artifactId>
+      <scope>system</scope>
+      <systemPath>${java.home}/../lib/tools.jar</systemPath>
+    </dependency>
+    
+  </dependencies>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/Activator.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2012 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.client.heap.swing;
+
+import java.util.Map;
+import java.util.Objects;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+import com.redhat.thermostat.client.core.VmInformationService;
+import com.redhat.thermostat.client.heap.HeapDumperService;
+import com.redhat.thermostat.client.osgi.service.ApplicationService;
+import com.redhat.thermostat.common.MultipleServiceTracker;
+import com.redhat.thermostat.common.MultipleServiceTracker.Action;
+import com.redhat.thermostat.common.dao.AgentInfoDAO;
+import com.redhat.thermostat.common.dao.HeapDAO;
+import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
+
+public class Activator implements BundleActivator {
+
+    private MultipleServiceTracker heapDumperServiceTracker;
+    private ServiceRegistration heapDumperServiceRegistration;
+    private BundleContext context;
+
+    @Override
+    public void start(final BundleContext context) throws Exception {
+
+        this.context = context;
+        Class<?>[] deps = new Class<?>[] {
+                ApplicationService.class,
+                AgentInfoDAO.class,
+                VmMemoryStatDAO.class,
+                HeapDAO.class,
+        };
+
+        heapDumperServiceTracker = new MultipleServiceTracker(context, deps,
+                getServiceAvailableAction());
+        heapDumperServiceTracker.open();
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        heapDumperServiceTracker.close();
+    }
+    
+    // package private for testing
+    ServicesAvailableAction getServiceAvailableAction() {
+        return new ServicesAvailableAction();
+    }
+    
+    class ServicesAvailableAction implements Action {
+
+        @Override
+        public void dependenciesAvailable(Map<String, Object> services) {
+            ApplicationService appService = (ApplicationService) services
+                    .get(ApplicationService.class.getName());
+            Objects.requireNonNull(appService);
+            AgentInfoDAO agentDao = (AgentInfoDAO) services
+                    .get(AgentInfoDAO.class.getName());
+            Objects.requireNonNull(agentDao);
+            VmMemoryStatDAO vmMemoryStatDao = (VmMemoryStatDAO) services
+                    .get(VmMemoryStatDAO.class.getName());
+            Objects.requireNonNull(vmMemoryStatDao);
+            HeapDAO heapDao = (HeapDAO) services.get(HeapDAO.class.getName());
+            Objects.requireNonNull(heapDao);
+            heapDumperServiceRegistration = context
+                    .registerService(VmInformationService.class
+                            .getName(), new HeapDumperService(
+                            appService, agentDao, vmMemoryStatDao, heapDao,
+                            new SwingHeapDumpDetailsViewProvider(),
+                            new SwingHeapViewProvider(),
+                            new SwingHeapHistogramViewProvider(),
+                            new SwingObjectDetailsViewProvider(),
+                            new SwingObjectRootsViewProvider()),
+                            null);
+            
+        }
+
+        @Override
+        public void dependenciesUnavailable() {
+            heapDumperServiceRegistration.unregister();
+        }
+        
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/HeapDetailsSwing.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2012 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.client.heap.swing;
+
+import java.awt.BorderLayout;
+
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.SwingUtilities;
+
+import com.redhat.thermostat.client.heap.HeapDumpDetailsView;
+import com.redhat.thermostat.client.heap.HeapHistogramView;
+import com.redhat.thermostat.client.heap.ObjectDetailsView;
+import com.redhat.thermostat.client.swing.SwingComponent;
+
+public class HeapDetailsSwing extends HeapDumpDetailsView implements SwingComponent {
+
+    /** For TESTING only! */
+    static final String TAB_NAME = "tabs";
+
+    private JPanel visiblePane;
+
+    private JTabbedPane tabPane = new JTabbedPane();
+
+    public HeapDetailsSwing() {
+        visiblePane = new JPanel();
+        visiblePane.setLayout(new BorderLayout());
+        visiblePane.add(tabPane, BorderLayout.CENTER);
+
+        tabPane.setName(TAB_NAME);
+    }
+
+    @Override
+    public void addSubView(final String title, final HeapHistogramView view) {
+        verifyIsSwingComponent(view);
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                tabPane.insertTab(title, null, ((SwingComponent)view).getUiComponent(), null, 0);
+            }
+        });
+    }
+
+    @Override
+    public void addSubView(final String title, final ObjectDetailsView view) {
+        verifyIsSwingComponent(view);
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                tabPane.insertTab(title, null, ((SwingComponent)view).getUiComponent(), null, 1);
+            }
+        });
+    }
+
+    @Override
+    public void removeSubView(final String title) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                int tabCount = tabPane.getTabCount();
+                for (int i = 0; i < tabCount; i++) {
+                    String tabTitle = tabPane.getTitleAt(i);
+                    if (tabTitle.equals(title)) {
+                        tabPane.removeTabAt(i);
+                        return;
+                    }
+                }
+            }
+        });
+    }
+
+    @Override
+    public JPanel getUiComponent() {
+        return visiblePane;
+    }
+
+    private void verifyIsSwingComponent(Object obj) {
+        if (!(obj instanceof SwingComponent)) {
+            throw new IllegalArgumentException("component is not swing");
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/HeapPanel.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2012 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.client.heap.swing;
+
+import java.awt.Dimension;
+
+import javax.swing.JPanel;
+import javax.swing.JSplitPane;
+import javax.swing.GroupLayout;
+import javax.swing.GroupLayout.Alignment;
+
+@SuppressWarnings("serial")
+public class HeapPanel extends JPanel {
+
+    private JSplitPane splitPane;
+    
+    public HeapPanel() {
+        
+        splitPane = new JSplitPane();
+        splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
+        GroupLayout groupLayout = new GroupLayout(this);
+        groupLayout.setHorizontalGroup(
+            groupLayout.createParallelGroup(Alignment.LEADING)
+                .addComponent(splitPane, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE)
+        );
+        groupLayout.setVerticalGroup(
+            groupLayout.createParallelGroup(Alignment.LEADING)
+                .addGroup(groupLayout.createSequentialGroup()
+                    .addGap(5)
+                    .addComponent(splitPane, GroupLayout.DEFAULT_SIZE, 295, Short.MAX_VALUE))
+        );
+
+        splitPane.setOneTouchExpandable(true);
+        setLayout(groupLayout);
+    }
+
+    void divideView() {
+        splitPane.setDividerLocation(.5d);
+    }
+    
+    void hideBottom() {
+        splitPane.getBottomComponent().setMinimumSize(new Dimension(0, 0));
+        splitPane.setDividerLocation(1.0d);
+    }
+    
+    void hideTop() {
+        splitPane.getTopComponent().setMinimumSize(new Dimension(0, 0));
+        splitPane.setDividerLocation(0.0d);
+    }
+    
+    void setTop(JPanel panel) {
+        splitPane.setTopComponent(panel);
+    }
+    
+    void setBottom(JPanel panel) {
+        splitPane.setBottomComponent(panel);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/HeapSwingView.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2012 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.client.heap.swing;
+
+import java.awt.Component;
+import java.awt.EventQueue;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+
+import javax.swing.BoxLayout;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import org.jfree.chart.ChartPanel;
+
+import com.redhat.thermostat.client.core.views.BasicView;
+import com.redhat.thermostat.client.heap.HeapView;
+import com.redhat.thermostat.client.heap.LocaleResources;
+import com.redhat.thermostat.client.heap.chart.OverviewChart;
+import com.redhat.thermostat.client.swing.SwingComponent;
+import com.redhat.thermostat.client.swing.components.HeaderPanel;
+import com.redhat.thermostat.client.ui.ComponentVisibleListener;
+import com.redhat.thermostat.common.heap.HeapDump;
+import com.redhat.thermostat.common.locale.Translate;
+
+public class HeapSwingView extends HeapView implements SwingComponent {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private StatsPanel stats;
+
+    private HeapPanel heapDetailPanel;
+    private HeaderPanel overview;
+    
+    private JPanel visiblePane;
+    
+    public HeapSwingView() {
+        stats = new StatsPanel();
+        stats.addHeapDumperListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                
+                stats.disableHeapDumperControl();
+                
+                heapDumperNotifier.fireAction(HeapDumperAction.DUMP_REQUESTED);
+            }
+        });
+        
+        stats.addDumpListListener(new ListSelectionListener() {
+            @Override
+            public void valueChanged(ListSelectionEvent arg0) {
+                HeapDump dump = stats.getSelectedHeapDump();
+                heapDumperNotifier.fireAction(HeapDumperAction.ANALYSE, dump);
+            }
+        });
+        
+        visiblePane = new JPanel();
+        visiblePane.setLayout(new BoxLayout(visiblePane, BoxLayout.X_AXIS));
+        
+        heapDetailPanel = new HeapPanel();
+        
+        overview = new HeaderPanel(translator.localize(LocaleResources.HEAP_OVERVIEW_TITLE));
+        overview.setContent(stats);
+        overview.addHierarchyListener(new ViewVisibleListener());
+
+        // at the beginning, only the overview is visible
+        visiblePane.add(overview);
+    }
+    
+    private class ViewVisibleListener extends ComponentVisibleListener {
+        @Override
+        public void componentShown(Component component) {
+            HeapSwingView.this.notify(Action.VISIBLE);
+        }
+
+        @Override
+        public void componentHidden(Component component) {
+            HeapSwingView.this.notify(Action.HIDDEN);
+        }
+    }
+
+    @Override
+    public void setModel(final OverviewChart model) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                ChartPanel charts = new ChartPanel(model.createChart(stats.getWidth(), stats.getBackground()));
+                /*
+                 * By default, ChartPanel scales itself instead of redrawing things when
+                 * it's resized. To have it resize automatically, we need to set minimum
+                 * and maximum sizes. Lets constrain the minimum, but not the maximum
+                 * size.
+                 */
+                final int MINIMUM_DRAW_SIZE = 100;
+
+                charts.setMinimumDrawHeight(MINIMUM_DRAW_SIZE);
+                charts.setMinimumDrawWidth(MINIMUM_DRAW_SIZE);
+
+                charts.setMaximumDrawHeight(Integer.MAX_VALUE);
+                charts.setMaximumDrawWidth(Integer.MAX_VALUE);
+
+                stats.setChartPanel(charts);
+            }
+        });
+    }
+
+    @Override
+    public void updateUsedAndCapacity(final String used, final String capacity) {
+        
+        SwingUtilities.invokeLater(new Runnable() {
+            
+            @Override
+            public void run() {
+                stats.setMax(capacity);
+                stats.setUsed(used);
+            }
+        });
+    }
+
+    @Override
+    public void addHeapDump(final HeapDump dump) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                stats.addDump(dump);
+            }
+        });
+    }
+    
+    @Override
+    public void clearHeapDumpList() {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                stats.clearDumpList();
+            }
+        });
+    }
+    
+    @Override
+    public void openDumpView() {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                visiblePane.removeAll();
+                heapDetailPanel.divideView();
+                heapDetailPanel.setTop(overview);
+
+                visiblePane.add(heapDetailPanel);
+                visiblePane.revalidate();
+            }
+        });
+    }
+
+    @Override
+    public void setChildView(BasicView childView) {
+        if (childView instanceof HeapDetailsSwing) {
+            final HeapDetailsSwing view = (HeapDetailsSwing)childView;
+            SwingUtilities.invokeLater(new Runnable() {
+                @Override
+                public void run() {
+                    heapDetailPanel.setBottom(view.getUiComponent());
+                    visiblePane.revalidate();
+                }
+            });
+        }
+    }
+    
+    @Override
+    public Component getUiComponent() {
+        return visiblePane;
+    }
+
+    @Override
+    public void notifyHeapDumpComplete() {
+        EventQueue.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                stats.enableHeapDumperControl();
+            }
+        });
+    }
+
+    @Override
+    public void updateHeapDumpList(final List<HeapDump> heapDumps) {
+        EventQueue.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                stats.updateHeapDumpList(heapDumps);
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/HistogramPanel.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2012 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.client.heap.swing;
+
+import java.awt.Component;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.BoxLayout;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.table.DefaultTableModel;
+
+import com.redhat.thermostat.client.heap.HeapHistogramView;
+import com.redhat.thermostat.client.heap.LocaleResources;
+import com.redhat.thermostat.client.swing.SwingComponent;
+import com.redhat.thermostat.client.swing.components.HeaderPanel;
+import com.redhat.thermostat.client.swing.components.ThermostatTable;
+import com.redhat.thermostat.client.swing.components.ThermostatTableRenderer;
+import com.redhat.thermostat.common.heap.HistogramRecord;
+import com.redhat.thermostat.common.heap.ObjectHistogram;
+import com.redhat.thermostat.common.locale.Translate;
+import com.redhat.thermostat.common.utils.DescriptorConverter;
+
+@SuppressWarnings("serial")
+public class HistogramPanel extends HeapHistogramView implements SwingComponent {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private final JPanel panel;
+
+    private HeaderPanel headerPanel;
+
+    public HistogramPanel() {
+        panel = new JPanel();
+        panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
+
+        headerPanel = new HeaderPanel(translator.localize(LocaleResources.HEAP_DUMP_CLASS_USAGE));
+        panel.add(headerPanel);
+    }
+
+    @Override
+    public void display(ObjectHistogram histogram) {
+        ThermostatTable table = new ThermostatTable(new HistogramTableModel(histogram));
+        table.setDefaultRenderer(Long.class, new NiceNumberFormatter());
+        headerPanel.setContent(table.wrap());
+    }
+
+    private final class NiceNumberFormatter extends ThermostatTableRenderer {
+
+        private final DecimalFormat formatter = new DecimalFormat("###,###.###");
+
+        private NiceNumberFormatter() {
+            setHorizontalAlignment(JLabel.RIGHT);
+        }
+
+        @Override
+        protected void setValue(Object v) {
+            String formatted = formatter.format(v);
+            setText(formatted);
+        }
+    }
+
+    private class HistogramTableModel extends DefaultTableModel {
+
+        private final String[] columnNames = new String[] {
+            translator.localize(LocaleResources.HEAP_DUMP_HISTOGRAM_COLUMN_CLASS),
+            translator.localize(LocaleResources.HEAP_DUMP_HISTOGRAM_COLUMN_INSTANCES),
+            translator.localize(LocaleResources.HEAP_DUMP_HISTOGRAM_COLUMN_SIZE),
+        };
+
+        private List<HistogramRecord> histogram;
+
+        public HistogramTableModel(ObjectHistogram objHistogram) {
+            histogram = new ArrayList<>();
+            histogram.addAll(objHistogram.getHistogram());
+        }
+
+        @Override
+        public String getColumnName(int column) {
+            return columnNames[column];
+        }
+
+        @Override
+        public Class<?> getColumnClass(int column) {
+            if (column == 0) {
+                return String.class;
+            } else {
+                return Long.class;
+            }
+        }
+
+        @Override
+        public Object getValueAt(int row, int column) {
+            Object result = null;
+            if (row >= histogram.size()) {
+                throw new ArrayIndexOutOfBoundsException();
+            }
+            if (histogram != null) {
+                HistogramRecord record = histogram.get(row);
+                switch (column) {
+                case 0:
+                    result = DescriptorConverter.toJavaType(record.getClassname());
+                    break;
+                case 1:
+                    result = Long.valueOf(record.getNumberOf());
+                    break;
+                case 2:
+                    result = Long.valueOf(record.getTotalSize());
+                    break;
+                default:
+                    throw new ArrayIndexOutOfBoundsException();
+                }
+            }
+            return result;
+        }
+
+        @Override
+        public int getColumnCount() {
+            return 3;
+        }
+
+        @Override
+        public int getRowCount() {
+            if (histogram != null) {
+                return histogram.size();
+            }
+            return 0;
+        }
+
+        @Override
+        public boolean isCellEditable(int row, int column) {
+            return false;
+        }
+    }
+
+    @Override
+    public Component getUiComponent() {
+        return panel;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/LazyMutableTreeNode.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012 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.client.heap.swing;
+
+import com.redhat.thermostat.client.heap.HeapObjectUI;
+
+class LazyMutableTreeNode extends javax.swing.tree.DefaultMutableTreeNode {
+
+    public LazyMutableTreeNode() {
+        super();
+    }
+
+    public LazyMutableTreeNode(HeapObjectUI heapObjectUI) {
+        super(heapObjectUI);
+    }
+
+    @Override
+    public boolean isLeaf() {
+        return !getAllowsChildren();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/ObjectDetailsPanel.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,435 @@
+/*
+ * Copyright 2012 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.client.heap.swing;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.GroupLayout;
+import javax.swing.JPopupMenu;
+import javax.swing.JToggleButton;
+import javax.swing.JTree;
+import javax.swing.SwingUtilities;
+import javax.swing.GroupLayout.Alignment;
+import javax.swing.JLabel;
+
+import com.redhat.thermostat.client.core.views.SearchFieldView.SearchAction;
+import com.redhat.thermostat.client.heap.HeapObjectUI;
+import com.redhat.thermostat.client.heap.LocaleResources;
+import com.redhat.thermostat.client.heap.ObjectDetailsView;
+import com.redhat.thermostat.client.swing.SwingComponent;
+import com.redhat.thermostat.client.swing.components.EdtHelper;
+import com.redhat.thermostat.client.swing.views.SearchFieldSwingView;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionNotifier;
+import com.redhat.thermostat.common.locale.Translate;
+import com.sun.tools.hat.internal.model.JavaHeapObject;
+
+import javax.swing.LayoutStyle.ComponentPlacement;
+import javax.swing.JScrollPane;
+import javax.swing.JTextPane;
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import javax.swing.JSplitPane;
+import javax.swing.event.TreeExpansionEvent;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.event.TreeWillExpandListener;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.ExpandVetoException;
+import javax.swing.tree.MutableTreeNode;
+import javax.swing.tree.TreePath;
+import javax.swing.tree.TreeSelectionModel;
+
+/**
+ * A Panel that displays JavaHeapObjects and referrers and references.
+ */
+public class ObjectDetailsPanel extends ObjectDetailsView implements SwingComponent {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    /** For TESTING ONLY! */
+    static final String TREE_NAME = "ref-tree";
+    /** For TESTING ONLY! */
+    static final String DETAILS_NAME = "object-details";
+
+    private final ActionNotifier<ObjectAction> notifier = new ActionNotifier<>(this);
+
+    private final JPanel panel;
+
+    private final SearchFieldSwingView searchField;
+
+    private final LazyMutableTreeNode ROOT = new LazyMutableTreeNode(null);
+    /** all the nodes in this model must be {@link LazyMutableTreeNode}s */
+    private final DefaultTreeModel model = new DefaultTreeModel(ROOT);
+    private final JTree objectTree = new JTree(model);
+
+    private final JTextPane objectDetailsPane;
+
+    private final ButtonGroup refGroup = new ButtonGroup();
+    private final JToggleButton toggleReferrersButton;
+    private final JToggleButton toggleReferencesButton;
+
+    private final List<ObjectReferenceCallback> callbacks = new CopyOnWriteArrayList<>();
+
+    public ObjectDetailsPanel() {
+
+        panel = new JPanel();
+
+        JLabel searchLabel = new JLabel(translator.localize(LocaleResources.HEAP_DUMP_OBJECT_BROWSE_SEARCH_LABEL));
+
+        searchField = new SearchFieldSwingView();
+        searchField.setTooltip(translator.localize(LocaleResources.HEAP_DUMP_OBJECT_BROWSE_SEARCH_PATTERN_HELP));
+
+        JSplitPane splitPane = new JSplitPane();
+        splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
+        splitPane.setDividerLocation(0.8 /* 80% */);
+
+        toggleReferrersButton = new JToggleButton(translator.localize(LocaleResources.HEAP_DUMP_OBJECT_BROWSE_REFERRERS));
+        refGroup.add(toggleReferrersButton);
+
+        toggleReferencesButton = new JToggleButton(translator.localize(LocaleResources.HEAP_DUMP_OBJECT_BROWSE_REFERENCES));
+        refGroup.add(toggleReferencesButton);
+
+        toggleReferrersButton.setSelected(true);
+
+        GroupLayout groupLayout = new GroupLayout(panel);
+        groupLayout.setHorizontalGroup(
+            groupLayout.createParallelGroup(Alignment.LEADING)
+                .addGroup(groupLayout.createSequentialGroup()
+                    .addContainerGap()
+                    .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
+                        .addGroup(groupLayout.createSequentialGroup()
+                            .addComponent(searchLabel)
+                            .addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                            .addComponent(toggleReferencesButton)
+                            .addPreferredGap(ComponentPlacement.RELATED)
+                            .addComponent(toggleReferrersButton))
+                        .addGroup(groupLayout.createSequentialGroup()
+                            .addGap(12)
+                            .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
+                                .addComponent(splitPane, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 447, Short.MAX_VALUE)
+                                .addComponent(searchField, GroupLayout.DEFAULT_SIZE, 447, Short.MAX_VALUE))))
+                    .addContainerGap())
+        );
+        groupLayout.setVerticalGroup(
+            groupLayout.createParallelGroup(Alignment.LEADING)
+                .addGroup(groupLayout.createSequentialGroup()
+                    .addContainerGap()
+                    .addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
+                        .addComponent(searchLabel)
+                        .addComponent(toggleReferrersButton)
+                        .addComponent(toggleReferencesButton))
+                    .addPreferredGap(ComponentPlacement.RELATED)
+                    .addComponent(searchField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
+                    .addPreferredGap(ComponentPlacement.RELATED)
+                    .addComponent(splitPane, GroupLayout.DEFAULT_SIZE, 314, Short.MAX_VALUE)
+                    .addContainerGap())
+        );
+
+        searchField.addActionListener(new ActionListener<SearchAction>() {
+            @Override
+            public void actionPerformed(ActionEvent<SearchAction> actionEvent) {
+                switch (actionEvent.getActionId()) {
+                case TEXT_CHANGED:
+                    notifier.fireAction(ObjectAction.SEARCH);
+                    break;
+                }
+            }
+        });
+        searchField.setLabel(translator.localize(LocaleResources.HEAP_DUMP_OBJECT_BROWSE_SEARCH_HINT));
+
+        java.awt.event.ActionListener treeToggleListener = new java.awt.event.ActionListener() {
+            @Override
+            public void actionPerformed(java.awt.event.ActionEvent e) {
+                notifier.fireAction(ObjectAction.SEARCH);
+            }
+        };
+
+        JToggleButton[] buttons = getTreeModeButtons();
+        for (JToggleButton button: buttons) {
+            button.addActionListener(treeToggleListener);
+        }
+
+        JScrollPane scrollPane = new JScrollPane();
+        scrollPane.setViewportView(objectTree);
+
+        splitPane.setLeftComponent(scrollPane);
+
+        JPanel panel = new JPanel();
+        splitPane.setRightComponent(panel);
+
+        panel.setLayout(new BorderLayout(0, 0));
+
+        objectDetailsPane = new JTextPane();
+        objectDetailsPane.setName(DETAILS_NAME);
+        objectDetailsPane.setEditable(false);
+        panel.add(objectDetailsPane);
+        this.panel.setLayout(groupLayout);
+
+        initializeTree();
+        clearTree();
+    }
+
+    private void initializeTree() {
+        objectTree.setName(TREE_NAME);
+        objectTree.setRootVisible(false);
+        objectTree.setShowsRootHandles(true);
+        objectTree.setEditable(false);
+
+        objectTree.addTreeSelectionListener(new TreeSelectionListener() {
+            @Override
+            public void valueChanged(TreeSelectionEvent e) {
+                notifier.fireAction(ObjectAction.GET_OBJECT_DETAIL);
+            }
+        });
+
+        if (objectTree.getCellRenderer() instanceof DefaultTreeCellRenderer) {
+            DefaultTreeCellRenderer cellRenderer = (DefaultTreeCellRenderer) objectTree.getCellRenderer();
+            cellRenderer.setClosedIcon(null);
+            cellRenderer.setOpenIcon(null);
+            cellRenderer.setLeafIcon(null);
+        }
+
+        objectTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+        objectTree.expandPath(new TreePath(ROOT.getPath()));
+
+        objectTree.addTreeWillExpandListener(new TreeWillExpandListener() {
+
+            @Override
+            public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException {
+                if (new TreePath(ROOT.getPath()).equals(event.getPath())) {
+                    return;
+                }
+
+                lazyLoadChildren(event.getPath());
+            }
+
+            @Override
+            public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException {
+                if (new TreePath(ROOT.getPath()).equals(event.getPath())) {
+                    throw new ExpandVetoException(event, "root cant be collapsed");
+                }
+            }
+        });
+
+        objectTree.addMouseListener(new MouseAdapter() {
+            @Override
+            public void mousePressed(MouseEvent e) {
+                if (e.isPopupTrigger()) {
+                    int row = objectTree.getRowForLocation(e.getX(), e.getY());
+                    if (row == -1) {
+                        return;
+                    }
+
+                    TreePath path = objectTree.getPathForRow(row);
+                    final HeapObjectUI heapObject = (HeapObjectUI) ((LazyMutableTreeNode)path.getLastPathComponent()).getUserObject();
+                    JPopupMenu popup = new JPopupMenu();
+                    JMenuItem findRootItem = new JMenuItem(translator.localize(LocaleResources.HEAP_DUMP_OBJECT_FIND_ROOT));
+                    findRootItem.addActionListener(new java.awt.event.ActionListener() {
+                        @Override
+                        public void actionPerformed(java.awt.event.ActionEvent e) {
+                            notifier.fireAction(ObjectAction.SHOW_ROOT_TO_GC, heapObject);
+                        }
+                    });
+                    popup.add(findRootItem);
+                    popup.show(e.getComponent(), e.getX(), e.getY());
+                }
+            }
+        });
+    }
+
+    private void clearTree() {
+        // clear children from model
+        int childrenCount = ROOT.getChildCount();
+        for (int i = 0; i < childrenCount; i++) {
+            MutableTreeNode child = (MutableTreeNode) ROOT.getChildAt(0);
+            model.removeNodeFromParent(child);
+        }
+    }
+
+    private void lazyLoadChildren(TreePath path) {
+        LazyMutableTreeNode node = (LazyMutableTreeNode) path.getLastPathComponent();
+        if (node.getChildCount() > 0) {
+            // already processed
+            return;
+        }
+
+        if (toggleReferencesButton.isSelected()) {
+            addReferences(node);
+        } else if (toggleReferrersButton.isSelected()) {
+            addReferrers(node);
+        }
+    }
+
+    private void addReferrers(LazyMutableTreeNode node) {
+        HeapObjectUI data = (HeapObjectUI) node.getUserObject();
+
+        List<HeapObjectUI> referrers = new ArrayList<>();
+        for (ObjectReferenceCallback callback : callbacks) {
+            referrers.addAll(callback.getReferrers(data));
+        }
+
+        for (HeapObjectUI obj: referrers) {
+            model.insertNodeInto(new LazyMutableTreeNode(obj), node, node.getChildCount());
+        }
+    }
+
+    private void addReferences(LazyMutableTreeNode node) {
+        HeapObjectUI data = (HeapObjectUI) node.getUserObject();
+
+        List<HeapObjectUI> referrers = new ArrayList<>();
+        for (ObjectReferenceCallback callback : callbacks) {
+            referrers.addAll(callback.getReferences(data));
+        }
+
+        for (HeapObjectUI obj: referrers) {
+            model.insertNodeInto(new LazyMutableTreeNode(obj), node, node.getChildCount());
+        }
+    }
+
+    private JToggleButton[] getTreeModeButtons() {
+        return new JToggleButton[] { toggleReferencesButton, toggleReferrersButton };
+    }
+
+    @Override
+    public void addObjectActionListener(ActionListener<ObjectAction> listener) {
+        notifier.addActionListener(listener);
+    }
+
+    @Override
+    public void removeObjectActionListnener(ActionListener<ObjectAction> listener) {
+        notifier.removeActionListener(listener);
+    }
+
+    @Override
+    public void addObjectReferenceCallback(ObjectReferenceCallback callback) {
+        callbacks.add(callback);
+    }
+
+    @Override
+    public void removeObjectReferenceCallback(ObjectReferenceCallback callback) {
+        callbacks.remove(callback);
+    }
+
+    @Override
+    public String getSearchText() {
+        try {
+            return new EdtHelper().callAndWait(new Callable<String>() {
+                @Override
+                public String call() throws Exception {
+                    return searchField.getSearchText();
+                }
+            });
+        } catch (InvocationTargetException | InterruptedException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    @Override
+    public void setMatchingObjects(final Collection<HeapObjectUI> objects) {
+        try {
+            new EdtHelper().callAndWait(new Runnable() {
+                @Override
+                public void run() {
+                    // clear children
+                    clearTree();
+
+                    // add new children
+                    for (HeapObjectUI object: objects) {
+                        MutableTreeNode node = new LazyMutableTreeNode(object);
+                        model.insertNodeInto(node, ROOT, ROOT.getChildCount());
+                    }
+                    objectTree.expandPath(new TreePath(ROOT.getPath()));
+                }
+            });
+        } catch (InvocationTargetException | InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void setObjectDetails(final JavaHeapObject obj) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                // TODO use some other gui control for this rather than a plain text box
+                String text = translator.localize(LocaleResources.COMMAND_OBJECT_INFO_OBJECT_ID) + obj.getIdString() + "\n" +
+                              translator.localize(LocaleResources.COMMAND_OBJECT_INFO_TYPE) + obj.getClazz().getName() + "\n" +
+                              translator.localize(LocaleResources.COMMAND_OBJECT_INFO_SIZE) + String.valueOf(obj.getSize()) + " bytes" + "\n" +
+                              translator.localize(LocaleResources.COMMAND_OBJECT_INFO_HEAP_ALLOCATED) + String.valueOf(obj.isHeapAllocated()) + "\n";
+                objectDetailsPane.setText(text);
+            }
+        });
+    }
+
+    /**
+     * @return null if no selected object
+     */
+    @Override
+    public HeapObjectUI getSelectedMatchingObject() {
+        try {
+            return new EdtHelper().callAndWait(new Callable<HeapObjectUI>() {
+                @Override
+                public HeapObjectUI call() throws Exception {
+                    LazyMutableTreeNode node = (LazyMutableTreeNode) objectTree.getSelectionPath().getLastPathComponent();
+                    return (HeapObjectUI) node.getUserObject();
+                }
+            });
+        } catch (InvocationTargetException | InterruptedException e) {
+            return null;
+        }
+    }
+
+    @Override
+    public Component getUiComponent() {
+        return panel;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/ObjectRootsFrame.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2012 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.client.heap.swing;
+
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import javax.swing.GroupLayout;
+import javax.swing.GroupLayout.Alignment;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextPane;
+import javax.swing.JTree;
+import javax.swing.LayoutStyle.ComponentPlacement;
+import javax.swing.SwingUtilities;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.MutableTreeNode;
+import javax.swing.tree.TreePath;
+
+import com.redhat.thermostat.client.heap.HeapObjectUI;
+import com.redhat.thermostat.client.heap.LocaleResources;
+import com.redhat.thermostat.client.heap.ObjectRootsView;
+import com.redhat.thermostat.client.swing.components.EdtHelper;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ActionNotifier;
+import com.redhat.thermostat.common.locale.Translate;
+
+@SuppressWarnings("serial")
+public class ObjectRootsFrame extends JFrame implements ObjectRootsView {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    /** For TESTING ONLY! */
+    static final String TREE_NAME = "roots-tree";
+
+    static final String DETAILS_NAME = "object-details";
+
+    private final ActionNotifier<Action> notifier = new ActionNotifier<>(this);
+
+    private final LazyMutableTreeNode ROOT = new LazyMutableTreeNode();
+    private final DefaultTreeModel dataModel;
+    private final JTree pathToRootTree;
+
+    private final JTextPane objectDetails;
+
+    public ObjectRootsFrame() {
+        setTitle(translator.localize(LocaleResources.OBJECT_ROOTS_VIEW_TITLE));
+
+        dataModel = new DefaultTreeModel(ROOT);
+        pathToRootTree = new JTree(dataModel);
+        pathToRootTree.setName(TREE_NAME);
+
+        JLabel lblNewLabel = new JLabel(translator.localize(LocaleResources.OBJECT_ROOTS_VIEW_TITLE));
+
+        JScrollPane scrollPane = new JScrollPane(pathToRootTree);
+
+        objectDetails = new JTextPane();
+        objectDetails.setName(DETAILS_NAME);
+
+        GroupLayout groupLayout = new GroupLayout(getContentPane());
+        groupLayout.setHorizontalGroup(
+            groupLayout.createParallelGroup(Alignment.TRAILING)
+                .addGroup(groupLayout.createSequentialGroup()
+                    .addContainerGap()
+                    .addGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
+                        .addComponent(scrollPane, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 416, Short.MAX_VALUE)
+                        .addComponent(objectDetails, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 416, Short.MAX_VALUE)
+                        .addComponent(lblNewLabel, Alignment.LEADING))
+                    .addContainerGap())
+        );
+        groupLayout.setVerticalGroup(
+            groupLayout.createParallelGroup(Alignment.LEADING)
+                .addGroup(groupLayout.createSequentialGroup()
+                    .addContainerGap()
+                    .addComponent(lblNewLabel)
+                    .addPreferredGap(ComponentPlacement.RELATED)
+                    .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 126, Short.MAX_VALUE)
+                    .addPreferredGap(ComponentPlacement.RELATED)
+                    .addComponent(objectDetails, GroupLayout.PREFERRED_SIZE, 93, GroupLayout.PREFERRED_SIZE)
+                    .addContainerGap())
+        );
+        getContentPane().setLayout(groupLayout);
+
+        addWindowListener(new WindowAdapter() {
+            @Override
+            public void windowOpened(WindowEvent e) {
+                notifier.fireAction(Action.VISIBLE);
+            }
+
+            @Override
+            public void windowClosing(WindowEvent e) {
+                notifier.fireAction(Action.HIDDEN);
+            }
+        });
+
+        pathToRootTree.addTreeSelectionListener(new TreeSelectionListener() {
+            @Override
+            public void valueChanged(TreeSelectionEvent e) {
+                HeapObjectUI obj = (HeapObjectUI) ((LazyMutableTreeNode)e.getPath().getLastPathComponent()).getUserObject();
+                notifier.fireAction(Action.OBJECT_SELECTED, obj);
+            }
+        });
+
+
+    }
+
+    @Override
+    public void addActionListener(ActionListener<Action> listener) {
+        notifier.addActionListener(listener);
+    }
+
+    @Override
+    public void removeActionListener(ActionListener<Action> listener) {
+        notifier.removeActionListener(listener);
+    }
+
+    @Override
+    public void showView() {
+        Callable<Boolean> hideViewRunnable = new Callable<Boolean>() {
+            @Override
+            public Boolean call() {
+                pack();
+                setVisible(true);
+                return new Boolean(true);
+            }
+        };
+        try {
+            new EdtHelper().callAndWait(hideViewRunnable);
+        } catch (InvocationTargetException | InterruptedException e) {
+            InternalError error = new InternalError();
+            error.initCause(e);
+            throw error;
+        }
+    }
+
+    @Override
+    public void hideView() {
+        Callable<Boolean> hideViewRunnable = new Callable<Boolean>() {
+            @Override
+            public Boolean call() {
+                setVisible(false);
+                dispose();
+                return new Boolean(true);
+            }
+        };
+        try {
+            new EdtHelper().callAndWait(hideViewRunnable);
+        } catch (InvocationTargetException | InterruptedException e) {
+            InternalError error = new InternalError();
+            error.initCause(e);
+            throw error;
+        }
+    }
+
+    @Override
+    public void setPathToRoot(List<HeapObjectUI> pathToRoot) {
+        final List<HeapObjectUI> path = new ArrayList<>(pathToRoot);
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                clearTree();
+
+                LazyMutableTreeNode node = ROOT;
+                node.setUserObject(path.get(0));
+                TreePath treePath = new TreePath(node);
+                LazyMutableTreeNode parent = ROOT;
+                for (int i = 1; i < path.size(); i++) {
+                    HeapObjectUI obj = path.get(i);
+                    node = new LazyMutableTreeNode(obj);
+                    dataModel.insertNodeInto(node, parent, node.getChildCount());
+                    parent = node;
+                    treePath = treePath.pathByAddingChild(node);
+                }
+
+                pathToRootTree.expandPath(treePath);
+                pathToRootTree.setSelectionPath(treePath);
+            }
+        });
+    }
+
+    private void clearTree() {
+        // clear children from model
+        int childrenCount = ROOT.getChildCount();
+        for (int i = 0; i < childrenCount; i++) {
+            MutableTreeNode child = (MutableTreeNode) ROOT.getChildAt(0);
+            dataModel.removeNodeFromParent(child);
+        }
+    }
+
+    @Override
+    public void setObjectDetails(final String information) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                objectDetails.setText(information);
+            }
+        });
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/StatsPanel.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2012 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.client.heap.swing;
+
+import java.awt.event.ActionListener;
+import java.util.List;
+
+import javax.swing.BoxLayout;
+import javax.swing.DefaultListModel;
+import javax.swing.GroupLayout;
+import javax.swing.GroupLayout.Alignment;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.LayoutStyle.ComponentPlacement;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingConstants;
+import javax.swing.event.ListSelectionListener;
+
+import com.redhat.thermostat.common.heap.HeapDump;
+
+@SuppressWarnings("serial")
+public class StatsPanel extends JPanel {
+    
+    private JPanel leftPanel;
+    
+    private JButton heapDumpButton;
+    private JList<HeapDump> dumpList;
+    private DefaultListModel<HeapDump> listModel;
+    
+    private JLabel max;
+    private JLabel current;
+    
+    public StatsPanel() {
+        
+        leftPanel = new JPanel();
+        leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.X_AXIS));
+        
+        JPanel rightPanel = new JPanel();
+        GroupLayout groupLayout = new GroupLayout(this);
+        groupLayout.setHorizontalGroup(
+            groupLayout.createParallelGroup(Alignment.LEADING)
+                .addGroup(Alignment.TRAILING, groupLayout.createSequentialGroup()
+                    .addComponent(leftPanel, GroupLayout.DEFAULT_SIZE, 343, Short.MAX_VALUE)
+                    .addPreferredGap(ComponentPlacement.UNRELATED)
+                    .addComponent(rightPanel, GroupLayout.PREFERRED_SIZE, 252, GroupLayout.PREFERRED_SIZE))
+        );
+        groupLayout.setVerticalGroup(
+            groupLayout.createParallelGroup(Alignment.LEADING)
+                .addComponent(rightPanel, GroupLayout.DEFAULT_SIZE, 293, Short.MAX_VALUE)
+                .addComponent(leftPanel, GroupLayout.DEFAULT_SIZE, 293, Short.MAX_VALUE)
+        );
+        
+        JLabel currentLabel = new JLabel("used:");
+        currentLabel.setHorizontalAlignment(SwingConstants.LEFT);
+        
+        JLabel maxLabel = new JLabel("capacity:");
+        maxLabel.setHorizontalAlignment(SwingConstants.LEFT);
+        
+        current = new JLabel("-");
+        current.setHorizontalAlignment(SwingConstants.RIGHT);
+        
+        max = new JLabel("-");
+        max.setHorizontalAlignment(SwingConstants.RIGHT);
+        
+        heapDumpButton = new JButton("Heap Dump");
+        heapDumpButton.setName("heapDumpButton");
+
+        JScrollPane dumpListScrollPane = new JScrollPane();
+        dumpList = new JList<>();
+        dumpList.setName("heapDumpList");
+        listModel = new DefaultListModel<>();
+        dumpList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+        dumpList.setModel(listModel);
+        
+        GroupLayout gl_rightPanel = new GroupLayout(rightPanel);
+        gl_rightPanel.setHorizontalGroup(
+            gl_rightPanel.createParallelGroup(Alignment.TRAILING)
+                .addGroup(gl_rightPanel.createSequentialGroup()
+                    .addContainerGap()
+                    .addGroup(gl_rightPanel.createParallelGroup(Alignment.TRAILING)
+                        .addComponent(dumpListScrollPane, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 173, Short.MAX_VALUE)
+                        .addComponent(heapDumpButton, GroupLayout.DEFAULT_SIZE, 173, Short.MAX_VALUE)
+                        .addGroup(gl_rightPanel.createSequentialGroup()
+                            .addGroup(gl_rightPanel.createParallelGroup(Alignment.TRAILING, false)
+                                .addComponent(maxLabel, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                                .addComponent(currentLabel, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 48, Short.MAX_VALUE))
+                            .addPreferredGap(ComponentPlacement.RELATED)
+                            .addGroup(gl_rightPanel.createParallelGroup(Alignment.TRAILING)
+                                .addComponent(current, GroupLayout.DEFAULT_SIZE, 119, Short.MAX_VALUE)
+                                .addComponent(max, GroupLayout.PREFERRED_SIZE, 119, GroupLayout.PREFERRED_SIZE))))
+                    .addContainerGap())
+        );
+        gl_rightPanel.setVerticalGroup(
+            gl_rightPanel.createParallelGroup(Alignment.LEADING)
+                .addGroup(gl_rightPanel.createSequentialGroup()
+                    .addContainerGap()
+                    .addGroup(gl_rightPanel.createParallelGroup(Alignment.BASELINE)
+                        .addComponent(currentLabel, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE)
+                        .addComponent(current))
+                    .addPreferredGap(ComponentPlacement.RELATED)
+                    .addGroup(gl_rightPanel.createParallelGroup(Alignment.BASELINE)
+                        .addComponent(maxLabel)
+                        .addComponent(max))
+                    .addGap(18)
+                    .addComponent(heapDumpButton)
+                    .addGap(18)
+                    .addComponent(dumpListScrollPane, GroupLayout.DEFAULT_SIZE, 172, Short.MAX_VALUE)
+                    .addContainerGap())
+        );
+        rightPanel.setLayout(gl_rightPanel);
+        setLayout(groupLayout);
+
+        dumpListScrollPane.setViewportView(dumpList);
+    }
+    
+    void setChartPanel(JPanel panel) {
+        leftPanel.removeAll();
+        leftPanel.add(panel);
+        leftPanel.revalidate();
+        repaint();
+    }
+
+    public void setMax(String capacity) {
+        max.setText(capacity);
+    }
+
+    public void setUsed(String used) {
+        current.setText(used);
+    }
+    
+    void addHeapDumperListener(ActionListener listener) {
+        heapDumpButton.addActionListener(listener);
+    }
+
+    void addDumpListListener(ListSelectionListener listener) {
+        dumpList.addListSelectionListener(listener);
+    }
+    
+    public void disableHeapDumperControl() {
+        heapDumpButton.setText("dumping...");
+        heapDumpButton.setEnabled(false);
+    }
+
+    public void enableHeapDumperControl() {
+        heapDumpButton.setText("Heap Dump");
+        heapDumpButton.setEnabled(true);
+    }
+
+    public void addDump(HeapDump dump) {
+        
+        listModel.addElement(dump);
+    }
+
+    public void clearDumpList() {
+        listModel.clear();
+    }
+    
+    public HeapDump getSelectedHeapDump() {
+        return dumpList.getSelectedValue();
+    }
+
+    public void updateHeapDumpList(List<HeapDump> heapDumps) {
+        int numItemsBefore = listModel.getSize();
+        for (HeapDump heapDump : heapDumps) {
+            if (! listModel.contains(heapDump)) {
+                listModel.addElement(heapDump);
+            }
+        }
+        if (numItemsBefore == 0 && listModel.getSize() > 0) {
+            dumpList.repaint();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/SwingHeapDumpDetailsViewProvider.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012 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.client.heap.swing;
+
+import com.redhat.thermostat.client.heap.HeapDumpDetailsView;
+import com.redhat.thermostat.client.heap.HeapDumpDetailsViewProvider;
+
+public class SwingHeapDumpDetailsViewProvider implements
+        HeapDumpDetailsViewProvider {
+
+    @Override
+    public HeapDumpDetailsView createView() {
+        return new HeapDetailsSwing();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/SwingHeapHistogramViewProvider.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012 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.client.heap.swing;
+
+import com.redhat.thermostat.client.heap.HeapHistogramView;
+import com.redhat.thermostat.client.heap.HeapHistogramViewProvider;
+
+public class SwingHeapHistogramViewProvider implements
+        HeapHistogramViewProvider {
+
+    @Override
+    public HeapHistogramView createView() {
+        return new HistogramPanel();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/SwingHeapViewProvider.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012 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.client.heap.swing;
+
+import com.redhat.thermostat.client.heap.HeapView;
+import com.redhat.thermostat.client.heap.HeapViewProvider;
+
+public class SwingHeapViewProvider implements HeapViewProvider {
+
+    @Override
+    public HeapView createView() {
+        return new HeapSwingView();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/SwingObjectDetailsViewProvider.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012 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.client.heap.swing;
+
+import com.redhat.thermostat.client.heap.ObjectDetailsView;
+import com.redhat.thermostat.client.heap.ObjectDetailsViewProvider;
+
+public class SwingObjectDetailsViewProvider implements
+        ObjectDetailsViewProvider {
+
+    @Override
+    public ObjectDetailsView createView() {
+        return new ObjectDetailsPanel();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/main/java/com/redhat/thermostat/client/heap/swing/SwingObjectRootsViewProvider.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012 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.client.heap.swing;
+
+import com.redhat.thermostat.client.heap.ObjectRootsView;
+import com.redhat.thermostat.client.heap.ObjectRootsViewProvider;
+
+public class SwingObjectRootsViewProvider implements ObjectRootsViewProvider {
+
+    @Override
+    public ObjectRootsView createView() {
+        return new ObjectRootsFrame();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/test/java/com/redhat/thermostat/client/heap/swing/HeapDetailsSwingTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2012 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.client.heap.swing;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.concurrent.Callable;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
+
+import org.fest.swing.annotation.GUITest;
+import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
+import org.fest.swing.edt.GuiActionRunner;
+import org.fest.swing.edt.GuiTask;
+import org.fest.swing.fixture.FrameFixture;
+import org.fest.swing.fixture.JTabbedPaneFixture;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.redhat.thermostat.client.swing.components.EdtHelper;
+
+@RunWith(CacioFESTRunner.class)
+public class HeapDetailsSwingTest {
+
+    private JFrame frame;
+    private FrameFixture frameFixture;
+    private HeapDetailsSwing view;
+
+    @BeforeClass
+    public static void setUpOnce() {
+        FailOnThreadViolationRepaintManager.install();
+    }
+
+    @Before
+    public void setUp() {
+        GuiActionRunner.execute(new GuiTask() {
+            @Override
+            protected void executeInEDT() throws Throwable {
+                view = new HeapDetailsSwing();
+                frame = new JFrame();
+                frame.add(view.getUiComponent());
+
+            }
+        });
+        frameFixture = new FrameFixture(frame);
+    }
+
+    @After
+    public void tearDown() {
+        frameFixture.cleanUp();
+        frameFixture = null;
+    }
+
+    @GUITest
+    @Test
+    public void verifyTabsAdded() throws InvocationTargetException, InterruptedException {
+        frameFixture.show();
+
+        JTabbedPaneFixture tabPane = frameFixture.tabbedPane("tabs");
+        assertNotNull(tabPane);
+
+        HistogramPanel histogramView = mock(HistogramPanel.class);
+        when(histogramView.getUiComponent()).thenReturn(new EdtHelper().callAndWait(new Callable<JPanel>() {
+            @Override
+            public JPanel call() throws Exception {
+                return new JPanel();
+            }
+        }));
+
+        ObjectDetailsPanel objectDetailsView = mock(ObjectDetailsPanel.class);
+        when(objectDetailsView.getUiComponent()).thenReturn(new EdtHelper().callAndWait(new Callable<JPanel>() {
+            @Override
+            public JPanel call() throws Exception {
+                return new JPanel();
+            }
+        }));
+        view.addSubView("test1", histogramView);
+        view.addSubView("test2", objectDetailsView);
+
+        tabPane.requireTabTitles("test1", "test2");
+    }
+
+
+    @GUITest
+    @Test
+    public void verifyAddRemove() throws InvocationTargetException, InterruptedException {
+        frameFixture.show();
+
+        JTabbedPaneFixture tabPane = frameFixture.tabbedPane("tabs");
+        assertNotNull(tabPane);
+
+        HistogramPanel histogramView = mock(HistogramPanel.class);
+        when(histogramView.getUiComponent()).thenReturn(new EdtHelper().callAndWait(new Callable<JPanel>() {
+            @Override
+            public JPanel call() throws Exception {
+                return new JPanel();
+            }
+        }));
+
+        view.addSubView("test1", histogramView);
+
+        tabPane.requireTabTitles("test1");
+
+        view.removeSubView("test1");
+
+        tabPane.requireTabTitles();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/test/java/com/redhat/thermostat/client/heap/swing/HeapSwingViewTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,110 @@
+package com.redhat.thermostat.client.heap.swing;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import java.awt.Container;
+import java.util.Arrays;
+import java.util.List;
+
+import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
+
+import org.fest.swing.annotation.GUITest;
+import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
+import org.fest.swing.edt.GuiActionRunner;
+import org.fest.swing.edt.GuiTask;
+import org.fest.swing.fixture.Containers;
+import org.fest.swing.fixture.FrameFixture;
+import org.fest.swing.fixture.JButtonFixture;
+import org.fest.swing.fixture.JListFixture;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.redhat.thermostat.client.heap.HeapView.HeapDumperAction;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.heap.HeapDump;
+
+@RunWith(CacioFESTRunner.class)
+public class HeapSwingViewTest {
+
+    private HeapSwingView view;
+
+    private FrameFixture frame;
+
+    @BeforeClass
+    public static void setUpOnce() {
+        FailOnThreadViolationRepaintManager.install();
+    }
+
+
+    @Before
+    public void setUp() throws Exception {
+        GuiActionRunner.execute(new GuiTask() {
+            
+            @Override
+            protected void executeInEDT() throws Throwable {
+                view = new HeapSwingView();
+            }
+        });
+        frame = Containers.showInFrame((Container) view.getUiComponent());
+    }
+
+    @After
+    public void tearDown() {
+        frame.cleanUp();
+        frame = null;
+        view = null;
+    }
+
+    @Test
+    @GUITest
+    public void testActivateHeapDump() {
+        @SuppressWarnings("unchecked")
+        ActionListener<HeapDumperAction> l = mock(ActionListener.class);
+        view.addDumperListener(l);
+        JButtonFixture heapDumpButton = frame.button("heapDumpButton");
+        heapDumpButton.click();
+        verify(l).actionPerformed(new ActionEvent<HeapDumperAction>(view, HeapDumperAction.DUMP_REQUESTED));
+    }
+
+    @Test
+    @GUITest
+    public void testNotifyHeapDumpComplete() {
+        final JButtonFixture heapDumpButton = frame.button("heapDumpButton");
+        GuiActionRunner.execute(new GuiTask() {
+            
+            @Override
+            protected void executeInEDT() throws Throwable {
+                heapDumpButton.component().setEnabled(false);
+            }
+        });
+
+        view.notifyHeapDumpComplete();
+        frame.robot.waitForIdle();
+
+        heapDumpButton.requireEnabled();
+    }
+
+    @Test
+    @GUITest
+    public void testUpdateHeapDumpList() {
+        JListFixture heapDumpList = frame.list("heapDumpList");
+        heapDumpList.requireItemCount(0);
+
+        HeapDump heapDump = mock(HeapDump.class);
+        List<HeapDump> heapDumps = Arrays.asList(heapDump);
+
+        view.updateHeapDumpList(heapDumps);
+        frame.robot.waitForIdle();
+        heapDumpList.requireItemCount(1);
+
+        view.updateHeapDumpList(heapDumps);
+        frame.robot.waitForIdle();
+        heapDumpList.requireItemCount(1);
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/test/java/com/redhat/thermostat/client/heap/swing/ObjectDetailsPanelTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2012 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.client.heap.swing;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.swing.JFrame;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreePath;
+
+import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
+
+import org.fest.swing.annotation.GUITest;
+import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
+import org.fest.swing.edt.GuiActionRunner;
+import org.fest.swing.edt.GuiTask;
+import org.fest.swing.fixture.FrameFixture;
+import org.fest.swing.fixture.JTextComponentFixture;
+import org.fest.swing.fixture.JTreeFixture;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.redhat.thermostat.client.core.views.SearchFieldView;
+import com.redhat.thermostat.client.heap.HeapObjectUI;
+import com.redhat.thermostat.client.heap.ObjectDetailsView.ObjectAction;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.sun.tools.hat.internal.model.JavaClass;
+import com.sun.tools.hat.internal.model.JavaHeapObject;
+
+@RunWith(CacioFESTRunner.class)
+public class ObjectDetailsPanelTest {
+
+    private JFrame frame;
+    private FrameFixture frameFixture;
+    private ObjectDetailsPanel view;
+    private ActionListener<ObjectAction> listener;
+
+    @BeforeClass
+    public static void setUpOnce() {
+        FailOnThreadViolationRepaintManager.install();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Before
+    public void setUp() {
+        GuiActionRunner.execute(new GuiTask() {
+            @Override
+            protected void executeInEDT() throws Throwable {
+                view = new ObjectDetailsPanel();
+                frame = new JFrame();
+                frame.add(view.getUiComponent());
+
+            }
+        });
+        frameFixture = new FrameFixture(frame);
+
+        listener = mock(ActionListener.class);
+        view.addObjectActionListener(listener);
+    }
+
+    @After
+    public void tearDown() {
+        frameFixture.cleanUp();
+        frameFixture = null;
+    }
+
+    @GUITest
+    @Test
+    public void verifySearchWorks() {
+        final String SEARCH_TEXT = "test";
+
+        frameFixture.show();
+
+        JTextComponentFixture searchBox = frameFixture.textBox(SearchFieldView.VIEW_NAME);
+        searchBox.enterText(SEARCH_TEXT);
+
+        verify(listener, times(SEARCH_TEXT.length())).actionPerformed(new ActionEvent<ObjectAction>(view, ObjectAction.SEARCH));
+
+        assertEquals(SEARCH_TEXT, view.getSearchText());
+    }
+
+    @GUITest
+    @Test
+    public void verifyMatchingObjectsWork() {
+        frameFixture.show();
+
+        HeapObjectUI obj1 = new HeapObjectUI("obj1", "obj1");
+        HeapObjectUI obj2 = new HeapObjectUI("obj2", "obj2");
+
+        view.setMatchingObjects(Arrays.asList(obj1, obj2));
+
+        JTreeFixture tree = frameFixture.tree(ObjectDetailsPanel.TREE_NAME);
+
+        TreePath[] paths = getRows(tree.component());
+
+        assertEquals(obj1, getUserObject(paths[0]));
+        assertEquals(obj2, getUserObject(paths[1]));
+
+        tree.selectPath("obj1");
+
+        assertEquals(obj1, view.getSelectedMatchingObject());
+    }
+
+    private static Object getUserObject(TreePath path) {
+        return ((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
+    }
+
+    private static TreePath[] getRows(JTree tree) {
+        List<TreePath> paths = new ArrayList<>();
+        for (int i = 0; i < tree.getRowCount(); i++) {
+            paths.add(tree.getPathForRow(i));
+        }
+        return paths.toArray(new TreePath[0]);
+    }
+
+    @GUITest
+    @Test
+    public void verifySettingObjectDetails() {
+        final String OBJECT_ID = "id";
+        final boolean HEAP_ALLOCATED = true;
+        final int OBJECT_SIZE = 10;
+        final String OBJECT_CLASS = "foo.bar.Baz";
+
+        frameFixture.show();
+
+        JavaClass klass = mock(JavaClass.class);
+        when(klass.getName()).thenReturn(OBJECT_CLASS);
+
+        JavaHeapObject heapObj = mock(JavaHeapObject.class);
+        when(heapObj.getIdString()).thenReturn(OBJECT_ID);
+        when(heapObj.isHeapAllocated()).thenReturn(HEAP_ALLOCATED);
+        when(heapObj.getSize()).thenReturn(OBJECT_SIZE);
+        when(heapObj.getClazz()).thenReturn(klass);
+
+        view.setObjectDetails(heapObj);
+
+        JTextComponentFixture textBox = frameFixture.textBox(ObjectDetailsPanel.DETAILS_NAME);
+        String expected = "Object ID:" + OBJECT_ID  + "\nType:" + OBJECT_CLASS + "\nSize:" + OBJECT_SIZE + " bytes\nHeap allocated:" + HEAP_ALLOCATED + "\n";
+        assertEquals(expected, textBox.text());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/test/java/com/redhat/thermostat/client/heap/swing/ObjectRootsFrameTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2012 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.client.heap.swing;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JTree;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreePath;
+
+import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
+
+import org.fest.swing.annotation.GUITest;
+import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
+import org.fest.swing.edt.GuiActionRunner;
+import org.fest.swing.edt.GuiQuery;
+import org.fest.swing.fixture.FrameFixture;
+import org.fest.swing.fixture.JTextComponentFixture;
+import org.fest.swing.fixture.JTreeFixture;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.client.heap.HeapObjectUI;
+import com.redhat.thermostat.client.heap.ObjectRootsView;
+import com.redhat.thermostat.client.heap.ObjectRootsView.Action;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+
+@RunWith(CacioFESTRunner.class)
+public class ObjectRootsFrameTest {
+
+    private ObjectRootsFrame frame;
+    private FrameFixture frameFixture;
+
+    @BeforeClass
+    public static void setUpOnce() {
+        FailOnThreadViolationRepaintManager.install();
+    }
+
+    @Before
+    public void setUp() {
+        frame = GuiActionRunner.execute(new GuiQuery<ObjectRootsFrame>() {
+            @Override
+            protected ObjectRootsFrame executeInEDT() throws Throwable {
+                return new ObjectRootsFrame();
+            }
+        });
+        frameFixture = new FrameFixture(frame);
+    }
+
+    @After
+    public void tearDown() {
+        frameFixture.cleanUp();
+        frameFixture = null;
+        frame.hideView();
+    }
+
+    @GUITest
+    @Test
+    public void verifyShowHide() {
+        frame.showView();
+
+        frameFixture.requireVisible();
+
+        frame.hideView();
+
+        frameFixture.requireNotVisible();
+    }
+
+    @GUITest
+    @Test
+    public void verifySetPath() {
+        List<HeapObjectUI> path = new ArrayList<>();
+        path.add(new HeapObjectUI("test", "test"));
+        path.add(new HeapObjectUI("test2", "test2"));
+        frame.setPathToRoot(path);
+
+        frame.showView();
+
+        frameFixture.requireVisible();
+
+        JTreeFixture tree = frameFixture.tree(ObjectRootsFrame.TREE_NAME);
+
+        TreePath[] paths = getRows(tree.component());
+
+        assertEquals(path.get(0), getUserObject(paths[0]));
+        assertEquals(path.get(1), getUserObject(paths[1]));
+    }
+
+    private static Object getUserObject(TreePath path) {
+        return ((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
+    }
+
+    private static TreePath[] getRows(JTree tree) {
+        List<TreePath> paths = new ArrayList<>();
+        for (int i = 0; i < tree.getRowCount(); i++) {
+            paths.add(tree.getPathForRow(i));
+        }
+        return paths.toArray(new TreePath[0]);
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @GUITest
+    @Test
+    public void verifyTreeInteraction() {
+        frame.showView();
+
+        frameFixture.requireVisible();
+
+        ActionListener<ObjectRootsView.Action> listener = mock(ActionListener.class);
+        frame.addActionListener(listener);
+
+        List<HeapObjectUI> path = new ArrayList<>();
+        path.add(new HeapObjectUI("test", "test"));
+        frame.setPathToRoot(path);
+
+        JTreeFixture tree = frameFixture.tree(ObjectRootsFrame.TREE_NAME);
+        tree.selectRow(0);
+
+        ArgumentCaptor<ActionEvent> argCaptor = ArgumentCaptor.forClass(ActionEvent.class);
+        // We really want to verify that there's exactly one actionPerformend() call.
+        // If there are more events (such as VISIBLE events) fired, this may be a recipe
+        // for desaster if visble events trigger other actions, such as spawning a thread or
+        // starting/stopping a timer.
+        verify(listener).actionPerformed(argCaptor.capture());
+
+        assertEquals(frame, argCaptor.getValue().getSource());
+        
+        assertEquals(Action.OBJECT_SELECTED, argCaptor.getValue().getActionId());
+        assertEquals(path.get(0), argCaptor.getValue().getPayload());
+    }
+
+    @GUITest
+    @Test
+    public void verifySetDetails() {
+        String detailsText = "foo-bar";
+        frame.setObjectDetails(detailsText);
+
+        frame.showView();
+
+        frameFixture.requireVisible();
+
+        JTextComponentFixture textBox = frameFixture.textBox(ObjectRootsFrame.DETAILS_NAME);
+        textBox.requireText(detailsText);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/heapdumper/swing/src/test/java/com/redhat/thermostat/client/heap/swing/ServicesAvailableActionTest.java	Tue Oct 23 11:21:06 2012 -0400
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2012 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.client.heap.swing;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.client.core.VmInformationService;
+import com.redhat.thermostat.client.heap.HeapDumperService;
+import com.redhat.thermostat.client.heap.swing.Activator;
+import com.redhat.thermostat.client.heap.swing.Activator.ServicesAvailableAction;
+import com.redhat.thermostat.client.osgi.service.ApplicationService;
+import com.redhat.thermostat.common.dao.AgentInfoDAO;
+import com.redhat.thermostat.common.dao.HeapDAO;
+import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
+import com.redhat.thermostat.test.StubBundleContext;
+
+public class ServicesAvailableActionTest {
+
+    @Test
+    public void verifyDepsAvailableRegistersVmInformationService() throws Exception {
+        StubBundleContext ctx = new StubBundleContext();
+        Activator activator = new Activator();
+        
+        activator.start(ctx);
+        
+        ServicesAvailableAction action = activator.getServiceAvailableAction();
+        ApplicationService appService = mock(ApplicationService.class);
+        AgentInfoDAO dao = mock(AgentInfoDAO.class);
+        VmMemoryStatDAO vmMemoryDao = mock(VmMemoryStatDAO.class);
+        HeapDAO heapDao = mock(HeapDAO.class);
+        Map<String, Object> services = new HashMap<>();
+        services.put(AgentInfoDAO.class.getName(), dao);
+        services.put(ApplicationService.class.getName(), appService);
+        services.put(VmMemoryStatDAO.class.getName(), vmMemoryDao);
+        services.put(HeapDAO.class.getName(), heapDao);
+        
+        action.dependenciesAvailable(services);
+        
+        assertTrue(ctx.isServiceRegistered(VmInformationService.class.getName(), HeapDumperService.class));
+        
+        // Check no other services are registered
+        assertEquals(1, ctx.getAllServices().size());
+    }
+}