changeset 813:48fdf038ff96

Make client controllers internal This commit moves the controllers to internal packages for the following: Host{Overview,Cpu,Memory} and Vm{Overview,Cpu,Gc,ClassStat}. This forces access to the controller through the Host/VmInformationServiceController interface. This commit also splits the above plugins activators into two. The new Activator in the core bundle is now responsible for registering the plugin's Host/VmInformationService, which is now the only accessor for its controller. The Swing bundle's activator now simply registers its ViewProvider. The associated Eclipse client code no longer instantiates the controllers itself, but obtains them through the associated Host/VmInformationService. Reviewed-by: vanaltj, jerboaa Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-November/004318.html
author Elliott Baron <ebaron@redhat.com>
date Fri, 30 Nov 2012 17:30:25 -0500
parents 7d6bdce41bcf
children 84e6878eb77e
files eclipse/com.redhat.thermostat.eclipse.chart.common/META-INF/MANIFEST.MF eclipse/com.redhat.thermostat.eclipse.chart.common/src/com/redhat/thermostat/eclipse/chart/common/HostCpuViewPart.java eclipse/com.redhat.thermostat.eclipse.chart.common/src/com/redhat/thermostat/eclipse/chart/common/HostMemoryViewPart.java eclipse/com.redhat.thermostat.eclipse.chart.common/src/com/redhat/thermostat/eclipse/chart/common/VmCpuViewPart.java eclipse/com.redhat.thermostat.eclipse.chart.common/src/com/redhat/thermostat/eclipse/chart/common/VmGcViewPart.java eclipse/com.redhat.thermostat.eclipse.chart.vmclassstat/META-INF/MANIFEST.MF eclipse/com.redhat.thermostat.eclipse.chart.vmclassstat/src/com/redhat/thermostat/eclipse/chart/vmclassstat/VmClassStatViewPart.java eclipse/com.redhat.thermostat.eclipse.test/META-INF/MANIFEST.MF eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/HostCpuViewPartTest.java eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/HostMemoryViewPartTest.java eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/HostOverviewViewPartTest.java eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/VmClassStatViewPartTest.java eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/VmCpuViewPartTest.java eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/VmGcViewPartTest.java eclipse/com.redhat.thermostat.eclipse/META-INF/MANIFEST.MF eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/internal/views/HostOverviewViewPart.java host-cpu/client-core/pom.xml host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/HostCpuController.java host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/HostCpuService.java host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/internal/Activator.java host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/internal/HostCpuController.java host-cpu/client-core/src/test/java/com/redhat/thermostat/host/cpu/client/core/HostCpuControllerTest.java host-cpu/client-core/src/test/java/com/redhat/thermostat/host/cpu/client/core/internal/ActivatorTest.java host-cpu/client-core/src/test/java/com/redhat/thermostat/host/cpu/client/core/internal/HostCpuControllerTest.java host-cpu/client-swing/src/main/java/com/redhat/thermostat/host/cpu/client/swing/Activator.java host-cpu/client-swing/src/test/java/com/redhat/thermostat/host/cpu/client/swing/ActivatorTest.java host-memory/client-core/pom.xml host-memory/client-core/src/main/java/com/redhat/thermostat/host/memory/client/core/HostMemoryController.java host-memory/client-core/src/main/java/com/redhat/thermostat/host/memory/client/core/HostMemoryService.java host-memory/client-core/src/main/java/com/redhat/thermostat/host/memory/client/core/internal/Activator.java host-memory/client-core/src/main/java/com/redhat/thermostat/host/memory/client/core/internal/HostMemoryController.java host-memory/client-core/src/test/java/com/redhat/thermostat/host/memory/client/core/HostMemoryControllerTest.java host-memory/client-core/src/test/java/com/redhat/thermostat/host/memory/client/core/internal/ActivatorTest.java host-memory/client-core/src/test/java/com/redhat/thermostat/host/memory/client/core/internal/HostMemoryControllerTest.java host-memory/client-swing/src/main/java/com/redhat/thermostat/host/memory/client/swing/Activator.java host-memory/client-swing/src/test/java/com/redhat/thermostat/host/memory/client/swing/ActivatorTest.java host-overview/client-core/pom.xml host-overview/client-core/src/main/java/com/redhat/thermostat/host/overview/client/core/HostOverviewController.java host-overview/client-core/src/main/java/com/redhat/thermostat/host/overview/client/core/HostOverviewService.java host-overview/client-core/src/main/java/com/redhat/thermostat/host/overview/client/core/internal/Activator.java host-overview/client-core/src/main/java/com/redhat/thermostat/host/overview/client/core/internal/HostOverviewController.java host-overview/client-core/src/test/java/com/redhat/thermostat/host/overview/client/core/HostOverviewControllerTest.java host-overview/client-core/src/test/java/com/redhat/thermostat/host/overview/client/core/internal/ActivatorTest.java host-overview/client-core/src/test/java/com/redhat/thermostat/host/overview/client/core/internal/HostOverviewControllerTest.java host-overview/client-swing/src/main/java/com/redhat/thermostat/host/overview/client/swing/Activator.java host-overview/client-swing/src/test/java/com/redhat/thermostat/host/overview/client/swing/ActivatorTest.java vm-classstat/client-core/pom.xml vm-classstat/client-core/src/main/java/com/redhat/thermostat/vm/classstat/client/core/VmClassStatController.java vm-classstat/client-core/src/main/java/com/redhat/thermostat/vm/classstat/client/core/VmClassStatService.java vm-classstat/client-core/src/main/java/com/redhat/thermostat/vm/classstat/client/core/internal/Activator.java vm-classstat/client-core/src/main/java/com/redhat/thermostat/vm/classstat/client/core/internal/VmClassStatController.java vm-classstat/client-core/src/test/java/com/redhat/thermostat/vm/classstat/client/core/VmClassStatControllerTest.java vm-classstat/client-core/src/test/java/com/redhat/thermostat/vm/classstat/client/core/internal/ActivatorTest.java vm-classstat/client-core/src/test/java/com/redhat/thermostat/vm/classstat/client/core/internal/VmClassStatControllerTest.java vm-classstat/client-swing/src/main/java/com/redhat/thermostat/vm/classstat/client/swing/Activator.java vm-classstat/client-swing/src/test/java/com/redhat/thermostat/vm/classstat/client/swing/ActivatorTest.java vm-cpu/client-core/pom.xml vm-cpu/client-core/src/main/java/com/redhat/thermostat/vm/cpu/client/core/VmCpuController.java vm-cpu/client-core/src/main/java/com/redhat/thermostat/vm/cpu/client/core/VmCpuService.java vm-cpu/client-core/src/main/java/com/redhat/thermostat/vm/cpu/client/core/internal/Activator.java vm-cpu/client-core/src/main/java/com/redhat/thermostat/vm/cpu/client/core/internal/VmCpuController.java vm-cpu/client-core/src/test/java/com/redhat/thermostat/vm/cpu/client/core/VmCpuControllerTest.java vm-cpu/client-core/src/test/java/com/redhat/thermostat/vm/cpu/client/core/internal/ActivatorTest.java vm-cpu/client-core/src/test/java/com/redhat/thermostat/vm/cpu/client/core/internal/VmCpuControllerTest.java vm-cpu/client-swing/src/main/java/com/redhat/thermostat/vm/cpu/client/swing/Activator.java vm-cpu/client-swing/src/test/java/com/redhat/thermostat/vm/cpu/client/swing/ActivatorTest.java vm-gc/client-core/pom.xml vm-gc/client-core/src/main/java/com/redhat/thermostat/vm/gc/client/core/VmGcController.java vm-gc/client-core/src/main/java/com/redhat/thermostat/vm/gc/client/core/VmGcService.java vm-gc/client-core/src/main/java/com/redhat/thermostat/vm/gc/client/core/internal/Activator.java vm-gc/client-core/src/main/java/com/redhat/thermostat/vm/gc/client/core/internal/VmGcController.java vm-gc/client-core/src/test/java/com/redhat/thermostat/vm/gc/client/core/VmGcControllerTest.java vm-gc/client-core/src/test/java/com/redhat/thermostat/vm/gc/client/core/internal/ActivatorTest.java vm-gc/client-core/src/test/java/com/redhat/thermostat/vm/gc/client/core/internal/VmGcControllerTest.java vm-gc/client-swing/src/main/java/com/redhat/thermostat/vm/gc/client/swing/Activator.java vm-gc/client-swing/src/test/java/com/redhat/thermostat/vm/gc/client/swing/ActivatorTest.java vm-overview/client-core/pom.xml vm-overview/client-core/src/main/java/com/redhat/thermostat/vm/overview/client/core/VmOverviewController.java vm-overview/client-core/src/main/java/com/redhat/thermostat/vm/overview/client/core/VmOverviewService.java vm-overview/client-core/src/main/java/com/redhat/thermostat/vm/overview/client/core/internal/Activator.java vm-overview/client-core/src/main/java/com/redhat/thermostat/vm/overview/client/core/internal/VmOverviewController.java vm-overview/client-core/src/test/java/com/redhat/thermostat/vm/overview/client/core/VmOverviewControllerTest.java vm-overview/client-core/src/test/java/com/redhat/thermostat/vm/overview/client/core/internal/ActivatorTest.java vm-overview/client-core/src/test/java/com/redhat/thermostat/vm/overview/client/core/internal/VmOverviewControllerTest.java vm-overview/client-swing/src/main/java/com/redhat/thermostat/vm/overview/client/swing/Activator.java vm-overview/client-swing/src/test/java/com/redhat/thermostat/vm/overview/client/swing/ActivatorTest.java
diffstat 86 files changed, 3603 insertions(+), 2981 deletions(-) [+]
line wrap: on
line diff
--- a/eclipse/com.redhat.thermostat.eclipse.chart.common/META-INF/MANIFEST.MF	Fri Nov 30 10:47:45 2012 -0500
+++ b/eclipse/com.redhat.thermostat.eclipse.chart.common/META-INF/MANIFEST.MF	Fri Nov 30 17:30:25 2012 -0500
@@ -6,7 +6,8 @@
 Bundle-Activator: com.redhat.thermostat.eclipse.chart.common.Activator
 Bundle-Vendor: Red Hat Inc.
 Bundle-RequiredExecutionEnvironment: JavaSE-1.7
-Import-Package: com.redhat.thermostat.client.core.views,
+Import-Package: com.redhat.thermostat.client.core.controllers,
+ com.redhat.thermostat.client.core.views,
  com.redhat.thermostat.client.locale,
  com.redhat.thermostat.client.osgi.service,
  com.redhat.thermostat.client.ui,
--- a/eclipse/com.redhat.thermostat.eclipse.chart.common/src/com/redhat/thermostat/eclipse/chart/common/HostCpuViewPart.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/eclipse/com.redhat.thermostat.eclipse.chart.common/src/com/redhat/thermostat/eclipse/chart/common/HostCpuViewPart.java	Fri Nov 30 17:30:25 2012 -0500
@@ -36,43 +36,28 @@
 
 package com.redhat.thermostat.eclipse.chart.common;
 
-import java.util.Objects;
-
 import org.eclipse.swt.widgets.Composite;
 
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.dao.CpuStatDAO;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.client.core.controllers.HostInformationServiceController;
 import com.redhat.thermostat.common.dao.HostRef;
 import com.redhat.thermostat.common.utils.OSGIUtils;
 import com.redhat.thermostat.eclipse.SWTComponent;
 import com.redhat.thermostat.eclipse.views.HostRefViewPart;
-import com.redhat.thermostat.host.cpu.client.core.HostCpuController;
+import com.redhat.thermostat.host.cpu.client.core.HostCpuService;
 import com.redhat.thermostat.host.cpu.client.core.HostCpuViewProvider;
 
 public class HostCpuViewPart extends HostRefViewPart {
 
     @Override
     protected SWTComponent createControllerView(HostRef ref, Composite parent) {
-        HostInfoDAO hostInfoDao = OSGIUtils.getInstance().getService(
-                HostInfoDAO.class);
-        CpuStatDAO cpuStatDao = OSGIUtils.getInstance().getService(
-                CpuStatDAO.class);
         SWTHostCpuViewProvider viewProvider = (SWTHostCpuViewProvider) OSGIUtils
                 .getInstance().getService(HostCpuViewProvider.class);
         viewProvider.setParent(parent);
 
-        HostCpuController cpuController = createController(hostInfoDao,
-                cpuStatDao, ref, viewProvider);
-        SWTComponent view = (SWTComponent) cpuController.getView();
+        HostCpuService service = OSGIUtils.getInstance().getService(HostCpuService.class);
+        HostInformationServiceController controller = service.getInformationServiceController(ref);
+        SWTComponent view = (SWTComponent) controller.getView();
         return view;
     }
 
-    public HostCpuController createController(HostInfoDAO hostInfoDao,
-            CpuStatDAO cpuStatDao, HostRef ref, HostCpuViewProvider viewProvider) {
-        ApplicationService appSvc = OSGIUtils.getInstance().getService(ApplicationService.class);
-        Objects.requireNonNull(appSvc);
-        return new HostCpuController(appSvc, hostInfoDao, cpuStatDao, ref, viewProvider);
-    }
-
 }
--- a/eclipse/com.redhat.thermostat.eclipse.chart.common/src/com/redhat/thermostat/eclipse/chart/common/HostMemoryViewPart.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/eclipse/com.redhat.thermostat.eclipse.chart.common/src/com/redhat/thermostat/eclipse/chart/common/HostMemoryViewPart.java	Fri Nov 30 17:30:25 2012 -0500
@@ -36,44 +36,28 @@
 
 package com.redhat.thermostat.eclipse.chart.common;
 
-import java.util.Objects;
-
 import org.eclipse.swt.widgets.Composite;
 
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.client.core.controllers.HostInformationServiceController;
 import com.redhat.thermostat.common.dao.HostRef;
-import com.redhat.thermostat.common.dao.MemoryStatDAO;
 import com.redhat.thermostat.common.utils.OSGIUtils;
 import com.redhat.thermostat.eclipse.SWTComponent;
 import com.redhat.thermostat.eclipse.views.HostRefViewPart;
-import com.redhat.thermostat.host.memory.client.core.HostMemoryController;
+import com.redhat.thermostat.host.memory.client.core.HostMemoryService;
 import com.redhat.thermostat.host.memory.client.core.HostMemoryViewProvider;
 
 public class HostMemoryViewPart extends HostRefViewPart {
 
     @Override
     protected SWTComponent createControllerView(HostRef ref, Composite parent) {
-        HostInfoDAO hostInfoDao = OSGIUtils.getInstance().getService(
-                HostInfoDAO.class);
-        MemoryStatDAO memoryStatDao = OSGIUtils.getInstance().getService(
-                MemoryStatDAO.class);
         SWTHostMemoryViewProvider viewProvider = (SWTHostMemoryViewProvider) OSGIUtils
                 .getInstance().getService(HostMemoryViewProvider.class);
         viewProvider.setParent(parent);
-        HostMemoryController controller = createController(hostInfoDao,
-                memoryStatDao, ref, viewProvider);
+        
+        HostMemoryService service = OSGIUtils.getInstance().getService(HostMemoryService.class);
+        HostInformationServiceController controller = service.getInformationServiceController(ref);
         SWTComponent view = (SWTComponent) controller.getView();
         return view;
     }
 
-    public HostMemoryController createController(HostInfoDAO hostInfoDao,
-            MemoryStatDAO memoryStatDao, HostRef ref,
-            HostMemoryViewProvider viewProvider) {
-        ApplicationService appSvc = OSGIUtils.getInstance().getService(ApplicationService.class);
-        Objects.requireNonNull(appSvc);
-        return new HostMemoryController(appSvc, hostInfoDao, memoryStatDao, ref,
-                viewProvider);
-    }
-
 }
--- a/eclipse/com.redhat.thermostat.eclipse.chart.common/src/com/redhat/thermostat/eclipse/chart/common/VmCpuViewPart.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/eclipse/com.redhat.thermostat.eclipse.chart.common/src/com/redhat/thermostat/eclipse/chart/common/VmCpuViewPart.java	Fri Nov 30 17:30:25 2012 -0500
@@ -36,39 +36,28 @@
 
 package com.redhat.thermostat.eclipse.chart.common;
 
-import java.util.Objects;
-
 import org.eclipse.swt.widgets.Composite;
 
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.dao.VmCpuStatDAO;
+import com.redhat.thermostat.client.core.controllers.VmInformationServiceController;
 import com.redhat.thermostat.common.dao.VmRef;
 import com.redhat.thermostat.common.utils.OSGIUtils;
 import com.redhat.thermostat.eclipse.SWTComponent;
 import com.redhat.thermostat.eclipse.views.VmRefViewPart;
-import com.redhat.thermostat.vm.cpu.client.core.VmCpuController;
+import com.redhat.thermostat.vm.cpu.client.core.VmCpuService;
 import com.redhat.thermostat.vm.cpu.client.core.VmCpuViewProvider;
 
 public class VmCpuViewPart extends VmRefViewPart {
 
     @Override
     protected SWTComponent createControllerView(VmRef ref, Composite parent) {
-        VmCpuStatDAO vmCpuStatDao = OSGIUtils.getInstance().getService(
-                VmCpuStatDAO.class);
         SWTVmCpuViewProvider viewProvider = (SWTVmCpuViewProvider) OSGIUtils
                 .getInstance().getService(VmCpuViewProvider.class);
         viewProvider.setParent(parent);
-        VmCpuController controller = createController(vmCpuStatDao, ref,
-                viewProvider);
+        
+        VmCpuService service = OSGIUtils.getInstance().getService(VmCpuService.class);
+        VmInformationServiceController controller = service.getInformationServiceController(ref);
         SWTComponent view = (SWTComponent) controller.getView();
         return view;
     }
 
-    public VmCpuController createController(VmCpuStatDAO vmCpuStatDao,
-            VmRef ref, VmCpuViewProvider viewProvider) {
-        ApplicationService appSvc = OSGIUtils.getInstance().getService(ApplicationService.class);
-        Objects.requireNonNull(appSvc);
-        return new VmCpuController(appSvc, vmCpuStatDao, ref, viewProvider);
-    }
-
 }
--- a/eclipse/com.redhat.thermostat.eclipse.chart.common/src/com/redhat/thermostat/eclipse/chart/common/VmGcViewPart.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/eclipse/com.redhat.thermostat.eclipse.chart.common/src/com/redhat/thermostat/eclipse/chart/common/VmGcViewPart.java	Fri Nov 30 17:30:25 2012 -0500
@@ -36,43 +36,28 @@
 
 package com.redhat.thermostat.eclipse.chart.common;
 
-import java.util.Objects;
-
 import org.eclipse.swt.widgets.Composite;
 
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.dao.VmGcStatDAO;
-import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
+import com.redhat.thermostat.client.core.controllers.VmInformationServiceController;
 import com.redhat.thermostat.common.dao.VmRef;
 import com.redhat.thermostat.common.utils.OSGIUtils;
 import com.redhat.thermostat.eclipse.SWTComponent;
 import com.redhat.thermostat.eclipse.views.VmRefViewPart;
-import com.redhat.thermostat.vm.gc.client.core.VmGcController;
+import com.redhat.thermostat.vm.gc.client.core.VmGcService;
 import com.redhat.thermostat.vm.gc.client.core.VmGcViewProvider;
 
 public class VmGcViewPart extends VmRefViewPart {
 
     @Override
     protected SWTComponent createControllerView(VmRef ref, Composite parent) {
-        VmMemoryStatDAO vmMemoryStatDao = OSGIUtils.getInstance().getService(
-                VmMemoryStatDAO.class);
-        VmGcStatDAO vmGcStatDao = OSGIUtils.getInstance().getService(
-                VmGcStatDAO.class);
         SWTVmGcViewProvider viewProvider = (SWTVmGcViewProvider) OSGIUtils.getInstance().getService(
                 VmGcViewProvider.class);
         viewProvider.setParent(parent);
-        VmGcController controller = createController(vmMemoryStatDao, vmGcStatDao, ref,
-                viewProvider);
+        
+        VmGcService service = OSGIUtils.getInstance().getService(VmGcService.class);
+        VmInformationServiceController controller = service.getInformationServiceController(ref);
         SWTComponent view = (SWTComponent) controller.getView();
         return view;
     }
 
-    public VmGcController createController(VmMemoryStatDAO vmMemoryStatDao,
-            VmGcStatDAO vmGcStatDao, VmRef ref, VmGcViewProvider viewProvider) {
-        ApplicationService appSvc = OSGIUtils.getInstance().getService(ApplicationService.class);
-        Objects.requireNonNull(appSvc);
-        return new VmGcController(appSvc, vmMemoryStatDao, vmGcStatDao, ref,
-                viewProvider);
-    }
-
 }
--- a/eclipse/com.redhat.thermostat.eclipse.chart.vmclassstat/META-INF/MANIFEST.MF	Fri Nov 30 10:47:45 2012 -0500
+++ b/eclipse/com.redhat.thermostat.eclipse.chart.vmclassstat/META-INF/MANIFEST.MF	Fri Nov 30 17:30:25 2012 -0500
@@ -9,7 +9,8 @@
  org.eclipse.core.runtime
 Bundle-RequiredExecutionEnvironment: JavaSE-1.7
 Bundle-ActivationPolicy: lazy
-Import-Package: com.redhat.thermostat.client.core.views,
+Import-Package: com.redhat.thermostat.client.core.controllers,
+ com.redhat.thermostat.client.core.views,
  com.redhat.thermostat.client.osgi.service,
  com.redhat.thermostat.client.ui,
  com.redhat.thermostat.common,
--- a/eclipse/com.redhat.thermostat.eclipse.chart.vmclassstat/src/com/redhat/thermostat/eclipse/chart/vmclassstat/VmClassStatViewPart.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/eclipse/com.redhat.thermostat.eclipse.chart.vmclassstat/src/com/redhat/thermostat/eclipse/chart/vmclassstat/VmClassStatViewPart.java	Fri Nov 30 17:30:25 2012 -0500
@@ -36,17 +36,14 @@
 
 package com.redhat.thermostat.eclipse.chart.vmclassstat;
 
-import java.util.Objects;
-
 import org.eclipse.swt.widgets.Composite;
 
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.dao.VmClassStatDAO;
+import com.redhat.thermostat.client.core.controllers.VmInformationServiceController;
 import com.redhat.thermostat.common.dao.VmRef;
 import com.redhat.thermostat.common.utils.OSGIUtils;
 import com.redhat.thermostat.eclipse.SWTComponent;
 import com.redhat.thermostat.eclipse.views.VmRefViewPart;
-import com.redhat.thermostat.vm.classstat.client.core.VmClassStatController;
+import com.redhat.thermostat.vm.classstat.client.core.VmClassStatService;
 import com.redhat.thermostat.vm.classstat.client.core.VmClassStatViewProvider;
 
 public class VmClassStatViewPart extends VmRefViewPart {
@@ -56,19 +53,11 @@
         SWTVmClassStatViewProvider viewProvider = (SWTVmClassStatViewProvider) OSGIUtils
                 .getInstance().getService(VmClassStatViewProvider.class);
         viewProvider.setParent(parent);
-        VmClassStatDAO classStatDAO = OSGIUtils.getInstance().getService(
-                VmClassStatDAO.class);
-        VmClassStatController controller = createController(classStatDAO, ref,
-                viewProvider);
+        
+        VmClassStatService service = OSGIUtils.getInstance().getService(VmClassStatService.class);
+        VmInformationServiceController controller = service.getInformationServiceController(ref);
         SWTComponent view = (SWTComponent) controller.getView();
         return view;
     }
 
-    public VmClassStatController createController(VmClassStatDAO classStatDao,
-            VmRef ref, VmClassStatViewProvider viewProvider) {
-        ApplicationService appSvc = OSGIUtils.getInstance().getService(ApplicationService.class);
-        Objects.requireNonNull(appSvc);
-        return new VmClassStatController(appSvc, classStatDao, ref, viewProvider);
-    }
-
 }
--- a/eclipse/com.redhat.thermostat.eclipse.test/META-INF/MANIFEST.MF	Fri Nov 30 10:47:45 2012 -0500
+++ b/eclipse/com.redhat.thermostat.eclipse.test/META-INF/MANIFEST.MF	Fri Nov 30 17:30:25 2012 -0500
@@ -12,7 +12,8 @@
  com.redhat.thermostat.bundles.org.objenesis;resolution:=optional,
  com.redhat.thermostat.bundles.org.mockito.mockito-core;resolution:=optional
 Bundle-RequiredExecutionEnvironment: JavaSE-1.7
-Import-Package: com.redhat.thermostat.client.core.views,
+Import-Package: com.redhat.thermostat.client.core.controllers,
+ com.redhat.thermostat.client.core.views,
  com.redhat.thermostat.client.osgi.service,
  com.redhat.thermostat.client.ui,
  com.redhat.thermostat.common,
--- a/eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/HostCpuViewPartTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/HostCpuViewPartTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -37,8 +37,6 @@
 package com.redhat.thermostat.eclipse.test.views;
 
 import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.same;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -50,9 +48,8 @@
 import org.junit.Test;
 import org.mockito.InOrder;
 
+import com.redhat.thermostat.client.core.controllers.HostInformationServiceController;
 import com.redhat.thermostat.client.core.views.UIComponent;
-import com.redhat.thermostat.common.dao.CpuStatDAO;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
 import com.redhat.thermostat.common.dao.HostRef;
 import com.redhat.thermostat.common.dao.VmRef;
 import com.redhat.thermostat.eclipse.ThermostatConstants;
@@ -60,13 +57,13 @@
 import com.redhat.thermostat.eclipse.chart.common.SWTHostCpuView;
 import com.redhat.thermostat.eclipse.chart.common.SWTHostCpuViewProvider;
 import com.redhat.thermostat.eclipse.internal.views.RefViewPart;
-import com.redhat.thermostat.host.cpu.client.core.HostCpuController;
+import com.redhat.thermostat.host.cpu.client.core.HostCpuService;
 import com.redhat.thermostat.host.cpu.client.core.HostCpuViewProvider;
 
 public class HostCpuViewPartTest extends AbstractRefViewPartTest<HostRef> {
     
     private SWTHostCpuViewProvider viewProvider;
-    private HostCpuController controller;
+    private HostInformationServiceController controller;
 
     @Test
     public void testSetFocus() throws Exception {
@@ -136,21 +133,17 @@
 
     @Override
     protected void mockController() {
-        controller = mock(HostCpuController.class);
+        HostCpuService service = mock(HostCpuService.class);
+        controller = mock(HostInformationServiceController.class);
         thermoView = mock(SWTHostCpuView.class);
-
-        HostInfoDAO hostInfoDao = mock(HostInfoDAO.class);
-        CpuStatDAO cpuStatDao = mock(CpuStatDAO.class);
+        
+        when(osgi.getService(HostCpuService.class)).thenReturn(service);
+        when(service.getInformationServiceController(any(HostRef.class))).thenReturn(controller);
+        when(controller.getView()).thenReturn((UIComponent) thermoView);
+        
         viewProvider = mock(SWTHostCpuViewProvider.class);
-        when(osgi.getService(HostInfoDAO.class)).thenReturn(hostInfoDao);
-        when(osgi.getService(CpuStatDAO.class)).thenReturn(cpuStatDao);
         when(osgi.getService(HostCpuViewProvider.class)).thenReturn(
                 viewProvider);
-
-        doReturn(controller).when(((HostCpuViewPart) view)).createController(
-                same(hostInfoDao), same(cpuStatDao), any(HostRef.class),
-                same(viewProvider));
-        when(controller.getView()).thenReturn((UIComponent) thermoView);
     }
 
     @Override
--- a/eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/HostMemoryViewPartTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/HostMemoryViewPartTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -37,8 +37,6 @@
 package com.redhat.thermostat.eclipse.test.views;
 
 import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.same;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -48,22 +46,21 @@
 import org.junit.Test;
 import org.mockito.InOrder;
 
+import com.redhat.thermostat.client.core.controllers.HostInformationServiceController;
 import com.redhat.thermostat.client.core.views.UIComponent;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
 import com.redhat.thermostat.common.dao.HostRef;
-import com.redhat.thermostat.common.dao.MemoryStatDAO;
 import com.redhat.thermostat.eclipse.ThermostatConstants;
 import com.redhat.thermostat.eclipse.chart.common.HostMemoryViewPart;
 import com.redhat.thermostat.eclipse.chart.common.SWTHostMemoryView;
 import com.redhat.thermostat.eclipse.chart.common.SWTHostMemoryViewProvider;
 import com.redhat.thermostat.eclipse.internal.views.RefViewPart;
-import com.redhat.thermostat.host.memory.client.core.HostMemoryController;
+import com.redhat.thermostat.host.memory.client.core.HostMemoryService;
 import com.redhat.thermostat.host.memory.client.core.HostMemoryViewProvider;
 
 public class HostMemoryViewPartTest extends AbstractRefViewPartTest<HostRef> {
 
     private SWTHostMemoryViewProvider viewProvider;
-    private HostMemoryController controller;
+    private HostInformationServiceController controller;
 
     @Test
     public void testSelectionAfter() throws Exception {
@@ -84,21 +81,17 @@
 
     @Override
     protected void mockController() {
-        controller = mock(HostMemoryController.class);
+        HostMemoryService service = mock(HostMemoryService.class);
+        controller = mock(HostInformationServiceController.class);
         thermoView = mock(SWTHostMemoryView.class);
 
-        HostInfoDAO hostInfoDao = mock(HostInfoDAO.class);
-        MemoryStatDAO memStatDao = mock(MemoryStatDAO.class);
+        when(osgi.getService(HostMemoryService.class)).thenReturn(service);
+        when(service.getInformationServiceController(any(HostRef.class))).thenReturn(controller);
+        when(controller.getView()).thenReturn((UIComponent) thermoView);
+        
         viewProvider = mock(SWTHostMemoryViewProvider.class);
-        when(osgi.getService(HostInfoDAO.class)).thenReturn(hostInfoDao);
-        when(osgi.getService(MemoryStatDAO.class)).thenReturn(memStatDao);
         when(osgi.getService(HostMemoryViewProvider.class)).thenReturn(
                 viewProvider);
-
-        doReturn(controller).when(((HostMemoryViewPart) view))
-                .createController(same(hostInfoDao), same(memStatDao),
-                        any(HostRef.class), same(viewProvider));
-        when(controller.getView()).thenReturn((UIComponent) thermoView);
     }
 
     @Override
--- a/eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/HostOverviewViewPartTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/HostOverviewViewPartTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -37,8 +37,6 @@
 package com.redhat.thermostat.eclipse.test.views;
 
 import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.same;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -48,21 +46,20 @@
 import org.junit.Test;
 import org.mockito.InOrder;
 
+import com.redhat.thermostat.client.core.controllers.HostInformationServiceController;
 import com.redhat.thermostat.client.core.views.UIComponent;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
 import com.redhat.thermostat.common.dao.HostRef;
-import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO;
 import com.redhat.thermostat.eclipse.ThermostatConstants;
 import com.redhat.thermostat.eclipse.internal.views.HostOverviewViewPart;
 import com.redhat.thermostat.eclipse.internal.views.RefViewPart;
 import com.redhat.thermostat.eclipse.internal.views.SWTHostOverviewView;
 import com.redhat.thermostat.eclipse.internal.views.SWTHostOverviewViewProvider;
-import com.redhat.thermostat.host.overview.client.core.HostOverviewController;
+import com.redhat.thermostat.host.overview.client.core.HostOverviewService;
 import com.redhat.thermostat.host.overview.client.core.HostOverviewViewProvider;
 
 public class HostOverviewViewPartTest extends AbstractRefViewPartTest<HostRef> {
 
-    private HostOverviewController controller;
+    private HostInformationServiceController controller;
     private SWTHostOverviewViewProvider viewProvider;
     
     @Test
@@ -84,22 +81,17 @@
 
     @Override
     protected void mockController() {
-        controller = mock(HostOverviewController.class);
+        HostOverviewService service = mock(HostOverviewService.class);
+        controller = mock(HostInformationServiceController.class);
         thermoView = mock(SWTHostOverviewView.class);
 
-        HostInfoDAO hostInfoDao = mock(HostInfoDAO.class);
-        NetworkInterfaceInfoDAO netIfaceDao = mock(NetworkInterfaceInfoDAO.class);
+        when(osgi.getService(HostOverviewService.class)).thenReturn(service);
+        when(service.getInformationServiceController(any(HostRef.class))).thenReturn(controller);
+        when(controller.getView()).thenReturn((UIComponent) thermoView);
+        
         viewProvider = mock(SWTHostOverviewViewProvider.class);
-        when(osgi.getService(HostInfoDAO.class)).thenReturn(hostInfoDao);
-        when(osgi.getService(NetworkInterfaceInfoDAO.class)).thenReturn(
-                netIfaceDao);
         when(osgi.getService(HostOverviewViewProvider.class)).thenReturn(
                 viewProvider);
-
-        doReturn(controller).when(((HostOverviewViewPart) view))
-                .createController(any(HostRef.class), same(hostInfoDao),
-                        same(netIfaceDao), same(viewProvider));
-        when(controller.getView()).thenReturn((UIComponent) thermoView);
     }
 
     @Override
--- a/eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/VmClassStatViewPartTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/VmClassStatViewPartTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -37,8 +37,6 @@
 package com.redhat.thermostat.eclipse.test.views;
 
 import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.same;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -48,21 +46,21 @@
 import org.junit.Test;
 import org.mockito.InOrder;
 
+import com.redhat.thermostat.client.core.controllers.VmInformationServiceController;
 import com.redhat.thermostat.common.dao.HostRef;
-import com.redhat.thermostat.common.dao.VmClassStatDAO;
 import com.redhat.thermostat.common.dao.VmRef;
 import com.redhat.thermostat.eclipse.chart.vmclassstat.Activator;
 import com.redhat.thermostat.eclipse.chart.vmclassstat.SWTVmClassStatView;
 import com.redhat.thermostat.eclipse.chart.vmclassstat.SWTVmClassStatViewProvider;
 import com.redhat.thermostat.eclipse.chart.vmclassstat.VmClassStatViewPart;
 import com.redhat.thermostat.eclipse.internal.views.RefViewPart;
-import com.redhat.thermostat.vm.classstat.client.core.VmClassStatController;
+import com.redhat.thermostat.vm.classstat.client.core.VmClassStatService;
 import com.redhat.thermostat.vm.classstat.client.core.VmClassStatViewProvider;
 
 public class VmClassStatViewPartTest extends AbstractRefViewPartTest<VmRef> {
 
     private SWTVmClassStatViewProvider viewProvider;
-    private VmClassStatController controller;
+    private VmInformationServiceController controller;
 
     @Test
     public void testSelectionAfter() throws Exception {
@@ -84,17 +82,16 @@
 
     @Override
     protected void mockController() {
-        controller = mock(VmClassStatController.class);
+        VmClassStatService service = mock(VmClassStatService.class);
+        controller = mock(VmInformationServiceController.class);
         thermoView = mock(SWTVmClassStatView.class);
 
-        VmClassStatDAO classStatDao = mock(VmClassStatDAO.class);
+        when(osgi.getService(VmClassStatService.class)).thenReturn(service);
+        when(service.getInformationServiceController(any(VmRef.class))).thenReturn(controller);
+        when(controller.getView()).thenReturn(thermoView);
+        
         viewProvider = mock(SWTVmClassStatViewProvider.class);
-        when(osgi.getService(VmClassStatDAO.class)).thenReturn(classStatDao);
         when(osgi.getService(VmClassStatViewProvider.class)).thenReturn(viewProvider);
-
-        doReturn(controller).when(((VmClassStatViewPart) view)).createController(
-                same(classStatDao), any(VmRef.class), same(viewProvider));
-        when(controller.getView()).thenReturn(thermoView);
     }
 
     @Override
--- a/eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/VmCpuViewPartTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/VmCpuViewPartTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -37,8 +37,6 @@
 package com.redhat.thermostat.eclipse.test.views;
 
 import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.same;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -50,21 +48,21 @@
 import org.junit.Test;
 import org.mockito.InOrder;
 
+import com.redhat.thermostat.client.core.controllers.VmInformationServiceController;
 import com.redhat.thermostat.common.dao.HostRef;
-import com.redhat.thermostat.common.dao.VmCpuStatDAO;
 import com.redhat.thermostat.common.dao.VmRef;
 import com.redhat.thermostat.eclipse.ThermostatConstants;
 import com.redhat.thermostat.eclipse.chart.common.SWTVmCpuView;
 import com.redhat.thermostat.eclipse.chart.common.SWTVmCpuViewProvider;
 import com.redhat.thermostat.eclipse.chart.common.VmCpuViewPart;
 import com.redhat.thermostat.eclipse.internal.views.RefViewPart;
-import com.redhat.thermostat.vm.cpu.client.core.VmCpuController;
+import com.redhat.thermostat.vm.cpu.client.core.VmCpuService;
 import com.redhat.thermostat.vm.cpu.client.core.VmCpuViewProvider;
 
 public class VmCpuViewPartTest extends AbstractRefViewPartTest<VmRef> {
 
     private SWTVmCpuViewProvider viewProvider;
-    private VmCpuController controller;
+    private VmInformationServiceController controller;
 
     @Test
     public void testSelectionHostRef() throws Exception {
@@ -112,17 +110,16 @@
 
     @Override
     protected void mockController() {
-        controller = mock(VmCpuController.class);
+        VmCpuService service = mock(VmCpuService.class);
+        controller = mock(VmInformationServiceController.class);
         thermoView = mock(SWTVmCpuView.class);
+        
+        when(osgi.getService(VmCpuService.class)).thenReturn(service);
+        when(service.getInformationServiceController(any(VmRef.class))).thenReturn(controller);
+        when(controller.getView()).thenReturn(thermoView);
 
-        VmCpuStatDAO cpuStatDao = mock(VmCpuStatDAO.class);
         viewProvider = mock(SWTVmCpuViewProvider.class);
-        when(osgi.getService(VmCpuStatDAO.class)).thenReturn(cpuStatDao);
         when(osgi.getService(VmCpuViewProvider.class)).thenReturn(viewProvider);
-
-        doReturn(controller).when(((VmCpuViewPart) view)).createController(
-                same(cpuStatDao), any(VmRef.class), same(viewProvider));
-        when(controller.getView()).thenReturn(thermoView);
     }
 
     @Override
--- a/eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/VmGcViewPartTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/test/views/VmGcViewPartTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -37,8 +37,6 @@
 package com.redhat.thermostat.eclipse.test.views;
 
 import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.same;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -48,22 +46,21 @@
 import org.junit.Test;
 import org.mockito.InOrder;
 
+import com.redhat.thermostat.client.core.controllers.VmInformationServiceController;
 import com.redhat.thermostat.common.dao.HostRef;
-import com.redhat.thermostat.common.dao.VmGcStatDAO;
-import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
 import com.redhat.thermostat.common.dao.VmRef;
 import com.redhat.thermostat.eclipse.ThermostatConstants;
 import com.redhat.thermostat.eclipse.chart.common.SWTVmGcView;
 import com.redhat.thermostat.eclipse.chart.common.SWTVmGcViewProvider;
 import com.redhat.thermostat.eclipse.chart.common.VmGcViewPart;
 import com.redhat.thermostat.eclipse.internal.views.RefViewPart;
-import com.redhat.thermostat.vm.gc.client.core.VmGcController;
+import com.redhat.thermostat.vm.gc.client.core.VmGcService;
 import com.redhat.thermostat.vm.gc.client.core.VmGcViewProvider;
 
 public class VmGcViewPartTest extends AbstractRefViewPartTest<VmRef> {
 
     private SWTVmGcViewProvider viewProvider;
-    private VmGcController controller;
+    private VmInformationServiceController controller;
 
     @Test
     public void testSelectionAfter() throws Exception {
@@ -85,20 +82,16 @@
 
     @Override
     protected void mockController() {
-        controller = mock(VmGcController.class);
+        VmGcService service = mock(VmGcService.class);
+        controller = mock(VmInformationServiceController.class);
         thermoView = mock(SWTVmGcView.class);
 
-        VmMemoryStatDAO memStatDao = mock(VmMemoryStatDAO.class);
-        VmGcStatDAO gcStatDao = mock(VmGcStatDAO.class);
+        when(osgi.getService(VmGcService.class)).thenReturn(service);
+        when(service.getInformationServiceController(any(VmRef.class))).thenReturn(controller);
+        when(controller.getView()).thenReturn(thermoView);
+
         viewProvider = mock(SWTVmGcViewProvider.class);
-        when(osgi.getService(VmMemoryStatDAO.class)).thenReturn(memStatDao);
-        when(osgi.getService(VmGcStatDAO.class)).thenReturn(gcStatDao);
         when(osgi.getService(VmGcViewProvider.class)).thenReturn(viewProvider);
-
-        doReturn(controller).when(((VmGcViewPart) view)).createController(
-                same(memStatDao), same(gcStatDao), any(VmRef.class),
-                same(viewProvider));
-        when(controller.getView()).thenReturn(thermoView);
     }
 
     @Override
--- a/eclipse/com.redhat.thermostat.eclipse/META-INF/MANIFEST.MF	Fri Nov 30 10:47:45 2012 -0500
+++ b/eclipse/com.redhat.thermostat.eclipse/META-INF/MANIFEST.MF	Fri Nov 30 17:30:25 2012 -0500
@@ -10,6 +10,7 @@
 Require-Bundle: org.eclipse.core.runtime,
  org.eclipse.ui
 Import-Package: com.redhat.thermostat.client.core.views,
+ com.redhat.thermostat.client.core.controllers,
  com.redhat.thermostat.client.locale,
  com.redhat.thermostat.client.ui,
  com.redhat.thermostat.common,
--- a/eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/internal/views/HostOverviewViewPart.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/internal/views/HostOverviewViewPart.java	Fri Nov 30 17:30:25 2012 -0500
@@ -36,44 +36,27 @@
 
 package com.redhat.thermostat.eclipse.internal.views;
 
-import java.util.Objects;
-
 import org.eclipse.swt.widgets.Composite;
 
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.client.core.controllers.HostInformationServiceController;
 import com.redhat.thermostat.common.dao.HostRef;
-import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO;
 import com.redhat.thermostat.common.utils.OSGIUtils;
 import com.redhat.thermostat.eclipse.SWTComponent;
 import com.redhat.thermostat.eclipse.views.HostRefViewPart;
-import com.redhat.thermostat.host.overview.client.core.HostOverviewController;
+import com.redhat.thermostat.host.overview.client.core.HostOverviewService;
 import com.redhat.thermostat.host.overview.client.core.HostOverviewViewProvider;
 
 public class HostOverviewViewPart extends HostRefViewPart {
 
     @Override
     protected SWTComponent createControllerView(HostRef ref, Composite top) {
-        HostInfoDAO hostInfoDAO = OSGIUtils.getInstance().getService(
-                HostInfoDAO.class);
-        NetworkInterfaceInfoDAO networkInfoDAO = OSGIUtils.getInstance()
-                .getService(NetworkInterfaceInfoDAO.class);
         SWTHostOverviewViewProvider provider = (SWTHostOverviewViewProvider) OSGIUtils
                 .getInstance().getService(HostOverviewViewProvider.class);
         provider.setParent(top);
 
-        HostOverviewController controller = createController(ref, hostInfoDAO,
-                networkInfoDAO, provider);
+        HostOverviewService service = OSGIUtils.getInstance().getService(HostOverviewService.class);
+        HostInformationServiceController controller = service.getInformationServiceController(ref);
         return (SWTComponent) controller.getView();
     }
 
-    public HostOverviewController createController(HostRef ref,
-            HostInfoDAO hostInfoDAO, NetworkInterfaceInfoDAO networkInfoDAO,
-            HostOverviewViewProvider provider) {
-        ApplicationService appSvc = OSGIUtils.getInstance().getService(ApplicationService.class);
-        Objects.requireNonNull(appSvc);
-        return new HostOverviewController(appSvc, hostInfoDAO, networkInfoDAO, ref,
-                provider);
-    }
-
 }
--- a/host-cpu/client-core/pom.xml	Fri Nov 30 10:47:45 2012 -0500
+++ b/host-cpu/client-core/pom.xml	Fri Nov 30 17:30:25 2012 -0500
@@ -17,13 +17,16 @@
         <extensions>true</extensions>
         <configuration>
           <instructions>
-            <Private-Package></Private-Package>
             <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
             <Bundle-SymbolicName>com.redhat.thermostat.host.cpu.client.core</Bundle-SymbolicName>
+            <Bundle-Activator>com.redhat.thermostat.host.cpu.client.core.internal.Activator</Bundle-Activator>
             <Export-Package>
               com.redhat.thermostat.host.cpu.client.core,
               com.redhat.thermostat.host.cpu.client.locale
             </Export-Package>
+            <Private-Package>
+              com.redhat.thermostat.host.cpu.client.core.internal
+            </Private-Package>
             <!-- Do not autogenerate uses clauses in Manifests -->
             <_nouses>true</_nouses>
           </instructions>
--- a/host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/HostCpuController.java	Fri Nov 30 10:47:45 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +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.host.cpu.client.core;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import com.redhat.thermostat.client.core.controllers.HostInformationServiceController;
-import com.redhat.thermostat.client.core.views.BasicView.Action;
-import com.redhat.thermostat.client.core.views.UIComponent;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.NotImplementedException;
-import com.redhat.thermostat.common.Timer;
-import com.redhat.thermostat.common.Timer.SchedulingType;
-import com.redhat.thermostat.common.dao.CpuStatDAO;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
-import com.redhat.thermostat.common.dao.HostRef;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.host.cpu.client.locale.LocaleResources;
-import com.redhat.thermostat.storage.model.CpuStat;
-import com.redhat.thermostat.storage.model.DiscreteTimeData;
-import com.redhat.thermostat.storage.model.HostInfo;
-
-public class HostCpuController implements HostInformationServiceController {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private final HostCpuView view;
-    private final Timer backgroundUpdateTimer;
-
-    private final HostInfoDAO hostInfoDAO;
-    private final CpuStatDAO cpuStatDAO;
-    private final HostRef ref;
-
-    private int chartsAdded = 0;
-    private long lastSeenTimeStamp = Long.MIN_VALUE;
-
-    public HostCpuController(ApplicationService appSvc, HostInfoDAO hostInfoDao, CpuStatDAO cpuStatDAO, HostRef ref, HostCpuViewProvider provider) {
-        this.ref = ref;
-        view = provider.createView();
-        view.clearCpuUsageData();
-        this.hostInfoDAO = hostInfoDao;
-        this.cpuStatDAO = cpuStatDAO;
-
-        backgroundUpdateTimer = appSvc.getTimerFactory().createTimer();
-        backgroundUpdateTimer.setAction(new Runnable() {
-
-            @Override
-            public void run() {
-                updateView();
-            }
-
-        });
-        backgroundUpdateTimer.setInitialDelay(0);
-        backgroundUpdateTimer.setDelay(5);
-        backgroundUpdateTimer.setTimeUnit(TimeUnit.SECONDS);
-        backgroundUpdateTimer.setSchedulingType(SchedulingType.FIXED_RATE);
-
-        view.addActionListener(new ActionListener<HostCpuView.Action>() {
-            @Override
-            public void actionPerformed(ActionEvent<Action> actionEvent) {
-                switch (actionEvent.getActionId()) {
-                    case VISIBLE:
-                        start();
-                        break;
-                    case HIDDEN:
-                        stop();
-                        break;
-                    default:
-                        throw new NotImplementedException("unhandled action: " + actionEvent.getActionId());
-                }
-            }
-        });
-
-    }
-
-    // TODO: Consider doing this in a background thread (move to view and use SwingWorker or such).
-    private void updateView() {
-        HostInfo hostInfo = hostInfoDAO.getHostInfo(ref);
-
-        view.setCpuCount(String.valueOf(hostInfo.getCpuCount()));
-        view.setCpuModel(hostInfo.getCpuModel());
-
-        doCpuChartUpdate();
-    }
-
-    private void start() {
-        backgroundUpdateTimer.start();
-    }
-
-    private void stop() {
-        backgroundUpdateTimer.stop();
-    }
-
-    private void doCpuChartUpdate() {
-        List<CpuStat> cpuStats = cpuStatDAO.getLatestCpuStats(ref, lastSeenTimeStamp);
-        List<List<DiscreteTimeData<Double>>> results = new ArrayList<>();
-        for (CpuStat stat : cpuStats) {
-            double[] data = stat.getPerProcessorUsage();
-            for (int i = 0 ; i < data.length; i++) {
-                if (results.size() == i) {
-                    results.add(new ArrayList<DiscreteTimeData<Double>>());
-                }
-                results.get(i).add(new DiscreteTimeData<Double>(stat.getTimeStamp(), data[i]));
-                lastSeenTimeStamp = Math.max(lastSeenTimeStamp, stat.getTimeStamp());
-            }
-        }
-
-        for (int i = 0; i < results.size(); i++) {
-            if (i == chartsAdded) {
-                view.addCpuUsageChart(i, translator.localize(LocaleResources.HOST_CPU_ID, String.valueOf(i)));
-                chartsAdded++;
-            }
-            view.addCpuUsageData(i, results.get(i));
-        }
-    }
-
-    public UIComponent getView() {
-        return view;
-    }
-
-    @Override
-    public String getLocalizedName() {
-        return translator.localize(LocaleResources.HOST_INFO_TAB_CPU);
-    }
-
-}
--- a/host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/HostCpuService.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/HostCpuService.java	Fri Nov 30 17:30:25 2012 -0500
@@ -44,6 +44,7 @@
 import com.redhat.thermostat.common.dao.HostInfoDAO;
 import com.redhat.thermostat.common.dao.HostRef;
 import com.redhat.thermostat.common.utils.OSGIUtils;
+import com.redhat.thermostat.host.cpu.client.core.internal.HostCpuController;
 
 public class HostCpuService implements HostInformationService {
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/internal/Activator.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,96 @@
+/*
+ * 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.host.cpu.client.core.internal;
+
+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.HostInformationService;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.MultipleServiceTracker;
+import com.redhat.thermostat.common.MultipleServiceTracker.Action;
+import com.redhat.thermostat.common.dao.CpuStatDAO;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.host.cpu.client.core.HostCpuService;
+
+public class Activator implements BundleActivator {
+    
+    private MultipleServiceTracker tracker;
+    private ServiceRegistration reg;
+
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        Class<?>[] deps = new Class<?>[] {
+            HostInfoDAO.class,
+            CpuStatDAO.class,
+            ApplicationService.class
+        };
+
+        tracker = new MultipleServiceTracker(context, deps, new Action() {
+
+            @Override
+            public void dependenciesAvailable(Map<String, Object> services) {
+                HostInfoDAO hostInfoDAO = (HostInfoDAO) services.get(HostInfoDAO.class.getName());
+                Objects.requireNonNull(hostInfoDAO);
+                CpuStatDAO cpuStatDAO = (CpuStatDAO) services.get(CpuStatDAO.class.getName());
+                Objects.requireNonNull(cpuStatDAO);
+                ApplicationService appSvc = (ApplicationService) services.get(ApplicationService.class.getName());
+                Objects.requireNonNull(appSvc);
+                HostCpuService service = new HostCpuService(appSvc, hostInfoDAO, cpuStatDAO);
+                reg = context.registerService(HostInformationService.class.getName(), service, null);
+            }
+
+            @Override
+            public void dependenciesUnavailable() {
+                reg.unregister();
+            }
+
+        });
+        tracker.open();
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        tracker.close();
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host-cpu/client-core/src/main/java/com/redhat/thermostat/host/cpu/client/core/internal/HostCpuController.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,166 @@
+/*
+ * 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.host.cpu.client.core.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import com.redhat.thermostat.client.core.controllers.HostInformationServiceController;
+import com.redhat.thermostat.client.core.views.BasicView.Action;
+import com.redhat.thermostat.client.core.views.UIComponent;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.NotImplementedException;
+import com.redhat.thermostat.common.Timer;
+import com.redhat.thermostat.common.Timer.SchedulingType;
+import com.redhat.thermostat.common.dao.CpuStatDAO;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.common.dao.HostRef;
+import com.redhat.thermostat.common.locale.Translate;
+import com.redhat.thermostat.host.cpu.client.core.HostCpuView;
+import com.redhat.thermostat.host.cpu.client.core.HostCpuViewProvider;
+import com.redhat.thermostat.host.cpu.client.locale.LocaleResources;
+import com.redhat.thermostat.storage.model.CpuStat;
+import com.redhat.thermostat.storage.model.DiscreteTimeData;
+import com.redhat.thermostat.storage.model.HostInfo;
+
+public class HostCpuController implements HostInformationServiceController {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private final HostCpuView view;
+    private final Timer backgroundUpdateTimer;
+
+    private final HostInfoDAO hostInfoDAO;
+    private final CpuStatDAO cpuStatDAO;
+    private final HostRef ref;
+
+    private int chartsAdded = 0;
+    private long lastSeenTimeStamp = Long.MIN_VALUE;
+
+    public HostCpuController(ApplicationService appSvc, HostInfoDAO hostInfoDao, CpuStatDAO cpuStatDAO, HostRef ref, HostCpuViewProvider provider) {
+        this.ref = ref;
+        view = provider.createView();
+        view.clearCpuUsageData();
+        this.hostInfoDAO = hostInfoDao;
+        this.cpuStatDAO = cpuStatDAO;
+
+        backgroundUpdateTimer = appSvc.getTimerFactory().createTimer();
+        backgroundUpdateTimer.setAction(new Runnable() {
+
+            @Override
+            public void run() {
+                updateView();
+            }
+
+        });
+        backgroundUpdateTimer.setInitialDelay(0);
+        backgroundUpdateTimer.setDelay(5);
+        backgroundUpdateTimer.setTimeUnit(TimeUnit.SECONDS);
+        backgroundUpdateTimer.setSchedulingType(SchedulingType.FIXED_RATE);
+
+        view.addActionListener(new ActionListener<HostCpuView.Action>() {
+            @Override
+            public void actionPerformed(ActionEvent<Action> actionEvent) {
+                switch (actionEvent.getActionId()) {
+                    case VISIBLE:
+                        start();
+                        break;
+                    case HIDDEN:
+                        stop();
+                        break;
+                    default:
+                        throw new NotImplementedException("unhandled action: " + actionEvent.getActionId());
+                }
+            }
+        });
+
+    }
+
+    // TODO: Consider doing this in a background thread (move to view and use SwingWorker or such).
+    private void updateView() {
+        HostInfo hostInfo = hostInfoDAO.getHostInfo(ref);
+
+        view.setCpuCount(String.valueOf(hostInfo.getCpuCount()));
+        view.setCpuModel(hostInfo.getCpuModel());
+
+        doCpuChartUpdate();
+    }
+
+    private void start() {
+        backgroundUpdateTimer.start();
+    }
+
+    private void stop() {
+        backgroundUpdateTimer.stop();
+    }
+
+    private void doCpuChartUpdate() {
+        List<CpuStat> cpuStats = cpuStatDAO.getLatestCpuStats(ref, lastSeenTimeStamp);
+        List<List<DiscreteTimeData<Double>>> results = new ArrayList<>();
+        for (CpuStat stat : cpuStats) {
+            double[] data = stat.getPerProcessorUsage();
+            for (int i = 0 ; i < data.length; i++) {
+                if (results.size() == i) {
+                    results.add(new ArrayList<DiscreteTimeData<Double>>());
+                }
+                results.get(i).add(new DiscreteTimeData<Double>(stat.getTimeStamp(), data[i]));
+                lastSeenTimeStamp = Math.max(lastSeenTimeStamp, stat.getTimeStamp());
+            }
+        }
+
+        for (int i = 0; i < results.size(); i++) {
+            if (i == chartsAdded) {
+                view.addCpuUsageChart(i, translator.localize(LocaleResources.HOST_CPU_ID, String.valueOf(i)));
+                chartsAdded++;
+            }
+            view.addCpuUsageData(i, results.get(i));
+        }
+    }
+
+    public UIComponent getView() {
+        return view;
+    }
+
+    @Override
+    public String getLocalizedName() {
+        return translator.localize(LocaleResources.HOST_INFO_TAB_CPU);
+    }
+
+}
--- a/host-cpu/client-core/src/test/java/com/redhat/thermostat/host/cpu/client/core/HostCpuControllerTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +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.host.cpu.client.core;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isNotNull;
-import static org.mockito.Mockito.doNothing;
-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 java.util.concurrent.TimeUnit;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.Timer;
-import com.redhat.thermostat.common.Timer.SchedulingType;
-import com.redhat.thermostat.common.TimerFactory;
-import com.redhat.thermostat.common.dao.CpuStatDAO;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
-import com.redhat.thermostat.common.dao.HostRef;
-import com.redhat.thermostat.host.cpu.client.core.HostCpuController;
-import com.redhat.thermostat.host.cpu.client.core.HostCpuView;
-import com.redhat.thermostat.host.cpu.client.core.HostCpuViewProvider;
-import com.redhat.thermostat.storage.model.CpuStat;
-import com.redhat.thermostat.storage.model.DiscreteTimeData;
-import com.redhat.thermostat.storage.model.HostInfo;
-
-public class HostCpuControllerTest {
-
-    @SuppressWarnings("unused")
-    private HostCpuController controller;
-
-    private HostCpuView view;
-
-    private Timer timer;
-
-    private ActionListener<HostCpuView.Action> viewListener;
-    private Runnable timerAction;
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    @Before
-    public void setUp() {
-        // Setup timer.
-        timer = mock(Timer.class);
-        ArgumentCaptor<Runnable> actionCaptor = ArgumentCaptor.forClass(Runnable.class);
-        doNothing().when(timer).setAction(actionCaptor.capture());
-
-        TimerFactory timerFactory = mock(TimerFactory.class);
-        when(timerFactory.createTimer()).thenReturn(timer);
-        ApplicationService appSvc = mock(ApplicationService.class);
-        when(appSvc.getTimerFactory()).thenReturn(timerFactory);
-
-        // Setup DAOs.
-        HostInfo hostInfo = new HostInfo("fluffhost1", "fluffOs1", "fluffKernel1", "fluffCpu1", 12345, 98765);
-        HostInfoDAO hostInfoDAO = mock(HostInfoDAO.class);
-        when(hostInfoDAO.getHostInfo(any(HostRef.class))).thenReturn(hostInfo);
-
-        CpuStat cpuStat1 = new CpuStat(1l, new double[] {10.0, 20.0, 30.0});
-        CpuStat cpuStat2 = new CpuStat(2l, new double[] {15.0, 25.0, 35.0});
-        CpuStatDAO cpuStatDAO = mock(CpuStatDAO.class);
-        when(cpuStatDAO.getLatestCpuStats(any(HostRef.class), anyLong())).thenReturn(Arrays.asList(cpuStat1, cpuStat2));
-
-        // Set up View
-        view = mock(HostCpuView.class);
-        ArgumentCaptor<ActionListener> viewArgumentCaptor = ArgumentCaptor.forClass(ActionListener.class);
-        doNothing().when(view).addActionListener(viewArgumentCaptor.capture());
-        HostCpuViewProvider viewProvider = mock(HostCpuViewProvider.class);
-        when(viewProvider.createView()).thenReturn(view);
-
-        HostRef host = new HostRef("123", "fluffhost");
-        controller = new HostCpuController(appSvc, hostInfoDAO, cpuStatDAO, host, viewProvider);
-
-        timerAction = actionCaptor.getValue();
-        viewListener = viewArgumentCaptor.getValue();
-    }
-
-    @After
-    public void tearDown() {
-        timerAction = null;
-        controller = null;
-        view = null;
-        timer = null;
-    }
-
-    @Test
-    public void testTimer() {
-        viewListener.actionPerformed(new ActionEvent<>(view, HostCpuView.Action.VISIBLE));
-
-        verify(timer).setAction(isNotNull(Runnable.class));
-        verify(timer).setDelay(5);
-        verify(timer).setTimeUnit(TimeUnit.SECONDS);
-        verify(timer).setInitialDelay(0);
-        verify(timer).setSchedulingType(SchedulingType.FIXED_RATE);
-        verify(timer).start();
-
-        viewListener.actionPerformed(new ActionEvent<>(view, HostCpuView.Action.HIDDEN));
-
-        verify(timer).stop();
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public void testTimerAction() {
-        timerAction.run();
-        verify(view).setCpuModel("fluffCpu1");
-        verify(view).setCpuCount("12345");
-        @SuppressWarnings("rawtypes")
-        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
-        verify(view).addCpuUsageChart(eq(0), anyString());
-        verify(view).addCpuUsageData(eq(0), captor.capture());
-        List<DiscreteTimeData<Double>> cpuLoadData = captor.getValue();
-        assertEquals(1, cpuLoadData.get(0).getTimeInMillis());
-        assertEquals(10.0, cpuLoadData.get(0).getData().doubleValue(), 0.0001);
-        assertEquals(2, cpuLoadData.get(1).getTimeInMillis());
-        assertEquals(15.0, cpuLoadData.get(1).getData().doubleValue(), 0.0001);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host-cpu/client-core/src/test/java/com/redhat/thermostat/host/cpu/client/core/internal/ActivatorTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -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.host.cpu.client.core.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.client.core.HostInformationService;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.dao.CpuStatDAO;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.host.cpu.client.core.HostCpuService;
+import com.redhat.thermostat.test.StubBundleContext;
+
+public class ActivatorTest {
+    
+    @Test
+    public void verifyActivatorDoesNotRegisterServiceOnMissingDeps() throws Exception {
+        StubBundleContext context = new StubBundleContext();
+
+        Activator activator = new Activator();
+
+        activator.start(context);
+
+        assertEquals(0, context.getAllServices().size());
+        assertNotSame(1, context.getServiceListeners().size());
+
+        activator.stop(context);
+    }
+
+    @Test
+    public void verifyActivatorRegistersServices() throws Exception {
+        StubBundleContext context = new StubBundleContext();
+        HostInfoDAO hostInfoDAO = mock(HostInfoDAO.class);
+        CpuStatDAO cpuStatDAO = mock(CpuStatDAO.class);
+        ApplicationService appSvc = mock(ApplicationService.class);
+
+        context.registerService(HostInfoDAO.class, hostInfoDAO, null);
+        context.registerService(CpuStatDAO.class, cpuStatDAO, null);
+        context.registerService(ApplicationService.class, appSvc, null);
+
+        Activator activator = new Activator();
+
+        activator.start(context);
+
+        assertTrue(context.isServiceRegistered(HostInformationService.class.getName(), HostCpuService.class));
+
+        activator.stop(context);
+
+        assertEquals(0, context.getServiceListeners().size());
+        assertEquals(3, context.getAllServices().size());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host-cpu/client-core/src/test/java/com/redhat/thermostat/host/cpu/client/core/internal/HostCpuControllerTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,164 @@
+/*
+ * 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.host.cpu.client.core.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNotNull;
+import static org.mockito.Mockito.doNothing;
+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 java.util.concurrent.TimeUnit;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.Timer;
+import com.redhat.thermostat.common.Timer.SchedulingType;
+import com.redhat.thermostat.common.TimerFactory;
+import com.redhat.thermostat.common.dao.CpuStatDAO;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.common.dao.HostRef;
+import com.redhat.thermostat.host.cpu.client.core.HostCpuView;
+import com.redhat.thermostat.host.cpu.client.core.HostCpuViewProvider;
+import com.redhat.thermostat.host.cpu.client.core.internal.HostCpuController;
+import com.redhat.thermostat.storage.model.CpuStat;
+import com.redhat.thermostat.storage.model.DiscreteTimeData;
+import com.redhat.thermostat.storage.model.HostInfo;
+
+public class HostCpuControllerTest {
+
+    @SuppressWarnings("unused")
+    private HostCpuController controller;
+
+    private HostCpuView view;
+
+    private Timer timer;
+
+    private ActionListener<HostCpuView.Action> viewListener;
+    private Runnable timerAction;
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Before
+    public void setUp() {
+        // Setup timer.
+        timer = mock(Timer.class);
+        ArgumentCaptor<Runnable> actionCaptor = ArgumentCaptor.forClass(Runnable.class);
+        doNothing().when(timer).setAction(actionCaptor.capture());
+
+        TimerFactory timerFactory = mock(TimerFactory.class);
+        when(timerFactory.createTimer()).thenReturn(timer);
+        ApplicationService appSvc = mock(ApplicationService.class);
+        when(appSvc.getTimerFactory()).thenReturn(timerFactory);
+
+        // Setup DAOs.
+        HostInfo hostInfo = new HostInfo("fluffhost1", "fluffOs1", "fluffKernel1", "fluffCpu1", 12345, 98765);
+        HostInfoDAO hostInfoDAO = mock(HostInfoDAO.class);
+        when(hostInfoDAO.getHostInfo(any(HostRef.class))).thenReturn(hostInfo);
+
+        CpuStat cpuStat1 = new CpuStat(1l, new double[] {10.0, 20.0, 30.0});
+        CpuStat cpuStat2 = new CpuStat(2l, new double[] {15.0, 25.0, 35.0});
+        CpuStatDAO cpuStatDAO = mock(CpuStatDAO.class);
+        when(cpuStatDAO.getLatestCpuStats(any(HostRef.class), anyLong())).thenReturn(Arrays.asList(cpuStat1, cpuStat2));
+
+        // Set up View
+        view = mock(HostCpuView.class);
+        ArgumentCaptor<ActionListener> viewArgumentCaptor = ArgumentCaptor.forClass(ActionListener.class);
+        doNothing().when(view).addActionListener(viewArgumentCaptor.capture());
+        HostCpuViewProvider viewProvider = mock(HostCpuViewProvider.class);
+        when(viewProvider.createView()).thenReturn(view);
+
+        HostRef host = new HostRef("123", "fluffhost");
+        controller = new HostCpuController(appSvc, hostInfoDAO, cpuStatDAO, host, viewProvider);
+
+        timerAction = actionCaptor.getValue();
+        viewListener = viewArgumentCaptor.getValue();
+    }
+
+    @After
+    public void tearDown() {
+        timerAction = null;
+        controller = null;
+        view = null;
+        timer = null;
+    }
+
+    @Test
+    public void testTimer() {
+        viewListener.actionPerformed(new ActionEvent<>(view, HostCpuView.Action.VISIBLE));
+
+        verify(timer).setAction(isNotNull(Runnable.class));
+        verify(timer).setDelay(5);
+        verify(timer).setTimeUnit(TimeUnit.SECONDS);
+        verify(timer).setInitialDelay(0);
+        verify(timer).setSchedulingType(SchedulingType.FIXED_RATE);
+        verify(timer).start();
+
+        viewListener.actionPerformed(new ActionEvent<>(view, HostCpuView.Action.HIDDEN));
+
+        verify(timer).stop();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testTimerAction() {
+        timerAction.run();
+        verify(view).setCpuModel("fluffCpu1");
+        verify(view).setCpuCount("12345");
+        @SuppressWarnings("rawtypes")
+        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
+        verify(view).addCpuUsageChart(eq(0), anyString());
+        verify(view).addCpuUsageData(eq(0), captor.capture());
+        List<DiscreteTimeData<Double>> cpuLoadData = captor.getValue();
+        assertEquals(1, cpuLoadData.get(0).getTimeInMillis());
+        assertEquals(10.0, cpuLoadData.get(0).getData().doubleValue(), 0.0001);
+        assertEquals(2, cpuLoadData.get(1).getTimeInMillis());
+        assertEquals(15.0, cpuLoadData.get(1).getData().doubleValue(), 0.0001);
+    }
+}
--- a/host-cpu/client-swing/src/main/java/com/redhat/thermostat/host/cpu/client/swing/Activator.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/host-cpu/client-swing/src/main/java/com/redhat/thermostat/host/cpu/client/swing/Activator.java	Fri Nov 30 17:30:25 2012 -0500
@@ -36,64 +36,22 @@
 
 package com.redhat.thermostat.host.cpu.client.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.HostInformationService;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.MultipleServiceTracker;
-import com.redhat.thermostat.common.MultipleServiceTracker.Action;
-import com.redhat.thermostat.common.dao.CpuStatDAO;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
-import com.redhat.thermostat.host.cpu.client.core.HostCpuService;
 import com.redhat.thermostat.host.cpu.client.core.HostCpuViewProvider;
 
 public class Activator implements BundleActivator {
     
-    private MultipleServiceTracker tracker;
-    private ServiceRegistration reg;
-
     @Override
-    public void start(final BundleContext context) throws Exception {
+    public void start(BundleContext context) throws Exception {
         HostCpuViewProvider viewProvider = new SwingHostCpuViewProvider();
+        // Unregistered on Activator.stop
         context.registerService(HostCpuViewProvider.class.getName(), viewProvider, null);
-
-        Class<?>[] deps = new Class<?>[] {
-            HostInfoDAO.class,
-            CpuStatDAO.class,
-            ApplicationService.class
-        };
-
-        tracker = new MultipleServiceTracker(context, deps, new Action() {
-
-            @Override
-            public void dependenciesAvailable(Map<String, Object> services) {
-                HostInfoDAO hostInfoDAO = (HostInfoDAO) services.get(HostInfoDAO.class.getName());
-                Objects.requireNonNull(hostInfoDAO);
-                CpuStatDAO cpuStatDAO = (CpuStatDAO) services.get(CpuStatDAO.class.getName());
-                Objects.requireNonNull(cpuStatDAO);
-                ApplicationService appSvc = (ApplicationService) services.get(ApplicationService.class.getName());
-                Objects.requireNonNull(appSvc);
-                HostCpuService service = new HostCpuService(appSvc, hostInfoDAO, cpuStatDAO);
-                reg = context.registerService(HostInformationService.class.getName(), service, null);
-            }
-
-            @Override
-            public void dependenciesUnavailable() {
-                reg.unregister();
-            }
-
-        });
-        tracker.open();
     }
 
     @Override
     public void stop(BundleContext context) throws Exception {
-        tracker.close();
     }
 
 }
--- a/host-cpu/client-swing/src/test/java/com/redhat/thermostat/host/cpu/client/swing/ActivatorTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/host-cpu/client-swing/src/test/java/com/redhat/thermostat/host/cpu/client/swing/ActivatorTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -37,65 +37,16 @@
 package com.redhat.thermostat.host.cpu.client.swing;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
 
 import org.junit.Test;
 
-import com.redhat.thermostat.client.core.HostInformationService;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.dao.CpuStatDAO;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
-import com.redhat.thermostat.host.cpu.client.core.HostCpuService;
 import com.redhat.thermostat.host.cpu.client.core.HostCpuViewProvider;
-import com.redhat.thermostat.host.cpu.client.swing.Activator;
-import com.redhat.thermostat.host.cpu.client.swing.SwingHostCpuViewProvider;
 import com.redhat.thermostat.test.StubBundleContext;
 
 public class ActivatorTest {
     
     @Test
-    public void verifyActivatorDoesNotRegisterServiceOnMissingDeps() throws Exception {
-        StubBundleContext context = new StubBundleContext();
-
-        Activator activator = new Activator();
-
-        activator.start(context);
-
-        // View provider registers unconditionally
-        assertEquals(1, context.getAllServices().size());
-        assertNotSame(1, context.getServiceListeners().size());
-
-        activator.stop(context);
-
-        assertEquals(0, context.getServiceListeners().size());
-    }
-
-    @Test
-    public void verifyActivatorRegistersServices() throws Exception {
-        StubBundleContext context = new StubBundleContext();
-        HostInfoDAO hostInfoDAO = mock(HostInfoDAO.class);
-        CpuStatDAO cpuStatDAO = mock(CpuStatDAO.class);
-        ApplicationService appSvc = mock(ApplicationService.class);
-
-        context.registerService(HostInfoDAO.class, hostInfoDAO, null);
-        context.registerService(CpuStatDAO.class, cpuStatDAO, null);
-        context.registerService(ApplicationService.class, appSvc, null);
-
-        Activator activator = new Activator();
-
-        activator.start(context);
-
-        assertTrue(context.isServiceRegistered(HostInformationService.class.getName(), HostCpuService.class));
-
-        activator.stop(context);
-
-        assertEquals(0, context.getServiceListeners().size());
-        assertEquals(4, context.getAllServices().size());
-    }
-
-    @Test
     public void verifyStartRegistersViewProvider() throws Exception {
         StubBundleContext ctx = new StubBundleContext();
         Activator activator = new Activator();
--- a/host-memory/client-core/pom.xml	Fri Nov 30 10:47:45 2012 -0500
+++ b/host-memory/client-core/pom.xml	Fri Nov 30 17:30:25 2012 -0500
@@ -17,13 +17,16 @@
         <extensions>true</extensions>
         <configuration>
           <instructions>
-            <Private-Package></Private-Package>
             <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
             <Bundle-SymbolicName>com.redhat.thermostat.host.memory.client.core</Bundle-SymbolicName>
+            <Bundle-Activator>com.redhat.thermostat.host.memory.client.core.internal.Activator</Bundle-Activator>
             <Export-Package>
               com.redhat.thermostat.host.memory.client.core,
               com.redhat.thermostat.host.memory.client.locale
             </Export-Package>
+            <Private-Package>
+              com.redhat.thermostat.host.memory.client.core.internal
+            </Private-Package>
             <!-- Do not autogenerate uses clauses in Manifests -->
             <_nouses>true</_nouses>
           </instructions>
--- a/host-memory/client-core/src/main/java/com/redhat/thermostat/host/memory/client/core/HostMemoryController.java	Fri Nov 30 10:47:45 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +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.host.memory.client.core;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import com.redhat.thermostat.client.core.controllers.HostInformationServiceController;
-import com.redhat.thermostat.client.core.views.BasicView.Action;
-import com.redhat.thermostat.client.core.views.UIComponent;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.NotImplementedException;
-import com.redhat.thermostat.common.Timer;
-import com.redhat.thermostat.common.Timer.SchedulingType;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
-import com.redhat.thermostat.common.dao.HostRef;
-import com.redhat.thermostat.common.dao.MemoryStatDAO;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.common.utils.DisplayableValues;
-import com.redhat.thermostat.host.memory.client.core.HostMemoryView.GraphVisibilityChangeListener;
-import com.redhat.thermostat.host.memory.client.locale.LocaleResources;
-import com.redhat.thermostat.storage.model.DiscreteTimeData;
-import com.redhat.thermostat.storage.model.MemoryStat;
-import com.redhat.thermostat.storage.model.MemoryType;
-
-public class HostMemoryController implements HostInformationServiceController {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private final HostMemoryView view;
-
-    private final HostInfoDAO hostInfoDAO;
-    private final MemoryStatDAO memoryStatDAO;
-    private final HostRef ref;
-
-    private final Timer backgroundUpdateTimer;
-    private final GraphVisibilityChangeListener listener = new ShowHideGraph();
-
-    private long lastSeenTimeStamp = Long.MIN_VALUE;
-
-    public HostMemoryController(ApplicationService appSvc, HostInfoDAO hostInfoDAO, MemoryStatDAO memoryStatDAO, final HostRef ref, HostMemoryViewProvider provider) {
-        this.ref = ref;
-        this.hostInfoDAO = hostInfoDAO;
-        this.memoryStatDAO = memoryStatDAO;
-
-        view = provider.createView();
-
-        view.addMemoryChart(MemoryType.MEMORY_TOTAL.name(), translator.localize(LocaleResources.HOST_MEMORY_TOTAL));
-        view.addMemoryChart(MemoryType.MEMORY_FREE.name(), translator.localize(LocaleResources.HOST_MEMORY_FREE));
-        view.addMemoryChart(MemoryType.MEMORY_USED.name(), translator.localize(LocaleResources.HOST_MEMORY_USED));
-        view.addMemoryChart(MemoryType.SWAP_TOTAL.name(), translator.localize(LocaleResources.HOST_SWAP_TOTAL));
-        view.addMemoryChart(MemoryType.SWAP_FREE.name(), translator.localize(LocaleResources.HOST_SWAP_FREE));
-        view.addMemoryChart(MemoryType.BUFFERS.name(), translator.localize(LocaleResources.HOST_BUFFERS));
-
-        view.addGraphVisibilityListener(listener);
-        view.addActionListener(new ActionListener<HostMemoryView.Action>() {
-            @Override
-            public void actionPerformed(ActionEvent<Action> actionEvent) {
-                switch (actionEvent.getActionId()) {
-                    case HIDDEN:
-                        stopBackgroundUpdates();
-                        break;
-                    case VISIBLE:
-                        startBackgroundUpdates();
-                        break;
-                    default:
-                        throw new NotImplementedException("action event not handled: " + actionEvent.getActionId());
-                }
-            }
-        });
-
-        backgroundUpdateTimer = appSvc.getTimerFactory().createTimer();
-        backgroundUpdateTimer.setAction(new Runnable() {
-            @Override
-            public void run() {
-                long memorySize = HostMemoryController.this.hostInfoDAO.getHostInfo(ref).getTotalMemory();
-                String[] memorySizeParts = DisplayableValues.bytes(memorySize);
-                view.setTotalMemory(translator.localize(LocaleResources.NUMBER_AND_UNIT, memorySizeParts[0], memorySizeParts[1]));
-                doMemoryChartUpdate();
-            }
-        });
-        backgroundUpdateTimer.setSchedulingType(SchedulingType.FIXED_RATE);
-        backgroundUpdateTimer.setTimeUnit(TimeUnit.SECONDS);
-        backgroundUpdateTimer.setInitialDelay(0);
-        backgroundUpdateTimer.setDelay(5);
-    }
-
-    private void startBackgroundUpdates() {
-        for (MemoryType type : MemoryType.values()) {
-            view.showMemoryChart(type.name());
-        }
-
-        backgroundUpdateTimer.start();
-    }
-
-    private void stopBackgroundUpdates() {
-        backgroundUpdateTimer.stop();
-        for (MemoryType type : MemoryType.values()) {
-            view.hideMemoryChart(type.name());
-        }
-    }
-
-    public UIComponent getView() {
-        return view;
-    }
-
-    private void doMemoryChartUpdate() {
-        List<DiscreteTimeData<? extends Number>> memFree = new LinkedList<>();
-        List<DiscreteTimeData<? extends Number>> memTotal = new LinkedList<>();
-        List<DiscreteTimeData<? extends Number>> memUsed = new LinkedList<>();
-        List<DiscreteTimeData<? extends Number>> buf = new LinkedList<>();
-        List<DiscreteTimeData<? extends Number>> swapTotal = new LinkedList<>();
-        List<DiscreteTimeData<? extends Number>> swapFree = new LinkedList<>();
-
-        for (MemoryStat stat : memoryStatDAO.getLatestMemoryStats(ref, lastSeenTimeStamp)) {
-            long timeStamp = stat.getTimeStamp();
-            memFree.add(new DiscreteTimeData<Long>(timeStamp, stat.getFree()));
-            memTotal.add(new DiscreteTimeData<Long>(timeStamp, stat.getTotal()));
-            memUsed.add(new DiscreteTimeData<Long>(timeStamp, stat.getTotal() - stat.getFree()));
-            buf.add(new DiscreteTimeData<Long>(timeStamp, stat.getBuffers()));
-            swapTotal.add(new DiscreteTimeData<Long>(timeStamp, stat.getSwapTotal()));
-            swapFree.add(new DiscreteTimeData<Long>(timeStamp, stat.getSwapFree()));
-            lastSeenTimeStamp = Math.max(lastSeenTimeStamp, stat.getTimeStamp());
-        }
-
-        view.addMemoryData(MemoryType.MEMORY_FREE.name(), memFree);
-        view.addMemoryData(MemoryType.MEMORY_TOTAL.name(), memTotal);
-        view.addMemoryData(MemoryType.MEMORY_USED.name(), memUsed);
-        view.addMemoryData(MemoryType.BUFFERS.name(), buf);
-        view.addMemoryData(MemoryType.SWAP_FREE.name(), swapFree);
-        view.addMemoryData(MemoryType.SWAP_TOTAL.name(), swapTotal);
-    }
-
-    private class ShowHideGraph implements GraphVisibilityChangeListener {
-        @Override
-        public void show(String tag) {
-            view.showMemoryChart(tag);
-        }
-        @Override
-        public void hide(String tag) {
-            view.hideMemoryChart(tag);
-        }
-    }
-
-    @Override
-    public String getLocalizedName() {
-        return translator.localize(LocaleResources.HOST_INFO_TAB_MEMORY);
-    }
-}
--- a/host-memory/client-core/src/main/java/com/redhat/thermostat/host/memory/client/core/HostMemoryService.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/host-memory/client-core/src/main/java/com/redhat/thermostat/host/memory/client/core/HostMemoryService.java	Fri Nov 30 17:30:25 2012 -0500
@@ -44,6 +44,7 @@
 import com.redhat.thermostat.common.dao.HostRef;
 import com.redhat.thermostat.common.dao.MemoryStatDAO;
 import com.redhat.thermostat.common.utils.OSGIUtils;
+import com.redhat.thermostat.host.memory.client.core.internal.HostMemoryController;
 
 public class HostMemoryService implements HostInformationService {
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host-memory/client-core/src/main/java/com/redhat/thermostat/host/memory/client/core/internal/Activator.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,96 @@
+/*
+ * 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.host.memory.client.core.internal;
+
+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.HostInformationService;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.MultipleServiceTracker;
+import com.redhat.thermostat.common.MultipleServiceTracker.Action;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.common.dao.MemoryStatDAO;
+import com.redhat.thermostat.host.memory.client.core.HostMemoryService;
+
+public class Activator implements BundleActivator {
+    
+    private MultipleServiceTracker tracker;
+    private ServiceRegistration reg;
+
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        Class<?>[] deps = new Class<?>[] {
+            HostInfoDAO.class,
+            MemoryStatDAO.class,
+            ApplicationService.class
+        };
+
+        tracker = new MultipleServiceTracker(context, deps, new Action() {
+
+            @Override
+            public void dependenciesAvailable(Map<String, Object> services) {
+                HostInfoDAO hostInfoDAO = (HostInfoDAO) services.get(HostInfoDAO.class.getName());
+                Objects.requireNonNull(hostInfoDAO);
+                MemoryStatDAO memoryStatDAO = (MemoryStatDAO) services.get(MemoryStatDAO.class.getName());
+                Objects.requireNonNull(memoryStatDAO);
+                ApplicationService appSvc = (ApplicationService) services.get(ApplicationService.class.getName());
+                Objects.requireNonNull(appSvc);
+                HostMemoryService service = new HostMemoryService(appSvc, hostInfoDAO, memoryStatDAO);
+                reg = context.registerService(HostInformationService.class.getName(), service, null);
+            }
+
+            @Override
+            public void dependenciesUnavailable() {
+                reg.unregister();
+            }
+
+        });
+        tracker.open();
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        tracker.close();
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host-memory/client-core/src/main/java/com/redhat/thermostat/host/memory/client/core/internal/HostMemoryController.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,188 @@
+/*
+ * 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.host.memory.client.core.internal;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import com.redhat.thermostat.client.core.controllers.HostInformationServiceController;
+import com.redhat.thermostat.client.core.views.BasicView.Action;
+import com.redhat.thermostat.client.core.views.UIComponent;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.NotImplementedException;
+import com.redhat.thermostat.common.Timer;
+import com.redhat.thermostat.common.Timer.SchedulingType;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.common.dao.HostRef;
+import com.redhat.thermostat.common.dao.MemoryStatDAO;
+import com.redhat.thermostat.common.locale.Translate;
+import com.redhat.thermostat.common.utils.DisplayableValues;
+import com.redhat.thermostat.host.memory.client.core.HostMemoryView;
+import com.redhat.thermostat.host.memory.client.core.HostMemoryViewProvider;
+import com.redhat.thermostat.host.memory.client.core.HostMemoryView.GraphVisibilityChangeListener;
+import com.redhat.thermostat.host.memory.client.locale.LocaleResources;
+import com.redhat.thermostat.storage.model.DiscreteTimeData;
+import com.redhat.thermostat.storage.model.MemoryStat;
+import com.redhat.thermostat.storage.model.MemoryType;
+
+public class HostMemoryController implements HostInformationServiceController {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private final HostMemoryView view;
+
+    private final HostInfoDAO hostInfoDAO;
+    private final MemoryStatDAO memoryStatDAO;
+    private final HostRef ref;
+
+    private final Timer backgroundUpdateTimer;
+    private final GraphVisibilityChangeListener listener = new ShowHideGraph();
+
+    private long lastSeenTimeStamp = Long.MIN_VALUE;
+
+    public HostMemoryController(ApplicationService appSvc, HostInfoDAO hostInfoDAO, MemoryStatDAO memoryStatDAO, final HostRef ref, HostMemoryViewProvider provider) {
+        this.ref = ref;
+        this.hostInfoDAO = hostInfoDAO;
+        this.memoryStatDAO = memoryStatDAO;
+
+        view = provider.createView();
+
+        view.addMemoryChart(MemoryType.MEMORY_TOTAL.name(), translator.localize(LocaleResources.HOST_MEMORY_TOTAL));
+        view.addMemoryChart(MemoryType.MEMORY_FREE.name(), translator.localize(LocaleResources.HOST_MEMORY_FREE));
+        view.addMemoryChart(MemoryType.MEMORY_USED.name(), translator.localize(LocaleResources.HOST_MEMORY_USED));
+        view.addMemoryChart(MemoryType.SWAP_TOTAL.name(), translator.localize(LocaleResources.HOST_SWAP_TOTAL));
+        view.addMemoryChart(MemoryType.SWAP_FREE.name(), translator.localize(LocaleResources.HOST_SWAP_FREE));
+        view.addMemoryChart(MemoryType.BUFFERS.name(), translator.localize(LocaleResources.HOST_BUFFERS));
+
+        view.addGraphVisibilityListener(listener);
+        view.addActionListener(new ActionListener<HostMemoryView.Action>() {
+            @Override
+            public void actionPerformed(ActionEvent<Action> actionEvent) {
+                switch (actionEvent.getActionId()) {
+                    case HIDDEN:
+                        stopBackgroundUpdates();
+                        break;
+                    case VISIBLE:
+                        startBackgroundUpdates();
+                        break;
+                    default:
+                        throw new NotImplementedException("action event not handled: " + actionEvent.getActionId());
+                }
+            }
+        });
+
+        backgroundUpdateTimer = appSvc.getTimerFactory().createTimer();
+        backgroundUpdateTimer.setAction(new Runnable() {
+            @Override
+            public void run() {
+                long memorySize = HostMemoryController.this.hostInfoDAO.getHostInfo(ref).getTotalMemory();
+                String[] memorySizeParts = DisplayableValues.bytes(memorySize);
+                view.setTotalMemory(translator.localize(LocaleResources.NUMBER_AND_UNIT, memorySizeParts[0], memorySizeParts[1]));
+                doMemoryChartUpdate();
+            }
+        });
+        backgroundUpdateTimer.setSchedulingType(SchedulingType.FIXED_RATE);
+        backgroundUpdateTimer.setTimeUnit(TimeUnit.SECONDS);
+        backgroundUpdateTimer.setInitialDelay(0);
+        backgroundUpdateTimer.setDelay(5);
+    }
+
+    private void startBackgroundUpdates() {
+        for (MemoryType type : MemoryType.values()) {
+            view.showMemoryChart(type.name());
+        }
+
+        backgroundUpdateTimer.start();
+    }
+
+    private void stopBackgroundUpdates() {
+        backgroundUpdateTimer.stop();
+        for (MemoryType type : MemoryType.values()) {
+            view.hideMemoryChart(type.name());
+        }
+    }
+
+    public UIComponent getView() {
+        return view;
+    }
+
+    private void doMemoryChartUpdate() {
+        List<DiscreteTimeData<? extends Number>> memFree = new LinkedList<>();
+        List<DiscreteTimeData<? extends Number>> memTotal = new LinkedList<>();
+        List<DiscreteTimeData<? extends Number>> memUsed = new LinkedList<>();
+        List<DiscreteTimeData<? extends Number>> buf = new LinkedList<>();
+        List<DiscreteTimeData<? extends Number>> swapTotal = new LinkedList<>();
+        List<DiscreteTimeData<? extends Number>> swapFree = new LinkedList<>();
+
+        for (MemoryStat stat : memoryStatDAO.getLatestMemoryStats(ref, lastSeenTimeStamp)) {
+            long timeStamp = stat.getTimeStamp();
+            memFree.add(new DiscreteTimeData<Long>(timeStamp, stat.getFree()));
+            memTotal.add(new DiscreteTimeData<Long>(timeStamp, stat.getTotal()));
+            memUsed.add(new DiscreteTimeData<Long>(timeStamp, stat.getTotal() - stat.getFree()));
+            buf.add(new DiscreteTimeData<Long>(timeStamp, stat.getBuffers()));
+            swapTotal.add(new DiscreteTimeData<Long>(timeStamp, stat.getSwapTotal()));
+            swapFree.add(new DiscreteTimeData<Long>(timeStamp, stat.getSwapFree()));
+            lastSeenTimeStamp = Math.max(lastSeenTimeStamp, stat.getTimeStamp());
+        }
+
+        view.addMemoryData(MemoryType.MEMORY_FREE.name(), memFree);
+        view.addMemoryData(MemoryType.MEMORY_TOTAL.name(), memTotal);
+        view.addMemoryData(MemoryType.MEMORY_USED.name(), memUsed);
+        view.addMemoryData(MemoryType.BUFFERS.name(), buf);
+        view.addMemoryData(MemoryType.SWAP_FREE.name(), swapFree);
+        view.addMemoryData(MemoryType.SWAP_TOTAL.name(), swapTotal);
+    }
+
+    private class ShowHideGraph implements GraphVisibilityChangeListener {
+        @Override
+        public void show(String tag) {
+            view.showMemoryChart(tag);
+        }
+        @Override
+        public void hide(String tag) {
+            view.hideMemoryChart(tag);
+        }
+    }
+
+    @Override
+    public String getLocalizedName() {
+        return translator.localize(LocaleResources.HOST_INFO_TAB_MEMORY);
+    }
+}
--- a/host-memory/client-core/src/test/java/com/redhat/thermostat/host/memory/client/core/HostMemoryControllerTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +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.host.memory.client.core;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.eq;
-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.LinkedList;
-import java.util.List;
-
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.Timer;
-import com.redhat.thermostat.common.TimerFactory;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
-import com.redhat.thermostat.common.dao.HostRef;
-import com.redhat.thermostat.common.dao.MemoryStatDAO;
-import com.redhat.thermostat.host.memory.client.core.HostMemoryController;
-import com.redhat.thermostat.host.memory.client.core.HostMemoryView;
-import com.redhat.thermostat.host.memory.client.core.HostMemoryViewProvider;
-import com.redhat.thermostat.storage.model.HostInfo;
-import com.redhat.thermostat.storage.model.MemoryStat;
-
-public class HostMemoryControllerTest {
-
-    @SuppressWarnings({ "unchecked", "rawtypes" }) // any(List.class)
-    @Test
-    public void testUpdate() {
-        final long TOTAL_MEMORY = 512;
-        HostInfo hostInfo = new HostInfo("someHost", "someOS", "linux_0.0.1", "lreally_fast_cpu", 2, TOTAL_MEMORY);
-        HostInfoDAO hostInfoDAO = mock(HostInfoDAO.class);
-        when(hostInfoDAO.getHostInfo(any(HostRef.class))).thenReturn(hostInfo);
-
-        MemoryStat memoryStat = new MemoryStat(1, 2, 3, 4, 5, 6, 7, 8);
-        List<MemoryStat> memoryStats = new LinkedList<>();
-        memoryStats.add(memoryStat);
-        MemoryStatDAO memoryStatDAO = mock(MemoryStatDAO.class);
-        when(memoryStatDAO.getLatestMemoryStats(any(HostRef.class), anyLong())).thenReturn(memoryStats);
-
-        Timer timer = mock(Timer.class);
-        ArgumentCaptor<Runnable> timerActionCaptor = ArgumentCaptor.forClass(Runnable.class);
-        doNothing().when(timer).setAction(timerActionCaptor.capture());
-
-        TimerFactory timerFactory = mock(TimerFactory.class);
-        when(timerFactory.createTimer()).thenReturn(timer);
-        ApplicationService appSvc = mock(ApplicationService.class);
-        when(appSvc.getTimerFactory()).thenReturn(timerFactory);
-
-        HostRef ref = mock(HostRef.class);
-
-        HostMemoryView view = mock(HostMemoryView.class);
-        ArgumentCaptor<ActionListener> viewArgumentCaptor = ArgumentCaptor.forClass(ActionListener.class);
-        doNothing().when(view).addActionListener(viewArgumentCaptor.capture());
-
-        HostMemoryViewProvider viewProvider = mock(HostMemoryViewProvider.class);
-        when(viewProvider.createView()).thenReturn(view);
-
-        @SuppressWarnings("unused")
-        HostMemoryController controller = new HostMemoryController(appSvc, hostInfoDAO, memoryStatDAO, ref, viewProvider);
-
-        ActionListener<HostMemoryView.Action> l = viewArgumentCaptor.getValue();
-
-        l.actionPerformed(new ActionEvent<>(view, HostMemoryView.Action.VISIBLE));
-
-        verify(timer).start();
-        timerActionCaptor.getValue().run();
-
-        verify(view, times(1)).setTotalMemory(eq(TOTAL_MEMORY + " B"));
-        verify(view, times(6)).addMemoryData(any(String.class), any(List.class));
-
-        l.actionPerformed(new ActionEvent<>(view, HostMemoryView.Action.HIDDEN));
-
-        verify(timer).stop();
-
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host-memory/client-core/src/test/java/com/redhat/thermostat/host/memory/client/core/internal/ActivatorTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -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.host.memory.client.core.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.client.core.HostInformationService;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.common.dao.MemoryStatDAO;
+import com.redhat.thermostat.host.memory.client.core.HostMemoryService;
+import com.redhat.thermostat.test.StubBundleContext;
+
+public class ActivatorTest {
+    
+    @Test
+    public void verifyActivatorDoesNotRegisterServiceOnMissingDeps() throws Exception {
+        StubBundleContext context = new StubBundleContext();
+
+        Activator activator = new Activator();
+
+        activator.start(context);
+
+        assertEquals(0, context.getAllServices().size());
+        assertNotSame(1, context.getServiceListeners().size());
+
+        activator.stop(context);
+
+        assertEquals(0, context.getServiceListeners().size());
+    }
+
+    @Test
+    public void verifyActivatorRegistersServices() throws Exception {
+        StubBundleContext context = new StubBundleContext();
+        HostInfoDAO hostInfoDAO = mock(HostInfoDAO.class);
+        MemoryStatDAO memoryStatDAO = mock(MemoryStatDAO.class);
+        ApplicationService appSvc = mock(ApplicationService.class);
+
+        context.registerService(HostInfoDAO.class, hostInfoDAO, null);
+        context.registerService(MemoryStatDAO.class, memoryStatDAO, null);
+        context.registerService(ApplicationService.class, appSvc, null);
+
+        Activator activator = new Activator();
+
+        activator.start(context);
+
+        assertTrue(context.isServiceRegistered(HostInformationService.class.getName(), HostMemoryService.class));
+
+        activator.stop(context);
+
+        assertEquals(0, context.getServiceListeners().size());
+        assertEquals(3, context.getAllServices().size());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host-memory/client-core/src/test/java/com/redhat/thermostat/host/memory/client/core/internal/HostMemoryControllerTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,120 @@
+/*
+ * 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.host.memory.client.core.internal;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.eq;
+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.LinkedList;
+import java.util.List;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.Timer;
+import com.redhat.thermostat.common.TimerFactory;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.common.dao.HostRef;
+import com.redhat.thermostat.common.dao.MemoryStatDAO;
+import com.redhat.thermostat.host.memory.client.core.HostMemoryView;
+import com.redhat.thermostat.host.memory.client.core.HostMemoryViewProvider;
+import com.redhat.thermostat.host.memory.client.core.internal.HostMemoryController;
+import com.redhat.thermostat.storage.model.HostInfo;
+import com.redhat.thermostat.storage.model.MemoryStat;
+
+public class HostMemoryControllerTest {
+
+    @SuppressWarnings({ "unchecked", "rawtypes" }) // any(List.class)
+    @Test
+    public void testUpdate() {
+        final long TOTAL_MEMORY = 512;
+        HostInfo hostInfo = new HostInfo("someHost", "someOS", "linux_0.0.1", "lreally_fast_cpu", 2, TOTAL_MEMORY);
+        HostInfoDAO hostInfoDAO = mock(HostInfoDAO.class);
+        when(hostInfoDAO.getHostInfo(any(HostRef.class))).thenReturn(hostInfo);
+
+        MemoryStat memoryStat = new MemoryStat(1, 2, 3, 4, 5, 6, 7, 8);
+        List<MemoryStat> memoryStats = new LinkedList<>();
+        memoryStats.add(memoryStat);
+        MemoryStatDAO memoryStatDAO = mock(MemoryStatDAO.class);
+        when(memoryStatDAO.getLatestMemoryStats(any(HostRef.class), anyLong())).thenReturn(memoryStats);
+
+        Timer timer = mock(Timer.class);
+        ArgumentCaptor<Runnable> timerActionCaptor = ArgumentCaptor.forClass(Runnable.class);
+        doNothing().when(timer).setAction(timerActionCaptor.capture());
+
+        TimerFactory timerFactory = mock(TimerFactory.class);
+        when(timerFactory.createTimer()).thenReturn(timer);
+        ApplicationService appSvc = mock(ApplicationService.class);
+        when(appSvc.getTimerFactory()).thenReturn(timerFactory);
+
+        HostRef ref = mock(HostRef.class);
+
+        HostMemoryView view = mock(HostMemoryView.class);
+        ArgumentCaptor<ActionListener> viewArgumentCaptor = ArgumentCaptor.forClass(ActionListener.class);
+        doNothing().when(view).addActionListener(viewArgumentCaptor.capture());
+
+        HostMemoryViewProvider viewProvider = mock(HostMemoryViewProvider.class);
+        when(viewProvider.createView()).thenReturn(view);
+
+        @SuppressWarnings("unused")
+        HostMemoryController controller = new HostMemoryController(appSvc, hostInfoDAO, memoryStatDAO, ref, viewProvider);
+
+        ActionListener<HostMemoryView.Action> l = viewArgumentCaptor.getValue();
+
+        l.actionPerformed(new ActionEvent<>(view, HostMemoryView.Action.VISIBLE));
+
+        verify(timer).start();
+        timerActionCaptor.getValue().run();
+
+        verify(view, times(1)).setTotalMemory(eq(TOTAL_MEMORY + " B"));
+        verify(view, times(6)).addMemoryData(any(String.class), any(List.class));
+
+        l.actionPerformed(new ActionEvent<>(view, HostMemoryView.Action.HIDDEN));
+
+        verify(timer).stop();
+
+    }
+}
--- a/host-memory/client-swing/src/main/java/com/redhat/thermostat/host/memory/client/swing/Activator.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/host-memory/client-swing/src/main/java/com/redhat/thermostat/host/memory/client/swing/Activator.java	Fri Nov 30 17:30:25 2012 -0500
@@ -36,64 +36,23 @@
 
 package com.redhat.thermostat.host.memory.client.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.HostInformationService;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.MultipleServiceTracker;
-import com.redhat.thermostat.common.MultipleServiceTracker.Action;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
-import com.redhat.thermostat.common.dao.MemoryStatDAO;
-import com.redhat.thermostat.host.memory.client.core.HostMemoryService;
 import com.redhat.thermostat.host.memory.client.core.HostMemoryViewProvider;
 
 public class Activator implements BundleActivator {
     
-    private MultipleServiceTracker tracker;
-    private ServiceRegistration reg;
 
     @Override
     public void start(final BundleContext context) throws Exception {
         HostMemoryViewProvider viewProvider = new SwingHostMemoryViewProvider();
+        // Unregistered on Activator.stop
         context.registerService(HostMemoryViewProvider.class.getName(), viewProvider, null);
-
-        Class<?>[] deps = new Class<?>[] {
-            ApplicationService.class,
-            HostInfoDAO.class,
-            MemoryStatDAO.class,
-        };
-
-        tracker = new MultipleServiceTracker(context, deps, new Action() {
-
-            @Override
-            public void dependenciesAvailable(Map<String, Object> services) {
-                HostInfoDAO hostInfoDAO = (HostInfoDAO) services.get(HostInfoDAO.class.getName());
-                Objects.requireNonNull(hostInfoDAO);
-                MemoryStatDAO memoryStatDAO = (MemoryStatDAO) services.get(MemoryStatDAO.class.getName());
-                Objects.requireNonNull(memoryStatDAO);
-                ApplicationService appSvc = (ApplicationService) services.get(ApplicationService.class.getName());
-                Objects.requireNonNull(appSvc);
-                HostMemoryService service = new HostMemoryService(appSvc, hostInfoDAO, memoryStatDAO);
-                reg = context.registerService(HostInformationService.class.getName(), service, null);
-            }
-
-            @Override
-            public void dependenciesUnavailable() {
-                reg.unregister();
-            }
-
-        });
-        tracker.open();
     }
 
     @Override
     public void stop(BundleContext context) throws Exception {
-        tracker.close();
     }
 
 }
--- a/host-memory/client-swing/src/test/java/com/redhat/thermostat/host/memory/client/swing/ActivatorTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/host-memory/client-swing/src/test/java/com/redhat/thermostat/host/memory/client/swing/ActivatorTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -37,65 +37,16 @@
 package com.redhat.thermostat.host.memory.client.swing;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
 
 import org.junit.Test;
 
-import com.redhat.thermostat.client.core.HostInformationService;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
-import com.redhat.thermostat.common.dao.MemoryStatDAO;
-import com.redhat.thermostat.host.memory.client.core.HostMemoryService;
 import com.redhat.thermostat.host.memory.client.core.HostMemoryViewProvider;
-import com.redhat.thermostat.host.memory.client.swing.Activator;
-import com.redhat.thermostat.host.memory.client.swing.SwingHostMemoryViewProvider;
 import com.redhat.thermostat.test.StubBundleContext;
 
 public class ActivatorTest {
     
     @Test
-    public void verifyActivatorDoesNotRegisterServiceOnMissingDeps() throws Exception {
-        StubBundleContext context = new StubBundleContext();
-
-        Activator activator = new Activator();
-
-        activator.start(context);
-
-        // View provider registers unconditionally
-        assertEquals(1, context.getAllServices().size());
-        assertNotSame(1, context.getServiceListeners().size());
-
-        activator.stop(context);
-
-        assertEquals(0, context.getServiceListeners().size());
-    }
-
-    @Test
-    public void verifyActivatorRegistersServices() throws Exception {
-        StubBundleContext context = new StubBundleContext();
-        HostInfoDAO hostInfoDAO = mock(HostInfoDAO.class);
-        MemoryStatDAO memoryStatDAO = mock(MemoryStatDAO.class);
-        ApplicationService appSvc = mock(ApplicationService.class);
-
-        context.registerService(HostInfoDAO.class, hostInfoDAO, null);
-        context.registerService(MemoryStatDAO.class, memoryStatDAO, null);
-        context.registerService(ApplicationService.class, appSvc, null);
-
-        Activator activator = new Activator();
-
-        activator.start(context);
-
-        assertTrue(context.isServiceRegistered(HostInformationService.class.getName(), HostMemoryService.class));
-
-        activator.stop(context);
-
-        assertEquals(0, context.getServiceListeners().size());
-        assertEquals(4, context.getAllServices().size());
-    }
-
-    @Test
     public void verifyStartRegistersViewProvider() throws Exception {
         StubBundleContext ctx = new StubBundleContext();
         Activator activator = new Activator();
--- a/host-overview/client-core/pom.xml	Fri Nov 30 10:47:45 2012 -0500
+++ b/host-overview/client-core/pom.xml	Fri Nov 30 17:30:25 2012 -0500
@@ -17,13 +17,16 @@
         <extensions>true</extensions>
         <configuration>
           <instructions>
-            <Private-Package></Private-Package>
             <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
             <Bundle-SymbolicName>com.redhat.thermostat.host.overview.client.core</Bundle-SymbolicName>
+            <Bundle-Activator>com.redhat.thermostat.host.overview.client.core.internal.Activator</Bundle-Activator>
             <Export-Package>
               com.redhat.thermostat.host.overview.client.core,
               com.redhat.thermostat.host.overview.client.locale
             </Export-Package>
+            <Private-Package>
+              com.redhat.thermostat.host.overview.client.core.internal
+            </Private-Package>
             <!-- Do not autogenerate uses clauses in Manifests -->
             <_nouses>true</_nouses>
           </instructions>
--- a/host-overview/client-core/src/main/java/com/redhat/thermostat/host/overview/client/core/HostOverviewController.java	Fri Nov 30 10:47:45 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +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.host.overview.client.core;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Vector;
-import java.util.concurrent.TimeUnit;
-
-import com.redhat.thermostat.client.core.controllers.HostInformationServiceController;
-import com.redhat.thermostat.client.core.views.BasicView.Action;
-import com.redhat.thermostat.client.core.views.UIComponent;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.NotImplementedException;
-import com.redhat.thermostat.common.Timer;
-import com.redhat.thermostat.common.Timer.SchedulingType;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
-import com.redhat.thermostat.common.dao.HostRef;
-import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.common.utils.DisplayableValues;
-import com.redhat.thermostat.host.overview.client.locale.LocaleResources;
-import com.redhat.thermostat.storage.model.HostInfo;
-import com.redhat.thermostat.storage.model.NetworkInterfaceInfo;
-
-public class HostOverviewController implements HostInformationServiceController {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private final HostInfoDAO hostInfoDAO;
-    private final NetworkInterfaceInfoDAO networkInfoDAO;
-
-    private final Timer backgroundUpdateTimer;
-    private final List<String> knownNetworkIfaces = new ArrayList<>();
-
-    private final HostOverviewView view;
-
-    public HostOverviewController(ApplicationService appSvc, HostInfoDAO hostInfoDAO, NetworkInterfaceInfoDAO networkInfoDAO, final HostRef ref, HostOverviewViewProvider provider) {
-        this.hostInfoDAO = hostInfoDAO;
-        this.networkInfoDAO = networkInfoDAO;
-
-        final Vector<String> networkTableColumnVector;
-        networkTableColumnVector = new Vector<String>();
-        networkTableColumnVector.add(translator.localize(LocaleResources.NETWORK_INTERFACE_COLUMN));
-        networkTableColumnVector.add(translator.localize(LocaleResources.NETWORK_IPV4_COLUMN));
-        networkTableColumnVector.add(translator.localize(LocaleResources.NETWORK_IPV6_COLUMN));
-
-        backgroundUpdateTimer = appSvc.getTimerFactory().createTimer();
-        backgroundUpdateTimer.setAction(new Runnable() {
-            @Override
-            public void run() {
-                HostInfo hostInfo = HostOverviewController.this.hostInfoDAO.getHostInfo(ref);
-                view.setHostName(hostInfo.getHostname());
-                view.setOsName(hostInfo.getOsName());
-                view.setOsKernel(hostInfo.getOsKernel());
-                view.setCpuModel(hostInfo.getCpuModel());
-                view.setCpuCount(String.valueOf(hostInfo.getCpuCount()));
-
-                String[] parts = DisplayableValues.bytes(hostInfo.getTotalMemory());
-                String readableTotalMemory = translator.localize(LocaleResources.NUMBER_AND_UNIT, parts[0], parts[1]);
-                view.setTotalMemory(readableTotalMemory);
-
-                List<NetworkInterfaceInfo> networkInfo =
-                        HostOverviewController.this.networkInfoDAO.getNetworkInterfaces(ref);
-
-                boolean firstRun = knownNetworkIfaces.isEmpty();
-                if (firstRun) {
-                    List<Object[]> data = new ArrayList<Object[]>();
-                    for (NetworkInterfaceInfo info: networkInfo) {
-                        String ifaceName = info.getInterfaceName();
-                        String ipv4 = info.getIp4Addr();
-                        String ipv6 = info.getIp6Addr();
-                        data.add(new String[] { ifaceName, ipv4, ipv6 });
-                        knownNetworkIfaces.add(ifaceName);
-                    }
-                    view.setInitialNetworkTableData(data.toArray(new Object[0][0]));
-                } else {
-                    for (NetworkInterfaceInfo info: networkInfo) {
-                        String ifaceName = info.getInterfaceName();
-                        String ipv4 = info.getIp4Addr();
-                        String ipv6 = info.getIp6Addr();
-                        int index = knownNetworkIfaces.indexOf(ifaceName);
-                        int row = index;
-                        view.updateNetworkTableData(index, 0, ifaceName);
-                        view.updateNetworkTableData(row, 1, ipv4);
-                        view.updateNetworkTableData(row, 2, ipv6);
-                    }
-                }
-            }
-        });
-        backgroundUpdateTimer.setSchedulingType(SchedulingType.FIXED_RATE);
-        backgroundUpdateTimer.setTimeUnit(TimeUnit.SECONDS);
-        backgroundUpdateTimer.setInitialDelay(0);
-        backgroundUpdateTimer.setDelay(5);
-
-        view = provider.createView();
-
-        view.setNetworkTableColumns(networkTableColumnVector.toArray());
-
-        view.addActionListener(new ActionListener<Action>() {
-            @Override
-            public void actionPerformed(ActionEvent<Action> actionEvent) {
-                switch (actionEvent.getActionId()) {
-                    case HIDDEN:
-                        stop();
-                        break;
-                    case VISIBLE:
-                        start();
-                        break;
-                    default:
-                        throw new NotImplementedException("unhandled: " + actionEvent.getActionId());
-                }
-            }
-        });
-    }
-
-    private void start() {
-        backgroundUpdateTimer.start();
-    }
-
-    private void stop() {
-        backgroundUpdateTimer.stop();
-    }
-
-    public UIComponent getView() {
-        return view;
-    }
-
-    @Override
-    public String getLocalizedName() {
-        return translator.localize(LocaleResources.HOST_INFO_TAB_OVERVIEW);
-    }
-}
--- a/host-overview/client-core/src/main/java/com/redhat/thermostat/host/overview/client/core/HostOverviewService.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/host-overview/client-core/src/main/java/com/redhat/thermostat/host/overview/client/core/HostOverviewService.java	Fri Nov 30 17:30:25 2012 -0500
@@ -44,6 +44,7 @@
 import com.redhat.thermostat.common.dao.HostRef;
 import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO;
 import com.redhat.thermostat.common.utils.OSGIUtils;
+import com.redhat.thermostat.host.overview.client.core.internal.HostOverviewController;
 
 public class HostOverviewService implements HostInformationService {
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host-overview/client-core/src/main/java/com/redhat/thermostat/host/overview/client/core/internal/Activator.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,97 @@
+/*
+ * 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.host.overview.client.core.internal;
+
+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.HostInformationService;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.MultipleServiceTracker;
+import com.redhat.thermostat.common.MultipleServiceTracker.Action;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO;
+import com.redhat.thermostat.host.overview.client.core.HostOverviewService;
+
+public class Activator implements BundleActivator {
+    
+    private MultipleServiceTracker tracker;
+    private ServiceRegistration reg;
+
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        Class<?>[] deps = new Class<?>[] {
+            HostInfoDAO.class,
+            NetworkInterfaceInfoDAO.class,
+            ApplicationService.class
+        };
+
+        tracker = new MultipleServiceTracker(context, deps, new Action() {
+
+            @Override
+            public void dependenciesAvailable(Map<String, Object> services) {
+                HostInfoDAO hostInfoDAO = (HostInfoDAO) services.get(HostInfoDAO.class.getName());
+                Objects.requireNonNull(hostInfoDAO);
+                NetworkInterfaceInfoDAO networkInfoDAO = (NetworkInterfaceInfoDAO) 
+                        services.get(NetworkInterfaceInfoDAO.class.getName());
+                Objects.requireNonNull(networkInfoDAO);
+                ApplicationService appSvc = (ApplicationService) services.get(ApplicationService.class.getName());
+                Objects.requireNonNull(appSvc);
+                HostOverviewService service = new HostOverviewService(appSvc, hostInfoDAO, networkInfoDAO);
+                reg = context.registerService(HostInformationService.class.getName(), service, null);
+            }
+
+            @Override
+            public void dependenciesUnavailable() {
+                reg.unregister();
+            }
+
+        });
+        tracker.open();
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        tracker.close();
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host-overview/client-core/src/main/java/com/redhat/thermostat/host/overview/client/core/internal/HostOverviewController.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,171 @@
+/*
+ * 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.host.overview.client.core.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Vector;
+import java.util.concurrent.TimeUnit;
+
+import com.redhat.thermostat.client.core.controllers.HostInformationServiceController;
+import com.redhat.thermostat.client.core.views.BasicView.Action;
+import com.redhat.thermostat.client.core.views.UIComponent;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.NotImplementedException;
+import com.redhat.thermostat.common.Timer;
+import com.redhat.thermostat.common.Timer.SchedulingType;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.common.dao.HostRef;
+import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO;
+import com.redhat.thermostat.common.locale.Translate;
+import com.redhat.thermostat.common.utils.DisplayableValues;
+import com.redhat.thermostat.host.overview.client.core.HostOverviewView;
+import com.redhat.thermostat.host.overview.client.core.HostOverviewViewProvider;
+import com.redhat.thermostat.host.overview.client.locale.LocaleResources;
+import com.redhat.thermostat.storage.model.HostInfo;
+import com.redhat.thermostat.storage.model.NetworkInterfaceInfo;
+
+public class HostOverviewController implements HostInformationServiceController {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private final HostInfoDAO hostInfoDAO;
+    private final NetworkInterfaceInfoDAO networkInfoDAO;
+
+    private final Timer backgroundUpdateTimer;
+    private final List<String> knownNetworkIfaces = new ArrayList<>();
+
+    private final HostOverviewView view;
+
+    public HostOverviewController(ApplicationService appSvc, HostInfoDAO hostInfoDAO, NetworkInterfaceInfoDAO networkInfoDAO, final HostRef ref, HostOverviewViewProvider provider) {
+        this.hostInfoDAO = hostInfoDAO;
+        this.networkInfoDAO = networkInfoDAO;
+
+        final Vector<String> networkTableColumnVector;
+        networkTableColumnVector = new Vector<String>();
+        networkTableColumnVector.add(translator.localize(LocaleResources.NETWORK_INTERFACE_COLUMN));
+        networkTableColumnVector.add(translator.localize(LocaleResources.NETWORK_IPV4_COLUMN));
+        networkTableColumnVector.add(translator.localize(LocaleResources.NETWORK_IPV6_COLUMN));
+
+        backgroundUpdateTimer = appSvc.getTimerFactory().createTimer();
+        backgroundUpdateTimer.setAction(new Runnable() {
+            @Override
+            public void run() {
+                HostInfo hostInfo = HostOverviewController.this.hostInfoDAO.getHostInfo(ref);
+                view.setHostName(hostInfo.getHostname());
+                view.setOsName(hostInfo.getOsName());
+                view.setOsKernel(hostInfo.getOsKernel());
+                view.setCpuModel(hostInfo.getCpuModel());
+                view.setCpuCount(String.valueOf(hostInfo.getCpuCount()));
+
+                String[] parts = DisplayableValues.bytes(hostInfo.getTotalMemory());
+                String readableTotalMemory = translator.localize(LocaleResources.NUMBER_AND_UNIT, parts[0], parts[1]);
+                view.setTotalMemory(readableTotalMemory);
+
+                List<NetworkInterfaceInfo> networkInfo =
+                        HostOverviewController.this.networkInfoDAO.getNetworkInterfaces(ref);
+
+                boolean firstRun = knownNetworkIfaces.isEmpty();
+                if (firstRun) {
+                    List<Object[]> data = new ArrayList<Object[]>();
+                    for (NetworkInterfaceInfo info: networkInfo) {
+                        String ifaceName = info.getInterfaceName();
+                        String ipv4 = info.getIp4Addr();
+                        String ipv6 = info.getIp6Addr();
+                        data.add(new String[] { ifaceName, ipv4, ipv6 });
+                        knownNetworkIfaces.add(ifaceName);
+                    }
+                    view.setInitialNetworkTableData(data.toArray(new Object[0][0]));
+                } else {
+                    for (NetworkInterfaceInfo info: networkInfo) {
+                        String ifaceName = info.getInterfaceName();
+                        String ipv4 = info.getIp4Addr();
+                        String ipv6 = info.getIp6Addr();
+                        int index = knownNetworkIfaces.indexOf(ifaceName);
+                        int row = index;
+                        view.updateNetworkTableData(index, 0, ifaceName);
+                        view.updateNetworkTableData(row, 1, ipv4);
+                        view.updateNetworkTableData(row, 2, ipv6);
+                    }
+                }
+            }
+        });
+        backgroundUpdateTimer.setSchedulingType(SchedulingType.FIXED_RATE);
+        backgroundUpdateTimer.setTimeUnit(TimeUnit.SECONDS);
+        backgroundUpdateTimer.setInitialDelay(0);
+        backgroundUpdateTimer.setDelay(5);
+
+        view = provider.createView();
+
+        view.setNetworkTableColumns(networkTableColumnVector.toArray());
+
+        view.addActionListener(new ActionListener<Action>() {
+            @Override
+            public void actionPerformed(ActionEvent<Action> actionEvent) {
+                switch (actionEvent.getActionId()) {
+                    case HIDDEN:
+                        stop();
+                        break;
+                    case VISIBLE:
+                        start();
+                        break;
+                    default:
+                        throw new NotImplementedException("unhandled: " + actionEvent.getActionId());
+                }
+            }
+        });
+    }
+
+    private void start() {
+        backgroundUpdateTimer.start();
+    }
+
+    private void stop() {
+        backgroundUpdateTimer.stop();
+    }
+
+    public UIComponent getView() {
+        return view;
+    }
+
+    @Override
+    public String getLocalizedName() {
+        return translator.localize(LocaleResources.HOST_INFO_TAB_OVERVIEW);
+    }
+}
--- a/host-overview/client-core/src/test/java/com/redhat/thermostat/host/overview/client/core/HostOverviewControllerTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +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.host.overview.client.core;
-
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isNotNull;
-import static org.mockito.Mockito.doNothing;
-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.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.core.views.BasicView.Action;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.Timer;
-import com.redhat.thermostat.common.Timer.SchedulingType;
-import com.redhat.thermostat.common.TimerFactory;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
-import com.redhat.thermostat.common.dao.HostRef;
-import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO;
-import com.redhat.thermostat.host.overview.client.core.HostOverviewController;
-import com.redhat.thermostat.host.overview.client.core.HostOverviewView;
-import com.redhat.thermostat.host.overview.client.core.HostOverviewViewProvider;
-import com.redhat.thermostat.storage.model.HostInfo;
-import com.redhat.thermostat.storage.model.NetworkInterfaceInfo;
-
-public class HostOverviewControllerTest {
-
-    private static final String HOST_NAME = "host-name";
-    private static final String OS_NAME = "some os";
-    private static final String KERNEL_NAME = "korn";
-    private static final int CPU_COUNT = 99;
-    private static final String CPU_MODEL = "cpu-model";
-    private static final long TOTAL_MEMORY = 99+99;
-    private static final String NETWORK_INTERFACE = "iface0";
-    private static final String IPV4_ADDR = "0xcafef00d";
-    private static final String IPV6_ADDR = "HOME_SWEET_HOME";
-
-    private Timer timer;
-    private Runnable timerAction;
-    private HostOverviewView view;
-    private ActionListener<HostOverviewView.Action> listener;
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    @Before
-    public void setUp() {
-        // Setup timer
-        timer = mock(Timer.class);
-        ArgumentCaptor<Runnable> timerActionCaptor = ArgumentCaptor.forClass(Runnable.class);
-        doNothing().when(timer).setAction(timerActionCaptor.capture());
-
-        TimerFactory timerFactory = mock(TimerFactory.class);
-        when(timerFactory.createTimer()).thenReturn(timer);
-        ApplicationService appSvc = mock(ApplicationService.class);
-        when(appSvc.getTimerFactory()).thenReturn(timerFactory);
-
-        // Setup DAOs
-        HostInfo hostInfo = new HostInfo(HOST_NAME, OS_NAME, KERNEL_NAME, CPU_MODEL, CPU_COUNT, TOTAL_MEMORY);
-
-        List<NetworkInterfaceInfo> networkInfo = new ArrayList<NetworkInterfaceInfo>();
-        NetworkInterfaceInfo ifaceInfo = new NetworkInterfaceInfo(NETWORK_INTERFACE);
-        ifaceInfo.setIp4Addr(IPV4_ADDR);
-        ifaceInfo.setIp6Addr(IPV6_ADDR);
-        networkInfo.add(ifaceInfo);
-
-        HostRef ref = mock(HostRef.class);
-
-        HostInfoDAO hostInfoDao = mock(HostInfoDAO.class);
-        when(hostInfoDao.getHostInfo(any(HostRef.class))).thenReturn(hostInfo);
-
-        NetworkInterfaceInfoDAO networkInfoDao = mock(NetworkInterfaceInfoDAO.class);
-        when(networkInfoDao.getNetworkInterfaces(any(HostRef.class))).thenReturn(networkInfo);
-
-        // Setup View
-        ArgumentCaptor<ActionListener> listenerCaptor = ArgumentCaptor.forClass(ActionListener.class);
-        view = mock(HostOverviewView.class);
-        doNothing().when(view).addActionListener(listenerCaptor.capture());
-        HostOverviewViewProvider viewProvider = mock(HostOverviewViewProvider.class);
-        when(viewProvider.createView()).thenReturn(view);
-
-        @SuppressWarnings("unused")
-        HostOverviewController controller = new HostOverviewController(appSvc, hostInfoDao, networkInfoDao, ref, viewProvider);
-
-        listener = listenerCaptor.getValue();
-        timerAction = timerActionCaptor.getValue();
-    }
-
-    @Test
-    public void verifyViewIsUpdatedWithData() {
-        timerAction.run();
-
-        verify(view).setCpuCount(eq(String.valueOf(CPU_COUNT)));
-        verify(view).setCpuModel(eq(CPU_MODEL));
-        verify(view).setHostName(eq(HOST_NAME));
-
-        verify(view).setNetworkTableColumns(any(String[][].class));
-        verify(view).setInitialNetworkTableData(eq(new String[][] { new String[] { NETWORK_INTERFACE, IPV4_ADDR, IPV6_ADDR }, }));
-
-        verify(view).setOsKernel(eq(KERNEL_NAME));
-        verify(view).setOsName(eq(OS_NAME));
-
-        final String UNITS = " B";
-        verify(view).setTotalMemory(eq(String.valueOf(TOTAL_MEMORY + UNITS)));
-    }
-
-    @Test
-    public void verifyTimerIsSetUpCorrectly() {
-        assertNotNull(timer);
-
-        verify(timer).setAction(isNotNull(Runnable.class));
-        verify(timer).setDelay(5);
-        verify(timer).setTimeUnit(TimeUnit.SECONDS);
-        verify(timer).setInitialDelay(0);
-        verify(timer).setSchedulingType(SchedulingType.FIXED_RATE);
-    }
-
-    @Test
-    public void verifyTimerRunsWhenNeeded() {
-        listener.actionPerformed(new ActionEvent<>(view, Action.VISIBLE));
-
-        verify(timer).start();
-
-        listener.actionPerformed(new ActionEvent<>(view, Action.HIDDEN));
-
-        verify(timer).stop();
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host-overview/client-core/src/test/java/com/redhat/thermostat/host/overview/client/core/internal/ActivatorTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -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.host.overview.client.core.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.client.core.HostInformationService;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO;
+import com.redhat.thermostat.host.overview.client.core.HostOverviewService;
+import com.redhat.thermostat.test.StubBundleContext;
+
+public class ActivatorTest {
+    
+    @Test
+    public void verifyActivatorDoesNotRegisterServiceOnMissingDeps() throws Exception {
+        StubBundleContext context = new StubBundleContext();
+
+        Activator activator = new Activator();
+
+        activator.start(context);
+
+        assertEquals(0, context.getAllServices().size());
+        assertNotSame(1, context.getServiceListeners().size());
+
+        activator.stop(context);
+    }
+
+    @Test
+    public void verifyActivatorRegistersServices() throws Exception {
+        StubBundleContext context = new StubBundleContext();
+        HostInfoDAO hostInfoDAO = mock(HostInfoDAO.class);
+        NetworkInterfaceInfoDAO networkInfoDAO = mock(NetworkInterfaceInfoDAO.class);
+        ApplicationService appSvc = mock(ApplicationService.class);
+
+        context.registerService(HostInfoDAO.class, hostInfoDAO, null);
+        context.registerService(NetworkInterfaceInfoDAO.class, networkInfoDAO, null);
+        context.registerService(ApplicationService.class, appSvc, null);
+
+        Activator activator = new Activator();
+
+        activator.start(context);
+
+        assertTrue(context.isServiceRegistered(HostInformationService.class.getName(), HostOverviewService.class));
+
+        activator.stop(context);
+
+        assertEquals(0, context.getServiceListeners().size());
+        assertEquals(3, context.getAllServices().size());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host-overview/client-core/src/test/java/com/redhat/thermostat/host/overview/client/core/internal/HostOverviewControllerTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,172 @@
+/*
+ * 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.host.overview.client.core.internal;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNotNull;
+import static org.mockito.Mockito.doNothing;
+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.List;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.client.core.views.BasicView.Action;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.Timer;
+import com.redhat.thermostat.common.Timer.SchedulingType;
+import com.redhat.thermostat.common.TimerFactory;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.common.dao.HostRef;
+import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO;
+import com.redhat.thermostat.host.overview.client.core.HostOverviewView;
+import com.redhat.thermostat.host.overview.client.core.HostOverviewViewProvider;
+import com.redhat.thermostat.storage.model.HostInfo;
+import com.redhat.thermostat.storage.model.NetworkInterfaceInfo;
+
+public class HostOverviewControllerTest {
+
+    private static final String HOST_NAME = "host-name";
+    private static final String OS_NAME = "some os";
+    private static final String KERNEL_NAME = "korn";
+    private static final int CPU_COUNT = 99;
+    private static final String CPU_MODEL = "cpu-model";
+    private static final long TOTAL_MEMORY = 99+99;
+    private static final String NETWORK_INTERFACE = "iface0";
+    private static final String IPV4_ADDR = "0xcafef00d";
+    private static final String IPV6_ADDR = "HOME_SWEET_HOME";
+
+    private Timer timer;
+    private Runnable timerAction;
+    private HostOverviewView view;
+    private ActionListener<HostOverviewView.Action> listener;
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Before
+    public void setUp() {
+        // Setup timer
+        timer = mock(Timer.class);
+        ArgumentCaptor<Runnable> timerActionCaptor = ArgumentCaptor.forClass(Runnable.class);
+        doNothing().when(timer).setAction(timerActionCaptor.capture());
+
+        TimerFactory timerFactory = mock(TimerFactory.class);
+        when(timerFactory.createTimer()).thenReturn(timer);
+        ApplicationService appSvc = mock(ApplicationService.class);
+        when(appSvc.getTimerFactory()).thenReturn(timerFactory);
+
+        // Setup DAOs
+        HostInfo hostInfo = new HostInfo(HOST_NAME, OS_NAME, KERNEL_NAME, CPU_MODEL, CPU_COUNT, TOTAL_MEMORY);
+
+        List<NetworkInterfaceInfo> networkInfo = new ArrayList<NetworkInterfaceInfo>();
+        NetworkInterfaceInfo ifaceInfo = new NetworkInterfaceInfo(NETWORK_INTERFACE);
+        ifaceInfo.setIp4Addr(IPV4_ADDR);
+        ifaceInfo.setIp6Addr(IPV6_ADDR);
+        networkInfo.add(ifaceInfo);
+
+        HostRef ref = mock(HostRef.class);
+
+        HostInfoDAO hostInfoDao = mock(HostInfoDAO.class);
+        when(hostInfoDao.getHostInfo(any(HostRef.class))).thenReturn(hostInfo);
+
+        NetworkInterfaceInfoDAO networkInfoDao = mock(NetworkInterfaceInfoDAO.class);
+        when(networkInfoDao.getNetworkInterfaces(any(HostRef.class))).thenReturn(networkInfo);
+
+        // Setup View
+        ArgumentCaptor<ActionListener> listenerCaptor = ArgumentCaptor.forClass(ActionListener.class);
+        view = mock(HostOverviewView.class);
+        doNothing().when(view).addActionListener(listenerCaptor.capture());
+        HostOverviewViewProvider viewProvider = mock(HostOverviewViewProvider.class);
+        when(viewProvider.createView()).thenReturn(view);
+
+        @SuppressWarnings("unused")
+        HostOverviewController controller = new HostOverviewController(appSvc, hostInfoDao, networkInfoDao, ref, viewProvider);
+
+        listener = listenerCaptor.getValue();
+        timerAction = timerActionCaptor.getValue();
+    }
+
+    @Test
+    public void verifyViewIsUpdatedWithData() {
+        timerAction.run();
+
+        verify(view).setCpuCount(eq(String.valueOf(CPU_COUNT)));
+        verify(view).setCpuModel(eq(CPU_MODEL));
+        verify(view).setHostName(eq(HOST_NAME));
+
+        verify(view).setNetworkTableColumns(any(String[][].class));
+        verify(view).setInitialNetworkTableData(eq(new String[][] { new String[] { NETWORK_INTERFACE, IPV4_ADDR, IPV6_ADDR }, }));
+
+        verify(view).setOsKernel(eq(KERNEL_NAME));
+        verify(view).setOsName(eq(OS_NAME));
+
+        final String UNITS = " B";
+        verify(view).setTotalMemory(eq(String.valueOf(TOTAL_MEMORY + UNITS)));
+    }
+
+    @Test
+    public void verifyTimerIsSetUpCorrectly() {
+        assertNotNull(timer);
+
+        verify(timer).setAction(isNotNull(Runnable.class));
+        verify(timer).setDelay(5);
+        verify(timer).setTimeUnit(TimeUnit.SECONDS);
+        verify(timer).setInitialDelay(0);
+        verify(timer).setSchedulingType(SchedulingType.FIXED_RATE);
+    }
+
+    @Test
+    public void verifyTimerRunsWhenNeeded() {
+        listener.actionPerformed(new ActionEvent<>(view, Action.VISIBLE));
+
+        verify(timer).start();
+
+        listener.actionPerformed(new ActionEvent<>(view, Action.HIDDEN));
+
+        verify(timer).stop();
+    }
+
+}
--- a/host-overview/client-swing/src/main/java/com/redhat/thermostat/host/overview/client/swing/Activator.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/host-overview/client-swing/src/main/java/com/redhat/thermostat/host/overview/client/swing/Activator.java	Fri Nov 30 17:30:25 2012 -0500
@@ -36,65 +36,22 @@
 
 package com.redhat.thermostat.host.overview.client.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.HostInformationService;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.MultipleServiceTracker;
-import com.redhat.thermostat.common.MultipleServiceTracker.Action;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
-import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO;
-import com.redhat.thermostat.host.overview.client.core.HostOverviewService;
 import com.redhat.thermostat.host.overview.client.core.HostOverviewViewProvider;
 
 public class Activator implements BundleActivator {
     
-    private MultipleServiceTracker tracker;
-    private ServiceRegistration reg;
-
     @Override
     public void start(final BundleContext context) throws Exception {
         HostOverviewViewProvider viewProvider = new SwingHostOverviewViewProvider();
+        // Unregistered on Activator.stop
         context.registerService(HostOverviewViewProvider.class.getName(), viewProvider, null);
-
-        Class<?>[] deps = new Class<?>[] {
-            ApplicationService.class,
-            HostInfoDAO.class,
-            NetworkInterfaceInfoDAO.class,
-        };
-
-        tracker = new MultipleServiceTracker(context, deps, new Action() {
-
-            @Override
-            public void dependenciesAvailable(Map<String, Object> services) {
-                HostInfoDAO hostInfoDAO = (HostInfoDAO) services.get(HostInfoDAO.class.getName());
-                Objects.requireNonNull(hostInfoDAO);
-                NetworkInterfaceInfoDAO networkInfoDAO = (NetworkInterfaceInfoDAO) 
-                        services.get(NetworkInterfaceInfoDAO.class.getName());
-                Objects.requireNonNull(networkInfoDAO);
-                ApplicationService appSvc = (ApplicationService) services.get(ApplicationService.class.getName());
-                Objects.requireNonNull(appSvc);
-                HostOverviewService service = new HostOverviewService(appSvc, hostInfoDAO, networkInfoDAO);
-                reg = context.registerService(HostInformationService.class.getName(), service, null);
-            }
-
-            @Override
-            public void dependenciesUnavailable() {
-                reg.unregister();
-            }
-
-        });
-        tracker.open();
     }
 
     @Override
     public void stop(BundleContext context) throws Exception {
-        tracker.close();
     }
 
 }
--- a/host-overview/client-swing/src/test/java/com/redhat/thermostat/host/overview/client/swing/ActivatorTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/host-overview/client-swing/src/test/java/com/redhat/thermostat/host/overview/client/swing/ActivatorTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -37,65 +37,16 @@
 package com.redhat.thermostat.host.overview.client.swing;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
 
 import org.junit.Test;
 
-import com.redhat.thermostat.client.core.HostInformationService;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.dao.HostInfoDAO;
-import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO;
-import com.redhat.thermostat.host.overview.client.core.HostOverviewService;
 import com.redhat.thermostat.host.overview.client.core.HostOverviewViewProvider;
-import com.redhat.thermostat.host.overview.client.swing.Activator;
-import com.redhat.thermostat.host.overview.client.swing.SwingHostOverviewViewProvider;
 import com.redhat.thermostat.test.StubBundleContext;
 
 public class ActivatorTest {
     
     @Test
-    public void verifyActivatorDoesNotRegisterServiceOnMissingDeps() throws Exception {
-        StubBundleContext context = new StubBundleContext();
-
-        Activator activator = new Activator();
-
-        activator.start(context);
-
-        // View provider registers unconditionally
-        assertEquals(1, context.getAllServices().size());
-        assertNotSame(1, context.getServiceListeners().size());
-
-        activator.stop(context);
-
-        assertEquals(0, context.getServiceListeners().size());
-    }
-
-    @Test
-    public void verifyActivatorRegistersServices() throws Exception {
-        StubBundleContext context = new StubBundleContext();
-        HostInfoDAO hostInfoDAO = mock(HostInfoDAO.class);
-        NetworkInterfaceInfoDAO networkInfoDAO = mock(NetworkInterfaceInfoDAO.class);
-        ApplicationService appSvc = mock(ApplicationService.class);
-
-        context.registerService(HostInfoDAO.class, hostInfoDAO, null);
-        context.registerService(NetworkInterfaceInfoDAO.class, networkInfoDAO, null);
-        context.registerService(ApplicationService.class, appSvc, null);
-
-        Activator activator = new Activator();
-
-        activator.start(context);
-
-        assertTrue(context.isServiceRegistered(HostInformationService.class.getName(), HostOverviewService.class));
-
-        activator.stop(context);
-
-        assertEquals(0, context.getServiceListeners().size());
-        assertEquals(4, context.getAllServices().size());
-    }
-
-    @Test
     public void verifyStartRegistersViewProvider() throws Exception {
         StubBundleContext ctx = new StubBundleContext();
         Activator activator = new Activator();
--- a/vm-classstat/client-core/pom.xml	Fri Nov 30 10:47:45 2012 -0500
+++ b/vm-classstat/client-core/pom.xml	Fri Nov 30 17:30:25 2012 -0500
@@ -17,13 +17,16 @@
         <extensions>true</extensions>
         <configuration>
           <instructions>
-            <Private-Package></Private-Package>
             <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
             <Bundle-SymbolicName>com.redhat.thermostat.vm.classstat.client.core</Bundle-SymbolicName>
+            <Bundle-Activator>com.redhat.thermostat.vm.classstat.client.core.internal.Activator</Bundle-Activator>
             <Export-Package>
               com.redhat.thermostat.vm.classstat.client.core,
               com.redhat.thermostat.vm.classstat.client.locale
             </Export-Package>
+            <Private-Package>
+              com.redhat.thermostat.vm.classstat.client.core.internal
+            </Private-Package>
             <!-- Do not autogenerate uses clauses in Manifests -->
             <_nouses>true</_nouses>
           </instructions>
--- a/vm-classstat/client-core/src/main/java/com/redhat/thermostat/vm/classstat/client/core/VmClassStatController.java	Fri Nov 30 10:47:45 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +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.vm.classstat.client.core;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import com.redhat.thermostat.client.core.controllers.VmInformationServiceController;
-import com.redhat.thermostat.client.core.views.UIComponent;
-import com.redhat.thermostat.client.core.views.BasicView.Action;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.NotImplementedException;
-import com.redhat.thermostat.common.Timer;
-import com.redhat.thermostat.common.Timer.SchedulingType;
-import com.redhat.thermostat.common.dao.VmClassStatDAO;
-import com.redhat.thermostat.common.dao.VmRef;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.storage.model.DiscreteTimeData;
-import com.redhat.thermostat.storage.model.VmClassStat;
-import com.redhat.thermostat.vm.classstat.client.locale.LocaleResources;
-
-public class VmClassStatController implements VmInformationServiceController {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private class UpdateChartData implements Runnable {
-        @Override
-        public void run() {
-            long timeStamp = lastSeenTimeStamp;
-            List<VmClassStat> latestClassStats = dao.getLatestClassStats(ref, timeStamp);
-            List<DiscreteTimeData<Long>> timeData = new ArrayList<>();
-            for (VmClassStat stat : latestClassStats) {
-                timeData.add(new DiscreteTimeData<Long>(stat.getTimeStamp(), stat.getLoadedClasses()));
-                timeStamp = Math.max(timeStamp, stat.getTimeStamp());
-            }
-            classesView.addClassCount(timeData);
-            lastSeenTimeStamp = timeStamp;
-        }
-    }
-
-    private final VmClassStatView classesView;
-    private final VmRef ref;
-    private final VmClassStatDAO dao;
-    private final Timer timer;
-
-    private volatile long lastSeenTimeStamp = Long.MIN_VALUE;
-
-    public VmClassStatController(ApplicationService appSvc, VmClassStatDAO vmClassStatDao, VmRef ref, VmClassStatViewProvider viewProvider) {
-        this.ref = ref;
-        dao = vmClassStatDao;
-        timer = appSvc.getTimerFactory().createTimer();
-
-        timer.setAction(new UpdateChartData());
-        timer.setSchedulingType(SchedulingType.FIXED_RATE);
-        timer.setTimeUnit(TimeUnit.SECONDS);
-        timer.setDelay(5);
-        timer.setInitialDelay(0);
-
-        classesView = viewProvider.createView();
-
-        classesView.addActionListener(new ActionListener<VmClassStatView.Action>() {
-            @Override
-            public void actionPerformed(ActionEvent<Action> actionEvent) {
-                switch(actionEvent.getActionId()) {
-                    case HIDDEN:
-                        stop();
-                        break;
-                    case VISIBLE:
-                        start();
-                        break;
-                    default:
-                        throw new NotImplementedException("unknown action: " + actionEvent.getActionId());
-                }
-            }
-        });
-    }
-
-    private void start() {
-        timer.start();
-    }
-
-    private void stop() {
-        timer.stop();
-    }
-
-    @Override
-    public String getLocalizedName() {
-        return translator.localize(LocaleResources.VM_INFO_TAB_CLASSES);
-    }
-
-    @Override
-    public UIComponent getView() {
-        return (UIComponent) classesView;
-    }
-
-}
--- a/vm-classstat/client-core/src/main/java/com/redhat/thermostat/vm/classstat/client/core/VmClassStatService.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/vm-classstat/client-core/src/main/java/com/redhat/thermostat/vm/classstat/client/core/VmClassStatService.java	Fri Nov 30 17:30:25 2012 -0500
@@ -44,6 +44,7 @@
 import com.redhat.thermostat.common.dao.VmClassStatDAO;
 import com.redhat.thermostat.common.dao.VmRef;
 import com.redhat.thermostat.common.utils.OSGIUtils;
+import com.redhat.thermostat.vm.classstat.client.core.internal.VmClassStatController;
 
 public class VmClassStatService implements VmInformationService {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-classstat/client-core/src/main/java/com/redhat/thermostat/vm/classstat/client/core/internal/Activator.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,90 @@
+/*
+ * 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.vm.classstat.client.core.internal;
+
+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.common.ApplicationService;
+import com.redhat.thermostat.common.MultipleServiceTracker;
+import com.redhat.thermostat.common.MultipleServiceTracker.Action;
+import com.redhat.thermostat.common.dao.VmClassStatDAO;
+import com.redhat.thermostat.vm.classstat.client.core.VmClassStatService;
+
+public class Activator implements BundleActivator {
+
+    private MultipleServiceTracker tracker;
+    private ServiceRegistration reg;
+
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        Class<?>[] deps = new Class<?>[] {
+            ApplicationService.class,
+            VmClassStatDAO.class,
+        };
+
+        tracker = new MultipleServiceTracker(context, deps, new Action() {
+
+            @Override
+            public void dependenciesAvailable(Map<String, Object> services) {
+                VmClassStatDAO dao = (VmClassStatDAO) services.get(VmClassStatDAO.class.getName());
+                Objects.requireNonNull(dao);
+                ApplicationService appSvc = (ApplicationService) services.get(ApplicationService.class.getName());
+                Objects.requireNonNull(appSvc);
+                VmClassStatService service = new VmClassStatService(appSvc, dao);
+                reg = context.registerService(VmInformationService.class.getName(), service, null);
+            }
+
+            @Override
+            public void dependenciesUnavailable() {
+                reg.unregister();
+            }
+
+        });
+        tracker.open();
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        tracker.close();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-classstat/client-core/src/main/java/com/redhat/thermostat/vm/classstat/client/core/internal/VmClassStatController.java	Fri Nov 30 17:30:25 2012 -0500
@@ -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.vm.classstat.client.core.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import com.redhat.thermostat.client.core.controllers.VmInformationServiceController;
+import com.redhat.thermostat.client.core.views.UIComponent;
+import com.redhat.thermostat.client.core.views.BasicView.Action;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.NotImplementedException;
+import com.redhat.thermostat.common.Timer;
+import com.redhat.thermostat.common.Timer.SchedulingType;
+import com.redhat.thermostat.common.dao.VmClassStatDAO;
+import com.redhat.thermostat.common.dao.VmRef;
+import com.redhat.thermostat.common.locale.Translate;
+import com.redhat.thermostat.storage.model.DiscreteTimeData;
+import com.redhat.thermostat.storage.model.VmClassStat;
+import com.redhat.thermostat.vm.classstat.client.core.VmClassStatView;
+import com.redhat.thermostat.vm.classstat.client.core.VmClassStatViewProvider;
+import com.redhat.thermostat.vm.classstat.client.locale.LocaleResources;
+
+public class VmClassStatController implements VmInformationServiceController {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private class UpdateChartData implements Runnable {
+        @Override
+        public void run() {
+            long timeStamp = lastSeenTimeStamp;
+            List<VmClassStat> latestClassStats = dao.getLatestClassStats(ref, timeStamp);
+            List<DiscreteTimeData<Long>> timeData = new ArrayList<>();
+            for (VmClassStat stat : latestClassStats) {
+                timeData.add(new DiscreteTimeData<Long>(stat.getTimeStamp(), stat.getLoadedClasses()));
+                timeStamp = Math.max(timeStamp, stat.getTimeStamp());
+            }
+            classesView.addClassCount(timeData);
+            lastSeenTimeStamp = timeStamp;
+        }
+    }
+
+    private final VmClassStatView classesView;
+    private final VmRef ref;
+    private final VmClassStatDAO dao;
+    private final Timer timer;
+
+    private volatile long lastSeenTimeStamp = Long.MIN_VALUE;
+
+    public VmClassStatController(ApplicationService appSvc, VmClassStatDAO vmClassStatDao, VmRef ref, VmClassStatViewProvider viewProvider) {
+        this.ref = ref;
+        dao = vmClassStatDao;
+        timer = appSvc.getTimerFactory().createTimer();
+
+        timer.setAction(new UpdateChartData());
+        timer.setSchedulingType(SchedulingType.FIXED_RATE);
+        timer.setTimeUnit(TimeUnit.SECONDS);
+        timer.setDelay(5);
+        timer.setInitialDelay(0);
+
+        classesView = viewProvider.createView();
+
+        classesView.addActionListener(new ActionListener<VmClassStatView.Action>() {
+            @Override
+            public void actionPerformed(ActionEvent<Action> actionEvent) {
+                switch(actionEvent.getActionId()) {
+                    case HIDDEN:
+                        stop();
+                        break;
+                    case VISIBLE:
+                        start();
+                        break;
+                    default:
+                        throw new NotImplementedException("unknown action: " + actionEvent.getActionId());
+                }
+            }
+        });
+    }
+
+    private void start() {
+        timer.start();
+    }
+
+    private void stop() {
+        timer.stop();
+    }
+
+    @Override
+    public String getLocalizedName() {
+        return translator.localize(LocaleResources.VM_INFO_TAB_CLASSES);
+    }
+
+    @Override
+    public UIComponent getView() {
+        return (UIComponent) classesView;
+    }
+
+}
--- a/vm-classstat/client-core/src/test/java/com/redhat/thermostat/vm/classstat/client/core/VmClassStatControllerTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +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.vm.classstat.client.core;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.doNothing;
-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.List;
-
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.Timer;
-import com.redhat.thermostat.common.TimerFactory;
-import com.redhat.thermostat.common.dao.VmClassStatDAO;
-import com.redhat.thermostat.common.dao.VmRef;
-import com.redhat.thermostat.storage.model.VmClassStat;
-import com.redhat.thermostat.vm.classstat.client.core.VmClassStatController;
-import com.redhat.thermostat.vm.classstat.client.core.VmClassStatView;
-import com.redhat.thermostat.vm.classstat.client.core.VmClassStatViewProvider;
-
-public class VmClassStatControllerTest {
-
-    @SuppressWarnings({ "unchecked", "rawtypes" }) // any(List.class)
-    @Test
-    public void testChartUpdate() {
-
-        VmClassStat stat1 = new VmClassStat(123, 12345, 1234);
-        List<VmClassStat> stats = new ArrayList<VmClassStat>();
-        stats.add(stat1);
-
-        VmClassStatDAO vmClassStatDAO = mock(VmClassStatDAO.class);
-        when(vmClassStatDAO.getLatestClassStats(any(VmRef.class), anyInt())).thenReturn(stats).thenReturn(new ArrayList<VmClassStat>());
-
-        VmRef ref = mock(VmRef.class);
-
-        Timer timer = mock(Timer.class);
-        ArgumentCaptor<Runnable> timerActionCaptor = ArgumentCaptor.forClass(Runnable.class);
-        doNothing().when(timer).setAction(timerActionCaptor.capture());
-
-        TimerFactory timerFactory = mock(TimerFactory.class);
-        when(timerFactory.createTimer()).thenReturn(timer);
-        ApplicationService appSvc = mock(ApplicationService.class);
-        when(appSvc.getTimerFactory()).thenReturn(timerFactory);
-
-        VmClassStatView view = mock(VmClassStatView.class);
-        ArgumentCaptor<ActionListener> viewArgumentCaptor = ArgumentCaptor.forClass(ActionListener.class);
-        doNothing().when(view).addActionListener(viewArgumentCaptor.capture());
-        
-        VmClassStatViewProvider viewProvider = mock(VmClassStatViewProvider.class);
-        when(viewProvider.createView()).thenReturn(view);
-
-        @SuppressWarnings("unused")
-        VmClassStatController controller = new VmClassStatController(appSvc, vmClassStatDAO, ref, viewProvider);
-
-        ActionListener<VmClassStatView.Action> l = viewArgumentCaptor.getValue();
-
-        l.actionPerformed(new ActionEvent<>(view, VmClassStatView.Action.VISIBLE));
-
-        verify(timer).start();
-        timerActionCaptor.getValue().run();
-        verify(view).addClassCount(any(List.class));
-
-        l.actionPerformed(new ActionEvent<>(view, VmClassStatView.Action.HIDDEN));
-
-        verify(timer).stop();
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-classstat/client-core/src/test/java/com/redhat/thermostat/vm/classstat/client/core/internal/ActivatorTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,91 @@
+/*
+ * 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.vm.classstat.client.core.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.client.core.VmInformationService;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.dao.VmClassStatDAO;
+import com.redhat.thermostat.test.StubBundleContext;
+import com.redhat.thermostat.vm.classstat.client.core.VmClassStatService;
+
+public class ActivatorTest {
+
+    @Test
+    public void verifyActivatorDoesNotRegisterServiceOnMissingDeps() throws Exception {
+        StubBundleContext context = new StubBundleContext();
+
+        Activator activator = new Activator();
+
+        activator.start(context);
+
+        assertEquals(0, context.getAllServices().size());
+        assertNotSame(1, context.getServiceListeners().size());
+
+        activator.stop(context);
+
+        assertEquals(0, context.getServiceListeners().size());
+    }
+
+    @Test
+    public void verifyActivatorRegistersServices() throws Exception {
+        StubBundleContext context = new StubBundleContext();
+        ApplicationService appService = mock(ApplicationService.class);
+        VmClassStatDAO daoService = mock(VmClassStatDAO.class);
+
+        context.registerService(ApplicationService.class, appService, null);
+        context.registerService(VmClassStatDAO.class, daoService, null);
+
+        Activator activator = new Activator();
+
+        activator.start(context);
+
+        assertTrue(context.isServiceRegistered(VmInformationService.class.getName(), VmClassStatService.class));
+
+        activator.stop(context);
+
+        assertEquals(0, context.getServiceListeners().size());
+        assertEquals(2, context.getAllServices().size());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-classstat/client-core/src/test/java/com/redhat/thermostat/vm/classstat/client/core/internal/VmClassStatControllerTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,110 @@
+/*
+ * 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.vm.classstat.client.core.internal;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.doNothing;
+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.List;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.Timer;
+import com.redhat.thermostat.common.TimerFactory;
+import com.redhat.thermostat.common.dao.VmClassStatDAO;
+import com.redhat.thermostat.common.dao.VmRef;
+import com.redhat.thermostat.storage.model.VmClassStat;
+import com.redhat.thermostat.vm.classstat.client.core.VmClassStatView;
+import com.redhat.thermostat.vm.classstat.client.core.VmClassStatViewProvider;
+
+public class VmClassStatControllerTest {
+
+    @SuppressWarnings({ "unchecked", "rawtypes" }) // any(List.class)
+    @Test
+    public void testChartUpdate() {
+
+        VmClassStat stat1 = new VmClassStat(123, 12345, 1234);
+        List<VmClassStat> stats = new ArrayList<VmClassStat>();
+        stats.add(stat1);
+
+        VmClassStatDAO vmClassStatDAO = mock(VmClassStatDAO.class);
+        when(vmClassStatDAO.getLatestClassStats(any(VmRef.class), anyInt())).thenReturn(stats).thenReturn(new ArrayList<VmClassStat>());
+
+        VmRef ref = mock(VmRef.class);
+
+        Timer timer = mock(Timer.class);
+        ArgumentCaptor<Runnable> timerActionCaptor = ArgumentCaptor.forClass(Runnable.class);
+        doNothing().when(timer).setAction(timerActionCaptor.capture());
+
+        TimerFactory timerFactory = mock(TimerFactory.class);
+        when(timerFactory.createTimer()).thenReturn(timer);
+        ApplicationService appSvc = mock(ApplicationService.class);
+        when(appSvc.getTimerFactory()).thenReturn(timerFactory);
+
+        VmClassStatView view = mock(VmClassStatView.class);
+        ArgumentCaptor<ActionListener> viewArgumentCaptor = ArgumentCaptor.forClass(ActionListener.class);
+        doNothing().when(view).addActionListener(viewArgumentCaptor.capture());
+        
+        VmClassStatViewProvider viewProvider = mock(VmClassStatViewProvider.class);
+        when(viewProvider.createView()).thenReturn(view);
+
+        @SuppressWarnings("unused")
+        VmClassStatController controller = new VmClassStatController(appSvc, vmClassStatDAO, ref, viewProvider);
+
+        ActionListener<VmClassStatView.Action> l = viewArgumentCaptor.getValue();
+
+        l.actionPerformed(new ActionEvent<>(view, VmClassStatView.Action.VISIBLE));
+
+        verify(timer).start();
+        timerActionCaptor.getValue().run();
+        verify(view).addClassCount(any(List.class));
+
+        l.actionPerformed(new ActionEvent<>(view, VmClassStatView.Action.HIDDEN));
+
+        verify(timer).stop();
+    }
+
+}
--- a/vm-classstat/client-swing/src/main/java/com/redhat/thermostat/vm/classstat/client/swing/Activator.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/vm-classstat/client-swing/src/main/java/com/redhat/thermostat/vm/classstat/client/swing/Activator.java	Fri Nov 30 17:30:25 2012 -0500
@@ -36,58 +36,21 @@
 
 package com.redhat.thermostat.vm.classstat.client.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.common.ApplicationService;
-import com.redhat.thermostat.common.MultipleServiceTracker;
-import com.redhat.thermostat.common.MultipleServiceTracker.Action;
-import com.redhat.thermostat.common.dao.VmClassStatDAO;
-import com.redhat.thermostat.vm.classstat.client.core.VmClassStatService;
 import com.redhat.thermostat.vm.classstat.client.core.VmClassStatViewProvider;
 
 public class Activator implements BundleActivator {
 
-    private MultipleServiceTracker classStatTracker;
-    private ServiceRegistration classStatRegistration;
-
     @Override
     public void start(final BundleContext context) throws Exception {
         VmClassStatViewProvider viewProvider = new SwingVmClassStatViewProvider();
+        // Unregistered on Activator.stop
         context.registerService(VmClassStatViewProvider.class.getName(), viewProvider, null);
-
-        Class<?>[] deps = new Class<?>[] {
-            ApplicationService.class,
-            VmClassStatDAO.class,
-        };
-
-        classStatTracker = new MultipleServiceTracker(context, deps, new Action() {
-
-            @Override
-            public void dependenciesAvailable(Map<String, Object> services) {
-                VmClassStatDAO dao = (VmClassStatDAO) services.get(VmClassStatDAO.class.getName());
-                ApplicationService appSvc = (ApplicationService) services.get(ApplicationService.class.getName());
-                Objects.requireNonNull(dao);
-                VmClassStatService service = new VmClassStatService(appSvc, dao);
-                classStatRegistration = context.registerService(VmInformationService.class.getName(), service, null);
-            }
-
-            @Override
-            public void dependenciesUnavailable() {
-                classStatRegistration.unregister();
-            }
-
-        });
-        classStatTracker.open();
     }
 
     @Override
     public void stop(BundleContext context) throws Exception {
-        classStatTracker.close();
     }
 }
--- a/vm-classstat/client-swing/src/test/java/com/redhat/thermostat/vm/classstat/client/swing/ActivatorTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/vm-classstat/client-swing/src/test/java/com/redhat/thermostat/vm/classstat/client/swing/ActivatorTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -37,60 +37,16 @@
 package com.redhat.thermostat.vm.classstat.client.swing;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
 
 import org.junit.Test;
 
-import com.redhat.thermostat.client.core.VmInformationService;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.dao.VmClassStatDAO;
 import com.redhat.thermostat.test.StubBundleContext;
-import com.redhat.thermostat.vm.classstat.client.core.VmClassStatService;
 import com.redhat.thermostat.vm.classstat.client.core.VmClassStatViewProvider;
 
 public class ActivatorTest {
 
     @Test
-    public void verifyActivatorDoesNotRegisterServiceOnMissingDeps() throws Exception {
-        StubBundleContext context = new StubBundleContext();
-
-        Activator activator = new Activator();
-
-        activator.start(context);
-
-        // View provider registers unconditionally
-        assertEquals(1, context.getAllServices().size());
-        assertNotSame(1, context.getServiceListeners().size());
-
-        activator.stop(context);
-
-        assertEquals(0, context.getServiceListeners().size());
-    }
-
-    @Test
-    public void verifyActivatorRegistersServices() throws Exception {
-        StubBundleContext context = new StubBundleContext();
-        ApplicationService appService = mock(ApplicationService.class);
-        VmClassStatDAO daoService = mock(VmClassStatDAO.class);
-
-        context.registerService(ApplicationService.class, appService, null);
-        context.registerService(VmClassStatDAO.class, daoService, null);
-
-        Activator activator = new Activator();
-
-        activator.start(context);
-
-        assertTrue(context.isServiceRegistered(VmInformationService.class.getName(), VmClassStatService.class));
-
-        activator.stop(context);
-
-        assertEquals(0, context.getServiceListeners().size());
-        assertEquals(3, context.getAllServices().size());
-    }
-
-    @Test
     public void verifyStartRegistersViewProvider() throws Exception {
         StubBundleContext ctx = new StubBundleContext();
         Activator activator = new Activator();
--- a/vm-cpu/client-core/pom.xml	Fri Nov 30 10:47:45 2012 -0500
+++ b/vm-cpu/client-core/pom.xml	Fri Nov 30 17:30:25 2012 -0500
@@ -17,13 +17,16 @@
         <extensions>true</extensions>
         <configuration>
           <instructions>
-            <Private-Package></Private-Package>
             <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
             <Bundle-SymbolicName>com.redhat.thermostat.vm.cpu.client.core</Bundle-SymbolicName>
+            <Bundle-Activator>com.redhat.thermostat.vm.cpu.client.core.internal.Activator</Bundle-Activator>
             <Export-Package>
               com.redhat.thermostat.vm.cpu.client.core,
               com.redhat.thermostat.vm.cpu.client.locale
             </Export-Package>
+            <Private-Package>
+              com.redhat.thermostat.vm.cpu.client.core.internal
+            </Private-Package>
             <!-- Do not autogenerate uses clauses in Manifests -->
             <_nouses>true</_nouses>
           </instructions>
--- a/vm-cpu/client-core/src/main/java/com/redhat/thermostat/vm/cpu/client/core/VmCpuController.java	Fri Nov 30 10:47:45 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +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.vm.cpu.client.core;
-
-import java.util.ArrayList;
-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.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.NotImplementedException;
-import com.redhat.thermostat.common.Timer;
-import com.redhat.thermostat.common.Timer.SchedulingType;
-import com.redhat.thermostat.common.dao.VmCpuStatDAO;
-import com.redhat.thermostat.common.dao.VmRef;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.storage.model.DiscreteTimeData;
-import com.redhat.thermostat.storage.model.VmCpuStat;
-import com.redhat.thermostat.vm.cpu.client.locale.LocaleResources;
-
-public class VmCpuController implements VmInformationServiceController {
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private final VmRef ref;
-    private final VmCpuStatDAO dao;
-    private final VmCpuView view;
-
-    private final Timer timer;
-
-    private long lastSeenTimeStamp = Long.MIN_VALUE;
-
-    public VmCpuController(ApplicationService appSvc, VmCpuStatDAO vmCpuStatDao, VmRef ref, VmCpuViewProvider provider) {
-        this.ref = ref;
-        dao = vmCpuStatDao;
-        timer = appSvc.getTimerFactory().createTimer();
-
-        timer.setAction(new Runnable() {
-            @Override
-            public void run() {
-                doUpdateVmCpuCharts();
-            }
-        });
-        timer.setTimeUnit(TimeUnit.SECONDS);
-        timer.setDelay(5);
-        timer.setInitialDelay(0);
-        timer.setSchedulingType(SchedulingType.FIXED_RATE);
-
-        view = provider.createView();
-
-        view.addActionListener(new ActionListener<VmCpuView.Action>() {
-            @Override
-            public void actionPerformed(ActionEvent<Action> actionEvent) {
-                switch (actionEvent.getActionId()) {
-                    case HIDDEN:
-                        stop();
-                        break;
-                    case VISIBLE:
-                        start();
-                        break;
-                    default:
-                        throw new NotImplementedException("unknown event : " + actionEvent.getActionId());
-                }
-            }
-        });
-    }
-
-    private void start() {
-        timer.start();
-    }
-
-    private void doUpdateVmCpuCharts() {
-        List<VmCpuStat> stats = dao.getLatestVmCpuStats(ref, lastSeenTimeStamp);
-        List<DiscreteTimeData<? extends Number>> toDisplay = new ArrayList<>(stats.size());
-        for (VmCpuStat stat: stats) {
-            DiscreteTimeData<? extends Number> data =
-                    new DiscreteTimeData<Number>(stat.getTimeStamp(), stat.getCpuLoad());
-            toDisplay.add(data);
-            lastSeenTimeStamp = Math.max(lastSeenTimeStamp, stat.getTimeStamp());
-        }
-
-        view.addData(toDisplay);
-    }
-
-    private void stop() {
-        timer.stop();
-    }
-
-    public UIComponent getView() {
-        return (UIComponent) view;
-    }
-
-    @Override
-    public String getLocalizedName() {
-        return translator.localize(LocaleResources.VM_INFO_TAB_CPU);
-    }
-}
--- a/vm-cpu/client-core/src/main/java/com/redhat/thermostat/vm/cpu/client/core/VmCpuService.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/vm-cpu/client-core/src/main/java/com/redhat/thermostat/vm/cpu/client/core/VmCpuService.java	Fri Nov 30 17:30:25 2012 -0500
@@ -44,6 +44,7 @@
 import com.redhat.thermostat.common.dao.VmCpuStatDAO;
 import com.redhat.thermostat.common.dao.VmRef;
 import com.redhat.thermostat.common.utils.OSGIUtils;
+import com.redhat.thermostat.vm.cpu.client.core.internal.VmCpuController;
 
 public class VmCpuService implements VmInformationService {
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-cpu/client-core/src/main/java/com/redhat/thermostat/vm/cpu/client/core/internal/Activator.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,91 @@
+/*
+ * 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.vm.cpu.client.core.internal;
+
+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.common.ApplicationService;
+import com.redhat.thermostat.common.MultipleServiceTracker;
+import com.redhat.thermostat.common.MultipleServiceTracker.Action;
+import com.redhat.thermostat.common.dao.VmCpuStatDAO;
+import com.redhat.thermostat.vm.cpu.client.core.VmCpuService;
+
+public class Activator implements BundleActivator {
+    
+    private MultipleServiceTracker tracker;
+    private ServiceRegistration reg;
+
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        Class<?>[] deps = new Class<?>[] {
+        	VmCpuStatDAO.class,
+        	ApplicationService.class
+        };
+        
+		tracker = new MultipleServiceTracker(context, deps , new Action() {
+            
+			@Override
+			public void dependenciesAvailable(Map<String, Object> services) {
+				VmCpuStatDAO vmCpuStatDAO = (VmCpuStatDAO) services.get(VmCpuStatDAO.class.getName());
+				Objects.requireNonNull(vmCpuStatDAO);
+				ApplicationService appSvc = (ApplicationService) services.get(ApplicationService.class.getName());
+				Objects.requireNonNull(appSvc);
+				VmCpuService service = new VmCpuService(appSvc, vmCpuStatDAO);
+				reg = context.registerService(VmInformationService.class.getName(), service, null);
+			}
+
+			@Override
+			public void dependenciesUnavailable() {
+				reg.unregister();
+			}
+        });
+        tracker.open();
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        tracker.close();
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-cpu/client-core/src/main/java/com/redhat/thermostat/vm/cpu/client/core/internal/VmCpuController.java	Fri Nov 30 17:30:25 2012 -0500
@@ -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.vm.cpu.client.core.internal;
+
+import java.util.ArrayList;
+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.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.NotImplementedException;
+import com.redhat.thermostat.common.Timer;
+import com.redhat.thermostat.common.Timer.SchedulingType;
+import com.redhat.thermostat.common.dao.VmCpuStatDAO;
+import com.redhat.thermostat.common.dao.VmRef;
+import com.redhat.thermostat.common.locale.Translate;
+import com.redhat.thermostat.storage.model.DiscreteTimeData;
+import com.redhat.thermostat.storage.model.VmCpuStat;
+import com.redhat.thermostat.vm.cpu.client.core.VmCpuView;
+import com.redhat.thermostat.vm.cpu.client.core.VmCpuViewProvider;
+import com.redhat.thermostat.vm.cpu.client.locale.LocaleResources;
+
+public class VmCpuController implements VmInformationServiceController {
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private final VmRef ref;
+    private final VmCpuStatDAO dao;
+    private final VmCpuView view;
+
+    private final Timer timer;
+
+    private long lastSeenTimeStamp = Long.MIN_VALUE;
+
+    public VmCpuController(ApplicationService appSvc, VmCpuStatDAO vmCpuStatDao, VmRef ref, VmCpuViewProvider provider) {
+        this.ref = ref;
+        dao = vmCpuStatDao;
+        timer = appSvc.getTimerFactory().createTimer();
+
+        timer.setAction(new Runnable() {
+            @Override
+            public void run() {
+                doUpdateVmCpuCharts();
+            }
+        });
+        timer.setTimeUnit(TimeUnit.SECONDS);
+        timer.setDelay(5);
+        timer.setInitialDelay(0);
+        timer.setSchedulingType(SchedulingType.FIXED_RATE);
+
+        view = provider.createView();
+
+        view.addActionListener(new ActionListener<VmCpuView.Action>() {
+            @Override
+            public void actionPerformed(ActionEvent<Action> actionEvent) {
+                switch (actionEvent.getActionId()) {
+                    case HIDDEN:
+                        stop();
+                        break;
+                    case VISIBLE:
+                        start();
+                        break;
+                    default:
+                        throw new NotImplementedException("unknown event : " + actionEvent.getActionId());
+                }
+            }
+        });
+    }
+
+    private void start() {
+        timer.start();
+    }
+
+    private void doUpdateVmCpuCharts() {
+        List<VmCpuStat> stats = dao.getLatestVmCpuStats(ref, lastSeenTimeStamp);
+        List<DiscreteTimeData<? extends Number>> toDisplay = new ArrayList<>(stats.size());
+        for (VmCpuStat stat: stats) {
+            DiscreteTimeData<? extends Number> data =
+                    new DiscreteTimeData<Number>(stat.getTimeStamp(), stat.getCpuLoad());
+            toDisplay.add(data);
+            lastSeenTimeStamp = Math.max(lastSeenTimeStamp, stat.getTimeStamp());
+        }
+
+        view.addData(toDisplay);
+    }
+
+    private void stop() {
+        timer.stop();
+    }
+
+    public UIComponent getView() {
+        return (UIComponent) view;
+    }
+
+    @Override
+    public String getLocalizedName() {
+        return translator.localize(LocaleResources.VM_INFO_TAB_CPU);
+    }
+}
--- a/vm-cpu/client-core/src/test/java/com/redhat/thermostat/vm/cpu/client/core/VmCpuControllerTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +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.vm.cpu.client.core;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doNothing;
-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.List;
-
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.Timer;
-import com.redhat.thermostat.common.TimerFactory;
-import com.redhat.thermostat.common.dao.VmCpuStatDAO;
-import com.redhat.thermostat.common.dao.VmRef;
-import com.redhat.thermostat.storage.model.VmCpuStat;
-import com.redhat.thermostat.vm.cpu.client.core.VmCpuController;
-import com.redhat.thermostat.vm.cpu.client.core.VmCpuView;
-import com.redhat.thermostat.vm.cpu.client.core.VmCpuViewProvider;
-
-
-public class VmCpuControllerTest {
-
-    @SuppressWarnings({ "unchecked", "rawtypes" }) // any(List.class)
-    @Test
-    public void testChartUpdate() {
-
-        VmCpuStat stat1 = new VmCpuStat(123, 12345, 50.5);
-        List<VmCpuStat> stats = new ArrayList<VmCpuStat>();
-        stats.add(stat1);
-
-        VmCpuStatDAO vmCpuStatDAO = mock(VmCpuStatDAO.class);
-        when(vmCpuStatDAO.getLatestVmCpuStats(any(VmRef.class), eq(Long.MIN_VALUE))).thenReturn(stats).thenReturn(new ArrayList<VmCpuStat>());
-
-        VmRef ref = mock(VmRef.class);
-
-        Timer timer = mock(Timer.class);
-        ArgumentCaptor<Runnable> timerActionCaptor = ArgumentCaptor.forClass(Runnable.class);
-        doNothing().when(timer).setAction(timerActionCaptor.capture());
-
-        TimerFactory timerFactory = mock(TimerFactory.class);
-        when(timerFactory.createTimer()).thenReturn(timer);
-        ApplicationService appSvc = mock(ApplicationService.class);
-        when(appSvc.getTimerFactory()).thenReturn(timerFactory);
-
-        final VmCpuView view = mock(VmCpuView.class);
-        ArgumentCaptor<ActionListener> viewArgumentCaptor = ArgumentCaptor.forClass(ActionListener.class);
-        doNothing().when(view).addActionListener(viewArgumentCaptor.capture());
-        
-        VmCpuViewProvider viewProvider = mock(VmCpuViewProvider.class);
-        when(viewProvider.createView()).thenReturn(view);
-
-        @SuppressWarnings("unused")
-        VmCpuController controller = new VmCpuController(appSvc, vmCpuStatDAO, ref, viewProvider);
-
-        ActionListener<VmCpuView.Action> l = viewArgumentCaptor.getValue();
-
-        l.actionPerformed(new ActionEvent<>(view, VmCpuView.Action.VISIBLE));
-
-        verify(timer).start();
-
-        timerActionCaptor.getValue().run();
-
-        l.actionPerformed(new ActionEvent<>(view, VmCpuView.Action.HIDDEN));
-
-        verify(timer).stop();
-
-        verify(view).addData(any(List.class));
-        // We don't verify atMost() since we might increase the update rate in the future.
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-cpu/client-core/src/test/java/com/redhat/thermostat/vm/cpu/client/core/internal/ActivatorTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,91 @@
+/*
+ * 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.vm.cpu.client.core.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.client.core.VmInformationService;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.dao.VmCpuStatDAO;
+import com.redhat.thermostat.test.StubBundleContext;
+import com.redhat.thermostat.vm.cpu.client.core.VmCpuService;
+
+public class ActivatorTest {
+    
+    @Test
+    public void verifyActivatorDoesNotRegisterServiceOnMissingDeps() throws Exception {
+        StubBundleContext context = new StubBundleContext();
+
+        Activator activator = new Activator();
+
+        activator.start(context);
+
+        assertEquals(0, context.getAllServices().size());
+        assertNotSame(1, context.getServiceListeners().size());
+        
+        activator.stop(context);
+
+        assertEquals(0, context.getServiceListeners().size());
+    }
+
+    @Test
+    public void verifyActivatorRegistersServices() throws Exception {
+        StubBundleContext context = new StubBundleContext();
+        VmCpuStatDAO vmCpuStatDAO = mock(VmCpuStatDAO.class);
+        ApplicationService appSvc = mock(ApplicationService.class);
+
+        context.registerService(VmCpuStatDAO.class, vmCpuStatDAO, null);
+        context.registerService(ApplicationService.class, appSvc, null);
+
+        Activator activator = new Activator();
+
+        activator.start(context);
+
+        assertTrue(context.isServiceRegistered(VmInformationService.class.getName(), VmCpuService.class));
+
+        activator.stop(context);
+
+        assertEquals(0, context.getServiceListeners().size());
+        assertEquals(2, context.getAllServices().size());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-cpu/client-core/src/test/java/com/redhat/thermostat/vm/cpu/client/core/internal/VmCpuControllerTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,114 @@
+/*
+ * 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.vm.cpu.client.core.internal;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
+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.List;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.Timer;
+import com.redhat.thermostat.common.TimerFactory;
+import com.redhat.thermostat.common.dao.VmCpuStatDAO;
+import com.redhat.thermostat.common.dao.VmRef;
+import com.redhat.thermostat.storage.model.VmCpuStat;
+import com.redhat.thermostat.vm.cpu.client.core.VmCpuView;
+import com.redhat.thermostat.vm.cpu.client.core.VmCpuViewProvider;
+import com.redhat.thermostat.vm.cpu.client.core.internal.VmCpuController;
+
+
+public class VmCpuControllerTest {
+
+    @SuppressWarnings({ "unchecked", "rawtypes" }) // any(List.class)
+    @Test
+    public void testChartUpdate() {
+
+        VmCpuStat stat1 = new VmCpuStat(123, 12345, 50.5);
+        List<VmCpuStat> stats = new ArrayList<VmCpuStat>();
+        stats.add(stat1);
+
+        VmCpuStatDAO vmCpuStatDAO = mock(VmCpuStatDAO.class);
+        when(vmCpuStatDAO.getLatestVmCpuStats(any(VmRef.class), eq(Long.MIN_VALUE))).thenReturn(stats).thenReturn(new ArrayList<VmCpuStat>());
+
+        VmRef ref = mock(VmRef.class);
+
+        Timer timer = mock(Timer.class);
+        ArgumentCaptor<Runnable> timerActionCaptor = ArgumentCaptor.forClass(Runnable.class);
+        doNothing().when(timer).setAction(timerActionCaptor.capture());
+
+        TimerFactory timerFactory = mock(TimerFactory.class);
+        when(timerFactory.createTimer()).thenReturn(timer);
+        ApplicationService appSvc = mock(ApplicationService.class);
+        when(appSvc.getTimerFactory()).thenReturn(timerFactory);
+
+        final VmCpuView view = mock(VmCpuView.class);
+        ArgumentCaptor<ActionListener> viewArgumentCaptor = ArgumentCaptor.forClass(ActionListener.class);
+        doNothing().when(view).addActionListener(viewArgumentCaptor.capture());
+        
+        VmCpuViewProvider viewProvider = mock(VmCpuViewProvider.class);
+        when(viewProvider.createView()).thenReturn(view);
+
+        @SuppressWarnings("unused")
+        VmCpuController controller = new VmCpuController(appSvc, vmCpuStatDAO, ref, viewProvider);
+
+        ActionListener<VmCpuView.Action> l = viewArgumentCaptor.getValue();
+
+        l.actionPerformed(new ActionEvent<>(view, VmCpuView.Action.VISIBLE));
+
+        verify(timer).start();
+
+        timerActionCaptor.getValue().run();
+
+        l.actionPerformed(new ActionEvent<>(view, VmCpuView.Action.HIDDEN));
+
+        verify(timer).stop();
+
+        verify(view).addData(any(List.class));
+        // We don't verify atMost() since we might increase the update rate in the future.
+    }
+}
--- a/vm-cpu/client-swing/src/main/java/com/redhat/thermostat/vm/cpu/client/swing/Activator.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/vm-cpu/client-swing/src/main/java/com/redhat/thermostat/vm/cpu/client/swing/Activator.java	Fri Nov 30 17:30:25 2012 -0500
@@ -36,60 +36,22 @@
 
 package com.redhat.thermostat.vm.cpu.client.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.common.ApplicationService;
-import com.redhat.thermostat.common.MultipleServiceTracker;
-import com.redhat.thermostat.common.MultipleServiceTracker.Action;
-import com.redhat.thermostat.common.dao.VmCpuStatDAO;
-import com.redhat.thermostat.vm.cpu.client.core.VmCpuService;
 import com.redhat.thermostat.vm.cpu.client.core.VmCpuViewProvider;
 
 public class Activator implements BundleActivator {
     
-    private MultipleServiceTracker tracker;
-    private ServiceRegistration reg;
-
     @Override
     public void start(final BundleContext context) throws Exception {
         VmCpuViewProvider viewProvider = new SwingVmCpuViewProvider();
+        // Unregistered on Activator.stop
         context.registerService(VmCpuViewProvider.class.getName(), viewProvider, null);
-
-        Class<?>[] deps = new Class<?>[] {
-                VmCpuStatDAO.class,
-                ApplicationService.class
-            };
-
-        tracker = new MultipleServiceTracker(context, deps, new Action() {
-
-            @Override
-            public void dependenciesAvailable(Map<String, Object> services) {
-                VmCpuStatDAO vmCpuStatDAO = (VmCpuStatDAO) services.get(VmCpuStatDAO.class.getName());
-                Objects.requireNonNull(vmCpuStatDAO);
-                ApplicationService appSvc = (ApplicationService) services.get(ApplicationService.class.getName());
-                Objects.requireNonNull(appSvc);
-                VmCpuService service = new VmCpuService(appSvc, vmCpuStatDAO);
-                reg = context.registerService(VmInformationService.class.getName(), service, null);
-            }
-
-            @Override
-            public void dependenciesUnavailable() {
-                reg.unregister();
-            }
-
-        });
-        tracker.open();
     }
 
     @Override
     public void stop(BundleContext context) throws Exception {
-        tracker.close();
     }
 
 }
--- a/vm-cpu/client-swing/src/test/java/com/redhat/thermostat/vm/cpu/client/swing/ActivatorTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/vm-cpu/client-swing/src/test/java/com/redhat/thermostat/vm/cpu/client/swing/ActivatorTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -38,58 +38,15 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
 
 import org.junit.Test;
 
-import com.redhat.thermostat.client.core.VmInformationService;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.dao.VmCpuStatDAO;
 import com.redhat.thermostat.test.StubBundleContext;
-import com.redhat.thermostat.vm.cpu.client.core.VmCpuService;
 import com.redhat.thermostat.vm.cpu.client.core.VmCpuViewProvider;
 
 public class ActivatorTest {
     
     @Test
-    public void verifyActivatorDoesNotRegisterServiceOnMissingDeps() throws Exception {
-        StubBundleContext context = new StubBundleContext();
-
-        Activator activator = new Activator();
-
-        activator.start(context);
-
-        // View provider registers unconditionally
-        assertEquals(1, context.getAllServices().size());
-        assertEquals(2, context.getServiceListeners().size());
-        
-        activator.stop(context);
-
-        assertEquals(0, context.getServiceListeners().size());
-    }
-
-    @Test
-    public void verifyActivatorRegistersServices() throws Exception {
-        StubBundleContext context = new StubBundleContext();
-        VmCpuStatDAO vmCpuStatDAO = mock(VmCpuStatDAO.class);
-        ApplicationService appSvc = mock(ApplicationService.class);
-
-        context.registerService(VmCpuStatDAO.class, vmCpuStatDAO, null);
-        context.registerService(ApplicationService.class, appSvc, null);
-
-        Activator activator = new Activator();
-
-        activator.start(context);
-
-        assertTrue(context.isServiceRegistered(VmInformationService.class.getName(), VmCpuService.class));
-
-        activator.stop(context);
-
-        assertEquals(0, context.getServiceListeners().size());
-        assertEquals(3, context.getAllServices().size());
-    }
-
-    @Test
     public void verifyStartRegistersViewProvider() throws Exception {
         StubBundleContext ctx = new StubBundleContext();
         Activator activator = new Activator();
--- a/vm-gc/client-core/pom.xml	Fri Nov 30 10:47:45 2012 -0500
+++ b/vm-gc/client-core/pom.xml	Fri Nov 30 17:30:25 2012 -0500
@@ -17,13 +17,16 @@
         <extensions>true</extensions>
         <configuration>
           <instructions>
-            <Private-Package></Private-Package>
             <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
             <Bundle-SymbolicName>com.redhat.thermostat.vm.gc.client.core</Bundle-SymbolicName>
+            <Bundle-Activator>com.redhat.thermostat.vm.gc.client.core.internal.Activator</Bundle-Activator>
             <Export-Package>
               com.redhat.thermostat.vm.gc.client.core,
               com.redhat.thermostat.vm.gc.client.locale
             </Export-Package>
+            <Private-Package>
+              com.redhat.thermostat.vm.gc.client.core.internal
+            </Private-Package>
             <!-- Do not autogenerate uses clauses in Manifests -->
             <_nouses>true</_nouses>
           </instructions>
--- a/vm-gc/client-core/src/main/java/com/redhat/thermostat/vm/gc/client/core/VmGcController.java	Fri Nov 30 10:47:45 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,201 +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.vm.gc.client.core;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-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.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.NotImplementedException;
-import com.redhat.thermostat.common.Timer;
-import com.redhat.thermostat.common.Timer.SchedulingType;
-import com.redhat.thermostat.common.dao.VmGcStatDAO;
-import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
-import com.redhat.thermostat.common.dao.VmRef;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.storage.model.IntervalTimeData;
-import com.redhat.thermostat.storage.model.TimeStampedPojoComparator;
-import com.redhat.thermostat.storage.model.VmGcStat;
-import com.redhat.thermostat.storage.model.VmMemoryStat;
-import com.redhat.thermostat.storage.model.VmMemoryStat.Generation;
-import com.redhat.thermostat.vm.gc.client.locale.LocaleResources;
-
-public class VmGcController implements VmInformationServiceController {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private final VmRef ref;
-    private final VmGcView view;
-
-    private final VmGcStatDAO gcDao;
-    private final VmMemoryStatDAO memDao;
-
-    private final Set<String> addedCollectors = new TreeSet<>();
-    // the last value seen for each collector
-    private final Map<String, VmGcStat> lastValueSeen = new TreeMap<>();
-
-    private final Timer timer;
-
-    private long lastSeenTimeStamp = Long.MIN_VALUE;
-
-    public VmGcController(ApplicationService appSvc, VmMemoryStatDAO vmMemoryStatDao, VmGcStatDAO vmGcStatDao, VmRef ref, VmGcViewProvider provider) {
-        this.ref = ref;
-        this.view = provider.createView();
-        this.timer = appSvc.getTimerFactory().createTimer();
-
-        gcDao = vmGcStatDao;
-        memDao = vmMemoryStatDao;
-
-        view.addActionListener(new ActionListener<VmGcView.Action>() {
-            @Override
-            public void actionPerformed(ActionEvent<Action> actionEvent) {
-                switch (actionEvent.getActionId()) {
-                    case HIDDEN:
-                        stop();
-                        break;
-                    case VISIBLE:
-                        start();
-                        break;
-                    default:
-                        throw new NotImplementedException("unkonwn action: " + actionEvent.getActionId());
-                }
-            }
-        });
-
-        timer.setAction(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    doUpdateCollectorData();
-                } catch (Throwable t) {
-                    t.printStackTrace();
-                    throw t;
-                }
-            }
-        });
-        timer.setSchedulingType(SchedulingType.FIXED_RATE);
-        timer.setInitialDelay(0);
-        timer.setDelay(5);
-        timer.setTimeUnit(TimeUnit.SECONDS);
-    }
-
-    private void start() {
-        timer.start();
-    }
-
-    private void stop() {
-         timer.stop();
-    }
-
-    // FIXME
-    private String chartName(String collectorName, String generationName) {
-        return translator.localize(LocaleResources.VM_GC_COLLECTOR_OVER_GENERATION,
-                collectorName, generationName);
-    }
-
-    private void doUpdateCollectorData() {
-        Map<String, List<IntervalTimeData<Double>>> dataToAdd = new HashMap<>();
-        List<VmGcStat> sortedList = gcDao.getLatestVmGcStats(ref, lastSeenTimeStamp);
-        Collections.sort(sortedList, new TimeStampedPojoComparator<>());
-
-        for (VmGcStat stat : sortedList) {
-            String collector = stat.getCollectorName();
-            List<IntervalTimeData<Double>> data = dataToAdd.get(collector);
-            if (data == null) {
-                data = new ArrayList<>();
-                dataToAdd.put(collector, data);
-            }
-            if (lastValueSeen.containsKey(collector)) {
-                if (stat.getTimeStamp() <= lastValueSeen.get(collector).getTimeStamp()) {
-                    System.out.println("new gc collector value is older than previous value");
-                }
-                VmGcStat last = lastValueSeen.get(collector);
-                lastSeenTimeStamp = Math.max(lastSeenTimeStamp, stat.getTimeStamp());
-                long diffInMicro = (stat.getWallTime() - last.getWallTime());
-                double diffInMillis = diffInMicro / 1000.0;
-                // TODO there is not much point in adding data when diff is 0,
-                // but we need to make the chart scroll automatically based on
-                // the current time when we do that
-                //  if (diff != 0) {
-                data.add(new IntervalTimeData<>(last.getTimeStamp(), stat.getTimeStamp(), diffInMillis));
-                // }
-            }
-            lastValueSeen.put(collector, stat);
-        }
-        for (Map.Entry<String, List<IntervalTimeData<Double>>> entry : dataToAdd.entrySet()) {
-            String name = entry.getKey();
-            if (!addedCollectors.contains(name)) {
-                view.addChart(name, chartName(name, getCollectorGeneration(name)), "ms");
-                addedCollectors.add(name);
-            }
-            view.addData(entry.getKey(), entry.getValue());
-        }
-    }
-
-    public String getCollectorGeneration(String collectorName) {
-        VmMemoryStat info = memDao.getLatestMemoryStat(ref);
-
-        for (Generation g: info.getGenerations()) {
-            if (g.getCollector().equals(collectorName)) {
-                return g.getName();
-            }
-        }
-        return translator.localize(LocaleResources.UNKNOWN_GEN);
-    }
-
-    public UIComponent getView() {
-        return (UIComponent) view;
-    }
-
-    @Override
-    public String getLocalizedName() {
-        return translator.localize(LocaleResources.VM_INFO_TAB_GC);
-    }
-
-}
--- a/vm-gc/client-core/src/main/java/com/redhat/thermostat/vm/gc/client/core/VmGcService.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/vm-gc/client-core/src/main/java/com/redhat/thermostat/vm/gc/client/core/VmGcService.java	Fri Nov 30 17:30:25 2012 -0500
@@ -45,6 +45,7 @@
 import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
 import com.redhat.thermostat.common.dao.VmRef;
 import com.redhat.thermostat.common.utils.OSGIUtils;
+import com.redhat.thermostat.vm.gc.client.core.internal.VmGcController;
 
 public class VmGcService implements VmInformationService {
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/client-core/src/main/java/com/redhat/thermostat/vm/gc/client/core/internal/Activator.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,96 @@
+/*
+ * 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.vm.gc.client.core.internal;
+
+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.common.ApplicationService;
+import com.redhat.thermostat.common.MultipleServiceTracker;
+import com.redhat.thermostat.common.MultipleServiceTracker.Action;
+import com.redhat.thermostat.common.dao.VmGcStatDAO;
+import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
+import com.redhat.thermostat.vm.gc.client.core.VmGcService;
+
+public class Activator implements BundleActivator {
+    
+    private MultipleServiceTracker tracker;
+    private ServiceRegistration reg;
+
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        Class<?>[] deps = new Class<?>[] {
+            VmMemoryStatDAO.class,
+            VmGcStatDAO.class,
+            ApplicationService.class
+        };
+
+        tracker = new MultipleServiceTracker(context, deps, new Action() {
+
+            @Override
+            public void dependenciesAvailable(Map<String, Object> services) {
+                VmMemoryStatDAO vmMemoryStatDAO = (VmMemoryStatDAO) services.get(VmMemoryStatDAO.class.getName());
+                Objects.requireNonNull(vmMemoryStatDAO);
+                VmGcStatDAO vmGcStatDAO = (VmGcStatDAO) services.get(VmGcStatDAO.class.getName());
+                Objects.requireNonNull(vmGcStatDAO);
+                ApplicationService appSvc = (ApplicationService) services.get(ApplicationService.class.getName());
+                Objects.requireNonNull(appSvc);
+                VmGcService service = new VmGcService(appSvc, vmMemoryStatDAO, vmGcStatDAO);
+                reg = context.registerService(VmInformationService.class.getName(), service, null);
+            }
+
+            @Override
+            public void dependenciesUnavailable() {
+                reg.unregister();
+            }
+
+        });
+        tracker.open();
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        tracker.close();
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/client-core/src/main/java/com/redhat/thermostat/vm/gc/client/core/internal/VmGcController.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,203 @@
+/*
+ * 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.vm.gc.client.core.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+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.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.NotImplementedException;
+import com.redhat.thermostat.common.Timer;
+import com.redhat.thermostat.common.Timer.SchedulingType;
+import com.redhat.thermostat.common.dao.VmGcStatDAO;
+import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
+import com.redhat.thermostat.common.dao.VmRef;
+import com.redhat.thermostat.common.locale.Translate;
+import com.redhat.thermostat.storage.model.IntervalTimeData;
+import com.redhat.thermostat.storage.model.TimeStampedPojoComparator;
+import com.redhat.thermostat.storage.model.VmGcStat;
+import com.redhat.thermostat.storage.model.VmMemoryStat;
+import com.redhat.thermostat.storage.model.VmMemoryStat.Generation;
+import com.redhat.thermostat.vm.gc.client.core.VmGcView;
+import com.redhat.thermostat.vm.gc.client.core.VmGcViewProvider;
+import com.redhat.thermostat.vm.gc.client.locale.LocaleResources;
+
+public class VmGcController implements VmInformationServiceController {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private final VmRef ref;
+    private final VmGcView view;
+
+    private final VmGcStatDAO gcDao;
+    private final VmMemoryStatDAO memDao;
+
+    private final Set<String> addedCollectors = new TreeSet<>();
+    // the last value seen for each collector
+    private final Map<String, VmGcStat> lastValueSeen = new TreeMap<>();
+
+    private final Timer timer;
+
+    private long lastSeenTimeStamp = Long.MIN_VALUE;
+
+    public VmGcController(ApplicationService appSvc, VmMemoryStatDAO vmMemoryStatDao, VmGcStatDAO vmGcStatDao, VmRef ref, VmGcViewProvider provider) {
+        this.ref = ref;
+        this.view = provider.createView();
+        this.timer = appSvc.getTimerFactory().createTimer();
+
+        gcDao = vmGcStatDao;
+        memDao = vmMemoryStatDao;
+
+        view.addActionListener(new ActionListener<VmGcView.Action>() {
+            @Override
+            public void actionPerformed(ActionEvent<Action> actionEvent) {
+                switch (actionEvent.getActionId()) {
+                    case HIDDEN:
+                        stop();
+                        break;
+                    case VISIBLE:
+                        start();
+                        break;
+                    default:
+                        throw new NotImplementedException("unkonwn action: " + actionEvent.getActionId());
+                }
+            }
+        });
+
+        timer.setAction(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    doUpdateCollectorData();
+                } catch (Throwable t) {
+                    t.printStackTrace();
+                    throw t;
+                }
+            }
+        });
+        timer.setSchedulingType(SchedulingType.FIXED_RATE);
+        timer.setInitialDelay(0);
+        timer.setDelay(5);
+        timer.setTimeUnit(TimeUnit.SECONDS);
+    }
+
+    private void start() {
+        timer.start();
+    }
+
+    private void stop() {
+         timer.stop();
+    }
+
+    // FIXME
+    private String chartName(String collectorName, String generationName) {
+        return translator.localize(LocaleResources.VM_GC_COLLECTOR_OVER_GENERATION,
+                collectorName, generationName);
+    }
+
+    private void doUpdateCollectorData() {
+        Map<String, List<IntervalTimeData<Double>>> dataToAdd = new HashMap<>();
+        List<VmGcStat> sortedList = gcDao.getLatestVmGcStats(ref, lastSeenTimeStamp);
+        Collections.sort(sortedList, new TimeStampedPojoComparator<>());
+
+        for (VmGcStat stat : sortedList) {
+            String collector = stat.getCollectorName();
+            List<IntervalTimeData<Double>> data = dataToAdd.get(collector);
+            if (data == null) {
+                data = new ArrayList<>();
+                dataToAdd.put(collector, data);
+            }
+            if (lastValueSeen.containsKey(collector)) {
+                if (stat.getTimeStamp() <= lastValueSeen.get(collector).getTimeStamp()) {
+                    System.out.println("new gc collector value is older than previous value");
+                }
+                VmGcStat last = lastValueSeen.get(collector);
+                lastSeenTimeStamp = Math.max(lastSeenTimeStamp, stat.getTimeStamp());
+                long diffInMicro = (stat.getWallTime() - last.getWallTime());
+                double diffInMillis = diffInMicro / 1000.0;
+                // TODO there is not much point in adding data when diff is 0,
+                // but we need to make the chart scroll automatically based on
+                // the current time when we do that
+                //  if (diff != 0) {
+                data.add(new IntervalTimeData<>(last.getTimeStamp(), stat.getTimeStamp(), diffInMillis));
+                // }
+            }
+            lastValueSeen.put(collector, stat);
+        }
+        for (Map.Entry<String, List<IntervalTimeData<Double>>> entry : dataToAdd.entrySet()) {
+            String name = entry.getKey();
+            if (!addedCollectors.contains(name)) {
+                view.addChart(name, chartName(name, getCollectorGeneration(name)), "ms");
+                addedCollectors.add(name);
+            }
+            view.addData(entry.getKey(), entry.getValue());
+        }
+    }
+
+    public String getCollectorGeneration(String collectorName) {
+        VmMemoryStat info = memDao.getLatestMemoryStat(ref);
+
+        for (Generation g: info.getGenerations()) {
+            if (g.getCollector().equals(collectorName)) {
+                return g.getName();
+            }
+        }
+        return translator.localize(LocaleResources.UNKNOWN_GEN);
+    }
+
+    public UIComponent getView() {
+        return (UIComponent) view;
+    }
+
+    @Override
+    public String getLocalizedName() {
+        return translator.localize(LocaleResources.VM_INFO_TAB_GC);
+    }
+
+}
--- a/vm-gc/client-core/src/test/java/com/redhat/thermostat/vm/gc/client/core/VmGcControllerTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ /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.vm.gc.client.core;
-
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isA;
-import static org.mockito.Matchers.isNotNull;
-import static org.mockito.Mockito.doNothing;
-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.List;
-import java.util.concurrent.TimeUnit;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.Timer;
-import com.redhat.thermostat.common.Timer.SchedulingType;
-import com.redhat.thermostat.common.TimerFactory;
-import com.redhat.thermostat.common.dao.VmGcStatDAO;
-import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
-import com.redhat.thermostat.common.dao.VmRef;
-import com.redhat.thermostat.storage.model.VmGcStat;
-import com.redhat.thermostat.storage.model.VmMemoryStat;
-import com.redhat.thermostat.storage.model.VmMemoryStat.Generation;
-import com.redhat.thermostat.vm.gc.client.core.VmGcController;
-import com.redhat.thermostat.vm.gc.client.core.VmGcView;
-import com.redhat.thermostat.vm.gc.client.core.VmGcViewProvider;
-
-public class VmGcControllerTest {
-
-    private Timer timer;
-    private Runnable timerAction;
-    private VmGcView view;
-    private ActionListener<VmGcView.Action> viewListener;
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    @Before
-    public void setUp() {
-
-        // Setup Timer
-        timer = mock(Timer.class);
-        ArgumentCaptor<Runnable> timerActionCaptor = ArgumentCaptor.forClass(Runnable.class);
-        doNothing().when(timer).setAction(timerActionCaptor.capture());
-
-        TimerFactory timerFactory = mock(TimerFactory.class);
-        when(timerFactory.createTimer()).thenReturn(timer);
-        ApplicationService appSvc = mock(ApplicationService.class);
-        when(appSvc.getTimerFactory()).thenReturn(timerFactory);
-
-        // Set up fake data
-        List<VmGcStat> stats = new ArrayList<>();
-        VmGcStat stat1 = new VmGcStat(42, 1, "collector1", 1, 10);
-        VmGcStat stat2 = new VmGcStat(42, 2, "collector1", 5, 20);
-        stats.add(stat1);
-        stats.add(stat2);
-
-        Generation gen;
-        gen = new Generation();
-        gen.setName("generation 1");
-        gen.setCollector("collector1");
-        VmMemoryStat memoryStat = new VmMemoryStat(1, 42, new Generation[] { gen });
-
-        // Setup DAO
-        VmGcStatDAO vmGcStatDAO = mock(VmGcStatDAO.class);
-        when(vmGcStatDAO.getLatestVmGcStats(isA(VmRef.class), eq(Long.MIN_VALUE))).thenReturn(stats);
-        VmMemoryStatDAO vmMemoryStatDAO = mock(VmMemoryStatDAO.class);
-        when(vmMemoryStatDAO.getLatestMemoryStat(isA(VmRef.class))).thenReturn(memoryStat);
-
-        // Setup View
-        view = mock(VmGcView.class);
-        ArgumentCaptor<ActionListener> viewArgumentCaptor = ArgumentCaptor.forClass(ActionListener.class);
-        doNothing().when(view).addActionListener(viewArgumentCaptor.capture());
-
-        VmGcViewProvider viewProvider = mock(VmGcViewProvider.class);
-        when(viewProvider.createView()).thenReturn(view);
-
-        // Now start the controller
-        VmRef ref = mock(VmRef.class);
-
-        new VmGcController(appSvc, vmMemoryStatDAO, vmGcStatDAO, ref, viewProvider);
-
-        // Extract relevant objects
-        viewListener = viewArgumentCaptor.getValue();
-        timerAction = timerActionCaptor.getValue();
-    }
-
-    @Test
-    public void verifyTimer() {
-        verify(timer).setAction(isNotNull(Runnable.class));
-        verify(timer).setAction(isA(Runnable.class));
-        verify(timer).setDelay(5);
-        verify(timer).setInitialDelay(0);
-        verify(timer).setTimeUnit(TimeUnit.SECONDS);
-        verify(timer).setSchedulingType(SchedulingType.FIXED_RATE);
-
-    }
-
-    @Test
-    public void verifyStartAndStop() {
-        viewListener.actionPerformed(new ActionEvent<>(view, VmGcView.Action.VISIBLE));
-
-        verify(timer).start();
-
-        viewListener.actionPerformed(new ActionEvent<>(view, VmGcView.Action.HIDDEN));
-
-        verify(timer).stop();
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public void verifyAction() {
-        timerAction.run();
-
-        verify(view).addData(isA(String.class), isA(List.class));
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/client-core/src/test/java/com/redhat/thermostat/vm/gc/client/core/internal/ActivatorTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -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.vm.gc.client.core.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.client.core.VmInformationService;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.dao.VmGcStatDAO;
+import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
+import com.redhat.thermostat.test.StubBundleContext;
+import com.redhat.thermostat.vm.gc.client.core.VmGcService;
+
+public class ActivatorTest {
+    
+    @Test
+    public void verifyActivatorDoesNotRegisterServiceOnMissingDeps() throws Exception {
+        StubBundleContext context = new StubBundleContext();
+
+        Activator activator = new Activator();
+
+        activator.start(context);
+
+        assertEquals(0, context.getAllServices().size());
+        assertNotSame(1, context.getServiceListeners().size());
+
+        activator.stop(context);
+
+        assertEquals(0, context.getServiceListeners().size());
+    }
+
+    @Test
+    public void verifyActivatorRegistersServices() throws Exception {
+        StubBundleContext context = new StubBundleContext();
+        VmMemoryStatDAO vmMemoryStatDAO = mock(VmMemoryStatDAO.class);
+        VmGcStatDAO vmGcStatDAO = mock(VmGcStatDAO.class);
+        ApplicationService appSvc = mock(ApplicationService.class);
+
+        context.registerService(VmMemoryStatDAO.class, vmMemoryStatDAO, null);
+        context.registerService(VmGcStatDAO.class, vmGcStatDAO, null);
+        context.registerService(ApplicationService.class, appSvc, null);
+
+        Activator activator = new Activator();
+
+        activator.start(context);
+
+        assertTrue(context.isServiceRegistered(VmInformationService.class.getName(), VmGcService.class));
+
+        activator.stop(context);
+
+        assertEquals(0, context.getServiceListeners().size());
+        assertEquals(3, context.getAllServices().size());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/client-core/src/test/java/com/redhat/thermostat/vm/gc/client/core/internal/VmGcControllerTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,159 @@
+/*
+ * 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.vm.gc.client.core.internal;
+
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Matchers.isNotNull;
+import static org.mockito.Mockito.doNothing;
+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.List;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.Timer;
+import com.redhat.thermostat.common.Timer.SchedulingType;
+import com.redhat.thermostat.common.TimerFactory;
+import com.redhat.thermostat.common.dao.VmGcStatDAO;
+import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
+import com.redhat.thermostat.common.dao.VmRef;
+import com.redhat.thermostat.storage.model.VmGcStat;
+import com.redhat.thermostat.storage.model.VmMemoryStat;
+import com.redhat.thermostat.storage.model.VmMemoryStat.Generation;
+import com.redhat.thermostat.vm.gc.client.core.VmGcView;
+import com.redhat.thermostat.vm.gc.client.core.VmGcViewProvider;
+import com.redhat.thermostat.vm.gc.client.core.internal.VmGcController;
+
+public class VmGcControllerTest {
+
+    private Timer timer;
+    private Runnable timerAction;
+    private VmGcView view;
+    private ActionListener<VmGcView.Action> viewListener;
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Before
+    public void setUp() {
+
+        // Setup Timer
+        timer = mock(Timer.class);
+        ArgumentCaptor<Runnable> timerActionCaptor = ArgumentCaptor.forClass(Runnable.class);
+        doNothing().when(timer).setAction(timerActionCaptor.capture());
+
+        TimerFactory timerFactory = mock(TimerFactory.class);
+        when(timerFactory.createTimer()).thenReturn(timer);
+        ApplicationService appSvc = mock(ApplicationService.class);
+        when(appSvc.getTimerFactory()).thenReturn(timerFactory);
+
+        // Set up fake data
+        List<VmGcStat> stats = new ArrayList<>();
+        VmGcStat stat1 = new VmGcStat(42, 1, "collector1", 1, 10);
+        VmGcStat stat2 = new VmGcStat(42, 2, "collector1", 5, 20);
+        stats.add(stat1);
+        stats.add(stat2);
+
+        Generation gen;
+        gen = new Generation();
+        gen.setName("generation 1");
+        gen.setCollector("collector1");
+        VmMemoryStat memoryStat = new VmMemoryStat(1, 42, new Generation[] { gen });
+
+        // Setup DAO
+        VmGcStatDAO vmGcStatDAO = mock(VmGcStatDAO.class);
+        when(vmGcStatDAO.getLatestVmGcStats(isA(VmRef.class), eq(Long.MIN_VALUE))).thenReturn(stats);
+        VmMemoryStatDAO vmMemoryStatDAO = mock(VmMemoryStatDAO.class);
+        when(vmMemoryStatDAO.getLatestMemoryStat(isA(VmRef.class))).thenReturn(memoryStat);
+
+        // Setup View
+        view = mock(VmGcView.class);
+        ArgumentCaptor<ActionListener> viewArgumentCaptor = ArgumentCaptor.forClass(ActionListener.class);
+        doNothing().when(view).addActionListener(viewArgumentCaptor.capture());
+
+        VmGcViewProvider viewProvider = mock(VmGcViewProvider.class);
+        when(viewProvider.createView()).thenReturn(view);
+
+        // Now start the controller
+        VmRef ref = mock(VmRef.class);
+
+        new VmGcController(appSvc, vmMemoryStatDAO, vmGcStatDAO, ref, viewProvider);
+
+        // Extract relevant objects
+        viewListener = viewArgumentCaptor.getValue();
+        timerAction = timerActionCaptor.getValue();
+    }
+
+    @Test
+    public void verifyTimer() {
+        verify(timer).setAction(isNotNull(Runnable.class));
+        verify(timer).setAction(isA(Runnable.class));
+        verify(timer).setDelay(5);
+        verify(timer).setInitialDelay(0);
+        verify(timer).setTimeUnit(TimeUnit.SECONDS);
+        verify(timer).setSchedulingType(SchedulingType.FIXED_RATE);
+
+    }
+
+    @Test
+    public void verifyStartAndStop() {
+        viewListener.actionPerformed(new ActionEvent<>(view, VmGcView.Action.VISIBLE));
+
+        verify(timer).start();
+
+        viewListener.actionPerformed(new ActionEvent<>(view, VmGcView.Action.HIDDEN));
+
+        verify(timer).stop();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void verifyAction() {
+        timerAction.run();
+
+        verify(view).addData(isA(String.class), isA(List.class));
+    }
+
+}
--- a/vm-gc/client-swing/src/main/java/com/redhat/thermostat/vm/gc/client/swing/Activator.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/vm-gc/client-swing/src/main/java/com/redhat/thermostat/vm/gc/client/swing/Activator.java	Fri Nov 30 17:30:25 2012 -0500
@@ -36,63 +36,22 @@
 
 package com.redhat.thermostat.vm.gc.client.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.common.ApplicationService;
-import com.redhat.thermostat.common.MultipleServiceTracker;
-import com.redhat.thermostat.common.MultipleServiceTracker.Action;
-import com.redhat.thermostat.common.dao.VmGcStatDAO;
-import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
-import com.redhat.thermostat.vm.gc.client.core.VmGcService;
 import com.redhat.thermostat.vm.gc.client.core.VmGcViewProvider;
 
 public class Activator implements BundleActivator {
 
-    private MultipleServiceTracker tracker;
-    private ServiceRegistration reg;
-
     @Override
     public void start(final BundleContext context) throws Exception {
         VmGcViewProvider viewProvider = new SwingVmGcViewProvider();
+        // Unregistered on Activator.stop
         context.registerService(VmGcViewProvider.class.getName(), viewProvider, null);
-
-        Class<?>[] deps = new Class<?>[] {
-            ApplicationService.class,
-            VmMemoryStatDAO.class,
-            VmGcStatDAO.class,
-        };
-
-        tracker = new MultipleServiceTracker(context, deps, new Action() {
-
-            @Override
-            public void dependenciesAvailable(Map<String, Object> services) {
-                VmMemoryStatDAO vmMemoryStatDAO = (VmMemoryStatDAO) services.get(VmMemoryStatDAO.class.getName());
-                Objects.requireNonNull(vmMemoryStatDAO);
-                VmGcStatDAO vmGcStatDAO = (VmGcStatDAO) services.get(VmGcStatDAO.class.getName());
-                Objects.requireNonNull(vmGcStatDAO);
-                ApplicationService appSvc = (ApplicationService) services.get(ApplicationService.class.getName());
-                VmGcService service = new VmGcService(appSvc, vmMemoryStatDAO, vmGcStatDAO);
-                reg = context.registerService(VmInformationService.class.getName(), service, null);
-            }
-
-            @Override
-            public void dependenciesUnavailable() {
-                reg.unregister();
-            }
-
-        });
-        tracker.open();
     }
 
     @Override
     public void stop(BundleContext context) throws Exception {
-        tracker.close();
     }
 
 }
--- a/vm-gc/client-swing/src/test/java/com/redhat/thermostat/vm/gc/client/swing/ActivatorTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/vm-gc/client-swing/src/test/java/com/redhat/thermostat/vm/gc/client/swing/ActivatorTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -37,63 +37,16 @@
 package com.redhat.thermostat.vm.gc.client.swing;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
 
 import org.junit.Test;
 
-import com.redhat.thermostat.client.core.VmInformationService;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.dao.VmGcStatDAO;
-import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
 import com.redhat.thermostat.test.StubBundleContext;
-import com.redhat.thermostat.vm.gc.client.core.VmGcService;
 import com.redhat.thermostat.vm.gc.client.core.VmGcViewProvider;
 
 public class ActivatorTest {
     
     @Test
-    public void verifyActivatorDoesNotRegisterServiceOnMissingDeps() throws Exception {
-        StubBundleContext context = new StubBundleContext();
-
-        Activator activator = new Activator();
-
-        activator.start(context);
-
-        // View provider registers unconditionally
-        assertEquals(1, context.getAllServices().size());
-        assertNotSame(1, context.getServiceListeners().size());
-
-        activator.stop(context);
-
-        assertEquals(0, context.getServiceListeners().size());
-    }
-
-    @Test
-    public void verifyActivatorRegistersServices() throws Exception {
-        StubBundleContext context = new StubBundleContext();
-        VmMemoryStatDAO vmMemoryStatDAO = mock(VmMemoryStatDAO.class);
-        VmGcStatDAO vmGcStatDAO = mock(VmGcStatDAO.class);
-        ApplicationService appSvc = mock(ApplicationService.class);
-
-        context.registerService(VmMemoryStatDAO.class, vmMemoryStatDAO, null);
-        context.registerService(VmGcStatDAO.class, vmGcStatDAO, null);
-        context.registerService(ApplicationService.class, appSvc, null);
-
-        Activator activator = new Activator();
-
-        activator.start(context);
-
-        assertTrue(context.isServiceRegistered(VmInformationService.class.getName(), VmGcService.class));
-
-        activator.stop(context);
-
-        assertEquals(0, context.getServiceListeners().size());
-        assertEquals(4, context.getAllServices().size());
-    }
-
-    @Test
     public void verifyStartRegistersViewProvider() throws Exception {
         StubBundleContext ctx = new StubBundleContext();
         Activator activator = new Activator();
--- a/vm-overview/client-core/pom.xml	Fri Nov 30 10:47:45 2012 -0500
+++ b/vm-overview/client-core/pom.xml	Fri Nov 30 17:30:25 2012 -0500
@@ -17,13 +17,16 @@
         <extensions>true</extensions>
         <configuration>
           <instructions>
-            <Private-Package></Private-Package>
             <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
             <Bundle-SymbolicName>com.redhat.thermostat.vm.overview.client.core</Bundle-SymbolicName>
+            <Bundle-Activator>com.redhat.thermostat.vm.overview.client.core.internal.Activator</Bundle-Activator>
             <Export-Package>
               com.redhat.thermostat.vm.overview.client.core,
               com.redhat.thermostat.vm.overview.client.locale
             </Export-Package>
+            <Private-Package>
+              com.redhat.thermostat.vm.overview.client.core.internal
+            </Private-Package>
             <!-- Do not autogenerate uses clauses in Manifests -->
             <_nouses>true</_nouses>
           </instructions>
--- a/vm-overview/client-core/src/main/java/com/redhat/thermostat/vm/overview/client/core/VmOverviewController.java	Fri Nov 30 10:47:45 2012 -0500
+++ /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.vm.overview.client.core;
-
-import java.text.DateFormat;
-import java.util.Date;
-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.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.NotImplementedException;
-import com.redhat.thermostat.common.Timer;
-import com.redhat.thermostat.common.Timer.SchedulingType;
-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.storage.model.VmInfo;
-import com.redhat.thermostat.vm.overview.client.locale.LocaleResources;
-
-public class VmOverviewController implements VmInformationServiceController {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-
-    private final VmRef ref;
-    private final VmInfoDAO dao;
-    private final DateFormat vmRunningTimeFormat;
-
-    private final Timer timer;
-
-    private final VmOverviewView view;
-
-    public VmOverviewController(ApplicationService appSvc, VmInfoDAO vmDao, VmRef vmRef, VmOverviewViewProvider provider) {
-        this.ref = vmRef;
-        this.view = provider.createView();
-
-        dao = vmDao;
-        timer = appSvc.getTimerFactory().createTimer();
-
-        vmRunningTimeFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.FULL);
-
-        view.addActionListener(new ActionListener<Action>() {
-            @Override
-            public void actionPerformed(ActionEvent<Action> actionEvent) {
-                switch(actionEvent.getActionId()) {
-                    case HIDDEN:
-                        stop();
-                        break;
-                    case VISIBLE:
-                        start();
-                        break;
-                    default:
-                        throw new NotImplementedException("unknown event: " + actionEvent.getActionId());
-                }
-            }
-        });
-
-        timer.setAction(new Runnable() {
-
-            @Override
-            public void run() {
-                VmInfo info = dao.getVmInfo(ref);
-                view.setVmPid(((Integer) info.getVmPid()).toString());
-                long actualStartTime = info.getStartTimeStamp();
-                view.setVmStartTimeStamp(vmRunningTimeFormat.format(new Date(actualStartTime)));
-                long actualStopTime = info.getStopTimeStamp();
-                if (actualStopTime >= actualStartTime) {
-                    // Only show a stop time if we have actually stopped.
-                    view.setVmStopTimeStamp(vmRunningTimeFormat.format(new Date(actualStopTime)));
-                } else {
-                    view.setVmStopTimeStamp(translator.localize(LocaleResources.VM_INFO_RUNNING));
-                }
-                view.setJavaVersion(info.getJavaVersion());
-                view.setJavaHome(info.getJavaHome());
-                view.setMainClass(info.getMainClass());
-                view.setJavaCommandLine(info.getJavaCommandLine());
-                String actualVmName = info.getVmName();
-                String actualVmVersion = info.getVmVersion();
-                String actualVmInfo = info.getVmInfo();
-                view.setVmNameAndVersion(translator.localize(LocaleResources.VM_INFO_VM_NAME_AND_VERSION,
-                        actualVmName, actualVmVersion, actualVmInfo));
-                view.setVmArguments(info.getVmArguments());
-            }
-        });
-        timer.setInitialDelay(0);
-        timer.setDelay(5);
-        timer.setTimeUnit(TimeUnit.SECONDS);
-        timer.setSchedulingType(SchedulingType.FIXED_RATE);
-    }
-
-    private void start() {
-        timer.start();
-    }
-
-    private void stop() {
-        timer.stop();
-    }
-
-    public UIComponent getView() {
-        return (UIComponent) view;
-    }
-
-    @Override
-    public String getLocalizedName() {
-        return translator.localize(LocaleResources.VM_INFO_TAB_OVERVIEW);
-    }
-    
-    /*
-     * For testing purposes only.
-     */
-    DateFormat getDateFormat() {
-        return vmRunningTimeFormat;
-    }
-}
--- a/vm-overview/client-core/src/main/java/com/redhat/thermostat/vm/overview/client/core/VmOverviewService.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/vm-overview/client-core/src/main/java/com/redhat/thermostat/vm/overview/client/core/VmOverviewService.java	Fri Nov 30 17:30:25 2012 -0500
@@ -44,6 +44,7 @@
 import com.redhat.thermostat.common.dao.VmInfoDAO;
 import com.redhat.thermostat.common.dao.VmRef;
 import com.redhat.thermostat.common.utils.OSGIUtils;
+import com.redhat.thermostat.vm.overview.client.core.internal.VmOverviewController;
 
 public class VmOverviewService implements VmInformationService {
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-overview/client-core/src/main/java/com/redhat/thermostat/vm/overview/client/core/internal/Activator.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,91 @@
+/*
+ * 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.vm.overview.client.core.internal;
+
+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.common.ApplicationService;
+import com.redhat.thermostat.common.MultipleServiceTracker;
+import com.redhat.thermostat.common.MultipleServiceTracker.Action;
+import com.redhat.thermostat.common.dao.VmInfoDAO;
+import com.redhat.thermostat.vm.overview.client.core.VmOverviewService;
+
+public class Activator implements BundleActivator {
+    
+    private MultipleServiceTracker tracker;
+    private ServiceRegistration reg;
+
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        Class<?>[] deps = new Class<?>[] {
+        	VmInfoDAO.class,
+        	ApplicationService.class
+        };
+        
+		tracker = new MultipleServiceTracker(context, deps , new Action() {
+            
+			@Override
+			public void dependenciesAvailable(Map<String, Object> services) {
+				VmInfoDAO vmInfoDAO = (VmInfoDAO) services.get(VmInfoDAO.class.getName());
+				Objects.requireNonNull(vmInfoDAO);
+				ApplicationService appSvc = (ApplicationService) services.get(ApplicationService.class.getName());
+				Objects.requireNonNull(appSvc);
+				VmOverviewService service = new VmOverviewService(appSvc, vmInfoDAO);
+				reg = context.registerService(VmInformationService.class.getName(), service, null);
+			}
+
+			@Override
+			public void dependenciesUnavailable() {
+				reg.unregister();
+			}
+        });
+        tracker.open();
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        tracker.close();
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-overview/client-core/src/main/java/com/redhat/thermostat/vm/overview/client/core/internal/VmOverviewController.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,153 @@
+/*
+ * 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.vm.overview.client.core.internal;
+
+import java.text.DateFormat;
+import java.util.Date;
+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.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.NotImplementedException;
+import com.redhat.thermostat.common.Timer;
+import com.redhat.thermostat.common.Timer.SchedulingType;
+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.storage.model.VmInfo;
+import com.redhat.thermostat.vm.overview.client.core.VmOverviewView;
+import com.redhat.thermostat.vm.overview.client.core.VmOverviewViewProvider;
+import com.redhat.thermostat.vm.overview.client.locale.LocaleResources;
+
+public class VmOverviewController implements VmInformationServiceController {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    private final VmRef ref;
+    private final VmInfoDAO dao;
+    private final DateFormat vmRunningTimeFormat;
+
+    private final Timer timer;
+
+    private final VmOverviewView view;
+
+    public VmOverviewController(ApplicationService appSvc, VmInfoDAO vmDao, VmRef vmRef, VmOverviewViewProvider provider) {
+        this.ref = vmRef;
+        this.view = provider.createView();
+
+        dao = vmDao;
+        timer = appSvc.getTimerFactory().createTimer();
+
+        vmRunningTimeFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.FULL);
+
+        view.addActionListener(new ActionListener<Action>() {
+            @Override
+            public void actionPerformed(ActionEvent<Action> actionEvent) {
+                switch(actionEvent.getActionId()) {
+                    case HIDDEN:
+                        stop();
+                        break;
+                    case VISIBLE:
+                        start();
+                        break;
+                    default:
+                        throw new NotImplementedException("unknown event: " + actionEvent.getActionId());
+                }
+            }
+        });
+
+        timer.setAction(new Runnable() {
+
+            @Override
+            public void run() {
+                VmInfo info = dao.getVmInfo(ref);
+                view.setVmPid(((Integer) info.getVmPid()).toString());
+                long actualStartTime = info.getStartTimeStamp();
+                view.setVmStartTimeStamp(vmRunningTimeFormat.format(new Date(actualStartTime)));
+                long actualStopTime = info.getStopTimeStamp();
+                if (actualStopTime >= actualStartTime) {
+                    // Only show a stop time if we have actually stopped.
+                    view.setVmStopTimeStamp(vmRunningTimeFormat.format(new Date(actualStopTime)));
+                } else {
+                    view.setVmStopTimeStamp(translator.localize(LocaleResources.VM_INFO_RUNNING));
+                }
+                view.setJavaVersion(info.getJavaVersion());
+                view.setJavaHome(info.getJavaHome());
+                view.setMainClass(info.getMainClass());
+                view.setJavaCommandLine(info.getJavaCommandLine());
+                String actualVmName = info.getVmName();
+                String actualVmVersion = info.getVmVersion();
+                String actualVmInfo = info.getVmInfo();
+                view.setVmNameAndVersion(translator.localize(LocaleResources.VM_INFO_VM_NAME_AND_VERSION,
+                        actualVmName, actualVmVersion, actualVmInfo));
+                view.setVmArguments(info.getVmArguments());
+            }
+        });
+        timer.setInitialDelay(0);
+        timer.setDelay(5);
+        timer.setTimeUnit(TimeUnit.SECONDS);
+        timer.setSchedulingType(SchedulingType.FIXED_RATE);
+    }
+
+    private void start() {
+        timer.start();
+    }
+
+    private void stop() {
+        timer.stop();
+    }
+
+    public UIComponent getView() {
+        return (UIComponent) view;
+    }
+
+    @Override
+    public String getLocalizedName() {
+        return translator.localize(LocaleResources.VM_INFO_TAB_OVERVIEW);
+    }
+    
+    /*
+     * For testing purposes only.
+     */
+    DateFormat getDateFormat() {
+        return vmRunningTimeFormat;
+    }
+}
--- a/vm-overview/client-core/src/test/java/com/redhat/thermostat/vm/overview/client/core/VmOverviewControllerTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ /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.vm.overview.client.core;
-
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isNotNull;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.text.DateFormat;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import com.redhat.thermostat.client.core.views.BasicView.Action;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.Timer;
-import com.redhat.thermostat.common.Timer.SchedulingType;
-import com.redhat.thermostat.common.TimerFactory;
-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.storage.model.VmInfo;
-import com.redhat.thermostat.vm.overview.client.locale.LocaleResources;
-
-public class VmOverviewControllerTest {
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-    
-    private static final int VM_PID = 1337;
-    private static final long START_TIME = 10000;
-    private static final long STOP_TIME = 20000;
-    private static final String JAVA_VERSION = "1.2000.1";
-    private static final String JAVA_HOME = "/path/to/java";
-    private static final String MAIN_CLASS = "Main";
-    private static final String COMMAND_LINE = "java Main command line args";
-    private static final String VM_NAME = "MyCoolJVM";
-    private static final String VM_INFO = "Info about MyCoolJVM";
-    private static final String VM_VERSION = "1.0";
-    private static final String VM_ARGS = "-Dvar=arg -DotherVar=otherArg";
-    private static final Map<String, String> PROPS = Collections.emptyMap();
-    private static final Map<String, String> ENV = Collections.emptyMap();
-    private static final String[] LIBS = new String[0];
-
-    private Timer timer;
-    private Runnable timerAction;
-    private VmOverviewView view;
-    private ActionListener<VmOverviewView.Action> listener;
-    private VmOverviewController controller;
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    @Before
-    public void setUp() {
-        // Setup timer
-        timer = mock(Timer.class);
-        ArgumentCaptor<Runnable> timerActionCaptor = ArgumentCaptor
-                .forClass(Runnable.class);
-        doNothing().when(timer).setAction(timerActionCaptor.capture());
-
-        TimerFactory timerFactory = mock(TimerFactory.class);
-        when(timerFactory.createTimer()).thenReturn(timer);
-        ApplicationService appSvc = mock(ApplicationService.class);
-        when(appSvc.getTimerFactory()).thenReturn(timerFactory);
-
-        // Setup DAOs
-        VmInfo vmInfo = new VmInfo(VM_PID, START_TIME, STOP_TIME, JAVA_VERSION,
-                JAVA_HOME, MAIN_CLASS, COMMAND_LINE, VM_NAME, VM_INFO,
-                VM_VERSION, VM_ARGS, PROPS, ENV, LIBS);
-
-        VmRef ref = mock(VmRef.class);
-
-        VmInfoDAO vmInfoDao = mock(VmInfoDAO.class);
-        when(vmInfoDao.getVmInfo(any(VmRef.class))).thenReturn(vmInfo);
-
-        // Setup View
-        ArgumentCaptor<ActionListener> listenerCaptor = ArgumentCaptor
-                .forClass(ActionListener.class);
-        view = mock(VmOverviewView.class);
-        doNothing().when(view).addActionListener(listenerCaptor.capture());
-        VmOverviewViewProvider viewProvider = mock(VmOverviewViewProvider.class);
-        when(viewProvider.createView()).thenReturn(view);
-
-        controller = new VmOverviewController(appSvc, vmInfoDao, ref, viewProvider);
-
-        listener = listenerCaptor.getValue();
-        timerAction = timerActionCaptor.getValue();
-    }
-
-    @Test
-    public void verifyViewIsUpdatedWithData() {
-        timerAction.run();
-
-        DateFormat timestampFormat = controller.getDateFormat();
-        verify(view).setVmPid(eq(String.valueOf(VM_PID)));
-        verify(view).setVmStartTimeStamp(eq(timestampFormat.format(new Date(START_TIME))));
-        verify(view).setVmStopTimeStamp(eq(timestampFormat.format(new Date(STOP_TIME))));
-        verify(view).setJavaVersion(eq(JAVA_VERSION));
-        verify(view).setJavaHome(eq(JAVA_HOME));
-        verify(view).setMainClass(eq(MAIN_CLASS));
-        verify(view).setJavaCommandLine(eq(COMMAND_LINE));
-        
-        verify(view).setVmNameAndVersion(eq(translator.localize(LocaleResources.VM_INFO_VM_NAME_AND_VERSION,
-                        VM_NAME, VM_VERSION, VM_INFO)));
-        verify(view).setVmArguments(eq(VM_ARGS));
-    }
-
-    @Test
-    public void verifyTimerIsSetUpCorrectly() {
-        assertNotNull(timer);
-
-        verify(timer).setAction(isNotNull(Runnable.class));
-        verify(timer).setDelay(5);
-        verify(timer).setTimeUnit(TimeUnit.SECONDS);
-        verify(timer).setInitialDelay(0);
-        verify(timer).setSchedulingType(SchedulingType.FIXED_RATE);
-    }
-
-    @Test
-    public void verifyTimerRunsWhenNeeded() {
-        listener.actionPerformed(new ActionEvent<>(view, Action.VISIBLE));
-
-        verify(timer).start();
-
-        listener.actionPerformed(new ActionEvent<>(view, Action.HIDDEN));
-
-        verify(timer).stop();
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-overview/client-core/src/test/java/com/redhat/thermostat/vm/overview/client/core/internal/ActivatorTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -0,0 +1,91 @@
+/*
+ * 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.vm.overview.client.core.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.client.core.VmInformationService;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.dao.VmInfoDAO;
+import com.redhat.thermostat.test.StubBundleContext;
+import com.redhat.thermostat.vm.overview.client.core.VmOverviewService;
+
+public class ActivatorTest {
+    
+    @Test
+    public void verifyActivatorDoesNotRegisterServiceOnMissingDeps() throws Exception {
+        StubBundleContext context = new StubBundleContext();
+
+        Activator activator = new Activator();
+
+        activator.start(context);
+
+        assertEquals(0, context.getAllServices().size());
+        assertNotSame(1, context.getServiceListeners().size());
+        
+        activator.stop(context);
+
+        assertEquals(0, context.getServiceListeners().size());
+    }
+
+    @Test
+    public void verifyActivatorRegistersServices() throws Exception {
+        StubBundleContext context = new StubBundleContext();
+        VmInfoDAO vmInfoDAO = mock(VmInfoDAO.class);
+        ApplicationService appSvc = mock(ApplicationService.class);
+
+        context.registerService(VmInfoDAO.class, vmInfoDAO, null);
+        context.registerService(ApplicationService.class, appSvc, null);
+
+        Activator activator = new Activator();
+
+        activator.start(context);
+
+        assertTrue(context.isServiceRegistered(VmInformationService.class.getName(), VmOverviewService.class));
+
+        activator.stop(context);
+
+        assertEquals(0, context.getServiceListeners().size());
+        assertEquals(2, context.getAllServices().size());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-overview/client-core/src/test/java/com/redhat/thermostat/vm/overview/client/core/internal/VmOverviewControllerTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -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.vm.overview.client.core.internal;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNotNull;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.text.DateFormat;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.client.core.views.BasicView.Action;
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.ApplicationService;
+import com.redhat.thermostat.common.Timer;
+import com.redhat.thermostat.common.Timer.SchedulingType;
+import com.redhat.thermostat.common.TimerFactory;
+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.storage.model.VmInfo;
+import com.redhat.thermostat.vm.overview.client.core.VmOverviewView;
+import com.redhat.thermostat.vm.overview.client.core.VmOverviewViewProvider;
+import com.redhat.thermostat.vm.overview.client.core.internal.VmOverviewController;
+import com.redhat.thermostat.vm.overview.client.locale.LocaleResources;
+
+public class VmOverviewControllerTest {
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+    
+    private static final int VM_PID = 1337;
+    private static final long START_TIME = 10000;
+    private static final long STOP_TIME = 20000;
+    private static final String JAVA_VERSION = "1.2000.1";
+    private static final String JAVA_HOME = "/path/to/java";
+    private static final String MAIN_CLASS = "Main";
+    private static final String COMMAND_LINE = "java Main command line args";
+    private static final String VM_NAME = "MyCoolJVM";
+    private static final String VM_INFO = "Info about MyCoolJVM";
+    private static final String VM_VERSION = "1.0";
+    private static final String VM_ARGS = "-Dvar=arg -DotherVar=otherArg";
+    private static final Map<String, String> PROPS = Collections.emptyMap();
+    private static final Map<String, String> ENV = Collections.emptyMap();
+    private static final String[] LIBS = new String[0];
+
+    private Timer timer;
+    private Runnable timerAction;
+    private VmOverviewView view;
+    private ActionListener<VmOverviewView.Action> listener;
+    private VmOverviewController controller;
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Before
+    public void setUp() {
+        // Setup timer
+        timer = mock(Timer.class);
+        ArgumentCaptor<Runnable> timerActionCaptor = ArgumentCaptor
+                .forClass(Runnable.class);
+        doNothing().when(timer).setAction(timerActionCaptor.capture());
+
+        TimerFactory timerFactory = mock(TimerFactory.class);
+        when(timerFactory.createTimer()).thenReturn(timer);
+        ApplicationService appSvc = mock(ApplicationService.class);
+        when(appSvc.getTimerFactory()).thenReturn(timerFactory);
+
+        // Setup DAOs
+        VmInfo vmInfo = new VmInfo(VM_PID, START_TIME, STOP_TIME, JAVA_VERSION,
+                JAVA_HOME, MAIN_CLASS, COMMAND_LINE, VM_NAME, VM_INFO,
+                VM_VERSION, VM_ARGS, PROPS, ENV, LIBS);
+
+        VmRef ref = mock(VmRef.class);
+
+        VmInfoDAO vmInfoDao = mock(VmInfoDAO.class);
+        when(vmInfoDao.getVmInfo(any(VmRef.class))).thenReturn(vmInfo);
+
+        // Setup View
+        ArgumentCaptor<ActionListener> listenerCaptor = ArgumentCaptor
+                .forClass(ActionListener.class);
+        view = mock(VmOverviewView.class);
+        doNothing().when(view).addActionListener(listenerCaptor.capture());
+        VmOverviewViewProvider viewProvider = mock(VmOverviewViewProvider.class);
+        when(viewProvider.createView()).thenReturn(view);
+
+        controller = new VmOverviewController(appSvc, vmInfoDao, ref, viewProvider);
+
+        listener = listenerCaptor.getValue();
+        timerAction = timerActionCaptor.getValue();
+    }
+
+    @Test
+    public void verifyViewIsUpdatedWithData() {
+        timerAction.run();
+
+        DateFormat timestampFormat = controller.getDateFormat();
+        verify(view).setVmPid(eq(String.valueOf(VM_PID)));
+        verify(view).setVmStartTimeStamp(eq(timestampFormat.format(new Date(START_TIME))));
+        verify(view).setVmStopTimeStamp(eq(timestampFormat.format(new Date(STOP_TIME))));
+        verify(view).setJavaVersion(eq(JAVA_VERSION));
+        verify(view).setJavaHome(eq(JAVA_HOME));
+        verify(view).setMainClass(eq(MAIN_CLASS));
+        verify(view).setJavaCommandLine(eq(COMMAND_LINE));
+        
+        verify(view).setVmNameAndVersion(eq(translator.localize(LocaleResources.VM_INFO_VM_NAME_AND_VERSION,
+                        VM_NAME, VM_VERSION, VM_INFO)));
+        verify(view).setVmArguments(eq(VM_ARGS));
+    }
+
+    @Test
+    public void verifyTimerIsSetUpCorrectly() {
+        assertNotNull(timer);
+
+        verify(timer).setAction(isNotNull(Runnable.class));
+        verify(timer).setDelay(5);
+        verify(timer).setTimeUnit(TimeUnit.SECONDS);
+        verify(timer).setInitialDelay(0);
+        verify(timer).setSchedulingType(SchedulingType.FIXED_RATE);
+    }
+
+    @Test
+    public void verifyTimerRunsWhenNeeded() {
+        listener.actionPerformed(new ActionEvent<>(view, Action.VISIBLE));
+
+        verify(timer).start();
+
+        listener.actionPerformed(new ActionEvent<>(view, Action.HIDDEN));
+
+        verify(timer).stop();
+    }
+
+}
--- a/vm-overview/client-swing/src/main/java/com/redhat/thermostat/vm/overview/client/swing/Activator.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/vm-overview/client-swing/src/main/java/com/redhat/thermostat/vm/overview/client/swing/Activator.java	Fri Nov 30 17:30:25 2012 -0500
@@ -36,59 +36,22 @@
 
 package com.redhat.thermostat.vm.overview.client.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.common.ApplicationService;
-import com.redhat.thermostat.common.MultipleServiceTracker;
-import com.redhat.thermostat.common.MultipleServiceTracker.Action;
-import com.redhat.thermostat.common.dao.VmInfoDAO;
-import com.redhat.thermostat.vm.overview.client.core.VmOverviewService;
 import com.redhat.thermostat.vm.overview.client.core.VmOverviewViewProvider;
 
 public class Activator implements BundleActivator {
     
-    private MultipleServiceTracker tracker;
-    private ServiceRegistration reg;
-
     @Override
     public void start(final BundleContext context) throws Exception {
         VmOverviewViewProvider viewProvider = new SwingVmOverviewViewProvider();
+        // Unregistered on Activator.stop
         context.registerService(VmOverviewViewProvider.class.getName(), viewProvider, null);
-
-        Class<?>[] deps = new Class<?>[] {
-                VmInfoDAO.class,
-                ApplicationService.class
-        };
-        tracker = new MultipleServiceTracker(context, deps, new Action() {
-
-            @Override
-            public void dependenciesAvailable(Map<String, Object> services) {
-                VmInfoDAO vmInfoDAO = (VmInfoDAO) services.get(VmInfoDAO.class.getName());
-                Objects.requireNonNull(vmInfoDAO);
-                ApplicationService appSvc = (ApplicationService) services.get(ApplicationService.class.getName());
-                Objects.requireNonNull(appSvc);
-                VmOverviewService service = new VmOverviewService(appSvc, vmInfoDAO);
-                reg = context.registerService(VmInformationService.class.getName(), service, null);
-            }
-
-            @Override
-            public void dependenciesUnavailable() {
-                reg.unregister();
-            }
-
-        });
-        tracker.open();
     }
 
     @Override
     public void stop(BundleContext context) throws Exception {
-        tracker.close();
     }
 
 }
--- a/vm-overview/client-swing/src/test/java/com/redhat/thermostat/vm/overview/client/swing/ActivatorTest.java	Fri Nov 30 10:47:45 2012 -0500
+++ b/vm-overview/client-swing/src/test/java/com/redhat/thermostat/vm/overview/client/swing/ActivatorTest.java	Fri Nov 30 17:30:25 2012 -0500
@@ -38,61 +38,15 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
 
 import org.junit.Test;
 
-import com.redhat.thermostat.client.core.VmInformationService;
-import com.redhat.thermostat.common.ApplicationService;
-import com.redhat.thermostat.common.dao.VmInfoDAO;
 import com.redhat.thermostat.test.StubBundleContext;
-import com.redhat.thermostat.vm.overview.client.core.VmOverviewService;
 import com.redhat.thermostat.vm.overview.client.core.VmOverviewViewProvider;
-import com.redhat.thermostat.vm.overview.client.swing.Activator;
-import com.redhat.thermostat.vm.overview.client.swing.SwingVmOverviewViewProvider;
 
 public class ActivatorTest {
     
     @Test
-    public void verifyActivatorDoesNotRegisterServiceOnMissingDeps() throws Exception {
-        StubBundleContext context = new StubBundleContext();
-
-        Activator activator = new Activator();
-
-        activator.start(context);
-
-        // View provider registers unconditionally
-        assertEquals(1, context.getAllServices().size());
-        assertEquals(2, context.getServiceListeners().size());
-        
-        activator.stop(context);
-
-        assertEquals(0, context.getServiceListeners().size());
-    }
-
-    @Test
-    public void verifyActivatorRegistersServices() throws Exception {
-        StubBundleContext context = new StubBundleContext();
-        VmInfoDAO vmInfoDAO = mock(VmInfoDAO.class);
-        ApplicationService appSvc = mock(ApplicationService.class);
-
-        context.registerService(VmInfoDAO.class, vmInfoDAO, null);
-        context.registerService(ApplicationService.class, appSvc, null);
-
-        Activator activator = new Activator();
-
-        activator.start(context);
-
-        assertTrue(context.isServiceRegistered(VmOverviewViewProvider.class.getName(), SwingVmOverviewViewProvider.class));
-        assertTrue(context.isServiceRegistered(VmInformationService.class.getName(), VmOverviewService.class));
-
-        activator.stop(context);
-
-        assertEquals(0, context.getServiceListeners().size());
-        assertEquals(3, context.getAllServices().size());
-    }
-
-    @Test
     public void verifyStartRegistersViewProvider() throws Exception {
         StubBundleContext ctx = new StubBundleContext();
         Activator activator = new Activator();