changeset 1290:5a545dca9fb5

Re-add history mode review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-October/008556.html reviewed-by: omajid
author Mario Torre <neugens.limasoftware@gmail.com>
date Mon, 28 Oct 2013 16:27:18 +0100
parents 7a0ff324a833
children 0e01dad5f877
files client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/LivingHostFilter.java client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/LivingVMFilter.java client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingHostFilterMenuAction.java client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/LocaleResources.java client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/VMFilterActivator.java client/living-vm-filter/core/src/main/resources/com/redhat/thermostat/client/filter/vm/core/internal/strings.properties client/living-vm-filter/core/src/test/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingHostFilterTest.java client/living-vm-filter/core/src/test/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingVMFilterTest.java client/living-vm-filter/core/src/test/java/com/redhat/thermostat/client/filter/vm/core/internal/VMFilterActivatorTest.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/LivingVMDecoratorProvider.java client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMFilterActivator.java client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/VMFilterActivatorTest.java client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/HostTreeController.java client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/HostTreeControllerTest.java storage/core/src/main/java/com/redhat/thermostat/storage/dao/HostInfoDAO.java storage/core/src/main/java/com/redhat/thermostat/storage/internal/dao/HostInfoDAOImpl.java
diffstat 16 files changed, 445 insertions(+), 99 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/LivingHostFilter.java	Mon Oct 28 16:27:18 2013 +0100
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2012, 2013 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.filter.vm.core;
+
+import com.redhat.thermostat.client.core.vmlist.HostFilter;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+
+public class LivingHostFilter extends HostFilter {
+
+    volatile boolean filterActive = true;
+    
+    private HostInfoDAO dao;
+    
+    public LivingHostFilter(HostInfoDAO dao) {
+        this.dao = dao;
+    }
+    
+    @Override
+    public boolean matches(HostRef ref) {
+        if (!filterActive)
+            return true;
+       return dao.isAlive(ref);
+    }
+
+    public void setActive(boolean active) {
+        boolean oldActive = this.filterActive;
+        this.filterActive = active;
+        if (oldActive != filterActive) {
+            notify(FilterEvent.FILTER_CHANGED);
+        }
+    }
+
+    public boolean isActive() {
+        return filterActive;
+    }
+}
--- a/client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/LivingVMFilter.java	Mon Oct 28 16:27:18 2013 +0100
+++ b/client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/LivingVMFilter.java	Mon Oct 28 16:27:18 2013 +0100
@@ -38,6 +38,7 @@
 
 import com.redhat.thermostat.client.core.vmlist.VMFilter;
 import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
 import com.redhat.thermostat.storage.model.VmInfo;
 
@@ -45,10 +46,12 @@
 
     volatile boolean filterActive = true;
     
-    private VmInfoDAO dao;
+    private VmInfoDAO vmDao;
+    private HostInfoDAO hostDao;
     
-    public LivingVMFilter(VmInfoDAO dao) {
-        this.dao = dao;
+    public LivingVMFilter(VmInfoDAO vmDao, HostInfoDAO hostDao) {
+        this.hostDao = hostDao;
+        this.vmDao = vmDao;
     }
     
     @Override
@@ -56,8 +59,15 @@
         if (!filterActive)
             return true;
 
-        VmInfo vmInfo = dao.getVmInfo(ref);
-        return vmInfo.isAlive();
+        // if the parent host if not alive, we don't want to hide this
+        boolean match = true;
+        
+        if (hostDao.isAlive(ref.getHostRef())) {
+            VmInfo vmInfo = vmDao.getVmInfo(ref);
+            match = vmInfo.isAlive();
+        }
+
+        return match;
     }
 
     public void setActive(boolean active) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingHostFilterMenuAction.java	Mon Oct 28 16:27:18 2013 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012, 2013 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.filter.vm.core.internal;
+
+import com.redhat.thermostat.client.filter.vm.core.LivingHostFilter;
+import com.redhat.thermostat.client.ui.MenuAction;
+import com.redhat.thermostat.shared.locale.LocalizedString;
+import com.redhat.thermostat.shared.locale.Translate;
+
+public class LivingHostFilterMenuAction implements MenuAction {
+
+    private static final Translate<LocaleResources> t = LocaleResources.createLocalizer();
+    private LivingHostFilter filter;
+    
+    public LivingHostFilterMenuAction(LivingHostFilter filter) {
+        this.filter = filter;
+    }
+    
+    @Override
+    public LocalizedString getName() {
+        return t.localize(LocaleResources.SHOW_DEAD_HOST_NAME);
+    }
+
+    @Override
+    public LocalizedString getDescription() {
+        return t.localize(LocaleResources.SHOW_DEAD_HOST_DESC);
+    }
+
+    @Override
+    public void execute() {
+        filter.setActive(!filter.isActive());
+    }
+
+    @Override
+    public Type getType() {
+        return Type.CHECK;
+    }
+
+    @Override
+    public LocalizedString[] getPath() {
+        return new LocalizedString[] { t.localize(LocaleResources.EDIT_MENU), getName() };
+    }
+}
--- a/client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/LocaleResources.java	Mon Oct 28 16:27:18 2013 +0100
+++ b/client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/LocaleResources.java	Mon Oct 28 16:27:18 2013 +0100
@@ -43,6 +43,9 @@
     SHOW_DEAD_VM_NAME,
     SHOW_DEAD_VM_DESC,
 
+    SHOW_DEAD_HOST_NAME,
+    SHOW_DEAD_HOST_DESC,
+    
     EDIT_MENU,
     ;
 
--- a/client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/VMFilterActivator.java	Mon Oct 28 16:27:18 2013 +0100
+++ b/client/living-vm-filter/core/src/main/java/com/redhat/thermostat/client/filter/vm/core/internal/VMFilterActivator.java	Mon Oct 28 16:27:18 2013 +0100
@@ -40,69 +40,83 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 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.vmlist.HostFilter;
 import com.redhat.thermostat.client.core.vmlist.VMFilter;
+import com.redhat.thermostat.client.filter.vm.core.LivingHostFilter;
 import com.redhat.thermostat.client.filter.vm.core.LivingVMFilter;
 import com.redhat.thermostat.client.ui.MenuAction;
+import com.redhat.thermostat.common.MultipleServiceTracker;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
 
 public class VMFilterActivator implements BundleActivator {
 
     @SuppressWarnings("rawtypes")
-    private final List<ServiceRegistration> registeredServices = Collections.synchronizedList(new ArrayList<ServiceRegistration>());
+    private final List<ServiceRegistration> registeredServices =
+        Collections.synchronizedList(new ArrayList<ServiceRegistration>());
 
-    @SuppressWarnings("rawtypes")
-    ServiceTracker vmInfoDaoTracker;
+    private MultipleServiceTracker tracker;
 
-    @SuppressWarnings({ "unchecked", "rawtypes" })
     @Override
-    public void start(BundleContext context) throws Exception {
+    public void start(final BundleContext context) throws Exception {
         
-        vmInfoDaoTracker = new ServiceTracker(context, VmInfoDAO.class.getName(), null) {
+        Class<?> [] services =  new Class<?> [] {
+            VmInfoDAO.class,
+            HostInfoDAO.class,
+        };
+        
+        tracker = new MultipleServiceTracker(context, services, new MultipleServiceTracker.Action() {
             @Override
-            public Object addingService(ServiceReference reference) {
+            public void dependenciesAvailable(Map<String, Object> services) {
+                @SuppressWarnings("rawtypes")
                 ServiceRegistration registration = null;
-
-                VmInfoDAO dao = (VmInfoDAO) context.getService(reference);
+                
+                VmInfoDAO vmDao = (VmInfoDAO) services.get(VmInfoDAO.class.getName());
+                HostInfoDAO hostDao = (HostInfoDAO) services.get(HostInfoDAO.class.getName());
 
-                LivingVMFilter filter = new LivingVMFilter(dao);
-                registration = context.registerService(VMFilter.class.getName(), filter, null);
-                
-                LivingVMFilterMenuAction menu = new LivingVMFilterMenuAction(filter);
-
-                registration = context.registerService(MenuAction.class.getName(), menu, null);
+                LivingHostFilter hostFilter = new LivingHostFilter(hostDao);
+                registration = context.registerService(HostFilter.class.getName(), hostFilter, null);
                 registeredServices.add(registration);
 
-                return super.addingService(reference);
-            }
+                LivingVMFilter vmFilter = new LivingVMFilter(vmDao, hostDao);
+                registration = context.registerService(VMFilter.class.getName(), vmFilter, null);
+                registeredServices.add(registration);
 
+                LivingVMFilterMenuAction vmMenu = new LivingVMFilterMenuAction(vmFilter);
+                registration = context.registerService(MenuAction.class.getName(), vmMenu, null);                
+                registeredServices.add(registration);
+                
+                LivingHostFilterMenuAction hostMenu = new LivingHostFilterMenuAction(hostFilter);
+                registration = context.registerService(MenuAction.class.getName(), hostMenu, null);                
+                registeredServices.add(registration);
+            }
+            
             @Override
-            public void removedService(ServiceReference reference, Object service) {
+            public void dependenciesUnavailable() {
+                @SuppressWarnings("rawtypes")
                 Iterator<ServiceRegistration> iterator = registeredServices.iterator();
                 while(iterator.hasNext()) {
+                    
+                    @SuppressWarnings("rawtypes")
                     ServiceRegistration registration = iterator.next();
                     registration.unregister();
                     iterator.remove();
                 }
-
-                context.ungetService(reference);
-                super.removedService(reference, service);
             }
-        };
-        vmInfoDaoTracker.open();
+        });
+        tracker.open();
     }
     
     @SuppressWarnings("rawtypes")
     @Override
     public void stop(BundleContext context) throws Exception {
-        vmInfoDaoTracker.close();
-        
+        tracker.close();
         for (ServiceRegistration registration : registeredServices) {
             registration.unregister();
         }
--- a/client/living-vm-filter/core/src/main/resources/com/redhat/thermostat/client/filter/vm/core/internal/strings.properties	Mon Oct 28 16:27:18 2013 +0100
+++ b/client/living-vm-filter/core/src/main/resources/com/redhat/thermostat/client/filter/vm/core/internal/strings.properties	Mon Oct 28 16:27:18 2013 +0100
@@ -1,3 +1,5 @@
 SHOW_DEAD_VM_NAME = Show dead VM processes
 SHOW_DEAD_VM_DESC = Includes Java processes that are no longer running in the vm list
+SHOW_DEAD_HOST_NAME = Show unconnected Hosts
+SHOW_DEAD_HOST_DESC = Display data for Host that do not have active agents
 EDIT_MENU = Edit
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/living-vm-filter/core/src/test/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingHostFilterTest.java	Mon Oct 28 16:27:18 2013 +0100
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2012, 2013 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.filter.vm.core.internal;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.client.filter.vm.core.LivingHostFilter;
+import com.redhat.thermostat.storage.core.HostRef;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+
+public class LivingHostFilterTest {
+
+    @Test
+    public void testFilter() {
+        HostInfoDAO hostDao = mock(HostInfoDAO.class);
+        HostRef hostRef1 = mock(HostRef.class);
+        HostRef hostRef2 = mock(HostRef.class);
+
+        when(hostDao.isAlive(hostRef1)).thenReturn(false).thenReturn(false).thenReturn(false);
+        when(hostDao.isAlive(hostRef2)).thenReturn(true).thenReturn(true).thenReturn(true);
+
+        LivingHostFilter filter = new LivingHostFilter(hostDao);
+        LivingHostFilterMenuAction action = new LivingHostFilterMenuAction(filter);
+
+        assertFalse(filter.matches(hostRef1));
+        assertTrue(filter.matches(hostRef2));
+        
+        action.execute();
+
+        assertTrue(filter.matches(hostRef1));
+        assertTrue(filter.matches(hostRef2));
+        
+        action.execute();
+
+        assertFalse(filter.matches(hostRef1));
+        assertTrue(filter.matches(hostRef2));
+    }
+
+}
--- a/client/living-vm-filter/core/src/test/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingVMFilterTest.java	Mon Oct 28 16:27:18 2013 +0100
+++ b/client/living-vm-filter/core/src/test/java/com/redhat/thermostat/client/filter/vm/core/internal/LivingVMFilterTest.java	Mon Oct 28 16:27:18 2013 +0100
@@ -46,31 +46,44 @@
 
 import com.redhat.thermostat.client.filter.vm.core.LivingVMFilter;
 import com.redhat.thermostat.client.filter.vm.core.internal.LivingVMFilterMenuAction;
+import com.redhat.thermostat.storage.core.HostRef;
 import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
 import com.redhat.thermostat.storage.model.VmInfo;
 
 public class LivingVMFilterTest {
 
-    private VmInfoDAO dao;
+    private VmInfoDAO vmDao;
+    private HostInfoDAO hostDao;
+    
     private VmRef vmRef1;
     private VmRef vmRef2;
     
+    private HostRef hostRef;
+    
     private VmInfo vmInfo1;
     private VmInfo vmInfo2;
     
     @Before
     public void setUp() {
-        dao = mock(VmInfoDAO.class);
+        
+        hostDao = mock(HostInfoDAO.class);
+        vmDao = mock(VmInfoDAO.class);
+        
+        hostRef = mock(HostRef.class);
         
         vmRef1 = mock(VmRef.class);
+        when(vmRef1.getHostRef()).thenReturn(hostRef);
+        
         vmRef2 = mock(VmRef.class);
+        when(vmRef2.getHostRef()).thenReturn(hostRef);
         
         vmInfo1 = mock(VmInfo.class);
         vmInfo2 = mock(VmInfo.class);
         
-        when(dao.getVmInfo(vmRef1)).thenReturn(vmInfo1);
-        when(dao.getVmInfo(vmRef2)).thenReturn(vmInfo2);
+        when(vmDao.getVmInfo(vmRef1)).thenReturn(vmInfo1);
+        when(vmDao.getVmInfo(vmRef2)).thenReturn(vmInfo2);
         
         when(vmInfo1.isAlive()).thenReturn(true);
         when(vmInfo2.isAlive()).thenReturn(false);
@@ -78,9 +91,11 @@
     
     @Test
     public void testFilter() {
-        LivingVMFilter filter = new LivingVMFilter(dao);
+        LivingVMFilter filter = new LivingVMFilter(vmDao, hostDao);
         LivingVMFilterMenuAction action = new LivingVMFilterMenuAction(filter);
         
+        when(hostDao.isAlive(hostRef)).thenReturn(true).thenReturn(true);
+        
         assertTrue(filter.matches(vmRef1));
         assertFalse(filter.matches(vmRef2));
         
@@ -88,7 +103,14 @@
         
         assertTrue(filter.matches(vmRef1));
         assertTrue(filter.matches(vmRef2));
+        
+        action.execute();
+        
+        when(hostDao.isAlive(hostRef)).thenReturn(false).thenReturn(false);
+        when(vmInfo1.isAlive()).thenReturn(false);
+
+        assertTrue(filter.matches(vmRef1));
+        assertTrue(filter.matches(vmRef2)); 
     }
-
 }
 
--- a/client/living-vm-filter/core/src/test/java/com/redhat/thermostat/client/filter/vm/core/internal/VMFilterActivatorTest.java	Mon Oct 28 16:27:18 2013 +0100
+++ b/client/living-vm-filter/core/src/test/java/com/redhat/thermostat/client/filter/vm/core/internal/VMFilterActivatorTest.java	Mon Oct 28 16:27:18 2013 +0100
@@ -40,18 +40,15 @@
 import static org.mockito.Mockito.mock;
 
 import org.junit.Test;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
 
-import com.redhat.thermostat.common.Filter;
+import com.redhat.thermostat.client.core.vmlist.HostFilter;
 import com.redhat.thermostat.client.core.vmlist.VMFilter;
+import com.redhat.thermostat.client.filter.vm.core.LivingHostFilter;
 import com.redhat.thermostat.client.filter.vm.core.LivingVMFilter;
-import com.redhat.thermostat.client.filter.vm.core.internal.VMFilterActivator;
 import com.redhat.thermostat.client.ui.MenuAction;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
 import com.redhat.thermostat.testutils.StubBundleContext;
-import com.redhat.thermostat.testutils.StubServiceReference;
-import com.redhat.thermostat.testutils.StubServiceRegistration;
 
 public class VMFilterActivatorTest {
     
@@ -61,13 +58,15 @@
         VMFilterActivator activator = new VMFilterActivator();
         activator.start(ctx);
         
-        VmInfoDAO dao = mock(VmInfoDAO.class);
-        ServiceRegistration reg = ctx.registerService(VmInfoDAO.class, dao, null);
-        ServiceReference ref = reg.getReference();
-        activator.vmInfoDaoTracker.addingService(ref);
+        VmInfoDAO vmDao = mock(VmInfoDAO.class);
+        ctx.registerService(VmInfoDAO.class, vmDao, null);
         
+        HostInfoDAO hostDao = mock(HostInfoDAO.class);
+        ctx.registerService(HostInfoDAO.class, hostDao, null);
+
         assertTrue(ctx.isServiceRegistered(MenuAction.class.getName(), LivingVMFilterMenuAction.class));
         assertTrue(ctx.isServiceRegistered(VMFilter.class.getName(), LivingVMFilter.class));
+        assertTrue(ctx.isServiceRegistered(HostFilter.class.getName(), LivingHostFilter.class));
     }
 
 }
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/LivingVMDecoratorProvider.java	Mon Oct 28 16:27:18 2013 +0100
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/LivingVMDecoratorProvider.java	Mon Oct 28 16:27:18 2013 +0100
@@ -39,12 +39,15 @@
 import java.io.IOException;
 
 import com.redhat.thermostat.common.Filter;
+import com.redhat.thermostat.client.filter.vm.core.LivingVMFilter;
 import com.redhat.thermostat.client.swing.IconResource;
 import com.redhat.thermostat.client.ui.Decorator;
 import com.redhat.thermostat.client.ui.DecoratorProvider;
 import com.redhat.thermostat.client.ui.IconDescriptor;
 import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
+
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -77,9 +80,9 @@
     private com.redhat.thermostat.client.filter.vm.core.LivingVMFilter decoratorFilter;
     private LivingVMDecorator decorator;
     
-    public LivingVMDecoratorProvider(VmInfoDAO dao) {
+    public LivingVMDecoratorProvider(VmInfoDAO vmDao, HostInfoDAO hostDao) {
         decorator = new LivingVMDecorator();
-        decoratorFilter = new com.redhat.thermostat.client.filter.vm.core.LivingVMFilter(dao);
+        decoratorFilter = new LivingVMFilter(vmDao, hostDao);
     }
     
     @Override
--- a/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMFilterActivator.java	Mon Oct 28 16:27:18 2013 +0100
+++ b/client/living-vm-filter/swing/src/main/java/com/redhat/thermostat/client/filter/vm/swing/VMFilterActivator.java	Mon Oct 28 16:27:18 2013 +0100
@@ -42,16 +42,17 @@
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 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.ui.DecoratorProvider;
 import com.redhat.thermostat.common.Constants;
+import com.redhat.thermostat.common.MultipleServiceTracker;
 import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
 
 public class VMFilterActivator implements BundleActivator {
@@ -59,56 +60,58 @@
     @SuppressWarnings("rawtypes")
     private final List<ServiceRegistration> registeredServices = Collections.synchronizedList(new ArrayList<ServiceRegistration>());
 
-    @SuppressWarnings("rawtypes")
-    ServiceTracker vmInfoDaoTracker;
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    @Override
-    public void start(BundleContext context) throws Exception {
-        
-        vmInfoDaoTracker = new ServiceTracker(context, VmInfoDAO.class.getName(), null) {
-            @Override
-            public Object addingService(ServiceReference reference) {
-                ServiceRegistration registration = null;
+    private MultipleServiceTracker tracker;
 
-                VmInfoDAO dao = (VmInfoDAO) context.getService(reference);
-                
-                LivingVMDecoratorProvider decorator = new LivingVMDecoratorProvider(dao);
-                DeadVMDecoratorProvider deadDecorator = new DeadVMDecoratorProvider(dao);
-                
-                Dictionary<String, String> decoratorProperties = new Hashtable<>();
-                decoratorProperties.put(Constants.GENERIC_SERVICE_CLASSNAME, VmRef.class.getName());
-                
-                registration = context.registerService(DecoratorProvider.class.getName(), deadDecorator, decoratorProperties);
-                registeredServices.add(registration);
-
-                registration = context.registerService(DecoratorProvider.class.getName(), decorator, decoratorProperties);
-                registeredServices.add(registration);
-
-                return super.addingService(reference);
-            }
-
+    @SuppressWarnings("rawtypes")
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        
+        Class<?> [] services =  new Class<?> [] {
+                VmInfoDAO.class,
+                HostInfoDAO.class,
+            };
+        
+        tracker = new MultipleServiceTracker(context, services, new MultipleServiceTracker.Action() {
+            
             @Override
-            public void removedService(ServiceReference reference, Object service) {
+            public void dependenciesUnavailable() {
                 Iterator<ServiceRegistration> iterator = registeredServices.iterator();
                 while(iterator.hasNext()) {
                     ServiceRegistration registration = iterator.next();
                     registration.unregister();
                     iterator.remove();
                 }
+            }
+            
+            @Override
+            public void dependenciesAvailable(Map<String, Object> services) {
+                ServiceRegistration registration = null;
 
-                context.ungetService(reference);
-                super.removedService(reference, service);
+                VmInfoDAO vmDao = (VmInfoDAO) services.get(VmInfoDAO.class.getName());
+                HostInfoDAO hostDao = (HostInfoDAO) services.get(HostInfoDAO.class.getName());
+
+                LivingVMDecoratorProvider decorator = new LivingVMDecoratorProvider(vmDao, hostDao);
+                DeadVMDecoratorProvider deadDecorator = new DeadVMDecoratorProvider(vmDao);
+                
+                Dictionary<String, String> decoratorProperties = new Hashtable<>();
+                decoratorProperties.put(Constants.GENERIC_SERVICE_CLASSNAME, VmRef.class.getName());
+                
+                registration = context.registerService(DecoratorProvider.class.getName(),
+                                                       deadDecorator, decoratorProperties);
+                registeredServices.add(registration);
+
+                registration = context.registerService(DecoratorProvider.class.getName(),
+                                                       decorator, decoratorProperties);
+                registeredServices.add(registration);
             }
-        };
-        vmInfoDaoTracker.open();
+        });
+        tracker.open();
     }
     
     @SuppressWarnings("rawtypes")
     @Override
     public void stop(BundleContext context) throws Exception {
-        vmInfoDaoTracker.close();
-        
+        tracker.close();
         for (ServiceRegistration registration : registeredServices) {
             registration.unregister();
         }
--- a/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/VMFilterActivatorTest.java	Mon Oct 28 16:27:18 2013 +0100
+++ b/client/living-vm-filter/swing/src/test/java/com/redhat/thermostat/client/filter/vm/swing/VMFilterActivatorTest.java	Mon Oct 28 16:27:18 2013 +0100
@@ -40,14 +40,11 @@
 import static org.mockito.Mockito.mock;
 
 import org.junit.Test;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
 
 import com.redhat.thermostat.client.ui.DecoratorProvider;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
 import com.redhat.thermostat.storage.dao.VmInfoDAO;
 import com.redhat.thermostat.testutils.StubBundleContext;
-import com.redhat.thermostat.testutils.StubServiceReference;
-import com.redhat.thermostat.testutils.StubServiceRegistration;
 
 public class VMFilterActivatorTest {
     
@@ -57,14 +54,13 @@
         VMFilterActivator activator = new VMFilterActivator();
         activator.start(ctx);
         
-        VmInfoDAO dao = mock(VmInfoDAO.class);
-        ServiceRegistration reg = ctx.registerService(VmInfoDAO.class, dao, null);
-        ServiceReference ref = reg.getReference();
-        activator.vmInfoDaoTracker.addingService(ref);
-        
+        VmInfoDAO vmDao = mock(VmInfoDAO.class);
+        HostInfoDAO hostDao = mock(HostInfoDAO.class);
+       
+        ctx.registerService(VmInfoDAO.class, vmDao, null);
+        ctx.registerService(HostInfoDAO.class, hostDao, null);
+
         assertTrue(ctx.isServiceRegistered(DecoratorProvider.class.getName(), LivingVMDecoratorProvider.class));
         assertTrue(ctx.isServiceRegistered(DecoratorProvider.class.getName(), DeadVMDecoratorProvider.class));
     }
-
 }
-
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/HostTreeController.java	Mon Oct 28 16:27:18 2013 +0100
+++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/HostTreeController.java	Mon Oct 28 16:27:18 2013 +0100
@@ -197,7 +197,17 @@
             @Override
             public void run() {
                 fullModel.addComponent(vm.getHostRef(), vm);
-                if (filter(vmFilters, vm)) {
+                
+                // adding a vm may add an host, so we need to be sure
+                // the host is not filtered before checking the vm itself
+                if (filter(hostFilters, vm.getHostRef())) {
+                    
+                    // this will also remove all the vm, so we can skip the
+                    // next filtering step
+                    proxyModel.removeHeader(vm.getHostRef());
+                    
+                } else
+                    if (filter(vmFilters, vm)) {
                     proxyModel.removeComponent(vm.getHostRef(), vm);
                 }
             }
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/HostTreeControllerTest.java	Mon Oct 28 16:27:18 2013 +0100
+++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/vmlist/controller/HostTreeControllerTest.java	Mon Oct 28 16:27:18 2013 +0100
@@ -59,6 +59,7 @@
 import com.redhat.thermostat.client.swing.internal.vmlist.HostTreeComponentFactory;
 import com.redhat.thermostat.storage.core.HostRef;
 import com.redhat.thermostat.storage.core.VmRef;
+import com.redhat.thermostat.test.Bug;
 
 public class HostTreeControllerTest {
 
@@ -253,4 +254,50 @@
         
         verify(hostDecoratorListener).decorationChanged();
     }
+    
+    @Test
+    public void testFilteredHostFiltersVMToo() {
+        HostTreeController controller =
+                new HostTreeController(accordion, decoratorManager,
+                                       componentFactory);
+        HostRef host0 = new HostRef("0", "0");
+        HostRef host1 = new HostRef("1", "1");
+        
+        VmRef vm0 = new VmRef(host0, "0", 0, "vm0");
+        VmRef vm1 = new VmRef(host1, "1", 1, "vm1");
+        VmRef vm2 = new VmRef(host1, "2", 2, "vm2");
+
+        TestHostFilter filter = new TestHostFilter() {
+            @Override
+            protected boolean matchesImpl(HostRef toMatch) {
+                return (toMatch.getName().equals("0"));
+            }
+        };
+        
+        // enabled the filter
+        filter.toggle();
+
+        controller.registerHost(host0);
+        controller.registerHost(host1);
+        
+        waitForSwing();
+        
+        // filter out host 0, then add the vms
+        controller.addHostFilter(filter);
+        
+        waitForSwing();
+        
+        controller.registerVM(vm0);
+        controller.registerVM(vm1);
+        controller.registerVM(vm2);
+        
+        waitForSwing();
+
+        List<VmRef> components  = proxyModel.getComponents(host0);
+        assertEquals(1, components.size());
+        assertTrue(components.contains(vm0));
+        
+        components  = proxyModel.getComponents(host1);
+        assertEquals(0, components.size());
+    }
 }
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/dao/HostInfoDAO.java	Mon Oct 28 16:27:18 2013 +0100
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/dao/HostInfoDAO.java	Mon Oct 28 16:27:18 2013 +0100
@@ -80,5 +80,11 @@
      * @return A collection of alive hosts which may be empty.
      */
     Collection<HostRef> getAliveHosts();
+    
+    /**
+     * 
+     * @return if this host is alive.
+     */
+    boolean isAlive(HostRef ref);
 }
 
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/dao/HostInfoDAOImpl.java	Mon Oct 28 16:27:18 2013 +0100
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/dao/HostInfoDAOImpl.java	Mon Oct 28 16:27:18 2013 +0100
@@ -214,5 +214,10 @@
         return count;
     }
     
+    @Override
+    public boolean isAlive(HostRef ref) {
+        AgentInformation info = agentInfoDao.getAgentInformation(ref);
+        return (info != null && info.isAlive());
+    }
 }