changeset 548:e47c726e6e60

Eclipse client prototype. This commit introduces a simple Eclipse plug-in based Thermostat client. A demo of it can be seen here: http://jerboaa.fedorapeople.org/demo/thermostat/eclipse_prototype_20120816.webm Reviewed-by: vanaltj, neugens Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-August/002667.html PR1082 PR1087 PR1088
author Severin Gehwolf <sgehwolf@redhat.com>
date Fri, 17 Aug 2012 15:34:32 +0200
parents 3d7b096dc162
children 379e7fdb34f0
files client/eclipse/com.redhat.thermostat.eclipse.boot/pom.xml client/eclipse/com.redhat.thermostat.eclipse.test/.classpath client/eclipse/com.redhat.thermostat.eclipse.test/.project client/eclipse/com.redhat.thermostat.eclipse.test/.settings/org.eclipse.jdt.core.prefs client/eclipse/com.redhat.thermostat.eclipse.test/META-INF/MANIFEST.MF client/eclipse/com.redhat.thermostat.eclipse.test/build.properties client/eclipse/com.redhat.thermostat.eclipse.test/fedora-packages.txt client/eclipse/com.redhat.thermostat.eclipse.test/pom.xml client/eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/model/HostVmsTreeContentProviderTest.java client/eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/model/HostsVmsLabelProviderTest.java client/eclipse/com.redhat.thermostat.eclipse/.classpath client/eclipse/com.redhat.thermostat.eclipse/.project client/eclipse/com.redhat.thermostat.eclipse/META-INF/MANIFEST.MF client/eclipse/com.redhat.thermostat.eclipse/build.properties client/eclipse/com.redhat.thermostat.eclipse/plugin.xml client/eclipse/com.redhat.thermostat.eclipse/pom.xml client/eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/Activator.java client/eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/ConnectionConfiguration.java client/eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/LoggerFacility.java client/eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/model/HostsVmsLabelProvider.java client/eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/model/HostsVmsTreeContentProvider.java client/eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/model/HostsVmsTreeRoot.java client/eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/views/HostOverviewViewPart.java client/eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/views/HostsVmsTreeViewPart.java client/eclipse/pom.xml
diffstat 25 files changed, 1811 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/client/eclipse/com.redhat.thermostat.eclipse.boot/pom.xml	Fri Aug 17 13:13:47 2012 +0200
+++ b/client/eclipse/com.redhat.thermostat.eclipse.boot/pom.xml	Fri Aug 17 15:34:32 2012 +0200
@@ -9,8 +9,8 @@
   </parent>
   <groupId>com.redhat.thermostat.eclipse.parent</groupId>
   <artifactId>com.redhat.thermostat.eclipse.boot</artifactId>
+  <packaging>eclipse-plugin</packaging>
   <version>0.4.0-SNAPSHOT</version>
-  <packaging>eclipse-plugin</packaging>
 
   <name>Thermostat Eclipse Client Boot Package</name>
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse.test/.classpath	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse.test/.project	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>com.redhat.thermostat.eclipse.test</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse.test/.settings/org.eclipse.jdt.core.prefs	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse.test/META-INF/MANIFEST.MF	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,12 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Version: 0.4.0.qualifier
+Fragment-Host: com.redhat.thermostat.eclipse;bundle-version="0.4.0.qualifier"
+Bundle-Name: Eclipse client tests
+Bundle-SymbolicName: com.redhat.thermostat.eclipse.test
+Bundle-Vendor: Redhat Inc.
+Require-Bundle: org.eclipse.jdt.core,
+ org.junit;bundle-version="3.8.2"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Import-Package: org.mockito,
+ org.mockito.stubbing
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse.test/build.properties	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse.test/fedora-packages.txt	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,5 @@
+The following Fedora packages required updates (OSGi metadata) in order
+for this fragment to work:
+- mockito
+- hamcrest
+- cglib
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse.test/pom.xml	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>thermostat-eclipse-parent</artifactId>
+    <groupId>com.redhat.thermostat.eclipse.parent</groupId>
+    <version>0.4.0-SNAPSHOT</version>
+  </parent>
+  <groupId>com.redhat.thermostat.eclipse.parent</groupId>
+  <artifactId>com.redhat.thermostat.eclipse.test</artifactId>
+  <packaging>eclipse-test-plugin</packaging>
+  <version>0.4.0-SNAPSHOT</version>
+
+  <name>Thermostat Eclipse Client Tests</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-common-core</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
+
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/model/HostVmsTreeContentProviderTest.java	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,211 @@
+/*
+ * 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.eclipse.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.HostsVMsLoader;
+import com.redhat.thermostat.common.dao.HostRef;
+import com.redhat.thermostat.common.dao.VmRef;
+
+public class HostVmsTreeContentProviderTest {
+
+    private HostsVmsTreeContentProvider treeProvider;
+    private HostRef hostRef;
+    HostsVMsLoader loader;
+    
+    @Before
+    public void setUp() throws Exception {
+        loader = mock(HostsVMsLoader.class);
+        hostRef = mock(HostRef.class);
+        treeProvider = new HostsVmsTreeContentProvider(loader);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        hostRef = null;
+        treeProvider = null;
+        loader = null;
+    }
+
+    @Test
+    public void canGetHosts() {
+        List<HostRef> expectedHosts = new ArrayList<>();
+        HostRef hostRef1 = mock(HostRef.class);
+        HostRef hostRef2 = mock(HostRef.class);
+        expectedHosts.add(hostRef1);
+        expectedHosts.add(hostRef2);
+        
+        when(loader.getHosts()).thenReturn(expectedHosts);
+        Object[] children = treeProvider.getChildren(new HostsVmsTreeRoot());
+        verifySameHosts(children, expectedHosts);
+        
+        children = treeProvider.getChildren(new String("ignored"));
+        assertTrue(children.length == 0);
+    }
+    
+    @Test
+    public void canGetVms() {
+        List<VmRef> expectedVms = new ArrayList<>();
+        expectedVms.add(mock(VmRef.class));
+        expectedVms.add(mock(VmRef.class));
+        when(loader.getVMs(hostRef)).thenReturn(expectedVms);
+        Object[] children = treeProvider.getChildren(hostRef);
+        verifySameVms(children, expectedVms);
+    }
+    
+    @Test
+    public void canGetElements() {
+        List<HostRef> expectedHosts = new ArrayList<>();
+        HostRef hostRef1 = mock(HostRef.class);
+        HostRef hostRef2 = mock(HostRef.class);
+        expectedHosts.add(hostRef1);
+        expectedHosts.add(hostRef2);
+        
+        when(loader.getHosts()).thenReturn(expectedHosts);
+        Object[] children = treeProvider.getElements(new HostsVmsTreeRoot());
+        verifySameHosts(children, expectedHosts);
+    }
+    
+    @Test
+    public void canGetRoot() {
+        assertNull(treeProvider.getParent(new HostsVmsTreeRoot()));
+    }
+    
+    @Test
+    public void canGetVmParent() {
+        List<HostRef> expectedHosts = new ArrayList<>();
+        HostRef hostRef1 = mock(HostRef.class);
+        HostRef hostRef2 = mock(HostRef.class);
+        expectedHosts.add(hostRef1);
+        expectedHosts.add(hostRef2);
+        List<VmRef> expectedVms = new ArrayList<>();
+        VmRef vm = mock(VmRef.class);
+        expectedVms.add(mock(VmRef.class));
+        expectedVms.add(vm);
+        expectedVms.add(mock(VmRef.class));
+        when(loader.getHosts()).thenReturn(expectedHosts);
+        when(loader.getVMs(hostRef1)).thenReturn(expectedVms);
+        treeProvider = new HostsVmsTreeContentProvider(loader);
+        assertEquals(hostRef1, treeProvider.getParent(vm));
+    }
+    
+    /**
+     * Implicitly tests inputChanged() as well
+     */
+    @Test
+    public void canGetHostParent() {
+        List<HostRef> expectedHosts = new ArrayList<>();
+        HostRef hostRef1 = mock(HostRef.class);
+        HostRef hostRef2 = mock(HostRef.class);
+        expectedHosts.add(hostRef1);
+        expectedHosts.add(hostRef2);
+        
+        // need this for reverse look-up map building
+        // which is triggered when inputChanged() is called
+        List<VmRef> expectedVms = new ArrayList<>();
+        VmRef vm = mock(VmRef.class);
+        expectedVms.add(mock(VmRef.class));
+        expectedVms.add(vm);
+        expectedVms.add(mock(VmRef.class));
+        when(loader.getVMs(hostRef)).thenReturn(expectedVms);
+        when(loader.getHosts()).thenReturn(expectedHosts);
+        
+        // need to call inputChanged in order to set root
+        // this is safe to do since treeViewer's setInput() method
+        // triggers the same action.
+        HostsVmsTreeRoot root = new HostsVmsTreeRoot();
+        treeProvider.inputChanged(null, null, root);
+        assertEquals(root, treeProvider.getParent(hostRef1));
+    }
+    
+    @Test
+    public void hasChildren() {
+        List<HostRef> expectedHosts = new ArrayList<>();
+        HostRef hostRef1 = mock(HostRef.class);
+        HostRef hostRef2 = mock(HostRef.class);
+        expectedHosts.add(hostRef1);
+        expectedHosts.add(hostRef2);
+        when(loader.getHosts()).thenReturn(expectedHosts);
+        assertTrue(treeProvider.hasChildren(new HostsVmsTreeRoot()));
+        expectedHosts = new ArrayList<>();
+        when(loader.getHosts()).thenReturn(expectedHosts);
+        assertFalse(treeProvider.hasChildren(new HostsVmsTreeRoot()));
+        
+        List<VmRef> expectedVms = new ArrayList<>();
+        VmRef vm = mock(VmRef.class);
+        expectedVms.add(mock(VmRef.class));
+        expectedVms.add(vm);
+        expectedVms.add(mock(VmRef.class));
+        when(loader.getVMs(hostRef)).thenReturn(expectedVms);
+        assertTrue(treeProvider.hasChildren(hostRef));
+        expectedVms = new ArrayList<>();
+        when(loader.getVMs(hostRef)).thenReturn(expectedVms);
+        assertFalse(treeProvider.hasChildren(hostRef));
+        
+        // VMs don't have children
+        assertFalse(treeProvider.hasChildren(mock(VmRef.class)));
+    }
+
+    private void verifySameHosts(Object[] children, List<HostRef> expectedHosts) {
+        assertEquals(children.length, expectedHosts.size());
+        for (int i = 0; i < children.length; i++) {
+            assertTrue(children[i] instanceof HostRef);
+            assertEquals(children[i], expectedHosts.get(i));
+        }
+    }
+    
+    private void verifySameVms(Object[] children, List<VmRef> expectedHosts) {
+        assertEquals(children.length, expectedHosts.size());
+        for (int i = 0; i < children.length; i++) {
+            assertTrue(children[i] instanceof VmRef);
+            assertEquals(children[i], expectedHosts.get(i));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse.test/src/com/redhat/thermostat/eclipse/model/HostsVmsLabelProviderTest.java	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,86 @@
+/*
+ * 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.eclipse.model;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.redhat.thermostat.common.dao.HostRef;
+import com.redhat.thermostat.common.dao.VmRef;
+
+public class HostsVmsLabelProviderTest {
+
+    private HostsVmsLabelProvider labelProvider;
+    
+    @Before
+    public void setUp() {
+        labelProvider = new HostsVmsLabelProvider();
+    }
+    
+    @After
+    public void tearDown() {
+        labelProvider = null;
+    }
+    
+    @Test
+    public void canGetLabels() {
+        String hostName = "host1";
+        HostRef host = mock(HostRef.class);
+        when(host.getHostName()).thenReturn(hostName);
+        assertEquals(hostName, labelProvider.getText(host));
+        String vmName = "vm1";
+        VmRef vm = mock(VmRef.class);
+        when(vm.getName()).thenReturn(vmName);
+    }
+    
+    @Test(expected = RuntimeException.class)
+    public void getLabelthrowsException() {
+        labelProvider.getText(new HostsVmsTreeRoot());
+    }
+    
+    @Test
+    public void canGetImage() {
+        assertNull(labelProvider.getImage(mock(HostRef.class)));
+        assertNull(labelProvider.getImage(mock(VmRef.class)));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse/.classpath	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse/.project	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>com.redhat.thermostat.eclipse</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse/META-INF/MANIFEST.MF	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,19 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Thermostat Eclipse Client
+Bundle-Activator: com.redhat.thermostat.eclipse.Activator
+Bundle-SymbolicName: com.redhat.thermostat.eclipse;singleton:=true
+Bundle-Version: 0.4.0.qualifier
+Bundle-Vendor: Red Hat Inc.
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-ActivationPolicy: lazy
+Require-Bundle: org.eclipse.core.runtime;bundle-version="3.8.0",
+ org.eclipse.ui;bundle-version="3.103.0"
+Import-Package: com.mongodb,
+ com.redhat.thermostat.common,
+ com.redhat.thermostat.common.appctx,
+ com.redhat.thermostat.common.config,
+ com.redhat.thermostat.common.dao,
+ com.redhat.thermostat.common.model,
+ com.redhat.thermostat.common.storage
+Eclipse-ExtensibleAPI: true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse/build.properties	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               plugin.xml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse/plugin.xml	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.5"?>
+<!--
+  
+   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.
+   
+-->
+<plugin>
+   <extension
+         point="org.eclipse.ui.views">
+      <category
+            id="com.redhat.thermostat.eclipse.main"
+            name="Thermostat">
+      </category>
+      <view
+            category="com.redhat.thermostat.eclipse.main"
+            class="com.redhat.thermostat.eclipse.views.HostsVmsTreeViewPart"
+            id="com.redhat.thermostat.eclipse.vmtree"
+            name="Hosts/VMs"
+            restorable="true">
+      </view>
+      <view
+            category="com.redhat.thermostat.eclipse.main"
+            class="com.redhat.thermostat.eclipse.views.HostOverviewViewPart"
+            id="com.redhat.thermostat.eclipse.mainContainer"
+            name="Host Overview"
+            restorable="true">
+      </view>
+   </extension>
+</plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse/pom.xml	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>thermostat-eclipse-parent</artifactId>
+    <groupId>com.redhat.thermostat.eclipse.parent</groupId>
+    <version>0.4.0-SNAPSHOT</version>
+  </parent>
+  <groupId>com.redhat.thermostat.eclipse.parent</groupId>
+  <artifactId>com.redhat.thermostat.eclipse</artifactId>
+  <packaging>eclipse-plugin</packaging>
+  <version>0.4.0-SNAPSHOT</version>
+
+  <name>Thermostat Eclipse Client</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-common-core</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
+
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/Activator.java	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,155 @@
+/*
+ * 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.eclipse;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+import com.redhat.thermostat.common.appctx.ApplicationContext;
+import com.redhat.thermostat.common.storage.Connection;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+    // Storage connection status
+    private volatile boolean connected = false;
+
+    // The plug-in ID
+    public static final String PLUGIN_ID = "com.redhat.thermostat.eclipse"; //$NON-NLS-1$
+
+    // The shared instance
+    private static Activator plugin;
+
+    /**
+     * The constructor
+     */
+    public Activator() {
+    }
+
+    public boolean isConnected() {
+        return connected;
+    }
+
+    public void setConnected(boolean connected) {
+        this.connected = connected;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext
+     * )
+     */
+    public void start(BundleContext context) throws Exception {
+        super.start(context);
+        plugin = this;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
+     * )
+     */
+    public void stop(BundleContext context) throws Exception {
+        if (isConnected()) {
+            Connection connection = ApplicationContext.getInstance()
+                    .getDAOFactory().getConnection();
+            connection.disconnect();
+        }
+        plugin = null;
+        super.stop(context);
+    }
+
+    /**
+     * Returns the shared instance
+     * 
+     * @return the shared instance
+     */
+    public static Activator getDefault() {
+        return plugin;
+    }
+
+    /**
+     * 
+     * @return {@code true} when platform was started in debug mode (
+     *         {@code -debug} switch) and
+     *         {@code com.redhat.thermostat.eclipse/debug=true} is set in some
+     *         .options file either in $HOME/.options or $(pwd)/.options.
+     */
+    public static boolean inDebugMode() {
+        if (Platform.inDebugMode()) {
+            String debugOption = Platform.getDebugOption(PLUGIN_ID + "/debug"); //$NON-NLS-1$
+            if (debugOption != null && debugOption.equals("true")) { //$NON-NLS-1$
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public IWorkbenchPage getActivePage() {
+        return internalGetActivePage();
+    }
+
+    private IWorkbenchPage internalGetActivePage() {
+        IWorkbenchWindow window = getWorkbench().getActiveWorkbenchWindow();
+        if (window == null)
+            return null;
+        return window.getActivePage();
+    }
+
+    /**
+     * Returns an image descriptor for the image file at the given plug-in
+     * relative path
+     * 
+     * @param path
+     *            the path
+     * @return the image descriptor
+     */
+    public static ImageDescriptor getImageDescriptor(String path) {
+        return imageDescriptorFromPlugin(PLUGIN_ID, path);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/ConnectionConfiguration.java	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.eclipse;
+
+import com.redhat.thermostat.common.config.StartupConfiguration;
+
+public class ConnectionConfiguration implements StartupConfiguration {
+
+    private String dbUrl;
+
+    // FIXME: Adapt to more dynamic requirements
+    public ConnectionConfiguration(String dbUrl) {
+        this.dbUrl = dbUrl;
+    }
+
+    @Override
+    public String getDBConnectionString() {
+        return dbUrl;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/LoggerFacility.java	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.eclipse;
+
+import org.eclipse.core.runtime.ILog;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+public class LoggerFacility {
+
+    private ILog log;
+    private static LoggerFacility instance;
+    private static boolean isLoggingEnabled; // want default of false
+
+    private LoggerFacility() {
+        log = Activator.getDefault().getLog();
+        isLoggingEnabled = Activator.inDebugMode();
+    }
+
+    /**
+     * Get a LoggerFacility singleton.
+     * 
+     * @return The singleton instance.
+     */
+    public static LoggerFacility getInstance() {
+        if (instance == null) {
+            instance = new LoggerFacility();
+        }
+        return instance;
+    }
+
+    /**
+     * Logs messages with the given severity.
+     * 
+     * @param message
+     *            The human readable localized message.
+     * @param throwable
+     *            The exception which occurred.
+     */
+    public void log(int severity, String message, Throwable throwable) {
+        if (isLoggingEnabled) {
+            log.log(new Status(severity, Activator.PLUGIN_ID, message,
+                    throwable));
+        }
+    }
+
+    /**
+     * Logs messages with the given severity.
+     * 
+     * @param message
+     *            A human readable localized message.
+     * @param severity
+     *            A suitable severity. See {@link IStatus}.
+     */
+    public void log(int severity, String message) {
+        if (isLoggingEnabled) {
+            log.log(new Status(severity, Activator.PLUGIN_ID, message));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/model/HostsVmsLabelProvider.java	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,78 @@
+/*
+ * 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.eclipse.model;
+
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+
+import com.redhat.thermostat.common.dao.HostRef;
+import com.redhat.thermostat.common.dao.VmRef;
+
+public class HostsVmsLabelProvider extends LabelProvider {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object)
+     */
+    @Override
+    public Image getImage(Object element) {
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
+     */
+    @Override
+    public String getText(Object element) {
+        if (element instanceof HostRef) {
+            return ((HostRef) element).getHostName();
+        } else if (element instanceof VmRef) {
+            return ((VmRef) element).getName();
+        } else {
+            throw unknownElement(element);
+        }
+    }
+
+    private RuntimeException unknownElement(Object element) {
+        return new RuntimeException("Unknown type of element in tree of type "
+                + element.getClass().getName());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/model/HostsVmsTreeContentProvider.java	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,139 @@
+/*
+ * 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.eclipse.model;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+import com.redhat.thermostat.common.HostsVMsLoader;
+import com.redhat.thermostat.common.dao.HostRef;
+import com.redhat.thermostat.common.dao.VmRef;
+
+public class HostsVmsTreeContentProvider implements ITreeContentProvider {
+
+    private static final Object[] EMPTY_LIST = new Object[0];
+
+    private HostsVMsLoader loader;
+    private Map<VmRef, HostRef> reverseLookupMap;
+    private HostsVmsTreeRoot root;
+
+    public HostsVmsTreeContentProvider(HostsVMsLoader loader) {
+        this.loader = loader;
+        this.reverseLookupMap = buildReverseLookupMap();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+     */
+    @Override
+    public void dispose() {
+        // nothing
+    }
+
+    @Override
+    public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+        if (newInput instanceof HostsVmsTreeRoot) {
+            root = (HostsVmsTreeRoot) newInput;
+        }
+        // refresh reverse look-up
+        this.reverseLookupMap = buildReverseLookupMap();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.eclipse.jface.viewers.ITreeContentProvider#getElements(java.lang.
+     * Object)
+     */
+    @Override
+    public Object[] getElements(Object root) {
+        return getChildren(root);
+    }
+
+    @Override
+    public Object[] getChildren(Object parentElement) {
+        if (parentElement instanceof HostsVmsTreeRoot) {
+            return loader.getHosts().toArray();
+        } else if (parentElement instanceof HostRef) {
+            HostRef hostRef = (HostRef) parentElement;
+            return loader.getVMs(hostRef).toArray();
+        } else {
+            return EMPTY_LIST;
+        }
+    }
+
+    @Override
+    public Object getParent(Object element) {
+        if (element instanceof HostsVmsTreeRoot) {
+            return null;
+        } else if (element instanceof HostRef) {
+            return root;
+        } else if (element instanceof VmRef) {
+            return this.reverseLookupMap.get(element);
+        }
+        return null;
+    }
+
+    @Override
+    public boolean hasChildren(Object element) {
+        if (element instanceof HostsVmsTreeRoot) {
+            return loader.getHosts().size() > 0;
+        } else if (element instanceof HostRef) {
+            HostRef host = (HostRef) element;
+            return loader.getVMs(host).size() > 0;
+        } else {
+            // VM refs don't have children
+            return false;
+        }
+    }
+
+    private Map<VmRef, HostRef> buildReverseLookupMap() {
+        Map<VmRef, HostRef> lookupMap = new HashMap<>();
+        for (HostRef ref : loader.getHosts()) {
+            for (VmRef vmRef : loader.getVMs(ref)) {
+                lookupMap.put(vmRef, ref);
+            }
+        }
+        return lookupMap;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/model/HostsVmsTreeRoot.java	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,44 @@
+/*
+ * 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.eclipse.model;
+
+/**
+ * A dummy root object, since the Hosts don't have a real root.
+ */
+public class HostsVmsTreeRoot {
+    // nothing
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/views/HostOverviewViewPart.java	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,401 @@
+/*
+ * 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.eclipse.views;
+
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.ISelectionListener;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.PageBook;
+import org.eclipse.ui.part.ViewPart;
+
+import com.redhat.thermostat.common.appctx.ApplicationContext;
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.common.dao.HostRef;
+import com.redhat.thermostat.common.dao.NetworkInterfaceInfoDAO;
+import com.redhat.thermostat.common.dao.Ref;
+import com.redhat.thermostat.common.dao.VmRef;
+import com.redhat.thermostat.common.model.HostInfo;
+import com.redhat.thermostat.common.model.NetworkInterfaceInfo;
+import com.redhat.thermostat.eclipse.Activator;
+
+public class HostOverviewViewPart extends ViewPart {
+
+    private static final int FIRST_COLUMN_WIDTH = 150;
+    private final String STR_UNKNOWN = "UNKNOWN";
+    private PageBook pageBook;
+    // VM page
+    private Composite vmPage;
+    private Label vmName;
+    private Composite notConnectedPage;
+    // Main compositie
+    private ScrolledComposite mainScrollPage;
+    private Label hostname;
+    private Label procModel;
+    private Label procCoreCount;
+    private Label totalMemory;
+    private TableViewer networkInterfaces;
+    private Label osName;
+    private Label osKernel;
+    private ISelection oldSelection = null;
+
+    // The listener we register with the selection service in order to listen
+    // for
+    // VmTreeView selection changes.
+    private ISelectionListener listener = new ISelectionListener() {
+        public void selectionChanged(IWorkbenchPart sourcepart,
+                ISelection selection) {
+            // only react upon hosts/vms tree changes. Then only if the selected
+            // element
+            // actually changed
+            if (sourcepart instanceof HostsVmsTreeViewPart
+                    && !selection.equals(oldSelection)) {
+                oldSelection = selection;
+                Ref ref = getRefFromSelection(selection);
+                if (Activator.getDefault().isConnected()) {
+                    if (ref != null) {
+                        updateText(ref);
+                        if (ref instanceof HostRef) {
+                            showPage(mainScrollPage);
+                        } else {
+                            showPage(vmPage);
+                        }
+                    }
+                } else {
+                    showPage(notConnectedPage);
+                }
+            }
+        }
+    };
+
+    private void showPage(final Control page) {
+        PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                if (page instanceof ScrolledComposite) {
+                    ((ScrolledComposite) page).getContent().pack();
+                } else {
+                    page.pack();
+                }
+                pageBook.showPage(page);
+            }
+        });
+    }
+
+    @Override
+    public void createPartControl(Composite parent) {
+        pageBook = new PageBook(parent, SWT.NONE);
+        mainScrollPage = new ScrolledComposite(pageBook, SWT.NONE
+                | SWT.V_SCROLL | SWT.H_SCROLL);
+        Composite main = new Composite(mainScrollPage, SWT.NONE);
+        mainScrollPage.setContent(main);
+        vmPage = new Composite(pageBook, SWT.NONE);
+
+        vmName = new Label(vmPage, SWT.NONE);
+        vmPage.setLayout(new RowLayout());
+
+        notConnectedPage = new Composite(pageBook, SWT.NONE);
+        notConnectedPage.setLayout(new RowLayout());
+
+        // ----------------------------------------
+        // Not connected page
+        // ----------------------------------------
+        Label notConn = new Label(notConnectedPage, SWT.NONE);
+        notConn.setText("Not connected to storage");
+
+        // ----------------------------------------
+        // Main overview page
+        // ----------------------------------------
+        main.setLayout(new GridLayout());
+
+        // Basics
+        Label lblBasics = new Label(main, SWT.NONE);
+        lblBasics.setText("Basics"); // TODO: Externalize
+        Font stdFont = lblBasics.getFont();
+        Font boldFont = new Font(stdFont.getDevice(),
+                stdFont.getFontData()[0].getName(),
+                stdFont.getFontData()[0].getHeight(), SWT.BOLD);
+        lblBasics.setFont(boldFont);
+        Composite basicsComps = new Composite(main, SWT.NONE);
+        GridLayout gridlayout = new GridLayout(2, false);
+        basicsComps.setLayout(gridlayout);
+        Label lblHostName = new Label(basicsComps, SWT.NONE);
+        lblHostName.setText("Hostname");
+        GridData hostNameGridData = new GridData(SWT.RIGHT, SWT.CENTER, false,
+                false);
+        hostNameGridData.widthHint = FIRST_COLUMN_WIDTH;
+        lblHostName.setLayoutData(hostNameGridData);
+        hostname = new Label(basicsComps, SWT.NONE);
+        hostname.setText(STR_UNKNOWN);
+        hostname.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true));
+
+        // Hardware
+        Label lblHardware = new Label(main, SWT.NONE);
+        lblHardware.setText("Hardware");
+        lblHardware.setFont(boldFont);
+        Composite hardwareComps = new Composite(main, SWT.NONE);
+        hardwareComps.setLayout(gridlayout);
+        Label lblProcModel = new Label(hardwareComps, SWT.NONE);
+        lblProcModel.setText("Processor Model");
+        GridData procModelGridData = new GridData(SWT.RIGHT, SWT.CENTER, false,
+                false);
+        procModelGridData.widthHint = FIRST_COLUMN_WIDTH;
+        lblProcModel.setLayoutData(procModelGridData);
+        procModel = new Label(hardwareComps, SWT.NONE);
+        procModel.setText(STR_UNKNOWN);
+        procModel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true));
+        Label lblProcCount = new Label(hardwareComps, SWT.NONE);
+        lblProcCount.setText("Processor Count");
+        GridData procCountGridData = new GridData(SWT.RIGHT, SWT.CENTER, false,
+                false);
+        procCountGridData.widthHint = FIRST_COLUMN_WIDTH;
+        lblProcCount.setLayoutData(procCountGridData);
+        procCoreCount = new Label(hardwareComps, SWT.NONE);
+        procCoreCount.setText(STR_UNKNOWN);
+        procCoreCount.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true,
+                true));
+        Label lblTotalMemory = new Label(hardwareComps, SWT.NONE);
+        lblTotalMemory.setText("Total Memory");
+        GridData totalMemGridData = new GridData(SWT.RIGHT, SWT.CENTER, false,
+                false);
+        totalMemGridData.widthHint = FIRST_COLUMN_WIDTH;
+        lblTotalMemory.setLayoutData(totalMemGridData);
+        lblTotalMemory.pack();
+        totalMemory = new Label(hardwareComps, SWT.NONE);
+        totalMemory.setText(STR_UNKNOWN);
+        totalMemory
+                .setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true));
+        Label lblNetwork = new Label(hardwareComps, SWT.NONE);
+        lblNetwork.setText("Network");
+        GridData networkLayout = new GridData(SWT.RIGHT, SWT.TOP, true, true);
+        networkLayout.widthHint = FIRST_COLUMN_WIDTH;
+        lblNetwork.setLayoutData(networkLayout);
+        networkInterfaces = new TableViewer(hardwareComps, SWT.BORDER);
+        createNetworkTableViewer(networkInterfaces);
+
+        // Software
+        Label lblSoftware = new Label(main, SWT.NONE);
+        lblSoftware.setText("Software");
+        lblSoftware.setFont(boldFont);
+        Composite softwareComps = new Composite(main, SWT.NONE);
+        softwareComps.setLayout(gridlayout);
+        Label lblOsName = new Label(softwareComps, SWT.NONE);
+        lblOsName.setText("OS Name");
+        GridData osNameGridData = new GridData(SWT.RIGHT, SWT.CENTER, false,
+                false);
+        osNameGridData.widthHint = FIRST_COLUMN_WIDTH;
+        lblOsName.setLayoutData(osNameGridData);
+        osName = new Label(softwareComps, SWT.NONE);
+        osName.setText(STR_UNKNOWN);
+        osName.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true));
+        Label lblKernel = new Label(softwareComps, SWT.NONE);
+        lblKernel.setText("OS Kernel");
+        GridData osKernelGridData = new GridData(SWT.RIGHT, SWT.CENTER, false,
+                false);
+        osKernelGridData.widthHint = FIRST_COLUMN_WIDTH;
+        lblKernel.setLayoutData(osKernelGridData);
+        osKernel = new Label(softwareComps, SWT.NONE);
+        osKernel.setText(STR_UNKNOWN);
+        osKernel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true));
+
+        // Listen for VMtree changes
+        getSite().getWorkbenchWindow().getSelectionService()
+                .addSelectionListener(listener);
+        if (Activator.getDefault().isConnected()) {
+            ISelection selection = getSite().getWorkbenchWindow()
+                    .getSelectionService().getSelection();
+            Ref ref = getRefFromSelection(selection);
+            if (ref != null) {
+                updateText(ref);
+                if (ref instanceof HostRef) {
+                    showPage(mainScrollPage);
+                } else {
+                    showPage(vmPage);
+                }
+            } else {
+                // FIXME: probably want to show something else, e.g. select x in
+                // VM tree
+                showPage(notConnectedPage);
+            }
+        } else {
+            showPage(notConnectedPage);
+        }
+    }
+
+    @Override
+    public void setFocus() {
+        pageBook.setFocus();
+    }
+
+    private void updateText(Ref ref) {
+        if (ref instanceof HostRef) {
+            updateText((HostRef) ref);
+        } else {
+            updateText((VmRef) ref);
+        }
+    }
+
+    private void updateText(final HostRef hostRef) {
+        DAOFactory df = ApplicationContext.getInstance().getDAOFactory();
+        HostInfoDAO hostInfoDAO = df.getHostInfoDAO();
+        final HostInfo hostInfo = hostInfoDAO.getHostInfo(hostRef);
+        final NetworkInterfaceInfoDAO networkInfoDAO = df
+                .getNetworkInterfaceInfoDAO();
+        PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                hostname.setText(hostRef.getHostName());
+                osName.setText(hostInfo.getOsName());
+                procModel.setText(hostInfo.getCpuModel());
+                procCoreCount.setText(Integer.toString(hostInfo.getCpuCount()));
+                osKernel.setText(hostInfo.getOsKernel());
+                totalMemory.setText(Long.toString(hostInfo.getTotalMemory()));
+                // set content for the network iface table
+                networkInterfaces.setInput(networkInfoDAO.getNetworkInterfaces(
+                        hostRef).toArray());
+            }
+        });
+    }
+
+    private void updateText(final VmRef vmRef) {
+        PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                vmName.setText(vmRef.getName());
+            }
+        });
+    }
+
+    private Ref getRefFromSelection(ISelection selection) {
+        if (selection instanceof IStructuredSelection) {
+            IStructuredSelection ss = (IStructuredSelection) selection;
+            // FIXME: hostsVms tree should only allow single selections
+            for (Object item : ss.toArray()) {
+                if (item instanceof Ref) {
+                    return (Ref) item;
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public void dispose() {
+        // important: We need do unregister our listener when the view is
+        // disposed
+        getSite().getWorkbenchWindow().getSelectionService()
+                .removeSelectionListener(listener);
+        super.dispose();
+    }
+
+    private void createNetworkTableViewer(TableViewer viewer) {
+        createColumns(viewer.getControl().getParent(), viewer);
+        final Table table = viewer.getTable();
+        table.setHeaderVisible(true);
+        table.setLinesVisible(true);
+
+        viewer.setContentProvider(new ArrayContentProvider());
+        // create empty table
+        viewer.setInput(new Object[0]);
+    }
+
+    // This will create the columns for the table
+    private void createColumns(final Composite parent, final TableViewer viewer) {
+        String[] titles = { "Interface", "IPv4 Address", "IPv6 Address" };
+        int[] bounds = { 80, 150, 150 };
+
+        // First column is iface name
+        TableViewerColumn col = createTableViewerColumn(viewer, titles[0],
+                bounds[0], 0);
+        col.setLabelProvider(new ColumnLabelProvider() {
+            @Override
+            public String getText(Object element) {
+                NetworkInterfaceInfo iface = (NetworkInterfaceInfo) element;
+                return iface.getInterfaceName();
+            }
+        });
+
+        // Second column is IPv4
+        col = createTableViewerColumn(viewer, titles[1], bounds[1], 1);
+        col.setLabelProvider(new ColumnLabelProvider() {
+            @Override
+            public String getText(Object element) {
+                NetworkInterfaceInfo iface = (NetworkInterfaceInfo) element;
+                return iface.getIp4Addr();
+            }
+        });
+
+        // IPv6
+        col = createTableViewerColumn(viewer, titles[2], bounds[2], 2);
+        col.setLabelProvider(new ColumnLabelProvider() {
+            @Override
+            public String getText(Object element) {
+                NetworkInterfaceInfo iface = (NetworkInterfaceInfo) element;
+                return iface.getIp6Addr();
+            }
+        });
+    }
+
+    private TableViewerColumn createTableViewerColumn(TableViewer viewer,
+            String title, int bound, final int colNumber) {
+        final TableViewerColumn viewerColumn = new TableViewerColumn(viewer,
+                SWT.NONE);
+        final TableColumn column = viewerColumn.getColumn();
+        column.setText(title);
+        column.setWidth(bound);
+        column.setResizable(true);
+        column.setMoveable(false);
+        return viewerColumn;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/eclipse/com.redhat.thermostat.eclipse/src/com/redhat/thermostat/eclipse/views/HostsVmsTreeViewPart.java	Fri Aug 17 15:34:32 2012 +0200
@@ -0,0 +1,289 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.eclipse.views;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.jobs.JobChangeAdapter;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.PageBook;
+import org.eclipse.ui.part.ViewPart;
+
+import com.redhat.thermostat.common.DefaultHostsVMsLoader;
+import com.redhat.thermostat.common.HostsVMsLoader;
+import com.redhat.thermostat.common.ThreadPoolTimerFactory;
+import com.redhat.thermostat.common.TimerFactory;
+import com.redhat.thermostat.common.appctx.ApplicationContext;
+import com.redhat.thermostat.common.config.InvalidConfigurationException;
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.common.dao.MongoDAOFactory;
+import com.redhat.thermostat.common.dao.VmInfoDAO;
+import com.redhat.thermostat.common.storage.Connection;
+import com.redhat.thermostat.common.storage.Connection.ConnectionListener;
+import com.redhat.thermostat.common.storage.Connection.ConnectionStatus;
+import com.redhat.thermostat.common.storage.ConnectionException;
+import com.redhat.thermostat.common.storage.MongoStorageProvider;
+import com.redhat.thermostat.common.storage.StorageProvider;
+import com.redhat.thermostat.eclipse.Activator;
+import com.redhat.thermostat.eclipse.ConnectionConfiguration;
+import com.redhat.thermostat.eclipse.LoggerFacility;
+import com.redhat.thermostat.eclipse.model.HostsVmsLabelProvider;
+import com.redhat.thermostat.eclipse.model.HostsVmsTreeContentProvider;
+import com.redhat.thermostat.eclipse.model.HostsVmsTreeRoot;
+
+/**
+ * 
+ * The main class for the VM tree view of the Thermostat Eclipse client.
+ * 
+ */
+public class HostsVmsTreeViewPart extends ViewPart {
+
+    private Action connectAction;
+    // Hosts and VMs viewer
+    private TreeViewer treeViewer;
+    // viewer for the connect viewing.
+    private Composite connectPage;
+    // Container for tree and connect
+    private PageBook pageBook;
+
+    private ConnectionConfiguration configuration;
+
+    private void showConnectionPage() {
+        PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                pageBook.showPage(connectPage);
+            }
+        });
+    }
+
+    private void showHostVmsPage() {
+        HostInfoDAO hostDAO = ApplicationContext.getInstance().getDAOFactory()
+                .getHostInfoDAO();
+        VmInfoDAO vmsDAO = ApplicationContext.getInstance().getDAOFactory()
+                .getVmInfoDAO();
+        final HostsVMsLoader loader = new DefaultHostsVMsLoader(hostDAO,
+                vmsDAO, false);
+
+        PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+
+            @Override
+            public void run() {
+                treeViewer.setContentProvider(new HostsVmsTreeContentProvider(
+                        loader));
+                treeViewer.setLabelProvider(new HostsVmsLabelProvider());
+                treeViewer.setUseHashlookup(true);
+                treeViewer.setInput(new HostsVmsTreeRoot());
+                pageBook.showPage(treeViewer.getControl());
+            }
+
+        });
+    }
+
+    @Override
+    public void createPartControl(final Composite parent) {
+        connectAction = new Action("Connect to storage...") {
+            public void run() {
+                Job connectJob = new ConnectJob(
+                        "Connecting to Thermostat storage...");
+                connectJob.setSystem(true);
+                connectJob.addJobChangeListener(new ConnectionJobListener());
+                connectJob.schedule();
+            }
+        };
+        connectAction.setImageDescriptor(Activator
+                .getImageDescriptor("icons/offline.png"));
+        IToolBarManager mgr = getViewSite().getActionBars().getToolBarManager();
+        mgr.add(connectAction);
+
+        configuration = new ConnectionConfiguration("mongodb://127.0.0.1:27518");
+        pageBook = new PageBook(parent, SWT.NONE);
+
+        // Prepare Hosts/VMs tree
+        treeViewer = new TreeViewer(pageBook, SWT.NONE);
+        // register the tree as selection provider
+        getSite().setSelectionProvider(treeViewer);
+
+        // Prepare connect page
+        RowLayout layout = new RowLayout();
+        layout.wrap = true;
+        connectPage = new Composite(pageBook, SWT.NONE);
+        connectPage.setLayout(layout);
+        Label test = new Label(connectPage, SWT.NONE);
+        test.setText("Not connected... ");
+        Link link = new Link(connectPage, SWT.NONE);
+        // FIXME: Externalize
+        link.setText("<a>Connect</a>");
+        link.addListener(SWT.Selection, new Listener() {
+            @Override
+            public void handleEvent(Event event) {
+                // implement connect
+                Job connectJob = new ConnectJob(
+                        "Connecting to Thermostat storage...");
+                connectJob.setSystem(true);
+                connectJob.addJobChangeListener(new ConnectionJobListener());
+                connectJob.schedule();
+            }
+        });
+        // Show appropriate page
+        boolean connected = Activator.getDefault().isConnected();
+        if (connected) {
+            showHostVmsPage();
+        } else {
+            showConnectionPage();
+        }
+    }
+
+    @Override
+    public void setFocus() {
+        pageBook.setFocus();
+    }
+
+    /*
+     * Mongo connection method
+     */
+    private boolean connectToBackEnd() throws InvalidConfigurationException {
+        StorageProvider connProv = new MongoStorageProvider(configuration);
+        DAOFactory daoFactory = new MongoDAOFactory(connProv);
+        ApplicationContext.getInstance().setDAOFactory(daoFactory);
+        TimerFactory timerFactory = new ThreadPoolTimerFactory(1);
+        ApplicationContext.getInstance().setTimerFactory(timerFactory);
+
+        Connection connection = daoFactory.getConnection();
+        ConnectionListener connectionListener = new ConnectionListener() {
+            @Override
+            public void changed(ConnectionStatus newStatus) {
+                switch (newStatus) {
+                case DISCONNECTED:
+                    LoggerFacility.getInstance().log(IStatus.WARNING,
+                            "Unexpected disconnect event.");
+                    break;
+                case CONNECTING:
+                    LoggerFacility.getInstance().log(IStatus.INFO,
+                            "Connecting to storage.");
+                    break;
+                case CONNECTED:
+                    LoggerFacility.getInstance().log(IStatus.INFO,
+                            "Connected to storage.");
+                    Activator.getDefault().setConnected(true);
+                    break;
+                case FAILED_TO_CONNECT:
+                    LoggerFacility.getInstance().log(IStatus.WARNING,
+                            "Could not connect to storage.");
+                default:
+                    LoggerFacility.getInstance().log(IStatus.WARNING,
+                            "Unfamiliar ConnectionStatus value");
+                }
+            }
+        };
+        connection.addListener(connectionListener);
+        try {
+            LoggerFacility.getInstance().log(IStatus.INFO,
+                    "Connecting to storage...");
+            connection.connect();
+            return true;
+        } catch (final ConnectionException e) {
+            LoggerFacility.getInstance().log(IStatus.ERROR,
+                    e.getCause().getMessage(), e.getCause());
+            PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+                @Override
+                public void run() {
+                    // FIXME: Show a nicer error message
+                    MessageDialog.openError(null, "Connection Problem", e
+                            .getCause().getMessage());
+                }
+
+            });
+            return false;
+        }
+    }
+
+    private class ConnectJob extends Job {
+
+        public ConnectJob(String name) {
+            super(name);
+        }
+
+        @Override
+        protected IStatus run(IProgressMonitor monitor) {
+            monitor.beginTask(
+                    "Connecting to " + configuration.getDBConnectionString(),
+                    IProgressMonitor.UNKNOWN);
+            try {
+                if (connectToBackEnd()) {
+                    return Status.OK_STATUS;
+                }
+            } catch (InvalidConfigurationException e) {
+                // FIXME: do something more reasonable
+            }
+            return Status.CANCEL_STATUS;
+        }
+
+    }
+
+    private class ConnectionJobListener extends JobChangeAdapter {
+
+        @Override
+        public void done(IJobChangeEvent event) {
+            IStatus result = event.getResult();
+            if (result.isOK() && result.getCode() != IStatus.CANCEL) {
+                showHostVmsPage();
+                connectAction.setImageDescriptor(Activator
+                        .getImageDescriptor("icons/online.png"));
+                connectAction.setEnabled(!Activator.getDefault().isConnected());
+                connectAction.setToolTipText("Online");
+            }
+        }
+
+    }
+
+}
--- a/client/eclipse/pom.xml	Fri Aug 17 13:13:47 2012 +0200
+++ b/client/eclipse/pom.xml	Fri Aug 17 15:34:32 2012 +0200
@@ -36,17 +36,7 @@
 <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <modelVersion>4.0.0</modelVersion>
-  
-  <parent>
-    <groupId>org.eclipse</groupId>
-    <artifactId>eclipse-parent</artifactId>
-    <version>3</version>
-  </parent>
-  
-  <prerequisites>
-    <maven>3.0</maven>
-  </prerequisites>
-  
+
   <groupId>com.redhat.thermostat.eclipse.parent</groupId>
   <artifactId>thermostat-eclipse-parent</artifactId>
   <version>0.4.0-SNAPSHOT</version>
@@ -65,7 +55,7 @@
     <tycho-extras-version>0.15.0</tycho-extras-version>
     <platform-version-name>juno</platform-version-name>
     <eclipse-site>http://download.eclipse.org/releases/${platform-version-name}</eclipse-site>
-    <orbit-site>http://download.eclipse.org/tools/orbit/downloads/drops/R20110523182458/repository/</orbit-site>
+    <orbit-site>http://download.eclipse.org/tools/orbit/downloads/drops/S20120726065500/repository/</orbit-site>
   </properties>
 
   <profiles>
@@ -100,6 +90,8 @@
   
   <modules>
     <module>com.redhat.thermostat.eclipse.boot</module>
+    <module>com.redhat.thermostat.eclipse</module>
+    <module>com.redhat.thermostat.eclipse.test</module>
   </modules>
 
   <repositories>
@@ -133,6 +125,8 @@
         <version>${tycho-version}</version>
         <configuration>
           <resolver>p2</resolver>
+          <!-- required for Thermostat core deps resolution -->
+          <pomDependencies>consider</pomDependencies>
         </configuration>
       </plugin>
       <plugin>
@@ -167,17 +161,24 @@
           <configuration>
             <encoding>UTF-8</encoding>
           </configuration>
-	    </plugin>
-		<plugin>
-			<groupId>org.eclipse.tycho</groupId>
-			<artifactId>tycho-surefire-plugin</artifactId>
-			<version>${tycho-version}</version>
-			<configuration>
-				<useUIHarness>true</useUIHarness>
-				<useUIThread>true</useUIThread>
-				<product>org.eclipse.sdk.ide</product>
-			</configuration>
-		</plugin>
+        </plugin>
+        <plugin>
+          <groupId>org.eclipse.tycho</groupId>
+          <artifactId>tycho-surefire-plugin</artifactId>
+          <version>${tycho-version}</version>
+          <configuration>
+            <useUIHarness>false</useUIHarness>
+            <useUIThread>flase</useUIThread>
+            <dependencies>
+              <dependency>
+                <type>p2-installable-unit</type>
+                <artifactId>org.eclipse.sdk.feature.group</artifactId>
+                <version>${sdk-version}</version>
+              </dependency>
+            </dependencies>
+            <product>org.eclipse.sdk.ide</product>
+          </configuration>
+        </plugin>
         <plugin>
           <!-- TODO remove workaround when
              https://issues.sonatype.org/browse/TYCHO-473