Mercurial > hg > release > thermostat-0.15
changeset 262:8bd725ac3bdf
Implement interactive Thermostat shell.
Reviewed-by: neugens
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-April/001053.html
PR 930
author | Roman Kennke <rkennke@redhat.com> |
---|---|
date | Tue, 24 Apr 2012 14:14:13 +0200 |
parents | 9c2e7e00665c |
children | 9a1a69250ee2 |
files | common/src/main/java/com/redhat/thermostat/test/ExceptionThrowingInputStream.java common/src/main/java/com/redhat/thermostat/test/TestCommandContextFactory.java tools/pom.xml tools/src/main/java/com/redhat/thermostat/tools/cli/ShellCommand.java tools/src/main/resources/META-INF/services/com.redhat.thermostat.cli.Command tools/src/test/java/com/redhat/thermostat/tools/cli/ShellCommandTest.java tools/src/test/java/com/redhat/thermostat/tools/cli/TestTerminal.java |
diffstat | 7 files changed, 408 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/src/main/java/com/redhat/thermostat/test/ExceptionThrowingInputStream.java Tue Apr 24 14:14:13 2012 +0200 @@ -0,0 +1,68 @@ +/* + * 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.test; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +class ExceptionThrowingInputStream extends InputStream { + + private InputStream in = new ByteArrayInputStream(new byte[0]); + private IOException exception; + + @Override + public int read() throws IOException { + throwExceptionIfNecessary(); + return in.read(); + } + + private void throwExceptionIfNecessary() throws IOException { + if (exception != null) { + throw exception; + } + } + + public void setInput(String input) { + in = new ByteArrayInputStream(input.getBytes()); + } + + public void setException(IOException ex) { + exception = ex; + } + +}
--- a/common/src/main/java/com/redhat/thermostat/test/TestCommandContextFactory.java Mon Apr 23 12:22:09 2012 +0200 +++ b/common/src/main/java/com/redhat/thermostat/test/TestCommandContextFactory.java Tue Apr 24 14:14:13 2012 +0200 @@ -36,8 +36,8 @@ package com.redhat.thermostat.test; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; @@ -52,7 +52,7 @@ private ByteArrayOutputStream out; private ByteArrayOutputStream err; - private ByteArrayInputStream in; + private ExceptionThrowingInputStream in; public TestCommandContextFactory() { reset(); @@ -130,8 +130,8 @@ return new String(out.toByteArray()); } - void setInput(String input) { - in = new ByteArrayInputStream(input.getBytes()); + public void setInput(String input) { + in.setInput(input); } public Object getError() { @@ -141,11 +141,15 @@ public void reset() { out = new ByteArrayOutputStream(); err = new ByteArrayOutputStream(); - in = new ByteArrayInputStream(new byte[0]); + in = new ExceptionThrowingInputStream(); console = new TestConsole(); } public Console getConsole() { return console; } + + public void setInputThrowsException(IOException ex) { + in.setException(ex); + } }
--- a/tools/pom.xml Mon Apr 23 12:22:09 2012 +0200 +++ b/tools/pom.xml Tue Apr 24 14:14:13 2012 +0200 @@ -74,6 +74,11 @@ <scope>test</scope> </dependency> <dependency> + <groupId>jline</groupId> + <artifactId>jline</artifactId> + <version>2.6</version> + </dependency> + <dependency> <groupId>com.redhat.thermostat</groupId> <artifactId>thermostat-common</artifactId> <version>${project.version}</version>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/src/main/java/com/redhat/thermostat/tools/cli/ShellCommand.java Tue Apr 24 14:14:13 2012 +0200 @@ -0,0 +1,133 @@ +/* + * 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.IOException; +import java.util.Collection; +import java.util.Collections; + +import jline.Terminal; +import jline.TerminalFactory; +import jline.console.ConsoleReader; + +import com.redhat.thermostat.cli.ArgumentSpec; +import com.redhat.thermostat.cli.Command; +import com.redhat.thermostat.cli.CommandContext; +import com.redhat.thermostat.cli.CommandException; +import com.redhat.thermostat.cli.Launcher; + +public class ShellCommand implements Command { + + private static final String NAME = "shell"; + + private static final String DESCRIPTION = "launches the Thermostat interactive shell"; + + private static final String USAGE = DESCRIPTION; + + private static final String PROMPT = "Thermostat > "; + + @Override + public void run(CommandContext ctx) throws CommandException { + Terminal term = TerminalFactory.create(); + try { + shellMainLoop(ctx, term); + } catch (IOException ex) { + throw new CommandException(ex); + } finally { + closeTerminal(term); + } + } + + private void closeTerminal(Terminal term) throws CommandException { + try { + term.restore(); + } catch (Exception e) { + System.err.println("restore kaputted"); + throw new CommandException(e); + } + } + + private void shellMainLoop(CommandContext ctx, Terminal term) throws IOException { + ConsoleReader reader = new ConsoleReader("fluff", ctx.getConsole().getInput(), ctx.getConsole().getOutput(), term); + while (handleConsoleInput(reader)); + } + + private boolean handleConsoleInput(ConsoleReader reader) throws IOException { + String line = reader.readLine(PROMPT).trim(); + if (line.equals("")) { + return true; + } else if (line.equals("exit")) { + return false; + } else { + launchCommand(line); + return true; + } + } + + private void launchCommand(String line) { + String[] parsed = line.split(" "); + Launcher launcher = new Launcher(); + launcher.run(parsed); + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String getDescription() { + return DESCRIPTION; + } + + @Override + public String getUsage() { + return USAGE; + } + + @Override + public Collection<ArgumentSpec> getAcceptedArguments() { + return Collections.emptyList(); + } + + @Override + public boolean isStorageRequired() { + // TODO Auto-generated method stub + return false; + } + +}
--- a/tools/src/main/resources/META-INF/services/com.redhat.thermostat.cli.Command Mon Apr 23 12:22:09 2012 +0200 +++ b/tools/src/main/resources/META-INF/services/com.redhat.thermostat.cli.Command Tue Apr 24 14:14:13 2012 +0200 @@ -3,3 +3,4 @@ com.redhat.thermostat.tools.db.DBService com.redhat.thermostat.agent.AgentApplication com.redhat.thermostat.tools.cli.ListVMsCommand +com.redhat.thermostat.tools.cli.ShellCommand
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/src/test/java/com/redhat/thermostat/tools/cli/ShellCommandTest.java Tue Apr 24 14:14:13 2012 +0200 @@ -0,0 +1,140 @@ +/* + * 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 static org.junit.Assert.assertFalse; + +import java.io.IOException; +import java.util.Collections; + +import jline.TerminalFactory; +import jline.TerminalFactory.Flavor; +import jline.TerminalFactory.Type; +import jline.UnixTerminal; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.cli.Arguments; +import com.redhat.thermostat.cli.CommandContext; +import com.redhat.thermostat.cli.CommandException; +import com.redhat.thermostat.cli.SimpleArguments; +import com.redhat.thermostat.test.TestCommandContextFactory; + +public class ShellCommandTest { + + private ShellCommand cmd; + + @Before + public void setUp() { + cmd = new ShellCommand(); + } + + @After + public void tearDown() { + cmd = null; + TerminalFactory.registerFlavor(Flavor.UNIX, UnixTerminal.class); + TerminalFactory.reset(); + } + + @Test + public void testBasic() throws CommandException { + TestCommandContextFactory ctxFactory = new TestCommandContextFactory(); + ctxFactory.setInput("help\nexit\n"); + Arguments args = new SimpleArguments(); + CommandContext ctx = ctxFactory.createContext(args); + cmd.run(ctx); + assertEquals("Thermostat > help\nThermostat > exit\n", ctxFactory.getOutput()); + } + + @Test + public void testDoNothingWithoutInput() throws CommandException { + TestCommandContextFactory ctxFactory = new TestCommandContextFactory(); + ctxFactory.setInput("\nexit\n"); + Arguments args = new SimpleArguments(); + CommandContext ctx = ctxFactory.createContext(args); + cmd.run(ctx); + assertEquals("Thermostat > \nThermostat > exit\n", ctxFactory.getOutput()); + } + + @Test(expected=CommandException.class) + public void testIOException() throws CommandException { + TestCommandContextFactory ctxFactory = new TestCommandContextFactory(); + ctxFactory.setInputThrowsException(new IOException()); + Arguments args = new SimpleArguments(); + CommandContext ctx = ctxFactory.createContext(args); + cmd.run(ctx); + } + + @Test(expected=CommandException.class) + public void testTerminalRestoreException() throws CommandException { + TerminalFactory.configure(Type.UNIX); + TerminalFactory.registerFlavor(Flavor.UNIX, TestTerminal.class); + TestCommandContextFactory ctxFactory = new TestCommandContextFactory(); + ctxFactory.setInputThrowsException(new IOException()); + Arguments args = new SimpleArguments(); + CommandContext ctx = ctxFactory.createContext(args); + cmd.run(ctx); + } + + @Test + public void testName() { + assertEquals("shell", cmd.getName()); + } + + @Test + public void testDescription() { + assertEquals("launches the Thermostat interactive shell", cmd.getDescription()); + } + + @Test + public void testUsage() { + assertEquals("launches the Thermostat interactive shell", cmd.getUsage()); + } + + @Test + public void testAcceptedArguments() { + assertEquals(Collections.EMPTY_LIST, cmd.getAcceptedArguments()); + } + + @Test + public void testStorageRequired() { + assertFalse(cmd.isStorageRequired()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/src/test/java/com/redhat/thermostat/tools/cli/TestTerminal.java Tue Apr 24 14:14:13 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.tools.cli; + +import jline.UnixTerminal; + +public class TestTerminal extends UnixTerminal { + + public TestTerminal() throws Exception { + super(); + } + + @Override + public void restore() throws Exception { + throw new Exception(); + } + +}