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>();

Reply via email to