Mercurial > hg > release > thermostat-1.0
changeset 380:adbe46431675
Preliminary heap dumper view
reviewed-by: rkennke
review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-June/001857.html
PR 944
PR 1033
line wrap: on
line diff
--- a/client/core/src/main/java/com/redhat/thermostat/client/internal/MainWindowControllerImpl.java Mon Jun 18 16:17:37 2012 +0200 +++ b/client/core/src/main/java/com/redhat/thermostat/client/internal/MainWindowControllerImpl.java Mon Jun 18 17:04:47 2012 +0200 @@ -167,7 +167,18 @@ } }; }; - + + private VMInformationRegistry vmInfoRegistry; + private ActionListener<ThermostatExtensionRegistry.Action> vmInfoRegistryListener = + new ActionListener<ThermostatExtensionRegistry.Action> () + { + public void actionPerformed(com.redhat.thermostat.common.ActionEvent<ThermostatExtensionRegistry.Action> + actionEvent) + { + updateView(); + }; + }; + private boolean showHistory; private VmInformationControllerProvider vmInfoControllerProvider; @@ -178,6 +189,7 @@ filterRegistry = registryFactory.createVMTreeFilterRegistry(); decoratorRegistry = registryFactory.createVMTreeDecoratorRegistry(); menuRegistry = registryFactory.createMenuRegistry(); + vmInfoRegistry = registryFactory.createVMInformationRegistry(); } catch (InvalidSyntaxException e) { throw new RuntimeException(e); @@ -214,6 +226,9 @@ decoratorRegistry.addActionListener(decoratorListener); decoratorRegistry.start(); + + vmInfoRegistry.addActionListener(vmInfoRegistryListener); + vmInfoRegistry.start(); } private class HostsVMsLoaderImpl implements HostsVMsLoader {
--- a/client/core/src/main/java/com/redhat/thermostat/client/internal/RegistryFactory.java Mon Jun 18 16:17:37 2012 +0200 +++ b/client/core/src/main/java/com/redhat/thermostat/client/internal/RegistryFactory.java Mon Jun 18 17:04:47 2012 +0200 @@ -57,4 +57,8 @@ MenuRegistry createMenuRegistry() throws InvalidSyntaxException { return new MenuRegistry(context); } + + VMInformationRegistry createVMInformationRegistry() throws InvalidSyntaxException { + return new VMInformationRegistry(context); + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/core/src/main/java/com/redhat/thermostat/client/internal/VMInformationRegistry.java Mon Jun 18 17:04:47 2012 +0200 @@ -0,0 +1,52 @@ +/* + * 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.internal; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.InvalidSyntaxException; + +import com.redhat.thermostat.client.osgi.service.VmInformationService; + +class VMInformationRegistry extends ThermostatExtensionRegistry<VmInformationService> { + + private static final String FILTER = "(&(" + Constants.OBJECTCLASS + "=" + VmInformationService.class.getName() + "))"; + + public VMInformationRegistry(BundleContext context) throws InvalidSyntaxException { + super(context, FILTER, VmInformationService.class); + } +}
--- a/client/core/src/test/java/com/redhat/thermostat/client/internal/MainWindowControllerImplTest.java Mon Jun 18 16:17:37 2012 +0200 +++ b/client/core/src/test/java/com/redhat/thermostat/client/internal/MainWindowControllerImplTest.java Mon Jun 18 17:04:47 2012 +0200 @@ -118,6 +118,7 @@ private VMTreeFilterRegistry filters; private VMTreeDecoratorRegistry decorators; + private VMInformationRegistry vmInfoRegistry; private MenuRegistry menues; private ActionListener<ThermostatExtensionRegistry.Action> filtersListener; @@ -155,11 +156,13 @@ RegistryFactory registryFactory = mock(RegistryFactory.class); filters = mock(VMTreeFilterRegistry.class); decorators = mock(VMTreeDecoratorRegistry.class); + vmInfoRegistry = mock(VMInformationRegistry.class); menues = mock(MenuRegistry.class); when(registryFactory.createMenuRegistry()).thenReturn(menues); when(registryFactory.createVMTreeDecoratorRegistry()).thenReturn(decorators); when(registryFactory.createVMTreeFilterRegistry()).thenReturn(filters); + when(registryFactory.createVMInformationRegistry()).thenReturn(vmInfoRegistry); ArgumentCaptor<ActionListener> grabFiltersListener = ArgumentCaptor.forClass(ActionListener.class); doNothing().when(filters).addActionListener(grabFiltersListener.capture()); @@ -167,6 +170,9 @@ ArgumentCaptor<ActionListener> grabDecoratorsListener = ArgumentCaptor.forClass(ActionListener.class); doNothing().when(decorators).addActionListener(grabDecoratorsListener.capture()); + ArgumentCaptor<ActionListener> grabInfoRegistry = ArgumentCaptor.forClass(ActionListener.class); + doNothing().when(vmInfoRegistry).addActionListener(grabInfoRegistry.capture()); + // TODO remove this asap. the main window has a hard dependency on summary controller/view ViewFactory viewFactory = mock(ViewFactory.class); SummaryView summaryView = mock(SummaryView.class);
--- a/client/heapdumper/pom.xml Mon Jun 18 16:17:37 2012 +0200 +++ b/client/heapdumper/pom.xml Mon Jun 18 17:04:47 2012 +0200 @@ -57,7 +57,11 @@ <instructions> <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor> <Bundle-Activator>com.redhat.thermostat.client.heap.Activator</Bundle-Activator> - <Private-Package>com.redhat.thermostat.client.heap</Private-Package> + <Private-Package> + com.redhat.thermostat.client.heap, + com.redhat.thermostat.client.heap.swing, + com.redhat.thermostat.client.heap.chart + </Private-Package> </instructions> </configuration> </plugin> @@ -92,5 +96,11 @@ <version>${project.version}</version> <type>bundle</type> </dependency> + + <dependency> + <groupId>org.jfree</groupId> + <artifactId>jfreechart</artifactId> + </dependency> + </dependencies> </project>
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/Activator.java Mon Jun 18 16:17:37 2012 +0200 +++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/Activator.java Mon Jun 18 17:04:47 2012 +0200 @@ -54,7 +54,6 @@ @Override public void start(final BundleContext context) throws Exception { - // FIXME: there should be a better way than this ServiceListener listener = new ServiceListener() { private ApplicationService appService; @@ -82,7 +81,7 @@ if (contextActionServiceLoaded && applicationServiceLoaded) { contextServiceReg = context.registerService(VMContextAction.class.getName(), - new HeapDumpAction(appService.getDAOFactory()), null); + new HeapDumpAction(appService.getDAOFactory(), context), null); } } };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDump.java Mon Jun 18 17:04:47 2012 +0200 @@ -0,0 +1,66 @@ +/* + * 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.Date; + +public class HeapDump { + + private String name; + private Date timestamp; + + void setTimestamp(long currentTimeMillis) { + this.timestamp = new Date(currentTimeMillis); + } + + void setVMName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public Date getTimestamp() { + return timestamp; + } + + @Override + public String toString() { + return "[" + getTimestamp() +"] "; + } +}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumpAction.java Mon Jun 18 16:17:37 2012 +0200 +++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumpAction.java Mon Jun 18 17:04:47 2012 +0200 @@ -36,21 +36,18 @@ package com.redhat.thermostat.client.heap; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.file.Files; -import java.util.logging.Level; 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.HeapDAO; import com.redhat.thermostat.common.dao.Ref; import com.redhat.thermostat.common.dao.VmRef; -import com.redhat.thermostat.common.model.HeapInfo; import com.redhat.thermostat.common.model.VmInfo; /** @@ -62,37 +59,27 @@ private static final Logger log = Logger.getLogger(HeapDumpAction.class.getName()); private final DAOFactory dao; + private final BundleContext context; - public HeapDumpAction(DAOFactory dao) { + public HeapDumpAction(DAOFactory dao, BundleContext context) { this.dao = dao; + this.context = context; } @Override public String getName() { - return "Heap Dump"; + return "Heap Analysis"; } @Override public String getDescription() { - return "Generate a heap dump"; + return "Heap View"; } @Override public void execute(VmRef reference) { - try { - File tempFile = Files.createTempFile("thermostat-", "-heapdump").toFile(); - String tempFileName = tempFile.getAbsolutePath(); - tempFile.delete(); // Need to delete before dumping heap, jmap does not override existing file and stop with an error. - Process proc = Runtime.getRuntime().exec(new String[] {"jmap", "-dump:format=b,file=" + tempFileName, reference.getIdString()}); - try { - proc.waitFor(); - log.info("Heap dump written to: " + tempFileName); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } catch (IOException e) { - log.log(Level.SEVERE, "Unexpected IO problem while writing heap dump", e); - } + ApplicationContext.getInstance().getViewFactory().setViewClass(HeapView.class, HeapSwingView.class); + context.registerService(VmInformationService.class.getName(), new HeapDumperService(), null); } @Override
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumpController.java Mon Jun 18 17:04:47 2012 +0200 @@ -0,0 +1,169 @@ +/* + * 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.awt.Component; +import javax.swing.JComponent; + +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import com.redhat.thermostat.client.heap.HeapView.HeadDumperAction; +import com.redhat.thermostat.client.heap.chart.OverviewChart; +import com.redhat.thermostat.client.osgi.service.VmInformationServiceController; +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.NotImplementedException; +import com.redhat.thermostat.common.Timer; +import com.redhat.thermostat.common.BasicView.Action; +import com.redhat.thermostat.common.Timer.SchedulingType; +import com.redhat.thermostat.common.appctx.ApplicationContext; +import com.redhat.thermostat.common.dao.VmMemoryStatDAO; +import com.redhat.thermostat.common.dao.VmRef; +import com.redhat.thermostat.common.model.VmMemoryStat; +import com.redhat.thermostat.common.model.VmMemoryStat.Generation; +import com.redhat.thermostat.common.model.VmMemoryStat.Space; +import com.redhat.thermostat.common.utils.DisplayableValues; +import com.redhat.thermostat.common.utils.DisplayableValues.Scale; + +public class HeapDumpController implements VmInformationServiceController { + + private final VmMemoryStatDAO vmDao; + private final VmRef ref; + + private HeapView<JComponent> view; + private final Timer timer; + + private OverviewChart model; + + public HeapDumpController(final VmRef ref) { + + this.ref = ref; + this.vmDao = ApplicationContext.getInstance().getDAOFactory().getVmMemoryStatDAO(); + + model = new OverviewChart("Heap Used vs. Current Capacity Difference", "Time", "Heap"); + + timer = ApplicationContext.getInstance().getTimerFactory().createTimer(); + timer.setAction(new HeapOverviewDataCollector()); + + timer.setInitialDelay(0); + timer.setDelay(1000); + timer.setTimeUnit(TimeUnit.MILLISECONDS); + timer.setSchedulingType(SchedulingType.FIXED_RATE); + + view = ApplicationContext.getInstance().getViewFactory().getView(HeapView.class); + view.addActionListener(new ActionListener<Action>() { + @Override + public void actionPerformed(ActionEvent<Action> actionEvent) { + switch (actionEvent.getActionId()) { + case HIDDEN: + timer.stop(); + break; + + case VISIBLE: + timer.start(); + break; + + default: + throw new NotImplementedException("unknown event: " + actionEvent.getActionId()); + } + } + }); + + final HeapDumperCommand command = new HeapDumperCommand(); + view.addDumperListener(new ActionListener<HeapView.HeadDumperAction>() { + @Override + public void actionPerformed(ActionEvent<HeadDumperAction> actionEvent) { + HeapDump dump = command.execute(ref); + view.addHeapDump(dump); + } + }); + } + + @Override + public Component getComponent() { + return view.getComponent(); + } + + @Override + public String getLocalizedName() { + return "Memory Analyzer"; + } + + class HeapOverviewDataCollector implements Runnable { + @Override + public void run() { + long used = 0l; + long capacity = 0l; + long max = 0l; + + List<VmMemoryStat> vmInfo = vmDao.getLatestVmMemoryStats(ref); + for (VmMemoryStat memoryStats: vmInfo) { + List<Generation> generations = memoryStats.getGenerations(); + for (Generation generation : generations) { + + // non heap + if (generation.name.equals("perm")) { + continue; + } + + List<Space> spaces = generation.spaces; + for (Space space: spaces) { + used += space.used; + capacity += space.capacity; + + // TODO + max =+ space.maxCapacity; + } + } + model.addData(memoryStats.getTimeStamp(), used, capacity); + + NumberFormat formatter = DecimalFormat.getInstance(); + + double res = Scale.convertTo(Scale.B, used); + String _used = formatter.format(res) + " " + Scale.B; + + res = Scale.convertTo(Scale.B, capacity); + String _capacity= formatter.format(capacity) + " " + Scale.B; + + view.updateOverview(model, _used, _capacity); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumperCommand.java Mon Jun 18 17:04:47 2012 +0200 @@ -0,0 +1,76 @@ +/* + * 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.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.redhat.thermostat.common.dao.VmRef; + +public class HeapDumperCommand { + + private static final Logger log = Logger.getLogger(HeapDumpAction.class.getName()); + + public HeapDump execute(VmRef reference) { + try { + File tempFile = Files.createTempFile("thermostat-", "-heapdump").toFile(); + String tempFileName = tempFile.getAbsolutePath(); + tempFile.delete(); // Need to delete before dumping heap, jmap does not override existing file and stop with an error. + Process proc = Runtime.getRuntime().exec(new String[] {"jmap", "-dump:format=b,file=" + tempFileName, reference.getIdString()}); + try { + proc.waitFor(); + log.info("Heap dump written to: " + tempFileName); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + + HeapDump dump = new HeapDump(); + dump.setTimestamp(System.currentTimeMillis()); + dump.setVMName(reference.getName()); + + return dump; + + } catch (IOException e) { + + log.log(Level.SEVERE, "Unexpected IO problem while writing heap dump", e); + return null; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapDumperService.java Mon Jun 18 17:04:47 2012 +0200 @@ -0,0 +1,49 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.client.heap; + +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 { + + @Override + public VmInformationServiceController getInformationServiceController(VmRef ref) { + return new HeapDumpController(ref); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/HeapView.java Mon Jun 18 17:04:47 2012 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.client.heap; + +import com.redhat.thermostat.client.heap.chart.OverviewChart; +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.ActionNotifier; +import com.redhat.thermostat.common.BasicView; +import com.redhat.thermostat.common.BasicView.Action; + +public abstract class HeapView<E> extends BasicView { + + public enum HeadDumperAction { + DUMP_REQUESTED, + REQUEST_ABORTED + } + + protected final ActionNotifier<HeadDumperAction> heapDumperNotifier; + protected HeapView() { + heapDumperNotifier = new ActionNotifier<HeadDumperAction>(this); + } + + public void addDumperListener(ActionListener<HeadDumperAction> listener) { + heapDumperNotifier.addActionListener(listener); + } + + public void removeDumperListener(ActionListener<HeadDumperAction> listener) { + heapDumperNotifier.removeActionListener(listener); + } + + public abstract E getComponent(); + + abstract public void updateOverview(OverviewChart model, String used, String capacity); + abstract public void addHeapDump(HeapDump dump); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/chart/Chart.java Mon Jun 18 17:04:47 2012 +0200 @@ -0,0 +1,58 @@ +/* + * 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.chart; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; + +import org.jfree.chart.JFreeChart; + +public abstract class Chart { + + public BufferedImage getChart(int width, int height, Color bgColor) { + JFreeChart chart = createChart(width, height, bgColor); + + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + chart.draw((Graphics2D) image.getGraphics(), new Rectangle2D.Double(0, 0, width, height), null); + + return image; + } + + protected abstract JFreeChart createChart(int width, int height, Color bgColor); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/chart/OverviewChart.java Mon Jun 18 17:04:47 2012 +0200 @@ -0,0 +1,132 @@ +/* + * 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.chart; + +import java.awt.Color; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.util.Date; + +import javax.swing.plaf.ColorUIResource; + +import org.jfree.chart.ChartFactory; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.DateAxis; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.renderer.xy.XYDifferenceRenderer; +import org.jfree.data.time.Millisecond; +import org.jfree.data.time.TimeSeries; +import org.jfree.data.time.TimeSeriesCollection; + +public class OverviewChart extends Chart { + + private static final ColorUIResource MAIN_BAR_BASE_COLOR = new ColorUIResource(0x4A90D9); + + + private TimeSeries total; + private TimeSeries used; + private String title; + private String xAxis; + private String yAxis; + + public OverviewChart(String title, String xAxis, String yAxis) { + + this.title = title; + this.xAxis = xAxis; + this.yAxis = yAxis; + + total = new TimeSeries(""); + total.setDescription("total"); + used = new TimeSeries(""); + used.setDescription("used"); + } + + @Override + protected JFreeChart createChart(int width, int height, Color bgColor) { + + TimeSeriesCollection dataset = new TimeSeriesCollection(); + dataset.addSeries(total); + dataset.addSeries(used); + + JFreeChart chart = ChartFactory.createTimeSeriesChart( + title, + xAxis, + yAxis, + dataset, + false, // legend + false, // tool tips + false // URLs + ); + + Paint paint = new GradientPaint(0, 0, MAIN_BAR_BASE_COLOR, 0, height, bgColor); + Paint paint2 = new GradientPaint(0, 0, Color.GREEN, 0, height, bgColor); + + XYPlot plot = (XYPlot) chart.getPlot(); + plot.setDomainPannable(true); + XYDifferenceRenderer r = new XYDifferenceRenderer(paint, paint2, false); + r.setRoundXCoordinates(true); + plot.setDomainCrosshairLockedOnData(true); + plot.setRangeCrosshairLockedOnData(true); + plot.setDomainCrosshairVisible(true); + plot.setRangeCrosshairVisible(true); + plot.setRenderer(r); + + ValueAxis domainAxis = new DateAxis(xAxis); + domainAxis.setLowerMargin(0.0); + domainAxis.setUpperMargin(0.0); + plot.setDomainAxis(domainAxis); + plot.setForegroundAlpha(0.5f); + + return chart; + } + + public void addData(long timeStamp, long used, long total) { + Millisecond millisecond = new Millisecond(new Date(timeStamp)); + if (this.total.getValue(millisecond) == null) { + this.total.add(millisecond, total); + this.total.removeAgedItems(true); + } + if (this.used.getValue(millisecond) == null) { + this.used.add(millisecond, used); + this.used.removeAgedItems(true); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/ChartPanel.java Mon Jun 18 17:04:47 2012 +0200 @@ -0,0 +1,59 @@ +/* + * 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.swing; + +import java.awt.Graphics; +import java.awt.image.BufferedImage; + +import javax.swing.JPanel; + +import com.redhat.thermostat.client.heap.chart.Chart; + +public class ChartPanel extends JPanel { + + private Chart chart; + + public ChartPanel(Chart chart) { + this.chart = chart; + } + + @Override + protected void paintComponent(Graphics g) { + BufferedImage image = chart.getChart(getWidth(), getHeight(), getBackground()); + g.drawImage(image, 0, 0, null); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/HeaderPanel.java Mon Jun 18 17:04:47 2012 +0200 @@ -0,0 +1,146 @@ +/* + * 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.swing; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.lang.reflect.InvocationTargetException; + +import javax.swing.BoxLayout; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.GroupLayout; +import javax.swing.GroupLayout.Alignment; +import javax.swing.LayoutStyle.ComponentPlacement; +import javax.swing.SwingUtilities; + +import sun.swing.SwingUtilities2; + +/** + * A component that hot a panel + */ +public class HeaderPanel extends JPanel { + + private String header; + private boolean open; + + private JPanel contentPanel; + + public HeaderPanel(String header) { + this(); + this.header = header; + } + + public HeaderPanel() { + + this.open = true; + + JPanel headerPanel = new TopPanel(); + + contentPanel = new JPanel(); + contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.X_AXIS)); + + GroupLayout groupLayout = new GroupLayout(this); + groupLayout.setHorizontalGroup( + groupLayout.createParallelGroup(Alignment.LEADING) + .addComponent(headerPanel, GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE) + .addComponent(contentPanel, GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE) + ); + groupLayout.setVerticalGroup( + groupLayout.createParallelGroup(Alignment.LEADING) + .addGroup(groupLayout.createSequentialGroup() + .addComponent(headerPanel, GroupLayout.PREFERRED_SIZE, 30, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(contentPanel, GroupLayout.DEFAULT_SIZE, 260, Short.MAX_VALUE)) + ); + setLayout(groupLayout); + } + + public String getHeader() { + return header; + } + + public void setHeader(String header) { + this.header = header; + } + + public void setContent(JComponent content) { + contentPanel.removeAll(); + contentPanel.add(content); + contentPanel.revalidate(); + repaint(); + } + + @SuppressWarnings({ "restriction", "serial" }) + private class TopPanel extends JPanel { + @Override + protected void paintComponent(Graphics g) { + + Graphics2D graphics = (Graphics2D) g.create(); + + graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + graphics.setColor(getForeground()); + graphics.drawRect(0, 0, getWidth() - 1, getHeight() - 1); + + if (header != null) { + int currentHeight = getHeight(); + int height = SwingUtilities2.getFontMetrics(this, getFont()).getAscent()/2 + currentHeight/2 - 1; + SwingUtilities2.drawString(this, graphics, header, 5, height); + } + + graphics.dispose(); + } + } + + public static void main(String[] args) throws InvocationTargetException, InterruptedException { + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + JFrame frame = new JFrame(); + HeaderPanel header = new HeaderPanel(); + header.setHeader("Test"); + frame.add(header); + frame.setSize(500, 500); + frame.setVisible(true); + } + }); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/HeapPanel.java Mon Jun 18 17:04:47 2012 +0200 @@ -0,0 +1,87 @@ +/* + * 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.swing; + +import java.awt.Dimension; + +import javax.swing.JPanel; +import javax.swing.JSplitPane; +import javax.swing.GroupLayout; +import javax.swing.GroupLayout.Alignment; + +public class HeapPanel extends JPanel { + + private JSplitPane splitPane; + + public HeapPanel() { + + splitPane = new JSplitPane(); + splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT); + GroupLayout groupLayout = new GroupLayout(this); + groupLayout.setHorizontalGroup( + groupLayout.createParallelGroup(Alignment.LEADING) + .addComponent(splitPane, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 450, Short.MAX_VALUE) + ); + groupLayout.setVerticalGroup( + groupLayout.createParallelGroup(Alignment.LEADING) + .addGroup(groupLayout.createSequentialGroup() + .addGap(5) + .addComponent(splitPane, GroupLayout.DEFAULT_SIZE, 295, Short.MAX_VALUE)) + ); + + splitPane.setOneTouchExpandable(true); + setLayout(groupLayout); + } + + void hideBottom() { + splitPane.getBottomComponent().setMinimumSize(new Dimension(0, 0)); + splitPane.setDividerLocation(1.0d); + } + + void hideTop() { + splitPane.getTopComponent().setMinimumSize(new Dimension(0, 0)); + splitPane.setDividerLocation(0.0d); + } + + void setTop(JPanel panel) { + splitPane.setTopComponent(panel); + } + + void setBottom(JPanel panel) { + splitPane.setBottomComponent(panel); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/HeapSwingView.java Mon Jun 18 17:04:47 2012 +0200 @@ -0,0 +1,136 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.client.heap.swing; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JComponent; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; + +import com.redhat.thermostat.client.heap.HeapDump; +import com.redhat.thermostat.client.heap.HeapView; +import com.redhat.thermostat.client.heap.chart.OverviewChart; +import com.redhat.thermostat.client.ui.ComponentVisibleListener; + +public class HeapSwingView extends HeapView<JComponent> { + + private StatsPanel stats; + + private HeapPanel panel; + private HeaderPanel overview; + + public HeapSwingView() { + + stats = new StatsPanel(); + stats.addHeapDumperListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + + stats.disableHeapDumperControl(); + + SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { + @Override + protected Void doInBackground() throws Exception { + heapDumperNotifier.fireAction(HeadDumperAction.DUMP_REQUESTED); + return null; + } + + @Override + protected void done() { + stats.enableHeapDumperControl(); + } + }; + worker.execute(); + } + }); + + panel = new HeapPanel(); + + overview = new HeaderPanel("Heap Usage Overview"); + overview.setContent(stats); + overview.addHierarchyListener(new ViewVisibleListener()); + + panel.setTop(overview); + } + + @Override + public JComponent getComponent() { + return overview; + } + + private class ViewVisibleListener extends ComponentVisibleListener { + @Override + public void componentShown(Component component) { + HeapSwingView.this.notify(Action.VISIBLE); + } + + @Override + public void componentHidden(Component component) { + HeapSwingView.this.notify(Action.HIDDEN); + } + } + + @Override + public void updateOverview(final OverviewChart model, final String used, final String capacity) { + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + ChartPanel charts = new ChartPanel(model); + stats.setChartPanel(charts); + + stats.setMax(capacity); + stats.setUsed(used); + } + }); + } + + @Override + public void addHeapDump(final HeapDump dump) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + stats.addDump(dump); + } + }); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/StatsPanel.java Mon Jun 18 17:04:47 2012 +0200 @@ -0,0 +1,181 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.client.heap.swing; + +import java.awt.event.ActionListener; + +import javax.swing.BoxLayout; +import javax.swing.DefaultListModel; +import javax.swing.GroupLayout; +import javax.swing.GroupLayout.Alignment; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.LayoutStyle.ComponentPlacement; +import javax.swing.SwingConstants; + +import com.redhat.thermostat.client.heap.HeapDump; +import javax.swing.JList; + +public class StatsPanel extends JPanel { + + private JPanel leftPanel; + + private JButton heapDumpButton; + private JList<HeapDump> dumpList; + private DefaultListModel<HeapDump> listModel; + + private JLabel max; + private JLabel current; + + public StatsPanel() { + + leftPanel = new JPanel(); + leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.X_AXIS)); + + JPanel rightPanel = new JPanel(); + GroupLayout groupLayout = new GroupLayout(this); + groupLayout.setHorizontalGroup( + groupLayout.createParallelGroup(Alignment.LEADING) + .addGroup(Alignment.TRAILING, groupLayout.createSequentialGroup() + .addComponent(leftPanel, GroupLayout.DEFAULT_SIZE, 343, Short.MAX_VALUE) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addComponent(rightPanel, GroupLayout.PREFERRED_SIZE, 252, GroupLayout.PREFERRED_SIZE)) + ); + groupLayout.setVerticalGroup( + groupLayout.createParallelGroup(Alignment.LEADING) + .addComponent(rightPanel, GroupLayout.DEFAULT_SIZE, 293, Short.MAX_VALUE) + .addComponent(leftPanel, GroupLayout.DEFAULT_SIZE, 293, Short.MAX_VALUE) + ); + + JLabel currentLabel = new JLabel("size:"); + currentLabel.setHorizontalAlignment(SwingConstants.LEFT); + + JLabel maxLabel = new JLabel("max:"); + maxLabel.setHorizontalAlignment(SwingConstants.LEFT); + + current = new JLabel("12"); + current.setHorizontalAlignment(SwingConstants.RIGHT); + + max = new JLabel("12"); + max.setHorizontalAlignment(SwingConstants.RIGHT); + + heapDumpButton = new JButton("Heap Dump"); + + dumpList = new JList<>(); + listModel = new DefaultListModel<>(); + dumpList.setModel(listModel); + + GroupLayout gl_rightPanel = new GroupLayout(rightPanel); + gl_rightPanel.setHorizontalGroup( + gl_rightPanel.createParallelGroup(Alignment.TRAILING) + .addGroup(gl_rightPanel.createSequentialGroup() + .addContainerGap() + .addGroup(gl_rightPanel.createParallelGroup(Alignment.TRAILING) + .addComponent(dumpList, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 173, Short.MAX_VALUE) + .addComponent(heapDumpButton, GroupLayout.DEFAULT_SIZE, 173, Short.MAX_VALUE) + .addGroup(gl_rightPanel.createSequentialGroup() + .addGroup(gl_rightPanel.createParallelGroup(Alignment.TRAILING, false) + .addComponent(maxLabel, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(currentLabel, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 48, Short.MAX_VALUE)) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(gl_rightPanel.createParallelGroup(Alignment.TRAILING) + .addComponent(current, GroupLayout.DEFAULT_SIZE, 119, Short.MAX_VALUE) + .addComponent(max, GroupLayout.PREFERRED_SIZE, 119, GroupLayout.PREFERRED_SIZE)))) + .addContainerGap()) + ); + gl_rightPanel.setVerticalGroup( + gl_rightPanel.createParallelGroup(Alignment.LEADING) + .addGroup(gl_rightPanel.createSequentialGroup() + .addContainerGap() + .addGroup(gl_rightPanel.createParallelGroup(Alignment.BASELINE) + .addComponent(currentLabel, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE) + .addComponent(current)) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(gl_rightPanel.createParallelGroup(Alignment.BASELINE) + .addComponent(maxLabel) + .addComponent(max)) + .addGap(18) + .addComponent(heapDumpButton) + .addGap(18) + .addComponent(dumpList, GroupLayout.DEFAULT_SIZE, 172, Short.MAX_VALUE) + .addContainerGap()) + ); + rightPanel.setLayout(gl_rightPanel); + setLayout(groupLayout); + + // initially invisible + dumpList.setVisible(false); + } + + void setChartPanel(JPanel panel) { + leftPanel.removeAll(); + leftPanel.add(panel); + leftPanel.revalidate(); + repaint(); + } + + public void setMax(String capacity) { + max.setText(capacity); + } + + public void setUsed(String used) { + current.setText(used); + } + + void addHeapDumperListener(ActionListener listener) { + heapDumpButton.addActionListener(listener); + } + + public void disableHeapDumperControl() { + heapDumpButton.setText("dumping..."); + heapDumpButton.setEnabled(false); + } + + public void enableHeapDumperControl() { + heapDumpButton.setText("Heap Dump"); + heapDumpButton.setEnabled(true); + } + + public void addDump(HeapDump dump) { + + listModel.addElement(dump); + if (!dumpList.isVisible()) { + dumpList.setVisible(true); + } + } +}
--- a/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/HeapDumpActionTest.java Mon Jun 18 16:17:37 2012 +0200 +++ b/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/HeapDumpActionTest.java Mon Jun 18 17:04:47 2012 +0200 @@ -47,6 +47,7 @@ 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; @@ -78,7 +79,9 @@ deadVmRef = mock(VmRef.class); when(vmInfoDAO.getVmInfo(deadVmRef)).thenReturn(vmInfo2); - heapDumpAction = new HeapDumpAction(dao); + + BundleContext bundleContext = mock(BundleContext.class); + heapDumpAction = new HeapDumpAction(dao, bundleContext); } @After @@ -91,12 +94,12 @@ @Test public void testName() { - assertEquals("Heap Dump", heapDumpAction.getName()); + assertEquals("Heap Analysis", heapDumpAction.getName()); } @Test public void testDescription() { - assertEquals("Generate a heap dump", heapDumpAction.getDescription()); + assertEquals("Heap View", heapDumpAction.getDescription()); } @Test
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/main/java/com/redhat/thermostat/common/BasicView.java Mon Jun 18 17:04:47 2012 +0200 @@ -0,0 +1,61 @@ +/* + * 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.common; + +public class BasicView implements View { + public enum Action { + VISIBLE, + HIDDEN, + } + private final ActionNotifier<Action> notifier; + + protected BasicView() { + notifier = new ActionNotifier<Action>(this); + } + + public void addActionListener(ActionListener<Action> listener) { + notifier.addActionListener(listener); + } + + public void removeActionListener(ActionListener<Action> listener) { + notifier.removeActionListener(listener); + } + + protected void notify(Action action) { + notifier.fireAction(action); + } +}