changeset 802:eeec7fc7c0ff

Move VM Overview to its own bundle This commit moves the VM Overview controller/views to its own bundles (client-core and client-swing) under vm-overview in the top-level of the Thermostat source tree. The client-swing bundle dynamically registers the controller via a VmInformationService. This commit also moves the SimpleTable and ChangeableText Swing components to this bundle, as these classes are not publicly accessible and only used by this view. This commit also adds a test for VmOverviewController as there was no test class before. Reviewed-by: jerboaa Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-November/004284.html
author Elliott Baron <ebaron@redhat.com>
date Tue, 27 Nov 2012 14:50:16 -0500
parents 18a8839b9638
children 01d39c35e3fc
files client/core/src/main/java/com/redhat/thermostat/client/core/VmInformationService.java client/core/src/main/java/com/redhat/thermostat/client/core/views/VmOverviewView.java client/core/src/main/java/com/redhat/thermostat/client/core/views/VmOverviewViewProvider.java client/core/src/main/java/com/redhat/thermostat/client/locale/LocaleResources.java client/core/src/main/java/com/redhat/thermostat/client/ui/VmInformationController.java client/core/src/main/java/com/redhat/thermostat/client/ui/VmOverviewController.java client/core/src/main/resources/com/redhat/thermostat/client/locale/strings.properties client/swing/src/main/java/com/redhat/thermostat/client/swing/components/SimpleTable.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/ChangeableText.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/UiFacadeFactoryImpl.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/osgi/ThermostatActivator.java client/swing/src/main/java/com/redhat/thermostat/client/swing/views/SwingVmOverviewViewProvider.java client/swing/src/main/java/com/redhat/thermostat/client/swing/views/VmOverviewPanel.java client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/osgi/ThermostatActivatorTest.java distribution/config/commands/gui.properties distribution/pom.xml pom.xml 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/VmOverviewView.java vm-overview/client-core/src/main/java/com/redhat/thermostat/vm/overview/client/core/VmOverviewViewProvider.java vm-overview/client-core/src/main/java/com/redhat/thermostat/vm/overview/client/locale/LocaleResources.java vm-overview/client-core/src/main/resources/com/redhat/thermostat/vm/overview/client/locale/strings.properties vm-overview/client-core/src/test/java/com/redhat/thermostat/vm/overview/client/core/VmOverviewControllerTest.java vm-overview/client-swing/pom.xml vm-overview/client-swing/src/main/java/com/redhat/thermostat/vm/overview/client/swing/Activator.java vm-overview/client-swing/src/main/java/com/redhat/thermostat/vm/overview/client/swing/ChangeableText.java vm-overview/client-swing/src/main/java/com/redhat/thermostat/vm/overview/client/swing/SimpleTable.java vm-overview/client-swing/src/main/java/com/redhat/thermostat/vm/overview/client/swing/SwingVmOverviewViewProvider.java vm-overview/client-swing/src/main/java/com/redhat/thermostat/vm/overview/client/swing/VmOverviewPanel.java vm-overview/client-swing/src/test/java/com/redhat/thermostat/vm/overview/client/swing/ActivatorTest.java vm-overview/pom.xml
diffstat 33 files changed, 1620 insertions(+), 911 deletions(-) [+]
line wrap: on
line diff
--- a/client/core/src/main/java/com/redhat/thermostat/client/core/VmInformationService.java	Tue Nov 27 14:49:03 2012 -0500
+++ b/client/core/src/main/java/com/redhat/thermostat/client/core/VmInformationService.java	Tue Nov 27 14:50:16 2012 -0500
@@ -42,7 +42,7 @@
 public interface VmInformationService extends InformationService {
 
     @Override
-    VmFilter getFilter();
+    public VmFilter getFilter();
 
-    VmInformationServiceController getInformationServiceController(VmRef ref);
+    public VmInformationServiceController getInformationServiceController(VmRef ref);
 }
--- a/client/core/src/main/java/com/redhat/thermostat/client/core/views/VmOverviewView.java	Tue Nov 27 14:49:03 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.client.core.views;
-
-
-public abstract class VmOverviewView extends BasicView implements UIComponent {
-
-    public abstract void setVmPid(String pid);
-
-    public abstract void setVmStartTimeStamp(String timestamp);
-
-    public abstract void setVmStopTimeStamp(String timeStamp);
-
-    public abstract void setMainClass(String mainClass);
-
-    public abstract void setJavaCommandLine(String javaCommandLine);
-
-    public abstract void setJavaHome(String string);
-
-    public abstract void setJavaVersion(String javaVersion);
-
-    public abstract void setVmNameAndVersion(String vmNameAndVersion);
-
-    public abstract void setVmArguments(String vmArguments);
-
-}
--- a/client/core/src/main/java/com/redhat/thermostat/client/core/views/VmOverviewViewProvider.java	Tue Nov 27 14:49:03 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.client.core.views;
-
-public interface VmOverviewViewProvider extends ViewProvider {
-
-    @Override
-    public VmOverviewView createView();
-    
-}
--- a/client/core/src/main/java/com/redhat/thermostat/client/locale/LocaleResources.java	Tue Nov 27 14:49:03 2012 -0500
+++ b/client/core/src/main/java/com/redhat/thermostat/client/locale/LocaleResources.java	Tue Nov 27 14:50:16 2012 -0500
@@ -110,28 +110,9 @@
 
     HOST_INFO_TAB_IO,
 
-    VM_INFO_TAB_OVERVIEW,
     VM_INFO_TAB_CPU,
     VM_INFO_TAB_GC,
 
-    VM_INFO_TITLE,
-    VM_INFO_SECTION_PROCESS,
-    VM_INFO_SECTION_JAVA,
-
-    VM_INFO_PROCESS_ID,
-    VM_INFO_START_TIME,
-    VM_INFO_STOP_TIME,
-    VM_INFO_RUNNING,
-    VM_INFO_MAIN_CLASS,
-    VM_INFO_COMMAND_LINE,
-    VM_INFO_JAVA_VERSION,
-    VM_INFO_VM,
-    VM_INFO_VM_ARGUMENTS,
-    VM_INFO_VM_NAME_AND_VERSION,
-    VM_INFO_PROPERTIES,
-    VM_INFO_ENVIRONMENT,
-    VM_INFO_LIBRARIES,
-
     VM_CPU_TITLE,
     VM_CPU_CHART_LOAD_LABEL,
     VM_CPU_CHART_TIME_LABEL,
--- a/client/core/src/main/java/com/redhat/thermostat/client/ui/VmInformationController.java	Tue Nov 27 14:49:03 2012 -0500
+++ b/client/core/src/main/java/com/redhat/thermostat/client/ui/VmInformationController.java	Tue Nov 27 14:50:16 2012 -0500
@@ -45,11 +45,9 @@
 import com.redhat.thermostat.client.core.views.VmGcViewProvider;
 import com.redhat.thermostat.client.core.views.VmInformationView;
 import com.redhat.thermostat.client.core.views.VmInformationViewProvider;
-import com.redhat.thermostat.client.core.views.VmOverviewViewProvider;
 import com.redhat.thermostat.client.locale.LocaleResources;
 import com.redhat.thermostat.common.dao.VmCpuStatDAO;
 import com.redhat.thermostat.common.dao.VmGcStatDAO;
-import com.redhat.thermostat.common.dao.VmInfoDAO;
 import com.redhat.thermostat.common.dao.VmMemoryStatDAO;
 import com.redhat.thermostat.common.dao.VmRef;
 import com.redhat.thermostat.common.locale.Translate;
@@ -61,24 +59,20 @@
 
     private final VmInformationView view;
 
-    private final VmOverviewController overviewController;
     private final VmCpuController cpuController;
     private final VmGcController gcController;
 
-    public VmInformationController(UiFacadeFactory uiFacadeFactory, VmInfoDAO vmInfoDao, VmCpuStatDAO vmCpuStatDao, VmMemoryStatDAO vmMemoryStatDao, VmGcStatDAO vmGcStatDao, VmRef vmRef, VmInformationViewProvider provider) {
-        this(OSGIUtils.getInstance(), uiFacadeFactory, vmInfoDao, vmCpuStatDao, vmMemoryStatDao,  vmGcStatDao, vmRef, provider);
+    public VmInformationController(UiFacadeFactory uiFacadeFactory, VmCpuStatDAO vmCpuStatDao, VmMemoryStatDAO vmMemoryStatDao, VmGcStatDAO vmGcStatDao, VmRef vmRef, VmInformationViewProvider provider) {
+        this(OSGIUtils.getInstance(), uiFacadeFactory, vmCpuStatDao, vmMemoryStatDao,  vmGcStatDao, vmRef, provider);
     }
     
-    VmInformationController(OSGIUtils serviceProvider, UiFacadeFactory uiFacadeFactory, VmInfoDAO vmInfoDao, VmCpuStatDAO vmCpuStatDao, VmMemoryStatDAO vmMemoryStatDao, VmGcStatDAO vmGcStatDao, VmRef vmRef, VmInformationViewProvider provider) {
-        VmOverviewViewProvider vmOverviewProvider = serviceProvider.getService(VmOverviewViewProvider.class);
-        overviewController = new VmOverviewController(vmInfoDao, vmRef, vmOverviewProvider);
+    VmInformationController(OSGIUtils serviceProvider, UiFacadeFactory uiFacadeFactory, VmCpuStatDAO vmCpuStatDao, VmMemoryStatDAO vmMemoryStatDao, VmGcStatDAO vmGcStatDao, VmRef vmRef, VmInformationViewProvider provider) {
         VmCpuViewProvider vmCpuProvider = serviceProvider.getService(VmCpuViewProvider.class);
         cpuController = new VmCpuController(vmCpuStatDao, vmRef, vmCpuProvider);
         VmGcViewProvider vmGCProvider = serviceProvider.getService(VmGcViewProvider.class);
         gcController = new VmGcController(vmMemoryStatDao, vmGcStatDao, vmRef, vmGCProvider);
 
         view = provider.createView();
-        view.addChildView(translator.localize(LocaleResources.VM_INFO_TAB_OVERVIEW), overviewController.getView());
         view.addChildView(translator.localize(LocaleResources.VM_INFO_TAB_CPU), cpuController.getView());
         view.addChildView(translator.localize(LocaleResources.VM_INFO_TAB_GC), gcController.getView());
 
--- a/client/core/src/main/java/com/redhat/thermostat/client/ui/VmOverviewController.java	Tue Nov 27 14:49:03 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.client.ui;
-
-import java.text.DateFormat;
-import java.util.Date;
-import java.util.concurrent.TimeUnit;
-
-import com.redhat.thermostat.client.core.views.BasicView;
-import com.redhat.thermostat.client.core.views.UIComponent;
-import com.redhat.thermostat.client.core.views.VmOverviewView;
-import com.redhat.thermostat.client.core.views.VmOverviewViewProvider;
-import com.redhat.thermostat.client.core.views.BasicView.Action;
-import com.redhat.thermostat.client.locale.LocaleResources;
-import com.redhat.thermostat.common.ActionEvent;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.NotImplementedException;
-import com.redhat.thermostat.common.Timer;
-import com.redhat.thermostat.common.Timer.SchedulingType;
-import com.redhat.thermostat.common.appctx.ApplicationContext;
-import com.redhat.thermostat.common.dao.VmInfoDAO;
-import com.redhat.thermostat.common.dao.VmRef;
-import com.redhat.thermostat.common.locale.Translate;
-import com.redhat.thermostat.storage.model.VmInfo;
-
-class VmOverviewController {
-
-    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(VmInfoDAO vmDao, VmRef vmRef, VmOverviewViewProvider provider) {
-        this.ref = vmRef;
-        this.view = provider.createView();
-
-        dao = vmDao;
-        timer = ApplicationContext.getInstance().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;
-    }
-}
--- a/client/core/src/main/resources/com/redhat/thermostat/client/locale/strings.properties	Tue Nov 27 14:49:03 2012 -0500
+++ b/client/core/src/main/resources/com/redhat/thermostat/client/locale/strings.properties	Tue Nov 27 14:50:16 2012 -0500
@@ -68,28 +68,9 @@
 
 HOST_INFO_TAB_IO = IO
 
-VM_INFO_TAB_OVERVIEW = Overview
 VM_INFO_TAB_CPU = CPU
 VM_INFO_TAB_GC = GC
 
-VM_INFO_TITLE = Virtual Machine Overview
-VM_INFO_SECTION_PROCESS = Process Information
-VM_INFO_SECTION_JAVA = Java Information
-
-VM_INFO_PROCESS_ID = Process Id
-VM_INFO_START_TIME = Start time
-VM_INFO_STOP_TIME = Stop time
-VM_INFO_RUNNING = Running
-VM_INFO_MAIN_CLASS = Main Class
-VM_INFO_COMMAND_LINE = Command Line
-VM_INFO_JAVA_VERSION = Java Version
-VM_INFO_VM = Virtual Machine
-VM_INFO_VM_ARGUMENTS = VM arguments
-VM_INFO_VM_NAME_AND_VERSION = {0} version {1} {2}
-VM_INFO_PROPERTIES = Properties
-VM_INFO_ENVIRONMENT = Environment
-VM_INFO_LIBRARIES = Native Libraries
-
 VM_CPU_TITLE = Cpu Usage by Virtual Machine
 VM_CPU_CHART_LOAD_LABEL = % CPU
 VM_CPU_CHART_TIME_LABEL = Time
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/SimpleTable.java	Tue Nov 27 14:49:03 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,290 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.client.swing.components;
-
-import java.awt.Component;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import javax.swing.Box;
-import javax.swing.JComponent;
-import javax.swing.JEditorPane;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JTextArea;
-import javax.swing.JTextField;
-import javax.swing.SwingUtilities;
-
-import com.redhat.thermostat.client.swing.internal.ChangeableText;
-import com.redhat.thermostat.client.ui.ComponentVisibleListener;
-
-public class SimpleTable implements ChangeableText.TextListener {
-
-    Map<ChangeableText, Set<JComponent>> updateMap = new HashMap<ChangeableText, Set<JComponent>>();
-
-    public static class Section {
-        private final String sectionName;
-        private final List<TableEntry> tableEntries = new ArrayList<TableEntry>();
-
-        public Section(String name) {
-            this.sectionName = name;
-        }
-
-        public String getText() {
-            return sectionName;
-        }
-
-        public void add(TableEntry entry) {
-            tableEntries.add(entry);
-        }
-
-        public void add(Key key, List<Value> values) {
-            tableEntries.add(new TableEntry(key, values));
-        }
-
-        public void add(Key key, Value value) {
-            tableEntries.add(new TableEntry(key, value));
-        }
-
-        public TableEntry[] getEntries() {
-            return tableEntries.toArray(new TableEntry[0]);
-        }
-    }
-
-    public static class TableEntry {
-        private final Key key;
-        private final List<Value> values;
-
-        public TableEntry(String key, ChangeableText value) {
-            this(new Key(key), new Value(value));
-        }
-
-        public TableEntry(Key key, Value value) {
-            this.key = key;
-            this.values = new ArrayList<Value>();
-            this.values.add(value);
-        }
-
-        public TableEntry(Key key, List<Value> values) {
-            this.key = key;
-            this.values = new ArrayList<Value>(values);
-        }
-
-        public Key getKey() {
-            return key;
-        }
-
-        public Value[] getValues() {
-            return values.toArray(new Value[0]);
-        }
-    }
-
-    public static class Key {
-        private final String text;
-
-        public Key(String text) {
-            this.text = text;
-        }
-
-        public String getText() {
-            return text;
-        }
-    }
-
-    public static class Value {
-        private final ChangeableText text;
-        private final Component actualComponent;
-
-        public Value(String text) {
-            this(new ChangeableText(text));
-        }
-
-        public Value(ChangeableText text) {
-            this.text = text;
-            this.actualComponent = null;
-        }
-
-        public Value(Component component) {
-            this.actualComponent = component;
-            this.text = null;
-        }
-
-        public Component getComponent() {
-            return actualComponent;
-        }
-
-        public ChangeableText getChangeableText() {
-            return text;
-        }
-    }
-
-    public JPanel createTable(List<Section> sections) {
-        final int SECTION_TOP_GAP = 10;
-        final int ROW_VERTICAL_GAP = 0;
-        final int ROW_HORIZONTAL_GAP = 10;
-
-        Insets sectionHeaderInsets = new Insets(SECTION_TOP_GAP, 0, 0, 0);
-        Insets rowInsets = new Insets(ROW_VERTICAL_GAP, ROW_HORIZONTAL_GAP, ROW_VERTICAL_GAP, ROW_HORIZONTAL_GAP);
-
-        JPanel container = new JPanel();
-        container.setLayout(new GridBagLayout());
-
-        GridBagConstraints keyConstraints = new GridBagConstraints();
-        GridBagConstraints valueConstraints = new GridBagConstraints();
-        GridBagConstraints sectionHeaderConstraints = new GridBagConstraints();
-
-        keyConstraints.insets = valueConstraints.insets = rowInsets;
-        keyConstraints.gridy = valueConstraints.gridy = 0;
-        keyConstraints.gridx = 0;
-        keyConstraints.anchor = GridBagConstraints.FIRST_LINE_END;
-        valueConstraints.gridx = 1;
-        keyConstraints.fill = valueConstraints.fill = GridBagConstraints.HORIZONTAL;
-
-        sectionHeaderConstraints.gridx = 0;
-        sectionHeaderConstraints.gridwidth = GridBagConstraints.REMAINDER;
-        sectionHeaderConstraints.fill = GridBagConstraints.HORIZONTAL;
-        sectionHeaderConstraints.insets = sectionHeaderInsets;
-
-        for (Section section : sections) {
-            sectionHeaderConstraints.gridy = keyConstraints.gridy = ++valueConstraints.gridy;
-            container.add(Components.header(section.getText()), sectionHeaderConstraints);
-            for (TableEntry tableEntry : section.getEntries()) {
-                keyConstraints.gridy = ++valueConstraints.gridy;
-                container.add(Components.label(tableEntry.getKey().getText()), keyConstraints);
-
-                for (Value value : tableEntry.getValues()) {
-                    if (value.getComponent() == null) {
-                        ChangeableText text = value.getChangeableText();
-                        JComponent valueLabel = new ValueField(text.getText());
-                        if (updateMap.containsKey(text)) {
-                            updateMap.get(text).add(valueLabel);
-                        } else {
-                            Set<JComponent> set = new HashSet<JComponent>();
-                            set.add(valueLabel);
-                            updateMap.put(text, set);
-                        }
-                        container.add(valueLabel, valueConstraints);
-                    } else {
-                        container.add(value.getComponent(), valueConstraints);
-                    }
-                    keyConstraints.gridy = ++valueConstraints.gridy;
-                }
-            }
-        }
-
-        GridBagConstraints glueConstraints = new GridBagConstraints();
-        glueConstraints.gridy = keyConstraints.gridy + 1;
-        glueConstraints.gridx = 0;
-        glueConstraints.weightx = 1;
-        glueConstraints.weighty = 1;
-        glueConstraints.fill = GridBagConstraints.BOTH;
-        glueConstraints.gridheight = GridBagConstraints.REMAINDER;
-        glueConstraints.gridwidth = GridBagConstraints.REMAINDER;
-        Component filler = Box.createGlue();
-        container.add(filler, glueConstraints);
-
-        container.addHierarchyListener(new ComponentVisibleListener() {
-            @Override
-            public void componentShown(Component c) {
-                updateAllValues();
-                addAllListeners();
-            }
-
-            @Override
-            public void componentHidden(Component c) {
-                removeAllListeners();
-            }
-        });
-
-        return container;
-    }
-
-
-    private void updateAllValues() {
-        for (Entry<ChangeableText, Set<JComponent>> entry: updateMap.entrySet()) {
-            for (JComponent label: entry.getValue()) {
-                setText(label, entry.getKey().getText());
-            }
-        }
-    }
-
-    private static void setText(JComponent target, String text) {
-        if (target instanceof JLabel) {
-            ((JLabel)target).setText(text);
-        } else if (target instanceof JTextField) {
-            ((JTextField)target).setText(text);
-        } else if (target instanceof JTextArea) {
-            ((JTextArea)target).setText(text);
-        } else if (target instanceof JEditorPane) {
-            ((JEditorPane)target).setText(text);
-        }
-    }
-
-    @Override
-    public void textChanged(final ChangeableText text) {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                String newValue = text.getText();
-                for (JComponent label: updateMap.get(text)) {
-                    setText(label, newValue);
-                }
-            }
-        });
-    }
-
-    public void addAllListeners() {
-        for (ChangeableText text : updateMap.keySet()) {
-            text.addListener(this);
-        }
-    }
-
-    public void removeAllListeners() {
-        for (ChangeableText text : updateMap.keySet()) {
-            text.removeListener(this);
-        }
-    }
-
-}
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/ChangeableText.java	Tue Nov 27 14:49:03 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.client.swing.internal;
-
-import java.util.HashSet;
-import java.util.Set;
-
-public class ChangeableText {
-
-    private final Set<TextListener> listeners = new HashSet<TextListener>();
-    private String text;
-
-    public static interface TextListener {
-        public void textChanged(ChangeableText text);
-    }
-
-    public ChangeableText(String text) {
-        this.text = text;
-    }
-
-    public synchronized void setText(String text) {
-        if (this.text.equals(text)) {
-            return;
-        }
-        this.text = text;
-        fireChanged();
-    }
-
-    public synchronized String getText() {
-        return text;
-    }
-
-    public synchronized void addListener(TextListener listener) {
-        this.listeners.add(listener);
-    }
-
-    public synchronized void removeListener(TextListener listener) {
-        this.listeners.remove(listener);
-    }
-
-    private void fireChanged() {
-        for (TextListener listener: listeners) {
-            listener.textChanged(this);
-        }
-    }
-
-}
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/UiFacadeFactoryImpl.java	Tue Nov 27 14:49:03 2012 -0500
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/UiFacadeFactoryImpl.java	Tue Nov 27 14:50:16 2012 -0500
@@ -136,7 +136,7 @@
     @Override
     public VmInformationController getVmController(VmRef ref) {
         VmInformationViewProvider viewProvider = serviceProvider.getService(VmInformationViewProvider.class);
-        return new VmInformationController(this, vmInfoDao, vmCpuStatDao, vmMemoryStatDao, vmGcStatDao, ref, viewProvider);
+        return new VmInformationController(this, vmCpuStatDao, vmMemoryStatDao, vmGcStatDao, ref, viewProvider);
     }
 
     @Override
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/osgi/ThermostatActivator.java	Tue Nov 27 14:49:03 2012 -0500
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/osgi/ThermostatActivator.java	Tue Nov 27 14:50:16 2012 -0500
@@ -50,7 +50,6 @@
 import com.redhat.thermostat.client.core.views.VmCpuViewProvider;
 import com.redhat.thermostat.client.core.views.VmGcViewProvider;
 import com.redhat.thermostat.client.core.views.VmInformationViewProvider;
-import com.redhat.thermostat.client.core.views.VmOverviewViewProvider;
 import com.redhat.thermostat.client.osgi.service.HostDecorator;
 import com.redhat.thermostat.client.swing.internal.GUIClientCommand;
 import com.redhat.thermostat.client.swing.internal.HostIconDecorator;
@@ -63,7 +62,6 @@
 import com.redhat.thermostat.client.swing.views.SwingVmCpuViewProvider;
 import com.redhat.thermostat.client.swing.views.SwingVmGcViewProvider;
 import com.redhat.thermostat.client.swing.views.SwingVmInformationViewProvider;
-import com.redhat.thermostat.client.swing.views.SwingVmOverviewViewProvider;
 import com.redhat.thermostat.client.ui.UiFacadeFactory;
 import com.redhat.thermostat.common.cli.CommandRegistry;
 import com.redhat.thermostat.common.cli.CommandRegistryImpl;
@@ -91,8 +89,6 @@
         // Vm views
         VmInformationViewProvider vmInfoProvider = new SwingVmInformationViewProvider();
         context.registerService(VmInformationViewProvider.class.getName(), vmInfoProvider, null);
-        VmOverviewViewProvider vmOverviewProvider = new SwingVmOverviewViewProvider();
-        context.registerService(VmOverviewViewProvider.class.getName(), vmOverviewProvider, null);
         VmGcViewProvider vmGcProvider = new SwingVmGcViewProvider();
         context.registerService(VmGcViewProvider.class.getName(), vmGcProvider, null);
         VmCpuViewProvider vmCpuProvider = new SwingVmCpuViewProvider();
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/views/SwingVmOverviewViewProvider.java	Tue Nov 27 14:49:03 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.client.swing.views;
-
-import com.redhat.thermostat.client.core.views.VmOverviewView;
-import com.redhat.thermostat.client.core.views.VmOverviewViewProvider;
-
-public class SwingVmOverviewViewProvider implements VmOverviewViewProvider {
-
-    @Override
-    public VmOverviewView createView() {
-        return new VmOverviewPanel();
-    }
-
-}
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/views/VmOverviewPanel.java	Tue Nov 27 14:49:03 2012 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.client.swing.views;
-
-import java.awt.Component;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.swing.JPanel;
-
-import com.redhat.thermostat.client.core.views.VmOverviewView;
-import com.redhat.thermostat.client.locale.LocaleResources;
-import com.redhat.thermostat.client.swing.SwingComponent;
-import com.redhat.thermostat.client.swing.components.Components;
-import com.redhat.thermostat.client.swing.components.HeaderPanel;
-import com.redhat.thermostat.client.swing.components.SimpleTable;
-import com.redhat.thermostat.client.swing.components.SimpleTable.Section;
-import com.redhat.thermostat.client.swing.components.SimpleTable.TableEntry;
-import com.redhat.thermostat.client.swing.internal.ChangeableText;
-import com.redhat.thermostat.client.ui.ComponentVisibleListener;
-import com.redhat.thermostat.common.ActionListener;
-import com.redhat.thermostat.common.locale.Translate;
-
-public class VmOverviewPanel extends VmOverviewView implements SwingComponent {
-
-    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
-    
-    private HeaderPanel visiblePanel;
-
-    private final ChangeableText pid = new ChangeableText("");
-    private final ChangeableText startTimeStamp = new ChangeableText("");
-    private final ChangeableText stopTimeStamp = new ChangeableText("");
-    private final ChangeableText mainClass = new ChangeableText("");
-    private final ChangeableText javaCommandLine = new ChangeableText("");
-    private final ChangeableText javaHome = new ChangeableText("");
-    private final ChangeableText javaVersion = new ChangeableText("");
-    private final ChangeableText vmNameAndVersion = new ChangeableText("");
-    private final ChangeableText vmArguments = new ChangeableText("");
-
-    public VmOverviewPanel() {
-        super();
-        initializePanel();
-        visiblePanel.addHierarchyListener(new ComponentVisibleListener() {
-            @Override
-            public void componentShown(Component component) {
-                notifier.fireAction(Action.VISIBLE);
-            }
-
-            @Override
-            public void componentHidden(Component component) {
-                notifier.fireAction(Action.HIDDEN);
-            }
-        });
-    }
-
-    @Override
-    public void addActionListener(ActionListener<Action> listener) {
-        notifier.addActionListener(listener);
-    }
-
-    @Override
-    public void removeActionListener(ActionListener<Action> listener) {
-        notifier.removeActionListener(listener);
-    }
-
-    @Override
-    public void setVmPid(String pid) {
-        this.pid.setText(pid);
-    }
-
-    @Override
-    public void setVmStartTimeStamp(String timeStamp) {
-        this.startTimeStamp.setText(timeStamp);
-    }
-
-    @Override
-    public void setVmStopTimeStamp(String timeStamp) {
-        this.stopTimeStamp.setText(timeStamp);
-    }
-
-    @Override
-    public void setMainClass(String mainClass) {
-        this.mainClass.setText(mainClass);
-    }
-
-    @Override
-    public void setJavaCommandLine(String javaCommandLine) {
-        this.javaCommandLine.setText(javaCommandLine);
-    }
-
-    @Override
-    public void setJavaHome(String javaHome) {
-        this.javaHome.setText(javaHome);
-
-    }
-
-    @Override
-    public void setJavaVersion(String javaVersion) {
-        this.javaVersion.setText(javaVersion);
-    }
-
-    @Override
-    public void setVmNameAndVersion(String vmNameAndVersion) {
-        this.vmNameAndVersion.setText(vmNameAndVersion);
-    }
-
-    @Override
-    public void setVmArguments(String vmArguments) {
-        this.vmArguments.setText(vmArguments);
-    }
-
-    @Override
-    public Component getUiComponent() {
-        return visiblePanel;
-    }
-
-    private void initializePanel() {
-        visiblePanel = new HeaderPanel();
-
-        visiblePanel.setHeader(translator.localize(LocaleResources.VM_INFO_TITLE));
-
-        TableEntry entry;
-        List<Section> allSections = new ArrayList<Section>();
-
-        Section processSection = new Section(translator.localize(LocaleResources.VM_INFO_SECTION_PROCESS));
-        allSections.add(processSection);
-
-        entry = new TableEntry(translator.localize(LocaleResources.VM_INFO_PROCESS_ID), pid);
-        processSection.add(entry);
-        entry = new TableEntry(translator.localize(LocaleResources.VM_INFO_START_TIME), startTimeStamp);
-        processSection.add(entry);
-        entry = new TableEntry(translator.localize(LocaleResources.VM_INFO_STOP_TIME), stopTimeStamp);
-        processSection.add(entry);
-
-        Section javaSection = new Section(translator.localize(LocaleResources.VM_INFO_SECTION_JAVA));
-        allSections.add(javaSection);
-
-        entry = new TableEntry(translator.localize(LocaleResources.VM_INFO_MAIN_CLASS), mainClass);
-        javaSection.add(entry);
-        entry = new TableEntry(translator.localize(LocaleResources.VM_INFO_COMMAND_LINE), javaCommandLine);
-        javaSection.add(entry);
-        entry = new TableEntry(translator.localize(LocaleResources.VM_INFO_JAVA_VERSION), javaVersion);
-        javaSection.add(entry);
-        entry = new TableEntry(translator.localize(LocaleResources.VM_INFO_VM), vmNameAndVersion);
-        javaSection.add(entry);
-        entry = new TableEntry(translator.localize(LocaleResources.VM_INFO_VM_ARGUMENTS), vmArguments);
-        javaSection.add(entry);
-
-        SimpleTable simpleTable = new SimpleTable();
-        JPanel table = simpleTable.createTable(allSections);
-        table.setBorder(Components.smallBorder());
-        visiblePanel.setContent(table);
-    }
-}
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/osgi/ThermostatActivatorTest.java	Tue Nov 27 14:49:03 2012 -0500
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/osgi/ThermostatActivatorTest.java	Tue Nov 27 14:50:16 2012 -0500
@@ -48,7 +48,6 @@
 import com.redhat.thermostat.client.core.views.VmCpuViewProvider;
 import com.redhat.thermostat.client.core.views.VmGcViewProvider;
 import com.redhat.thermostat.client.core.views.VmInformationViewProvider;
-import com.redhat.thermostat.client.core.views.VmOverviewViewProvider;
 import com.redhat.thermostat.client.osgi.service.HostDecorator;
 import com.redhat.thermostat.client.swing.internal.HostIconDecorator;
 import com.redhat.thermostat.client.swing.views.SwingAgentInformationViewProvider;
@@ -58,7 +57,6 @@
 import com.redhat.thermostat.client.swing.views.SwingVmCpuViewProvider;
 import com.redhat.thermostat.client.swing.views.SwingVmGcViewProvider;
 import com.redhat.thermostat.client.swing.views.SwingVmInformationViewProvider;
-import com.redhat.thermostat.client.swing.views.SwingVmOverviewViewProvider;
 import com.redhat.thermostat.test.StubBundleContext;
 
 public class ThermostatActivatorTest {
@@ -77,10 +75,9 @@
         assertTrue(ctx.isServiceRegistered(VmInformationViewProvider.class.getName(), SwingVmInformationViewProvider.class));
         assertTrue(ctx.isServiceRegistered(VmCpuViewProvider.class.getName(), SwingVmCpuViewProvider.class));
         assertTrue(ctx.isServiceRegistered(VmGcViewProvider.class.getName(), SwingVmGcViewProvider.class));
-        assertTrue(ctx.isServiceRegistered(VmOverviewViewProvider.class.getName(), SwingVmOverviewViewProvider.class));
         assertTrue(ctx.isServiceRegistered(AgentInformationViewProvider.class.getName(), SwingAgentInformationViewProvider.class));
         assertTrue(ctx.isServiceRegistered(ClientConfigViewProvider.class.getName(), SwingClientConfigurationViewProvider.class));
         
-        assertEquals(9, ctx.getAllServices().size());
+        assertEquals(8, ctx.getAllServices().size());
     }
 }
--- a/distribution/config/commands/gui.properties	Tue Nov 27 14:49:03 2012 -0500
+++ b/distribution/config/commands/gui.properties	Tue Nov 27 14:50:16 2012 -0500
@@ -13,6 +13,8 @@
           thermostat-host-cpu-client-swing-@project.version@.jar, \
           thermostat-host-memory-client-core-@project.version@.jar, \
           thermostat-host-memory-client-swing-@project.version@.jar, \
+          thermostat-vm-overview-client-core-@project.version@.jar, \
+          thermostat-vm-overview-client-swing-@project.version@.jar, \
           thermostat-client-heapdumper-core-@project.version@.jar, \
           thermostat-client-heapdumper-swing-@project.version@.jar, \
           thermostat-killvm-client-swing-@project.version@.jar, \
--- a/distribution/pom.xml	Tue Nov 27 14:49:03 2012 -0500
+++ b/distribution/pom.xml	Tue Nov 27 14:50:16 2012 -0500
@@ -343,6 +343,16 @@
     </dependency>
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-vm-overview-client-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-vm-overview-client-swing</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
       <artifactId>thermostat-client-vmclassstat-swing</artifactId>
       <version>${project.version}</version>
     </dependency>
--- a/pom.xml	Tue Nov 27 14:49:03 2012 -0500
+++ b/pom.xml	Tue Nov 27 14:50:16 2012 -0500
@@ -134,6 +134,7 @@
     <module>host-overview</module>
     <module>host-cpu</module>
     <module>host-memory</module>
+    <module>vm-overview</module>
     <!-- development related modules -->
     <module>dev</module>
   </modules>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-overview/client-core/pom.xml	Tue Nov 27 14:50:16 2012 -0500
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>thermostat-vm-overview</artifactId>
+    <groupId>com.redhat.thermostat</groupId>
+    <version>0.5.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>thermostat-vm-overview-client-core</artifactId>
+  <packaging>bundle</packaging>
+  <name>Thermostat VM Overview Core Client plugin</name>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <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>
+            <Export-Package>
+              com.redhat.thermostat.vm.overview.client.core,
+              com.redhat.thermostat.vm.overview.client.locale
+            </Export-Package>
+            <!-- Do not autogenerate uses clauses in Manifests -->
+            <_nouses>true</_nouses>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-common-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-client-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>
--- /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/VmOverviewController.java	Tue Nov 27 14:50:16 2012 -0500
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.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.NotImplementedException;
+import com.redhat.thermostat.common.Timer;
+import com.redhat.thermostat.common.Timer.SchedulingType;
+import com.redhat.thermostat.common.appctx.ApplicationContext;
+import com.redhat.thermostat.common.dao.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(VmInfoDAO vmDao, VmRef vmRef, VmOverviewViewProvider provider) {
+        this.ref = vmRef;
+        this.view = provider.createView();
+
+        dao = vmDao;
+        timer = ApplicationContext.getInstance().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;
+    }
+}
--- /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/VmOverviewService.java	Tue Nov 27 14:50:16 2012 -0500
@@ -0,0 +1,69 @@
+/*
+ * 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 com.redhat.thermostat.client.core.VmFilter;
+import com.redhat.thermostat.client.core.VmInformationService;
+import com.redhat.thermostat.client.core.controllers.VmInformationServiceController;
+import com.redhat.thermostat.client.osgi.service.AlwaysMatchFilter;
+import com.redhat.thermostat.common.dao.VmInfoDAO;
+import com.redhat.thermostat.common.dao.VmRef;
+import com.redhat.thermostat.common.utils.OSGIUtils;
+
+public class VmOverviewService implements VmInformationService {
+    
+    private static final VmFilter FILTER = new AlwaysMatchFilter();
+    
+    private VmInfoDAO vmInfoDAO;
+    
+    public VmOverviewService(VmInfoDAO vmInfoDAO) {
+        this.vmInfoDAO = vmInfoDAO;
+    }
+
+    @Override
+    public VmInformationServiceController getInformationServiceController(
+            VmRef ref) {
+        VmOverviewViewProvider provider = OSGIUtils.getInstance().getService(VmOverviewViewProvider.class);
+        return new VmOverviewController(vmInfoDAO, ref, provider);
+    }
+
+    @Override
+    public VmFilter getFilter() {
+        return FILTER;
+    }
+
+}
--- /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/VmOverviewView.java	Tue Nov 27 14:50:16 2012 -0500
@@ -0,0 +1,63 @@
+/*
+ * 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 com.redhat.thermostat.client.core.views.BasicView;
+import com.redhat.thermostat.client.core.views.UIComponent;
+
+
+public abstract class VmOverviewView extends BasicView implements UIComponent {
+
+    public abstract void setVmPid(String pid);
+
+    public abstract void setVmStartTimeStamp(String timestamp);
+
+    public abstract void setVmStopTimeStamp(String timeStamp);
+
+    public abstract void setMainClass(String mainClass);
+
+    public abstract void setJavaCommandLine(String javaCommandLine);
+
+    public abstract void setJavaHome(String string);
+
+    public abstract void setJavaVersion(String javaVersion);
+
+    public abstract void setVmNameAndVersion(String vmNameAndVersion);
+
+    public abstract void setVmArguments(String vmArguments);
+
+}
--- /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/VmOverviewViewProvider.java	Tue Nov 27 14:50:16 2012 -0500
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.vm.overview.client.core;
+
+import com.redhat.thermostat.client.core.views.ViewProvider;
+
+public interface VmOverviewViewProvider extends ViewProvider {
+
+    @Override
+    public VmOverviewView createView();
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-overview/client-core/src/main/java/com/redhat/thermostat/vm/overview/client/locale/LocaleResources.java	Tue Nov 27 14:50:16 2012 -0500
@@ -0,0 +1,69 @@
+/*
+ * 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.locale;
+
+import com.redhat.thermostat.common.locale.Translate;
+
+public enum LocaleResources {
+    VM_INFO_TAB_OVERVIEW,
+    
+    VM_INFO_TITLE,
+    VM_INFO_SECTION_PROCESS,
+    VM_INFO_SECTION_JAVA,
+
+    VM_INFO_PROCESS_ID,
+    VM_INFO_START_TIME,
+    VM_INFO_STOP_TIME,
+    VM_INFO_RUNNING,
+    VM_INFO_MAIN_CLASS,
+    VM_INFO_COMMAND_LINE,
+    VM_INFO_JAVA_VERSION,
+    VM_INFO_VM,
+    VM_INFO_VM_ARGUMENTS,
+    VM_INFO_VM_NAME_AND_VERSION,
+    VM_INFO_PROPERTIES,
+    VM_INFO_ENVIRONMENT,
+    VM_INFO_LIBRARIES,
+    ;
+
+    static final String RESOURCE_BUNDLE =
+            "com.redhat.thermostat.vm.overview.client.locale.strings";
+
+    public static Translate<LocaleResources> createLocalizer() {
+        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-overview/client-core/src/main/resources/com/redhat/thermostat/vm/overview/client/locale/strings.properties	Tue Nov 27 14:50:16 2012 -0500
@@ -0,0 +1,19 @@
+VM_INFO_TAB_OVERVIEW = Overview
+
+VM_INFO_TITLE = Virtual Machine Overview
+VM_INFO_SECTION_PROCESS = Process Information
+VM_INFO_SECTION_JAVA = Java Information
+
+VM_INFO_PROCESS_ID = Process Id
+VM_INFO_START_TIME = Start time
+VM_INFO_STOP_TIME = Stop time
+VM_INFO_RUNNING = Running
+VM_INFO_MAIN_CLASS = Main Class
+VM_INFO_COMMAND_LINE = Command Line
+VM_INFO_JAVA_VERSION = Java Version
+VM_INFO_VM = Virtual Machine
+VM_INFO_VM_ARGUMENTS = VM arguments
+VM_INFO_VM_NAME_AND_VERSION = {0} version {1}
+VM_INFO_PROPERTIES = Properties
+VM_INFO_ENVIRONMENT = Environment
+VM_INFO_LIBRARIES = Native Libraries
--- /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/VmOverviewControllerTest.java	Tue Nov 27 14:50:16 2012 -0500
@@ -0,0 +1,181 @@
+/*
+ * 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.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.Timer;
+import com.redhat.thermostat.common.Timer.SchedulingType;
+import com.redhat.thermostat.common.TimerFactory;
+import com.redhat.thermostat.common.appctx.ApplicationContext;
+import com.redhat.thermostat.common.appctx.ApplicationContextUtil;
+import com.redhat.thermostat.common.dao.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() {
+        ApplicationContextUtil.resetApplicationContext();
+
+        // 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);
+        ApplicationContext.getInstance().setTimerFactory(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(vmInfoDao, ref, viewProvider);
+
+        listener = listenerCaptor.getValue();
+        timerAction = timerActionCaptor.getValue();
+    }
+
+    @After
+    public void tearDown() {
+        ApplicationContextUtil.resetApplicationContext();
+    }
+
+    @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-swing/pom.xml	Tue Nov 27 14:50:16 2012 -0500
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>thermostat-vm-overview</artifactId>
+    <groupId>com.redhat.thermostat</groupId>
+    <version>0.5.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>thermostat-vm-overview-client-swing</artifactId>
+  <packaging>bundle</packaging>
+  <name>Thermostat VM Overview Swing Client plugin</name>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Private-Package>com.redhat.thermostat.vm.overview.client.swing</Private-Package>
+            <Bundle-Activator>com.redhat.thermostat.vm.overview.client.swing.Activator</Bundle-Activator>
+            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
+            <Bundle-SymbolicName>com.redhat.thermostat.vm.overview.client.swing</Bundle-SymbolicName>
+            <!-- Do not autogenerate uses clauses in Manifests -->
+            <_nouses>true</_nouses>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.easytesting</groupId>
+      <artifactId>fest-swing</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>net.java.openjdk.cacio</groupId>
+      <artifactId>cacio-tta</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jfree</groupId>
+      <artifactId>jfreechart</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-common-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-client-swing</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-vm-overview-client-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-overview/client-swing/src/main/java/com/redhat/thermostat/vm/overview/client/swing/Activator.java	Tue Nov 27 14:50:16 2012 -0500
@@ -0,0 +1,89 @@
+/*
+ * 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.swing;
+
+import java.util.Objects;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.util.tracker.ServiceTracker;
+
+import com.redhat.thermostat.client.core.VmInformationService;
+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 ServiceTracker tracker;
+    private ServiceRegistration reg;
+
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        VmOverviewViewProvider viewProvider = new SwingVmOverviewViewProvider();
+        context.registerService(VmOverviewViewProvider.class.getName(), viewProvider, null);
+
+        tracker = new ServiceTracker(context, VmInfoDAO.class.getName(), null) {
+            
+            @Override
+            public Object addingService(ServiceReference reference) {
+                VmInfoDAO vmInfoDAO = (VmInfoDAO) context.getService(reference);
+                Objects.requireNonNull(vmInfoDAO);
+                VmOverviewService service = new VmOverviewService(vmInfoDAO);
+                reg = context.registerService(VmInformationService.class.getName(), service, null);
+                
+                return super.addingService(reference);
+            }
+
+            @Override
+            public void removedService(ServiceReference reference, Object service) {
+                context.ungetService(reference);
+                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-swing/src/main/java/com/redhat/thermostat/vm/overview/client/swing/ChangeableText.java	Tue Nov 27 14:50:16 2012 -0500
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.vm.overview.client.swing;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class ChangeableText {
+
+    private final Set<TextListener> listeners = new HashSet<TextListener>();
+    private String text;
+
+    public static interface TextListener {
+        public void textChanged(ChangeableText text);
+    }
+
+    public ChangeableText(String text) {
+        this.text = text;
+    }
+
+    public synchronized void setText(String text) {
+        if (this.text.equals(text)) {
+            return;
+        }
+        this.text = text;
+        fireChanged();
+    }
+
+    public synchronized String getText() {
+        return text;
+    }
+
+    public synchronized void addListener(TextListener listener) {
+        this.listeners.add(listener);
+    }
+
+    public synchronized void removeListener(TextListener listener) {
+        this.listeners.remove(listener);
+    }
+
+    private void fireChanged() {
+        for (TextListener listener: listeners) {
+            listener.textChanged(this);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-overview/client-swing/src/main/java/com/redhat/thermostat/vm/overview/client/swing/SimpleTable.java	Tue Nov 27 14:50:16 2012 -0500
@@ -0,0 +1,291 @@
+/*
+ * 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.swing;
+
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.swing.Box;
+import javax.swing.JComponent;
+import javax.swing.JEditorPane;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+
+import com.redhat.thermostat.client.swing.components.Components;
+import com.redhat.thermostat.client.swing.components.ValueField;
+import com.redhat.thermostat.client.ui.ComponentVisibleListener;
+
+public class SimpleTable implements ChangeableText.TextListener {
+
+    Map<ChangeableText, Set<JComponent>> updateMap = new HashMap<ChangeableText, Set<JComponent>>();
+
+    public static class Section {
+        private final String sectionName;
+        private final List<TableEntry> tableEntries = new ArrayList<TableEntry>();
+
+        public Section(String name) {
+            this.sectionName = name;
+        }
+
+        public String getText() {
+            return sectionName;
+        }
+
+        public void add(TableEntry entry) {
+            tableEntries.add(entry);
+        }
+
+        public void add(Key key, List<Value> values) {
+            tableEntries.add(new TableEntry(key, values));
+        }
+
+        public void add(Key key, Value value) {
+            tableEntries.add(new TableEntry(key, value));
+        }
+
+        public TableEntry[] getEntries() {
+            return tableEntries.toArray(new TableEntry[0]);
+        }
+    }
+
+    public static class TableEntry {
+        private final Key key;
+        private final List<Value> values;
+
+        public TableEntry(String key, ChangeableText value) {
+            this(new Key(key), new Value(value));
+        }
+
+        public TableEntry(Key key, Value value) {
+            this.key = key;
+            this.values = new ArrayList<Value>();
+            this.values.add(value);
+        }
+
+        public TableEntry(Key key, List<Value> values) {
+            this.key = key;
+            this.values = new ArrayList<Value>(values);
+        }
+
+        public Key getKey() {
+            return key;
+        }
+
+        public Value[] getValues() {
+            return values.toArray(new Value[0]);
+        }
+    }
+
+    public static class Key {
+        private final String text;
+
+        public Key(String text) {
+            this.text = text;
+        }
+
+        public String getText() {
+            return text;
+        }
+    }
+
+    public static class Value {
+        private final ChangeableText text;
+        private final Component actualComponent;
+
+        public Value(String text) {
+            this(new ChangeableText(text));
+        }
+
+        public Value(ChangeableText text) {
+            this.text = text;
+            this.actualComponent = null;
+        }
+
+        public Value(Component component) {
+            this.actualComponent = component;
+            this.text = null;
+        }
+
+        public Component getComponent() {
+            return actualComponent;
+        }
+
+        public ChangeableText getChangeableText() {
+            return text;
+        }
+    }
+
+    public JPanel createTable(List<Section> sections) {
+        final int SECTION_TOP_GAP = 10;
+        final int ROW_VERTICAL_GAP = 0;
+        final int ROW_HORIZONTAL_GAP = 10;
+
+        Insets sectionHeaderInsets = new Insets(SECTION_TOP_GAP, 0, 0, 0);
+        Insets rowInsets = new Insets(ROW_VERTICAL_GAP, ROW_HORIZONTAL_GAP, ROW_VERTICAL_GAP, ROW_HORIZONTAL_GAP);
+
+        JPanel container = new JPanel();
+        container.setLayout(new GridBagLayout());
+
+        GridBagConstraints keyConstraints = new GridBagConstraints();
+        GridBagConstraints valueConstraints = new GridBagConstraints();
+        GridBagConstraints sectionHeaderConstraints = new GridBagConstraints();
+
+        keyConstraints.insets = valueConstraints.insets = rowInsets;
+        keyConstraints.gridy = valueConstraints.gridy = 0;
+        keyConstraints.gridx = 0;
+        keyConstraints.anchor = GridBagConstraints.FIRST_LINE_END;
+        valueConstraints.gridx = 1;
+        keyConstraints.fill = valueConstraints.fill = GridBagConstraints.HORIZONTAL;
+
+        sectionHeaderConstraints.gridx = 0;
+        sectionHeaderConstraints.gridwidth = GridBagConstraints.REMAINDER;
+        sectionHeaderConstraints.fill = GridBagConstraints.HORIZONTAL;
+        sectionHeaderConstraints.insets = sectionHeaderInsets;
+
+        for (Section section : sections) {
+            sectionHeaderConstraints.gridy = keyConstraints.gridy = ++valueConstraints.gridy;
+            container.add(Components.header(section.getText()), sectionHeaderConstraints);
+            for (TableEntry tableEntry : section.getEntries()) {
+                keyConstraints.gridy = ++valueConstraints.gridy;
+                container.add(Components.label(tableEntry.getKey().getText()), keyConstraints);
+
+                for (Value value : tableEntry.getValues()) {
+                    if (value.getComponent() == null) {
+                        ChangeableText text = value.getChangeableText();
+                        JComponent valueLabel = new ValueField(text.getText());
+                        if (updateMap.containsKey(text)) {
+                            updateMap.get(text).add(valueLabel);
+                        } else {
+                            Set<JComponent> set = new HashSet<JComponent>();
+                            set.add(valueLabel);
+                            updateMap.put(text, set);
+                        }
+                        container.add(valueLabel, valueConstraints);
+                    } else {
+                        container.add(value.getComponent(), valueConstraints);
+                    }
+                    keyConstraints.gridy = ++valueConstraints.gridy;
+                }
+            }
+        }
+
+        GridBagConstraints glueConstraints = new GridBagConstraints();
+        glueConstraints.gridy = keyConstraints.gridy + 1;
+        glueConstraints.gridx = 0;
+        glueConstraints.weightx = 1;
+        glueConstraints.weighty = 1;
+        glueConstraints.fill = GridBagConstraints.BOTH;
+        glueConstraints.gridheight = GridBagConstraints.REMAINDER;
+        glueConstraints.gridwidth = GridBagConstraints.REMAINDER;
+        Component filler = Box.createGlue();
+        container.add(filler, glueConstraints);
+
+        container.addHierarchyListener(new ComponentVisibleListener() {
+            @Override
+            public void componentShown(Component c) {
+                updateAllValues();
+                addAllListeners();
+            }
+
+            @Override
+            public void componentHidden(Component c) {
+                removeAllListeners();
+            }
+        });
+
+        return container;
+    }
+
+
+    private void updateAllValues() {
+        for (Entry<ChangeableText, Set<JComponent>> entry: updateMap.entrySet()) {
+            for (JComponent label: entry.getValue()) {
+                setText(label, entry.getKey().getText());
+            }
+        }
+    }
+
+    private static void setText(JComponent target, String text) {
+        if (target instanceof JLabel) {
+            ((JLabel)target).setText(text);
+        } else if (target instanceof JTextField) {
+            ((JTextField)target).setText(text);
+        } else if (target instanceof JTextArea) {
+            ((JTextArea)target).setText(text);
+        } else if (target instanceof JEditorPane) {
+            ((JEditorPane)target).setText(text);
+        }
+    }
+
+    @Override
+    public void textChanged(final ChangeableText text) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                String newValue = text.getText();
+                for (JComponent label: updateMap.get(text)) {
+                    setText(label, newValue);
+                }
+            }
+        });
+    }
+
+    public void addAllListeners() {
+        for (ChangeableText text : updateMap.keySet()) {
+            text.addListener(this);
+        }
+    }
+
+    public void removeAllListeners() {
+        for (ChangeableText text : updateMap.keySet()) {
+            text.removeListener(this);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-overview/client-swing/src/main/java/com/redhat/thermostat/vm/overview/client/swing/SwingVmOverviewViewProvider.java	Tue Nov 27 14:50:16 2012 -0500
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.vm.overview.client.swing;
+
+import com.redhat.thermostat.vm.overview.client.core.VmOverviewView;
+import com.redhat.thermostat.vm.overview.client.core.VmOverviewViewProvider;
+
+public class SwingVmOverviewViewProvider implements VmOverviewViewProvider {
+
+    @Override
+    public VmOverviewView createView() {
+        return new VmOverviewPanel();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-overview/client-swing/src/main/java/com/redhat/thermostat/vm/overview/client/swing/VmOverviewPanel.java	Tue Nov 27 14:50:16 2012 -0500
@@ -0,0 +1,186 @@
+/*
+ * 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.swing;
+
+import java.awt.Component;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JPanel;
+
+import com.redhat.thermostat.client.swing.SwingComponent;
+import com.redhat.thermostat.client.swing.components.Components;
+import com.redhat.thermostat.client.swing.components.HeaderPanel;
+import com.redhat.thermostat.client.ui.ComponentVisibleListener;
+import com.redhat.thermostat.common.ActionListener;
+import com.redhat.thermostat.common.locale.Translate;
+import com.redhat.thermostat.vm.overview.client.core.VmOverviewView;
+import com.redhat.thermostat.vm.overview.client.locale.LocaleResources;
+import com.redhat.thermostat.vm.overview.client.swing.SimpleTable.Section;
+import com.redhat.thermostat.vm.overview.client.swing.SimpleTable.TableEntry;
+
+public class VmOverviewPanel extends VmOverviewView implements SwingComponent {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+    
+    private HeaderPanel visiblePanel;
+
+    private final ChangeableText pid = new ChangeableText("");
+    private final ChangeableText startTimeStamp = new ChangeableText("");
+    private final ChangeableText stopTimeStamp = new ChangeableText("");
+    private final ChangeableText mainClass = new ChangeableText("");
+    private final ChangeableText javaCommandLine = new ChangeableText("");
+    private final ChangeableText javaHome = new ChangeableText("");
+    private final ChangeableText javaVersion = new ChangeableText("");
+    private final ChangeableText vmNameAndVersion = new ChangeableText("");
+    private final ChangeableText vmArguments = new ChangeableText("");
+
+    public VmOverviewPanel() {
+        super();
+        initializePanel();
+        visiblePanel.addHierarchyListener(new ComponentVisibleListener() {
+            @Override
+            public void componentShown(Component component) {
+                notifier.fireAction(Action.VISIBLE);
+            }
+
+            @Override
+            public void componentHidden(Component component) {
+                notifier.fireAction(Action.HIDDEN);
+            }
+        });
+    }
+
+    @Override
+    public void addActionListener(ActionListener<Action> listener) {
+        notifier.addActionListener(listener);
+    }
+
+    @Override
+    public void removeActionListener(ActionListener<Action> listener) {
+        notifier.removeActionListener(listener);
+    }
+
+    @Override
+    public void setVmPid(String pid) {
+        this.pid.setText(pid);
+    }
+
+    @Override
+    public void setVmStartTimeStamp(String timeStamp) {
+        this.startTimeStamp.setText(timeStamp);
+    }
+
+    @Override
+    public void setVmStopTimeStamp(String timeStamp) {
+        this.stopTimeStamp.setText(timeStamp);
+    }
+
+    @Override
+    public void setMainClass(String mainClass) {
+        this.mainClass.setText(mainClass);
+    }
+
+    @Override
+    public void setJavaCommandLine(String javaCommandLine) {
+        this.javaCommandLine.setText(javaCommandLine);
+    }
+
+    @Override
+    public void setJavaHome(String javaHome) {
+        this.javaHome.setText(javaHome);
+
+    }
+
+    @Override
+    public void setJavaVersion(String javaVersion) {
+        this.javaVersion.setText(javaVersion);
+    }
+
+    @Override
+    public void setVmNameAndVersion(String vmNameAndVersion) {
+        this.vmNameAndVersion.setText(vmNameAndVersion);
+    }
+
+    @Override
+    public void setVmArguments(String vmArguments) {
+        this.vmArguments.setText(vmArguments);
+    }
+
+    @Override
+    public Component getUiComponent() {
+        return visiblePanel;
+    }
+
+    private void initializePanel() {
+        visiblePanel = new HeaderPanel();
+
+        visiblePanel.setHeader(translator.localize(LocaleResources.VM_INFO_TITLE));
+
+        TableEntry entry;
+        List<Section> allSections = new ArrayList<Section>();
+
+        Section processSection = new Section(translator.localize(LocaleResources.VM_INFO_SECTION_PROCESS));
+        allSections.add(processSection);
+
+        entry = new TableEntry(translator.localize(LocaleResources.VM_INFO_PROCESS_ID), pid);
+        processSection.add(entry);
+        entry = new TableEntry(translator.localize(LocaleResources.VM_INFO_START_TIME), startTimeStamp);
+        processSection.add(entry);
+        entry = new TableEntry(translator.localize(LocaleResources.VM_INFO_STOP_TIME), stopTimeStamp);
+        processSection.add(entry);
+
+        Section javaSection = new Section(translator.localize(LocaleResources.VM_INFO_SECTION_JAVA));
+        allSections.add(javaSection);
+
+        entry = new TableEntry(translator.localize(LocaleResources.VM_INFO_MAIN_CLASS), mainClass);
+        javaSection.add(entry);
+        entry = new TableEntry(translator.localize(LocaleResources.VM_INFO_COMMAND_LINE), javaCommandLine);
+        javaSection.add(entry);
+        entry = new TableEntry(translator.localize(LocaleResources.VM_INFO_JAVA_VERSION), javaVersion);
+        javaSection.add(entry);
+        entry = new TableEntry(translator.localize(LocaleResources.VM_INFO_VM), vmNameAndVersion);
+        javaSection.add(entry);
+        entry = new TableEntry(translator.localize(LocaleResources.VM_INFO_VM_ARGUMENTS), vmArguments);
+        javaSection.add(entry);
+
+        SimpleTable simpleTable = new SimpleTable();
+        JPanel table = simpleTable.createTable(allSections);
+        table.setBorder(Components.smallBorder());
+        visiblePanel.setContent(table);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-overview/client-swing/src/test/java/com/redhat/thermostat/vm/overview/client/swing/ActivatorTest.java	Tue Nov 27 14:50:16 2012 -0500
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */ 
+
+package com.redhat.thermostat.vm.overview.client.swing;
+
+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.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(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);
+
+        context.registerService(VmInfoDAO.class, vmInfoDAO, 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());
+    }
+
+    @Test
+    public void verifyStartRegistersViewProvider() throws Exception {
+        StubBundleContext ctx = new StubBundleContext();
+        Activator activator = new Activator();
+        activator.start(ctx);
+        assertTrue(ctx.isServiceRegistered(VmOverviewViewProvider.class.getName(), SwingVmOverviewViewProvider.class));
+        assertEquals(1, ctx.getAllServices().size());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-overview/pom.xml	Tue Nov 27 14:50:16 2012 -0500
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+
+ Copyright 2012 Red Hat, Inc.
+
+ This file is part of Thermostat.
+
+ Thermostat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ Thermostat is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Thermostat; see the file COPYING.  If not see
+ <http://www.gnu.org/licenses />.
+
+ Linking this code with other modules is making a combined work
+ based on this code.  Thus, the terms and conditions of the GNU
+ General Public License cover the whole combination.
+
+ As a special exception, the copyright holders of this code give
+ you permission to link this code with independent modules to
+ produce an executable, regardless of the license terms of these
+ independent modules, and to copy and distribute the resulting
+ executable under terms of your choice, provided that you also
+ meet, for each linked independent module, the terms and conditions
+ of the license of that module.  An independent module is a module
+ which is not derived from or based on this code.  If you modify
+ this code, you may extend this exception to your version of the
+ library, but you are not obligated to do so.  If you do not wish
+ to do so, delete this exception statement from your version.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.redhat.thermostat</groupId>
+    <artifactId>thermostat</artifactId>
+    <version>0.5.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>thermostat-vm-overview</artifactId>
+  <packaging>pom</packaging>
+
+  <name>Thermostat VM Overview plugin</name>
+
+  <modules>
+    <module>client-core</module>
+    <module>client-swing</module>
+  </modules>
+
+</project>