Mercurial > hg > release > thermostat-1.0
changeset 414:79c07f5c005a
Merge
author | Roman Kennke <rkennke@redhat.com> |
---|---|
date | Thu, 21 Jun 2012 17:41:40 +0200 |
parents | 05d1331db40e (current diff) aebfbb3d4d03 (diff) |
children | 17313a694032 |
files | tools/src/main/java/com/redhat/thermostat/tools/cli/TableRenderer.java tools/src/test/java/com/redhat/thermostat/tools/cli/TableRendererTest.java |
diffstat | 14 files changed, 541 insertions(+), 224 deletions(-) [+] |
line wrap: on
line diff
--- a/client/heapdumper/pom.xml Thu Jun 21 17:38:44 2012 +0200 +++ b/client/heapdumper/pom.xml Thu Jun 21 17:41:40 2012 +0200 @@ -102,7 +102,12 @@ <version>${project.version}</version> <type>bundle</type> </dependency> - + <dependency> + <groupId>com.redhat.thermostat</groupId> + <artifactId>thermostat-tools</artifactId> + <version>${project.version}</version> + <type>bundle</type> + </dependency> <dependency> <groupId>org.jfree</groupId> <artifactId>jfreechart</artifactId>
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/Activator.java Thu Jun 21 17:38:44 2012 +0200 +++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/Activator.java Thu Jun 21 17:41:40 2012 +0200 @@ -36,6 +36,8 @@ package com.redhat.thermostat.client.heap; +import java.util.ServiceLoader; + import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; @@ -47,9 +49,13 @@ import com.redhat.thermostat.client.osgi.service.ApplicationService; import com.redhat.thermostat.client.osgi.service.VmInformationService; import com.redhat.thermostat.common.appctx.ApplicationContext; +import com.redhat.thermostat.common.cli.Command; +import com.redhat.thermostat.common.cli.CommandRegistry; +import com.redhat.thermostat.common.cli.CommandRegistryImpl; public class Activator implements BundleActivator { + private CommandRegistry reg; private ServiceRegistration contextServiceReg; @Override @@ -59,13 +65,17 @@ @Override public Object addingService(ServiceReference reference) { ApplicationService appService = (ApplicationService) context.getService(reference); - + ApplicationContext.getInstance().getViewFactory().setViewClass(HeapView.class, HeapSwingView.class); context.registerService(VmInformationService.class.getName(), new HeapDumperService(appService), null); return super.addingService(reference); } }; tracker.open(); + + reg = new CommandRegistryImpl(context); + ServiceLoader<Command> cmds = ServiceLoader.load(Command.class, getClass().getClassLoader()); + reg.registerCommands(cmds); } @Override @@ -73,5 +83,7 @@ if (contextServiceReg != null) { contextServiceReg.unregister(); } + + reg.unregisterCommands(); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/ListHeapDumpsCommand.java Thu Jun 21 17:41:40 2012 +0200 @@ -0,0 +1,122 @@ +/* + * 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.ArrayList; +import java.util.Collection; +import java.util.Date; + +import com.redhat.thermostat.common.appctx.ApplicationContext; +import com.redhat.thermostat.common.cli.ArgumentSpec; +import com.redhat.thermostat.common.cli.Command; +import com.redhat.thermostat.common.cli.CommandContext; +import com.redhat.thermostat.common.cli.CommandException; +import com.redhat.thermostat.common.cli.TableRenderer; +import com.redhat.thermostat.common.dao.DAOFactory; +import com.redhat.thermostat.common.dao.HeapDAO; +import com.redhat.thermostat.common.dao.HostInfoDAO; +import com.redhat.thermostat.common.dao.HostRef; +import com.redhat.thermostat.common.dao.VmInfoDAO; +import com.redhat.thermostat.common.dao.VmRef; +import com.redhat.thermostat.common.model.HeapInfo; + +public class ListHeapDumpsCommand implements Command { + + private static final String NAME = "list-heap-dumps"; + private static final String DESCRIPTION = "list all heap dumps"; + private static final String USAGE = DESCRIPTION; + + // TODO localize + private static final String[] COLUMN_NAMES = {"HOST ID", "VM ID", "HEAP ID", "TIMESTAMP"}; + + @Override + public String getName() { + return NAME; + } + + @Override + public String getDescription() { + return DESCRIPTION; + } + + @Override + public String getUsage() { + return USAGE; + } + + @Override + public Collection<ArgumentSpec> getAcceptedArguments() { + return new ArrayList<>(); + } + + @Override + public boolean isStorageRequired() { + return true; + } + + @Override + public void run(CommandContext ctx) throws CommandException { + TableRenderer renderer = new TableRenderer(4); + + renderer.printLine(COLUMN_NAMES); + + DAOFactory daoFactory = ApplicationContext.getInstance().getDAOFactory(); + HostInfoDAO hostDAO = daoFactory.getHostInfoDAO(); + VmInfoDAO vmDAO = daoFactory.getVmInfoDAO(); + HeapDAO heapDAO = daoFactory.getHeapDAO(); + + for (HostRef hostRef : hostDAO.getHosts()) { + for (VmRef vmRef : vmDAO.getVMs(hostRef)) { + Collection<HeapInfo> infos = heapDAO.getAllHeapInfo(vmRef); + for (HeapInfo info : infos) { + renderer.printLine(hostRef.getStringID(), + vmRef.getStringID(), + info.getHeapDumpId(), + new Date(info.getTimestamp()).toString()); + } + } + } + + renderer.render(ctx.getConsole().getOutput()); + } + + @Override + public void disable() { + /* NO-OP */ + } + +}
--- a/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/StatsPanel.java Thu Jun 21 17:38:44 2012 +0200 +++ b/client/heapdumper/src/main/java/com/redhat/thermostat/client/heap/swing/StatsPanel.java Thu Jun 21 17:41:40 2012 +0200 @@ -46,6 +46,7 @@ import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.JScrollPane; import javax.swing.LayoutStyle.ComponentPlacement; import javax.swing.ListSelectionModel; import javax.swing.SwingConstants; @@ -99,6 +100,7 @@ heapDumpButton = new JButton("Heap Dump"); + JScrollPane dumpListScrollPane = new JScrollPane(); dumpList = new JList<>(); listModel = new DefaultListModel<>(); dumpList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); @@ -110,7 +112,7 @@ .addGroup(gl_rightPanel.createSequentialGroup() .addContainerGap() .addGroup(gl_rightPanel.createParallelGroup(Alignment.TRAILING) - .addComponent(dumpList, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 173, Short.MAX_VALUE) + .addComponent(dumpListScrollPane, 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) @@ -136,12 +138,14 @@ .addGap(18) .addComponent(heapDumpButton) .addGap(18) - .addComponent(dumpList, GroupLayout.DEFAULT_SIZE, 172, Short.MAX_VALUE) + .addComponent(dumpListScrollPane, GroupLayout.DEFAULT_SIZE, 172, Short.MAX_VALUE) .addContainerGap()) ); rightPanel.setLayout(gl_rightPanel); setLayout(groupLayout); + dumpListScrollPane.setViewportView(dumpList); + // initially invisible dumpList.setVisible(false); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/heapdumper/src/main/resources/META-INF/services/com.redhat.thermostat.common.cli.Command Thu Jun 21 17:41:40 2012 +0200 @@ -0,0 +1,1 @@ +com.redhat.thermostat.client.heap.ListHeapDumpsCommand \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/heapdumper/src/test/java/com/redhat/thermostat/client/heap/ListHeapDumpsCommandTest.java Thu Jun 21 17:41:40 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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.List; +import java.util.TimeZone; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.redhat.thermostat.common.appctx.ApplicationContext; +import com.redhat.thermostat.common.appctx.ApplicationContextUtil; +import com.redhat.thermostat.common.cli.ArgumentSpec; +import com.redhat.thermostat.common.cli.Command; +import com.redhat.thermostat.common.cli.CommandException; +import com.redhat.thermostat.common.dao.DAOFactory; +import com.redhat.thermostat.common.dao.HeapDAO; +import com.redhat.thermostat.common.dao.HostInfoDAO; +import com.redhat.thermostat.common.dao.HostRef; +import com.redhat.thermostat.common.dao.VmInfoDAO; +import com.redhat.thermostat.common.dao.VmRef; +import com.redhat.thermostat.common.model.HeapInfo; +import com.redhat.thermostat.test.TestCommandContextFactory; + +public class ListHeapDumpsCommandTest { + + private static TimeZone defaultTimezone; + + @BeforeClass + public static void setUpClass() { + defaultTimezone = TimeZone.getDefault(); + TimeZone.setDefault(TimeZone.getTimeZone("UTC")); + } + + @AfterClass + public static void tearDownClass() { + TimeZone.setDefault(defaultTimezone); + } + + @Before + public void setUp() { + ApplicationContextUtil.resetApplicationContext(); + } + + @After + public void tearDown() { + ApplicationContextUtil.resetApplicationContext(); + + } + + @Test + public void verifyBasics() { + Command command = new ListHeapDumpsCommand(); + assertEquals("list-heap-dumps", command.getName()); + assertNotNull(command.getDescription()); + assertNotNull(command.getUsage()); + } + + @Test + public void verifyArguments() { + Command command = new ListHeapDumpsCommand(); + List<ArgumentSpec> arguments = new ArrayList<>(command.getAcceptedArguments()); + assertTrue(arguments.isEmpty()); + } + + @Test + public void verifyWorksWithoutAnyInformation() throws CommandException { + HostInfoDAO hostInfo = mock(HostInfoDAO.class); + + VmInfoDAO vmInfo = mock(VmInfoDAO.class); + + DAOFactory daoFactory = mock(DAOFactory.class); + when(daoFactory.getHostInfoDAO()).thenReturn(hostInfo); + when(daoFactory.getVmInfoDAO()).thenReturn(vmInfo); + + ApplicationContext.getInstance().setDAOFactory(daoFactory); + + Command command = new ListHeapDumpsCommand(); + TestCommandContextFactory factory = new TestCommandContextFactory(); + command.run(factory.createContext(null)); + assertEquals("HOST ID VM ID HEAP ID TIMESTAMP\n", factory.getOutput()); + } + + @Test + public void verifyWorks() throws CommandException { + HostRef hostRef = mock(HostRef.class); + when(hostRef.getStringID()).thenReturn("host-id"); + VmRef vmRef = mock(VmRef.class); + when(vmRef.getStringID()).thenReturn("vm-id"); + + HeapInfo heapInfo = mock(HeapInfo.class); + Calendar timestamp = Calendar.getInstance(); + timestamp.set(2012, 5, 7, 15, 32, 0); + when(heapInfo.getTimestamp()).thenReturn(timestamp.getTimeInMillis()); + when(heapInfo.getHeapDumpId()).thenReturn("0001"); + + HeapDAO heapDao = mock(HeapDAO.class); + + VmInfoDAO vmInfo = mock(VmInfoDAO.class); + when(vmInfo.getVMs(hostRef)).thenReturn(Arrays.asList(vmRef)); + + HostInfoDAO hostInfo = mock(HostInfoDAO.class); + when(hostInfo.getHosts()).thenReturn(Arrays.asList(hostRef)); + + when(heapDao.getAllHeapInfo(vmRef)).thenReturn(Arrays.asList(heapInfo)); + + DAOFactory daoFactory = mock(DAOFactory.class); + when(daoFactory.getHostInfoDAO()).thenReturn(hostInfo); + when(daoFactory.getVmInfoDAO()).thenReturn(vmInfo); + when(daoFactory.getHeapDAO()).thenReturn(heapDao); + + ApplicationContext.getInstance().setDAOFactory(daoFactory); + + Command command = new ListHeapDumpsCommand(); + TestCommandContextFactory factory = new TestCommandContextFactory(); + command.run(factory.createContext(null)); + + String expected = "HOST ID VM ID HEAP ID TIMESTAMP\n" + + "host-id vm-id 0001 Thu Jun 07 15:32:00 UTC 2012\n"; + + assertEquals(expected, factory.getOutput()); + } +}
--- a/common/core/src/main/java/com/redhat/thermostat/common/cli/HelpCommand.java Thu Jun 21 17:38:44 2012 +0200 +++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/HelpCommand.java Thu Jun 21 17:41:40 2012 +0200 @@ -44,7 +44,7 @@ public class HelpCommand implements Command { - private static final int COMMANDS_COLUMNS_WIDTH = 15; + private static final int COMMANDS_COLUMNS_WIDTH = 14; private static final String NAME = "help"; private static final String DESCRIPTION = "show help for a given command or help overview"; private static final String USAGE = DESCRIPTION; @@ -65,27 +65,22 @@ private void printCommandSummaries(CommandContext ctx) { CommandRegistry cmdRegistry = ctx.getCommandRegistry(); - StringBuilder out = new StringBuilder(); - out.append("list of commands:\n\n"); + ctx.getConsole().getOutput().print("list of commands:\n\n"); + + TableRenderer renderer = new TableRenderer(2, COMMANDS_COLUMNS_WIDTH); Collection<Command> commands = cmdRegistry.getRegisteredCommands(); List<Command> sortedCommands = new ArrayList<>(commands); Collections.sort(sortedCommands, comparator); for (Command cmd : sortedCommands) { - printCommandSummary(out, cmd); + printCommandSummary(renderer, cmd); } - ctx.getConsole().getOutput().print(out); + renderer.render(ctx.getConsole().getOutput()); } - private void printCommandSummary(StringBuilder out, Command cmd) { - out.append(" "); - out.append(cmd.getName()); - for (int i = 0; i < COMMANDS_COLUMNS_WIDTH - cmd.getName().length() - 1; i++) { - out.append(" "); - } - out.append(cmd.getDescription()); - out.append("\n"); + private void printCommandSummary(TableRenderer renderer, Command cmd) { + renderer.printLine(" " + cmd.getName(), cmd.getDescription()); } private void printCommandUsage(CommandContext ctx, String cmdName) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/TableRenderer.java Thu Jun 21 17:41:40 2012 +0200 @@ -0,0 +1,110 @@ +/* + * 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.cli; + +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; + +public class TableRenderer { + + private List<String[]> lines; + private int[] maxColumnWidths; + private int lastPrintedLine = -1; + + private int numColumns; + private int minWidth; + + public TableRenderer(int numColumns) { + this(numColumns, 1); + } + + public TableRenderer(int numColumns, int minWidth) { + this.numColumns = numColumns; + lines = new ArrayList<>(); + maxColumnWidths = new int[numColumns]; + this.minWidth = minWidth; + } + + public void printLine(String... line) { + if (line.length != numColumns) { + throw new IllegalArgumentException("Invalid number of columns: " + line.length + ", expected: " + numColumns); + } + lines.add(line); + for (int i = 0; i < numColumns; i++) { + maxColumnWidths[i] = Math.max(Math.max(maxColumnWidths[i], line[i].length()), minWidth); + } + } + + public void render(OutputStream os) { + PrintStream out = new PrintStream(os); + render(out); + } + + public void render(PrintStream out) { + for (int i = lastPrintedLine + 1; i < lines.size(); i++) { + String[] line = lines.get(i); + renderLine(out, line); + lastPrintedLine = i; + } + } + + private void renderLine(PrintStream out, String[] line) { + for (int i = 0; i < numColumns; i++) { + out.print(line[i]); + padOrNewline(out, line, i); + + } + } + + private void padOrNewline(PrintStream out, String[] line, int i) { + if (i < numColumns - 1) { + int pad = maxColumnWidths[i] - line[i].length() + 1; + fillSpaces(out, pad); + } else { + out.println(); + } + } + + private void fillSpaces(PrintStream out, int pad) { + for (int i = 0; i < pad; i++) { + out.print(" "); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/core/src/test/java/com/redhat/thermostat/common/cli/TableRendererTest.java Thu Jun 21 17:41:40 2012 +0200 @@ -0,0 +1,103 @@ +/* + * 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.cli; + +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayOutputStream; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class TableRendererTest { + + private TableRenderer tableRenderer; + private ByteArrayOutputStream out; + + @Before + public void setUp() { + tableRenderer = new TableRenderer(3); + out = new ByteArrayOutputStream(); + } + + @After + public void tearDown() { + out = null; + tableRenderer = null; + } + + @Test + public void testSingleLine() { + tableRenderer.printLine("hello", "fluff", "world"); + tableRenderer.render(out); + assertEquals("hello fluff world\n", new String(out.toByteArray())); + } + + @Test + public void testMultiLine() { + tableRenderer.printLine("hello", "fluff", "world"); + tableRenderer.printLine("looooooong", "f1", "foobar"); + tableRenderer.printLine("f2", "shoooooooooooort", "poo"); + tableRenderer.render(out); + assertEquals("hello fluff world\n" + + "looooooong f1 foobar\n" + + "f2 shoooooooooooort poo\n", new String(out.toByteArray())); + } + + @Test + public void testMultiLineContinuous() { + tableRenderer.printLine("hello", "fluff", "world"); + tableRenderer.printLine("looooooong", "f1", "foobar"); + tableRenderer.printLine("f2", "shoooooooooooort", "poo"); + tableRenderer.render(out); + assertEquals("hello fluff world\n" + + "looooooong f1 foobar\n" + + "f2 shoooooooooooort poo\n", new String(out.toByteArray())); + tableRenderer.printLine("f3", "foobar", "poo"); + tableRenderer.render(out); + assertEquals("hello fluff world\n" + + "looooooong f1 foobar\n" + + "f2 shoooooooooooort poo\n" + + "f3 foobar poo\n", new String(out.toByteArray())); + } + + @Test(expected=IllegalArgumentException.class) + public void testInvalidLine() { + tableRenderer.printLine("hello", "fluff", "world", "boom"); + } +}
--- a/tools/src/main/java/com/redhat/thermostat/tools/cli/TableRenderer.java Thu Jun 21 17:38:44 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +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.tools.cli; - -import java.io.OutputStream; -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.List; - -class TableRenderer { - - private List<String[]> lines; - private int[] maxColumnWidths; - private int lastPrintedLine = -1; - - private int numColumns; - - TableRenderer(int numColumns) { - this.numColumns = numColumns; - lines = new ArrayList<>(); - maxColumnWidths = new int[numColumns]; - } - - void printLine(String... line) { - if (line.length != numColumns) { - throw new IllegalArgumentException("Invalid number of columns: " + line.length + ", expected: " + numColumns); - } - lines.add(line); - for (int i = 0; i < numColumns; i++) { - maxColumnWidths[i] = Math.max(maxColumnWidths[i], line[i].length()); - } - } - - void render(OutputStream os) { - PrintStream out = new PrintStream(os); - render(out); - } - - void render(PrintStream out) { - for (int i = lastPrintedLine + 1; i < lines.size(); i++) { - String[] line = lines.get(i); - renderLine(out, line); - lastPrintedLine = i; - } - } - - private void renderLine(PrintStream out, String[] line) { - for (int i = 0; i < numColumns; i++) { - out.print(line[i]); - padOrNewline(out, line, i); - - } - } - - private void padOrNewline(PrintStream out, String[] line, int i) { - if (i < numColumns - 1) { - int pad = maxColumnWidths[i] - line[i].length() + 1; - fillSpaces(out, pad); - } else { - out.println(); - } - } - - private void fillSpaces(PrintStream out, int pad) { - for (int i = 0; i < pad; i++) { - out.print(" "); - } - } - -}
--- a/tools/src/main/java/com/redhat/thermostat/tools/cli/VMInfoCommand.java Thu Jun 21 17:38:44 2012 +0200 +++ b/tools/src/main/java/com/redhat/thermostat/tools/cli/VMInfoCommand.java Thu Jun 21 17:41:40 2012 +0200 @@ -45,6 +45,7 @@ import com.redhat.thermostat.common.cli.Command; import com.redhat.thermostat.common.cli.CommandContext; import com.redhat.thermostat.common.cli.CommandException; +import com.redhat.thermostat.common.cli.TableRenderer; import com.redhat.thermostat.common.dao.DAOException; import com.redhat.thermostat.common.dao.DAOFactory; import com.redhat.thermostat.common.dao.HostRef;
--- a/tools/src/main/java/com/redhat/thermostat/tools/cli/VMListFormatter.java Thu Jun 21 17:38:44 2012 +0200 +++ b/tools/src/main/java/com/redhat/thermostat/tools/cli/VMListFormatter.java Thu Jun 21 17:41:40 2012 +0200 @@ -38,6 +38,7 @@ import java.io.PrintStream; +import com.redhat.thermostat.common.cli.TableRenderer; import com.redhat.thermostat.common.dao.VmRef; import com.redhat.thermostat.common.model.VmInfo;
--- a/tools/src/main/java/com/redhat/thermostat/tools/cli/VMStatPrinter.java Thu Jun 21 17:38:44 2012 +0200 +++ b/tools/src/main/java/com/redhat/thermostat/tools/cli/VMStatPrinter.java Thu Jun 21 17:41:40 2012 +0200 @@ -44,6 +44,7 @@ import java.util.Iterator; import java.util.List; +import com.redhat.thermostat.common.cli.TableRenderer; import com.redhat.thermostat.common.dao.VmCpuStatDAO; import com.redhat.thermostat.common.dao.VmMemoryStatDAO; import com.redhat.thermostat.common.dao.VmRef;
--- a/tools/src/test/java/com/redhat/thermostat/tools/cli/TableRendererTest.java Thu Jun 21 17:38:44 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +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.tools.cli; - -import static org.junit.Assert.assertEquals; - -import java.io.ByteArrayOutputStream; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public class TableRendererTest { - - private TableRenderer tableRenderer; - private ByteArrayOutputStream out; - - @Before - public void setUp() { - tableRenderer = new TableRenderer(3); - out = new ByteArrayOutputStream(); - } - - @After - public void tearDown() { - out = null; - tableRenderer = null; - } - - @Test - public void testSingleLine() { - tableRenderer.printLine("hello", "fluff", "world"); - tableRenderer.render(out); - assertEquals("hello fluff world\n", new String(out.toByteArray())); - } - - @Test - public void testMultiLine() { - tableRenderer.printLine("hello", "fluff", "world"); - tableRenderer.printLine("looooooong", "f1", "foobar"); - tableRenderer.printLine("f2", "shoooooooooooort", "poo"); - tableRenderer.render(out); - assertEquals("hello fluff world\n" + - "looooooong f1 foobar\n" + - "f2 shoooooooooooort poo\n", new String(out.toByteArray())); - } - - @Test - public void testMultiLineContinuous() { - tableRenderer.printLine("hello", "fluff", "world"); - tableRenderer.printLine("looooooong", "f1", "foobar"); - tableRenderer.printLine("f2", "shoooooooooooort", "poo"); - tableRenderer.render(out); - assertEquals("hello fluff world\n" + - "looooooong f1 foobar\n" + - "f2 shoooooooooooort poo\n", new String(out.toByteArray())); - tableRenderer.printLine("f3", "foobar", "poo"); - tableRenderer.render(out); - assertEquals("hello fluff world\n" + - "looooooong f1 foobar\n" + - "f2 shoooooooooooort poo\n" + - "f3 foobar poo\n", new String(out.toByteArray())); - } - - @Test(expected=IllegalArgumentException.class) - public void testInvalidLine() { - tableRenderer.printLine("hello", "fluff", "world", "boom"); - } -}