Repository: incubator-brooklyn Updated Branches: refs/heads/master e5800c9cb -> b35c338a9
Improve CLI customisability for downstream projects - Make ASCII art banner customisable - Make info command customisable - Remove redundant duplicate Main.cliScriptName, as already declared in AbstractMain - Adds tests Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/fa770403 Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/fa770403 Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/fa770403 Branch: refs/heads/master Commit: fa770403df304410d51484549bd683182847b4cc Parents: 177b57b Author: Aled Sage <[email protected]> Authored: Sat Feb 28 23:09:27 2015 +0000 Committer: Aled Sage <[email protected]> Committed: Sun Mar 1 00:26:37 2015 +0000 ---------------------------------------------------------------------- .../main/java/brooklyn/cli/AbstractMain.java | 14 +++- usage/cli/src/main/java/brooklyn/cli/Main.java | 24 ++++--- .../cli/src/test/java/brooklyn/cli/CliTest.java | 71 ++++++++++++++++++++ 3 files changed, 97 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/fa770403/usage/cli/src/main/java/brooklyn/cli/AbstractMain.java ---------------------------------------------------------------------- diff --git a/usage/cli/src/main/java/brooklyn/cli/AbstractMain.java b/usage/cli/src/main/java/brooklyn/cli/AbstractMain.java index 1378c82..7e52461 100644 --- a/usage/cli/src/main/java/brooklyn/cli/AbstractMain.java +++ b/usage/cli/src/main/java/brooklyn/cli/AbstractMain.java @@ -70,7 +70,7 @@ public abstract class AbstractMain { private static final Logger log = LoggerFactory.getLogger(AbstractMain.class); // Launch banner - public static final String BANNER = + public static final String DEFAULT_BANNER = " _ _ _ \n" + "| |__ _ __ ___ ___ | | _| |_ _ _ __ (R)\n" + "| '_ \\| '__/ _ \\ / _ \\| |/ / | | | | '_ \\ \n" + @@ -84,6 +84,16 @@ public abstract class AbstractMain { public static final int EXECUTION_ERROR = 2; public static final int CONFIGURATION_ERROR = 3; + /** + * Field intended for sub-classes (with their own {@code main()}) to customize the banner. + * All accesses to the banner are done through this field, to ensure consistent customization. + * + * Note that a {@code getBanner()} method is not an option for supporting this, because + * it is accessed from static inner-classes (such as {@link InfoCommand}, so non-static + * methods are not an option (and one can't override static methods). + */ + protected static volatile String banner = DEFAULT_BANNER; + /** abstract superclass for commands defining global options, but not arguments, * as that prevents Help from being injectable in the {@link HelpCommand} subclass */ public static abstract class BrooklynCommand implements Callable<Void> { @@ -163,7 +173,7 @@ public abstract class AbstractMain { if (log.isDebugEnabled()) log.debug("Invoked info command: {}", this); warnIfArguments(); - System.out.println(BANNER); + System.out.println(banner); System.out.println("Version: " + BrooklynVersion.get()); if (BrooklynVersion.INSTANCE.isSnapshot()) { System.out.println("Git SHA1: " + BrooklynVersion.INSTANCE.getSha1FromOsgiManifest()); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/fa770403/usage/cli/src/main/java/brooklyn/cli/Main.java ---------------------------------------------------------------------- diff --git a/usage/cli/src/main/java/brooklyn/cli/Main.java b/usage/cli/src/main/java/brooklyn/cli/Main.java index 7a79721..e674c1d 100644 --- a/usage/cli/src/main/java/brooklyn/cli/Main.java +++ b/usage/cli/src/main/java/brooklyn/cli/Main.java @@ -351,7 +351,7 @@ public class Main extends AbstractMain { try { if (log.isDebugEnabled()) log.debug("Invoked launch command {}", this); - if (!quiet) stdout.println(BANNER); + if (!quiet) stdout.println(banner); if (verbose) { if (app != null) { @@ -773,7 +773,7 @@ public class Main extends AbstractMain { try { log.info("Retrieving and copying persisted state to "+destinationDir+(Strings.isBlank(destinationLocation) ? "" : " @ "+destinationLocation)); - if (!quiet) stdout.println(BANNER); + if (!quiet) stdout.println(banner); PersistMode persistMode = PersistMode.AUTO; HighAvailabilityMode highAvailabilityMode = HighAvailabilityMode.DISABLED; @@ -828,12 +828,6 @@ public class Main extends AbstractMain { } } - /** method intended for overriding when the script filename is different - * @return the name of the script the user has invoked */ - protected String cliScriptName() { - return "brooklyn"; - } - /** method intended for overriding when a different {@link Cli} is desired, * or when the subclass wishes to change any of the arguments */ @SuppressWarnings("unchecked") @@ -841,10 +835,10 @@ public class Main extends AbstractMain { protected CliBuilder<BrooklynCommand> cliBuilder() { CliBuilder<BrooklynCommand> builder = Cli.<BrooklynCommand>builder(cliScriptName()) .withDescription("Brooklyn Management Service") - .withDefaultCommand(DefaultInfoCommand.class) + .withDefaultCommand(cliDefaultInfoCommand()) .withCommands( HelpCommand.class, - InfoCommand.class, + cliInfoCommand(), GeneratePasswordCommand.class, CopyStateCommand.class, ListAllCommand.class, @@ -877,4 +871,14 @@ public class Main extends AbstractMain { protected Class<? extends BrooklynCommand> cliLaunchCommand() { return LaunchCommand.class; } + + /** method intended for overriding when a custom {@link InfoCommand} is being specified */ + protected Class<? extends BrooklynCommand> cliInfoCommand() { + return InfoCommand.class; + } + + /** method intended for overriding when a custom {@link InfoCommand} is being specified */ + protected Class<? extends BrooklynCommand> cliDefaultInfoCommand() { + return DefaultInfoCommand.class; + } } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/fa770403/usage/cli/src/test/java/brooklyn/cli/CliTest.java ---------------------------------------------------------------------- diff --git a/usage/cli/src/test/java/brooklyn/cli/CliTest.java b/usage/cli/src/test/java/brooklyn/cli/CliTest.java index 79e1b56..a50b058 100644 --- a/usage/cli/src/test/java/brooklyn/cli/CliTest.java +++ b/usage/cli/src/test/java/brooklyn/cli/CliTest.java @@ -24,6 +24,7 @@ import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import groovy.lang.GroovyClassLoader; import io.airlift.command.Cli; +import io.airlift.command.Command; import io.airlift.command.ParseException; import java.io.ByteArrayInputStream; @@ -48,6 +49,7 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import brooklyn.cli.AbstractMain.BrooklynCommand; +import brooklyn.cli.AbstractMain.BrooklynCommandCollectingArgs; import brooklyn.cli.AbstractMain.HelpCommand; import brooklyn.cli.Main.GeneratePasswordCommand; import brooklyn.cli.Main.LaunchCommand; @@ -410,6 +412,71 @@ public class CliTest { } } + @Test + public void testInfoShowsDefaultBanner() throws Exception { + List<String> stdoutLines = runCommand(ImmutableList.of("info"), ""); + + for (String line : Splitter.on("\n").split(Main.DEFAULT_BANNER)) { + assertTrue(stdoutLines.contains(line), "out="+stdoutLines); + } + } + + @Test + public void testInfoSupportsCustomizedBanner() throws Exception { + String origBanner = Main.banner; + String origBannerFirstLine = Iterables.get(Splitter.on("\n").split(Main.DEFAULT_BANNER), 0); + try { + String customBanner = "My Custom Banner"; + Main.banner = customBanner; + List<String> stdoutLines = runCommand(ImmutableList.of("info"), ""); + + assertTrue(stdoutLines.contains(customBanner), "out="+stdoutLines); + assertFalse(stdoutLines.contains(origBannerFirstLine), "out="+stdoutLines); + } finally { + Main.banner = origBanner; + } + } + + @Test + public void testCanCustomiseInfoCommand() throws Exception { + Main main = new Main() { + protected Class<? extends BrooklynCommand> cliInfoCommand() { + return CustomInfoCommand.class; + } + }; + List<String> stdoutLines = runCommand(main.cliBuilder().build(), ImmutableList.of("info"), ""); + assertTrue(stdoutLines.contains("My Custom Info"), "out="+stdoutLines); + } + + @Command(name = "info", description = "Display information about brooklyn") + public static class CustomInfoCommand extends BrooklynCommandCollectingArgs { + @Override + public Void call() throws Exception { + System.out.println("My Custom Info"); + return null; + } + } + + @Test + public void testCanCustomiseLaunchCommand() throws Exception { + Main main = new Main() { + protected Class<? extends BrooklynCommand> cliLaunchCommand() { + return CustomLaunchCommand.class; + } + }; + List<String> stdoutLines = runCommand(main.cliBuilder().build(), ImmutableList.of("launch"), ""); + assertTrue(stdoutLines.contains("My Custom Launch"), "out="+stdoutLines); + } + + @Command(name = "launch", description = "Starts a server, optionally with applications") + public static class CustomLaunchCommand extends BrooklynCommandCollectingArgs { + @Override + public Void call() throws Exception { + System.out.println("My Custom Launch"); + return null; + } + } + protected Throwable runCommandExpectingException(Iterable<String> args, String input) throws Exception { try { List<String> stdout = runCommand(args, input); @@ -422,6 +489,10 @@ public class CliTest { protected List<String> runCommand(Iterable<String> args, String input) throws Exception { Cli<BrooklynCommand> cli = buildCli(); + return runCommand(cli, args, input); + } + + protected List<String> runCommand(Cli<BrooklynCommand> cli, Iterable<String> args, String input) throws Exception { final BrooklynCommand command = cli.parse(args); final AtomicReference<Exception> exception = new AtomicReference<Exception>();
