changeset 406:966e565b1d4b

Fix workflow for HeapView review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-June/001942.html reviewed-by: omajid PR 1033 PR 944
author Mario Torre <neugens.limasoftware@gmail.com>
date Wed, 20 Jun 2012 23:31:53 +0200
parents 2d05f43e292f
children 9fb6f2c51ec0
files client/heapdumper/pom.xml client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/Activator.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumpAction.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumpController.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumperService.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapView.java client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/HeapSwingView.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/ActivatorTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/HeapDumpActionTest.java client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/HeapDumpControllerTest.java
diffstat 10 files changed, 164 insertions(+), 486 deletions(-) [+]
line wrap: on
line diff
--- a/client/heapdumper/pom.xml	Wed Jun 20 16:45:53 2012 -0400
+++ b/client/heapdumper/pom.xml	Wed Jun 20 23:31:53 2012 +0200
@@ -85,6 +85,12 @@
       <scope>provided</scope>
     </dependency>
     <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    
+    <dependency>
       <groupId>com.redhat.thermostat</groupId>
       <artifactId>thermostat-common-core</artifactId>
       <version>${project.version}</version>
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/Activator.java	Wed Jun 20 16:45:53 2012 -0400
+++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/Activator.java	Wed Jun 20 23:31:53 2012 +0200
@@ -38,14 +38,15 @@
 
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceEvent;
-import org.osgi.framework.ServiceListener;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 
+import org.osgi.util.tracker.ServiceTracker;
+
+import com.redhat.thermostat.client.heap.swing.HeapSwingView;
 import com.redhat.thermostat.client.osgi.service.ApplicationService;
-import com.redhat.thermostat.client.osgi.service.ContextAction;
-import com.redhat.thermostat.client.osgi.service.VMContextAction;
+import com.redhat.thermostat.client.osgi.service.VmInformationService;
+import com.redhat.thermostat.common.appctx.ApplicationContext;
 
 public class Activator implements BundleActivator {
 
@@ -54,49 +55,17 @@
     @Override
     public void start(final BundleContext context) throws Exception {
 
-        ServiceListener listener = new ServiceListener() {
-            
-            private ApplicationService appService;
-            private boolean contextActionServiceLoaded;
-            private boolean applicationServiceLoaded;
-            
+        ServiceTracker tracker = new ServiceTracker(context, ApplicationService.class.getName(), null) {
             @Override
-            public void serviceChanged(ServiceEvent event) {
+            public Object addingService(ServiceReference reference) {
+                ApplicationService appService = (ApplicationService) context.getService(reference);
                 
-                ServiceReference reference = event.getServiceReference();
-                Object service = context.getService(reference);
-                switch (event.getType()) {
-                case ServiceEvent.REGISTERED:
-                    if (service instanceof ContextAction) {
-                        contextActionServiceLoaded = true;
-                    } else if (service instanceof ApplicationService) {
-                        applicationServiceLoaded = true;
-                        appService = (ApplicationService) service;
-                    }
-                    break;
-
-                default:
-                    break;
-                }
-                
-                if (contextActionServiceLoaded && applicationServiceLoaded) {
-                    contextServiceReg = context.registerService(VMContextAction.class.getName(),
-                                            new HeapDumpAction(appService.getDAOFactory(), context), null);
-                }
+                ApplicationContext.getInstance().getViewFactory().setViewClass(HeapView.class, HeapSwingView.class);
+                context.registerService(VmInformationService.class.getName(), new HeapDumperService(appService), null);
+                return super.addingService(reference);
             }
         };
-        
-        String filter = "(|(objectClass=" + ContextAction.class.getName() + ")"
-                + "  (objectClass=" + ApplicationService.class.getName() + "))";
-
-        context.addServiceListener(listener, filter);
-        ServiceReference[] services = context.getServiceReferences(null, null);
-        if (services != null) {
-            for (int i = 0; i < services.length; i++) {
-                listener.serviceChanged(new ServiceEvent(
-                        ServiceEvent.REGISTERED, services[i]));
-            }
-        }
+        tracker.open();
     }
 
     @Override
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumpAction.java	Wed Jun 20 16:45:53 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.client.heap;
-
-import java.util.logging.Logger;
-
-import org.osgi.framework.BundleContext;
-
-import com.redhat.thermostat.client.heap.swing.HeapSwingView;
-import com.redhat.thermostat.client.osgi.service.Filter;
-import com.redhat.thermostat.client.osgi.service.VMContextAction;
-import com.redhat.thermostat.client.osgi.service.VmInformationService;
-import com.redhat.thermostat.common.appctx.ApplicationContext;
-import com.redhat.thermostat.common.dao.DAOFactory;
-import com.redhat.thermostat.common.dao.Ref;
-import com.redhat.thermostat.common.dao.VmRef;
-import com.redhat.thermostat.common.model.VmInfo;
-
-/**
- * Implements the {@link VMContextAction} entry point to provide a kill switch
- * for the currently selected Virtual Machine.
- */
-public class HeapDumpAction implements VMContextAction {
-
-    private static final Logger log = Logger.getLogger(HeapDumpAction.class.getName());
-
-    private final DAOFactory dao;
-    private final BundleContext context;
-
-    public HeapDumpAction(DAOFactory dao, BundleContext context) {
-        this.dao = dao;
-        this.context = context;
-    }
-
-    @Override
-    public String getName() {
-        return "Heap Analysis";
-    }
-
-    @Override
-    public String getDescription() {
-        return "Heap View";
-    }
-
-    @Override
-    public void execute(VmRef reference) {
-        ApplicationContext.getInstance().getViewFactory().setViewClass(HeapView.class, HeapSwingView.class);
-        context.registerService(VmInformationService.class.getName(), new HeapDumperService(reference), null);
-    }
-
-    @Override
-    public Filter getFilter() {
-        return new LocalAndAliveFilter();
-    }
-
-    private class LocalAndAliveFilter implements Filter {
-
-        @Override
-        public boolean matches(Ref ref) {
-            // TODO implement local checking too
-            if (ref instanceof VmRef) {
-                VmRef vm = (VmRef) ref;
-                VmInfo vmInfo = dao.getVmInfoDAO().getVmInfo(vm);
-                return vmInfo.isAlive();
-            } else {
-                return false;
-            }
-        }
-
-    }
-}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumpController.java	Wed Jun 20 16:45:53 2012 -0400
+++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumpController.java	Wed Jun 20 23:31:53 2012 +0200
@@ -54,6 +54,7 @@
 
 import com.redhat.thermostat.client.heap.HeapView.HeadDumperAction;
 import com.redhat.thermostat.client.heap.chart.OverviewChart;
+import com.redhat.thermostat.client.osgi.service.ApplicationService;
 import com.redhat.thermostat.client.osgi.service.VmInformationServiceController;
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
@@ -86,9 +87,11 @@
     private final Timer timer;
     
     private OverviewChart model;
+    private ApplicationService appService;
     
-    public HeapDumpController(final VmRef ref) {
+    public HeapDumpController(final VmRef ref, final ApplicationService appService) {
         
+        this.appService = appService;
         this.ref = ref;
         this.vmDao = ApplicationContext.getInstance().getDAOFactory().getVmMemoryStatDAO();
         this.heapDAO = ApplicationContext.getInstance().getDAOFactory().getHeapDAO();
@@ -104,7 +107,7 @@
         timer.setSchedulingType(SchedulingType.FIXED_RATE);
         
         view = ApplicationContext.getInstance().getViewFactory().getView(HeapView.class);
-
+        
         HeapDump dump = null;
         view.clearHeapDumpList();
         Collection<HeapInfo> infos = heapDAO.getAllHeapInfo(ref);
@@ -114,6 +117,13 @@
             view.addHeapDump(dump);
         }
         
+        // check if we were reading some of the dumps
+        dump = (HeapDump) appService.getApplicationCache().getAttribute(ref);
+        if (dump != null && infos.contains(dump.getInfo())) {
+            readAndSetHistogram(dump);
+            view.openDumpView(dump);
+        }
+        
         view.addActionListener(new ActionListener<Action>() {            
             @Override
             public void actionPerformed(ActionEvent<Action> actionEvent) {
@@ -141,15 +151,27 @@
                 case DUMP_REQUESTED:
                     dump = command.execute(ref);
                     view.addHeapDump(dump);
+                    
+                    // also, only if it's the fist dump, we jump there
+                    // it doesn't disrupt the workflow if it's the first dump
+                    if (appService.getApplicationCache().getAttribute(ref) == null) {
+                        analyseDump(dump);
+                    }
+                    
                     break;
                 
                 case ANALYSE:
                     dump = (HeapDump) actionEvent.getPayload();
-                    readAndSetHistogram(dump);
-                    view.openDumpView(dump);
+                    analyseDump(dump);
                     break;
                 }
             }
+            
+            private void analyseDump(HeapDump dump) {
+                readAndSetHistogram(dump);
+                view.openDumpView(dump);
+                appService.getApplicationCache().addAttribute(ref, dump);
+            }
         });
     }
 
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumperService.java	Wed Jun 20 16:45:53 2012 -0400
+++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumperService.java	Wed Jun 20 23:31:53 2012 +0200
@@ -36,25 +36,26 @@
 
 package com.redhat.thermostat.client.heap;
 
+import com.redhat.thermostat.client.osgi.service.ApplicationService;
 import com.redhat.thermostat.client.osgi.service.VmInformationService;
 import com.redhat.thermostat.client.osgi.service.VmInformationServiceController;
 import com.redhat.thermostat.common.dao.VmRef;
 
 public class HeapDumperService implements VmInformationService {
 
-    private VmRef vmRef;
-
-    public HeapDumperService(VmRef reference) {
-        this.vmRef = reference;
+    private ApplicationService appService;
+    
+    public HeapDumperService(ApplicationService appService) {
+        this.appService = appService;
     }
 
     @Override
     public VmInformationServiceController getInformationServiceController(VmRef ref) {
-        return new HeapDumpController(ref);
+        return new HeapDumpController(ref, appService);
     }
 
     @Override
     public boolean isApplicableFor(VmRef ref) {
-        return vmRef.equals(ref);
+        return true;
     }
 }
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapView.java	Wed Jun 20 16:45:53 2012 -0400
+++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapView.java	Wed Jun 20 23:31:53 2012 +0200
@@ -48,7 +48,7 @@
         ANALYSE,
         REQUEST_ABORTED
     }
-    
+   
     protected final ActionNotifier<HeadDumperAction> heapDumperNotifier;
     protected HeapView() {
         heapDumperNotifier = new ActionNotifier<HeadDumperAction>(this);
@@ -61,7 +61,7 @@
     public void removeDumperListener(ActionListener<HeadDumperAction> listener) {
         heapDumperNotifier.removeActionListener(listener);
     }
-        
+
     public abstract E getComponent();
 
     abstract public void updateOverview(OverviewChart model, String used, String capacity);
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/HeapSwingView.java	Wed Jun 20 16:45:53 2012 -0400
+++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/HeapSwingView.java	Wed Jun 20 23:31:53 2012 +0200
@@ -45,7 +45,6 @@
 import javax.swing.BoxLayout;
 import javax.swing.JComponent;
 import javax.swing.JPanel;
-import javax.swing.JTable;
 import javax.swing.SwingUtilities;
 import javax.swing.SwingWorker;
 
@@ -55,9 +54,7 @@
 import com.redhat.thermostat.client.ui.ComponentVisibleListener;
 
 public class HeapSwingView extends HeapView<JComponent> {
-
-    private boolean heapDetailIsShowing;
-    
+        
     private StatsPanel stats;
 
     private HeapPanel heapDetailPanel;
@@ -93,10 +90,8 @@
         stats.addDumpListListener(new MouseAdapter() {
             @Override
             public void mouseClicked(MouseEvent e) {
-                if (e.getClickCount() == 2) { 
-                    HeapDump dump = stats.getSelectedHeapDump();
-                    heapDumperNotifier.fireAction(HeadDumperAction.ANALYSE, dump);
-                }
+                HeapDump dump = stats.getSelectedHeapDump();
+                heapDumperNotifier.fireAction(HeadDumperAction.ANALYSE, dump);
             }
         });
         
@@ -172,22 +167,16 @@
         SwingUtilities.invokeLater(new Runnable() {
             @Override
             public void run() {
-                if (!heapDetailIsShowing) {
-                    visiblePane.removeAll();
-                    
-                    heapDetailIsShowing = true;
-                    
-                    heapDetailPanel.divideView();
-                    heapDetailPanel.setTop(overview);
+                visiblePane.removeAll();                    
+                heapDetailPanel.divideView();
+                heapDetailPanel.setTop(overview);
                     
-                    HistogramPanel histogram = new HistogramPanel();
-                    histogram.display(dump.getHistogram());
-                    heapDetailPanel.setBottom(histogram);
-
-                    visiblePane.add(heapDetailPanel);
-                    
-                    visiblePane.revalidate();                    
-                }
+                HistogramPanel histogram = new HistogramPanel();
+                histogram.display(dump.getHistogram());
+                heapDetailPanel.setBottom(histogram);
+                
+                visiblePane.add(heapDetailPanel);                    
+                visiblePane.revalidate();
             }
         });
     }
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/ActivatorTest.java	Wed Jun 20 16:45:53 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.client.heap;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.Dictionary;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Matchers;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceEvent;
-import org.osgi.framework.ServiceListener;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-
-import com.redhat.thermostat.client.osgi.service.ApplicationService;
-import com.redhat.thermostat.client.osgi.service.ContextAction;
-import com.redhat.thermostat.client.osgi.service.VMContextAction;
-
-public class ActivatorTest {
-
-    private Activator activator;
-    private BundleContext bundleContext;
-    private ArgumentCaptor<ServiceListener> serviceListener;
-    private ServiceReference ref1;
-    private ContextAction service1;
-    private ServiceReference ref2;
-    private ApplicationService service2;
-    private ServiceReference ref3;
-
-    @Before
-    public void setUp() throws InvalidSyntaxException {
-        activator = new Activator();
-        bundleContext = mock(BundleContext.class);
-        serviceListener = ArgumentCaptor.forClass(ServiceListener.class);
-        doNothing().when(bundleContext).addServiceListener(serviceListener.capture(), anyString());
-        ref1 = mock(ServiceReference.class);
-        service1 = mock(ContextAction.class);
-        when(bundleContext.getService(ref1)).thenReturn(service1);
-        ref2 = mock(ServiceReference.class);
-        service2 = mock(ApplicationService.class);
-        when(bundleContext.getService(ref2)).thenReturn(service2);
-        ref3 = mock(ServiceReference.class);
-        when(bundleContext.getService(ref3)).thenReturn(new Object());
-    }
-
-    @Test
-    public void testStart() throws Exception {
-        activator.start(bundleContext);
-        verifyRegistration(false);
-        fireServiceEventAndVerifyRegistration(ServiceEvent.REGISTERED, ref1, false);
-        fireServiceEventAndVerifyRegistration(ServiceEvent.REGISTERED, ref2, true);
-    }
-
-    @Test
-    public void testStartAppServiceFirst() throws Exception {
-        activator.start(bundleContext);
-        verifyRegistration(false);
-        fireServiceEventAndVerifyRegistration(ServiceEvent.REGISTERED, ref2, false);
-        fireServiceEventAndVerifyRegistration(ServiceEvent.REGISTERED, ref1, true);
-    }
-
-    @Test
-    public void testStartOtherService() throws Exception {
-        activator.start(bundleContext);
-        verifyRegistration(false);
-        fireServiceEventAndVerifyRegistration(ServiceEvent.REGISTERED, ref2, false);
-        fireServiceEventAndVerifyRegistration(ServiceEvent.REGISTERED, ref3, false);
-        fireServiceEventAndVerifyRegistration(ServiceEvent.REGISTERED, ref1, true);
-    }
-
-    @Test
-    public void testStartDifferentEventType() throws Exception {
-        activator.start(bundleContext);
-        verifyRegistration(false);
-        fireServiceEventAndVerifyRegistration(ServiceEvent.REGISTERED, ref2, false);
-        fireServiceEventAndVerifyRegistration(ServiceEvent.MODIFIED, ref1, false);
-        fireServiceEventAndVerifyRegistration(ServiceEvent.REGISTERED, ref1, true);
-    }
-
-    @Test
-    public void testStartExistingServices() throws Exception {
-
-        when(bundleContext.getServiceReferences(null, null)).thenReturn(new ServiceReference[] { ref1, ref2 });
-
-        activator.start(bundleContext);
-
-        verifyRegistration(true);
-    }
-
-    @Test
-    public void testStop() throws Exception {
-        ServiceRegistration serviceReg = mock(ServiceRegistration.class);
-        when(bundleContext.registerService(eq(VMContextAction.class.getName()), any(), any(Dictionary.class))).thenReturn(serviceReg);
-        testStart(); // Performs all the registration tasks.
-        verify(serviceReg, never()).unregister();
-        activator.stop(bundleContext);
-        verify(serviceReg).unregister();
-    }
-
-    @Test
-    public void testStopIncompleteRegistration() throws Exception {
-        ServiceRegistration serviceReg = mock(ServiceRegistration.class);
-        when(bundleContext.registerService(eq(VMContextAction.class.getName()), any(), any(Dictionary.class))).thenReturn(serviceReg);
-
-        activator.start(bundleContext);
-        fireServiceEvent(ServiceEvent.REGISTERED, ref2);
-        verify(serviceReg, never()).unregister();
-
-        activator.stop(bundleContext);
-        verify(serviceReg, never()).unregister();
-    }
-
-    private void fireServiceEventAndVerifyRegistration(int type, ServiceReference ref, boolean expectRegisterCalled) {
-        fireServiceEvent(type, ref);
-        verifyRegistration(expectRegisterCalled);
-    }
-
-    private void fireServiceEvent(int type, ServiceReference ref) {
-        ServiceEvent event = new ServiceEvent(type, ref);
-        serviceListener.getValue().serviceChanged(event);
-    }
-
-    private void verifyRegistration(boolean expectRegisterCalled) {
-        if (expectRegisterCalled) {
-            verify(bundleContext).registerService(eq(VMContextAction.class.getName()), Matchers.isA(HeapDumpAction.class), any(Dictionary.class));
-        } else {
-            verify(bundleContext, never()).registerService(anyString(), any(), any(Dictionary.class));
-        }
-    }
-
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/HeapDumpActionTest.java	Wed Jun 20 16:45:53 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.client.heap;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.osgi.framework.BundleContext;
-
-import com.redhat.thermostat.client.osgi.service.Filter;
-import com.redhat.thermostat.common.dao.DAOFactory;
-import com.redhat.thermostat.common.dao.Ref;
-import com.redhat.thermostat.common.dao.VmInfoDAO;
-import com.redhat.thermostat.common.dao.VmRef;
-import com.redhat.thermostat.common.model.VmInfo;
-
-public class HeapDumpActionTest {
-
-    private HeapDumpAction heapDumpAction;
-    private DAOFactory dao;
-    private VmRef aliveVmRef;
-    private VmRef deadVmRef;
-
-    @Before
-    public void setUp() {
-        dao = mock(DAOFactory.class);
-        VmInfoDAO vmInfoDAO = mock(VmInfoDAO.class);
-        when(dao.getVmInfoDAO()).thenReturn(vmInfoDAO);
-
-        VmInfo vmInfo1 = mock(VmInfo.class);
-        when(vmInfo1.isAlive()).thenReturn(true);
-        aliveVmRef = mock(VmRef.class);
-        when(vmInfoDAO.getVmInfo(aliveVmRef)).thenReturn(vmInfo1);
-
-        VmInfo vmInfo2 = mock(VmInfo.class);
-        when(vmInfo2.isAlive()).thenReturn(false);
-        deadVmRef = mock(VmRef.class);
-        when(vmInfoDAO.getVmInfo(deadVmRef)).thenReturn(vmInfo2);
-
-        
-        BundleContext bundleContext = mock(BundleContext.class);
-        heapDumpAction = new HeapDumpAction(dao, bundleContext);
-    }
-
-    @After
-    public void tearDown() {
-        heapDumpAction = null;
-        deadVmRef = null;
-        aliveVmRef = null;
-        dao = null;
-    }
-
-    @Test
-    public void testName() {
-        assertEquals("Heap Analysis", heapDumpAction.getName());
-    }
-
-    @Test
-    public void testDescription() {
-        assertEquals("Heap View", heapDumpAction.getDescription());
-    }
-
-    @Test
-    public void testFilter() {
-        Filter filter = heapDumpAction.getFilter();
-        assertTrue(filter.matches(aliveVmRef));
-        assertFalse(filter.matches(deadVmRef));
-        assertFalse(filter.matches(mock(Ref.class)));
-    }
-
-    @Test
-    public void testExec() throws IOException {
-        // TODO: Not tested yet. We cannot mock Runtime.exec(), not even with PowerMock.
-        // We should create a wrapper API (that needs to remain untested, and for this
-        // reason should be *really* dumb), against which we can test.
-    }
-}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/HeapDumpControllerTest.java	Wed Jun 20 16:45:53 2012 -0400
+++ b/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/HeapDumpControllerTest.java	Wed Jun 20 23:31:53 2012 +0200
@@ -43,8 +43,10 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.times;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
 import javax.swing.JComponent;
@@ -54,7 +56,10 @@
 import org.junit.Test;
 
 import org.mockito.ArgumentCaptor;
+import org.mockito.internal.verification.Times;
 
+import com.redhat.thermostat.client.osgi.service.ApplicationCache;
+import com.redhat.thermostat.client.osgi.service.ApplicationService;
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
 import com.redhat.thermostat.common.Timer;
@@ -67,6 +72,7 @@
 import com.redhat.thermostat.common.dao.MongoDAOFactory;
 import com.redhat.thermostat.common.dao.VmClassStatDAO;
 import com.redhat.thermostat.common.dao.VmRef;
+import com.redhat.thermostat.common.model.HeapInfo;
 import com.redhat.thermostat.common.model.VmClassStat;
 
 public class HeapDumpControllerTest {
@@ -76,9 +82,11 @@
     
     private Timer timer;
     
+    private HeapDAO heapDao;
     private HeapView<JComponent> view;
     
     private HeapDumpController controller;
+    private ApplicationService appService;
     
     @Before
     public void setUp() {
@@ -88,15 +96,13 @@
         DAOFactory daoFactory = mock(MongoDAOFactory.class);
         when(daoFactory.getVmClassStatsDAO()).thenReturn(vmClassStatDAO);
         
-        HeapDAO heapDao = mock(HeapDAO.class);
+        heapDao = mock(HeapDAO.class);
         when(daoFactory.getHeapDAO()).thenReturn(heapDao);
         
         ApplicationContext.getInstance().setDAOFactory(daoFactory);
 
         setUpTimers();
         setUpView();
-
-        setUpListeners();
     }
     
     private void setUpTimers() {
@@ -118,32 +124,118 @@
         ApplicationContext.getInstance().setViewFactory(viewFactory);
     }
     
-    private void setUpListeners() {
+    private void setUpListeners() {        
         ArgumentCaptor<ActionListener> viewArgumentCaptor1 = ArgumentCaptor.forClass(ActionListener.class);
         doNothing().when(view).addActionListener(viewArgumentCaptor1.capture());
         
         ArgumentCaptor<ActionListener> viewArgumentCaptor2 = ArgumentCaptor.forClass(ActionListener.class);
         doNothing().when(view).addDumperListener(viewArgumentCaptor2.capture());
-
-        VmRef ref = mock(VmRef.class); 
-        controller = new HeapDumpController(ref);
+        
+        createController();
         
         actionListener = viewArgumentCaptor1.getValue();
         heapDumperListener = viewArgumentCaptor2.getValue();
     }
     
+    private void createController() {
+        ApplicationCache cache = mock(ApplicationCache.class);
+        appService = mock(ApplicationService.class);
+        when(appService.getApplicationCache()).thenReturn(cache);
+        VmRef ref = mock(VmRef.class); 
+        controller = new HeapDumpController(ref, appService);
+    }
+    
     @Test
     public void testTimerStartOnViewVisible() {
+        
+        setUpListeners();
+
         actionListener.actionPerformed(new ActionEvent<>(view, HeapView.Action.VISIBLE));
         verify(timer).start();
     }
 
     @Test
     public void testTimerStopsOnViewHidden() {
+        
+        setUpListeners();
+        
         actionListener.actionPerformed(new ActionEvent<>(view, HeapView.Action.HIDDEN));
         verify(timer).stop();
     }
     
+    @Test
+    public void testNotAddHeapDumpsAtStartupWhenNoDumps() {
+                
+        when(heapDao.getAllHeapInfo(any(VmRef.class))).thenReturn(new ArrayList<HeapInfo>());
+        
+        createController();
+        
+        verify(view, times(0)).addHeapDump(any(HeapDump.class));
+    }
+    
+    @Test
+    public void testAddHeapDumpsAtStartupWhenDumpsAreThere() {
+        HeapInfo info1 = mock(HeapInfo.class);
+        HeapInfo info2 = mock(HeapInfo.class);
+        Collection<HeapInfo> infos = new ArrayList<HeapInfo>();
+        infos.add(info1);
+        infos.add(info2);
+        
+        when(heapDao.getAllHeapInfo(any(VmRef.class))).thenReturn(infos);
+        
+        createController();
+        
+        verify(view, times(2)).addHeapDump(any(HeapDump.class));
+    }
+    
+    @Test
+    public void testOpenDumpCalledWhenPreviousDump() {
+        
+        HeapDump dump = mock(HeapDump.class);
+        
+        HeapInfo info1 = mock(HeapInfo.class);
+        when(dump.getInfo()).thenReturn(info1);
+        
+        HeapInfo info2 = mock(HeapInfo.class);
+        Collection<HeapInfo> infos = new ArrayList<HeapInfo>();
+        infos.add(info1);
+        infos.add(info2);
+        
+        when(heapDao.getAllHeapInfo(any(VmRef.class))).thenReturn(infos);
+        
+        ApplicationCache cache = mock(ApplicationCache.class);
+        when(cache.getAttribute(any(VmRef.class))).thenReturn(dump);
+        
+        appService = mock(ApplicationService.class);
+        when(appService.getApplicationCache()).thenReturn(cache);
+        VmRef ref = mock(VmRef.class);
+        controller = new HeapDumpController(ref, appService);
+        
+        verify(view, times(1)).openDumpView(dump);
+    }
+    
+    @Test
+    public void testNotOpenDumpCalledWhenNoPreviousDump() {
+                
+        HeapInfo info1 = mock(HeapInfo.class);        
+        HeapInfo info2 = mock(HeapInfo.class);
+        Collection<HeapInfo> infos = new ArrayList<HeapInfo>();
+        infos.add(info1);
+        infos.add(info2);
+        
+        when(heapDao.getAllHeapInfo(any(VmRef.class))).thenReturn(infos);
+        
+        ApplicationCache cache = mock(ApplicationCache.class);
+        when(cache.getAttribute(any(VmRef.class))).thenReturn(null);
+        
+        appService = mock(ApplicationService.class);
+        when(appService.getApplicationCache()).thenReturn(cache);
+        VmRef ref = mock(VmRef.class);
+        controller = new HeapDumpController(ref, appService);
+        
+        verify(view, times(0)).openDumpView(any(HeapDump.class));
+    }
+        
     @After
     public void tearDown() {
         ApplicationContextUtil.resetApplicationContext();