You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ji...@apache.org on 2016/12/06 16:43:27 UTC

[7/7] geode git commit: GEODE-1912: use Spring shell's parser and delete our own parsing code

GEODE-1912: use Spring shell's parser and delete our own parsing code


Project: http://git-wip-us.apache.org/repos/asf/geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/ce9e138c
Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/ce9e138c
Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/ce9e138c

Branch: refs/heads/GEODE-1912
Commit: ce9e138cc99df17df95b394540aca28b01ec06cb
Parents: 4876c78
Author: Jinmei Liao <ji...@pivotal.io>
Authored: Thu Oct 27 10:24:07 2016 -0700
Committer: Jinmei Liao <ji...@pivotal.io>
Committed: Tue Dec 6 08:42:49 2016 -0800

----------------------------------------------------------------------
 .../management/internal/cli/CommandManager.java |  545 ++----
 .../internal/cli/CommandResponseBuilder.java    |    5 +-
 .../internal/cli/GfshParseResult.java           |   71 +-
 .../management/internal/cli/GfshParser.java     | 1590 ++----------------
 .../geode/management/internal/cli/Launcher.java |   51 +-
 .../internal/cli/annotation/CliArgument.java    |   81 -
 .../internal/cli/commands/GfshHelpCommands.java |   75 +-
 .../cli/commands/LauncherLifecycleCommands.java |    6 +-
 .../internal/cli/commands/ShellCommands.java    |  418 +++--
 .../cli/converters/BooleanConverter.java        |   54 -
 .../internal/cli/converters/EnumConverter.java  |   64 -
 .../internal/cli/converters/HelpConverter.java  |   68 -
 .../cli/converters/HintTopicConverter.java      |   71 -
 .../cli/converters/StringArrayConverter.java    |   53 -
 .../cli/converters/StringListConverter.java     |   56 -
 .../cli/exceptions/CliCommandException.java     |   66 -
 .../exceptions/CliCommandInvalidException.java  |   39 -
 .../CliCommandMultiModeOptionException.java     |   49 -
 .../CliCommandNotAvailableException.java        |   36 -
 .../exceptions/CliCommandOptionException.java   |   65 -
 ...CommandOptionHasMultipleValuesException.java |   47 -
 .../CliCommandOptionInvalidException.java       |   37 -
 .../CliCommandOptionMissingException.java       |   45 -
 .../CliCommandOptionNotApplicableException.java |   46 -
 ...liCommandOptionValueConversionException.java |   38 -
 .../CliCommandOptionValueException.java         |   49 -
 .../CliCommandOptionValueMissingException.java  |   46 -
 .../cli/exceptions/ExceptionGenerator.java      |   48 -
 .../cli/exceptions/ExceptionHandler.java        |   92 -
 .../management/internal/cli/help/CliTopic.java  |  132 --
 .../internal/cli/help/format/Block.java         |   42 -
 .../internal/cli/help/format/DataNode.java      |   48 -
 .../internal/cli/help/format/Help.java          |   44 -
 .../internal/cli/help/format/HelpBlock.java     |   76 +
 .../internal/cli/help/format/NewHelp.java       |   52 -
 .../internal/cli/help/format/Row.java           |   28 -
 .../internal/cli/help/utils/FormatOutput.java   |   33 -
 .../internal/cli/help/utils/HelpUtils.java      |  422 ++---
 .../internal/cli/parser/Argument.java           |   71 -
 .../internal/cli/parser/AvailabilityTarget.java |  106 --
 .../internal/cli/parser/CommandTarget.java      |  176 --
 .../internal/cli/parser/GfshMethodTarget.java   |  121 --
 .../internal/cli/parser/GfshOptionParser.java   |   37 -
 .../internal/cli/parser/MethodParameter.java    |   39 -
 .../management/internal/cli/parser/Option.java  |  217 ---
 .../internal/cli/parser/OptionSet.java          |  128 --
 .../internal/cli/parser/Parameter.java          |  116 --
 .../internal/cli/parser/ParserUtils.java        |  186 --
 .../internal/cli/parser/SyntaxConstants.java    |   34 -
 .../cli/parser/jopt/JoptOptionParser.java       |  302 ----
 .../preprocessor/EnclosingCharacters.java       |   32 -
 .../cli/parser/preprocessor/Preprocessor.java   |  151 --
 .../parser/preprocessor/PreprocessorUtils.java  |  327 ----
 .../internal/cli/parser/preprocessor/Stack.java |   52 -
 .../cli/parser/preprocessor/TrimmedInput.java   |   44 -
 .../internal/cli/remote/CommandProcessor.java   |   23 +-
 .../management/internal/cli/shell/Gfsh.java     |  577 +++----
 .../internal/cli/shell/MultiCommandHelper.java  |   10 +-
 .../internal/cli/shell/jline/GfshHistory.java   |   21 +-
 .../internal/cli/util/CommandStringBuilder.java |   29 +-
 .../internal/cli/CommandManagerJUnitTest.java   |  148 +-
 .../internal/cli/GfshParserIntegrationTest.java |  259 ++-
 .../internal/cli/GfshParserJUnitTest.java       |  863 ----------
 .../internal/cli/JoptOptionParserTest.java      |  527 ------
 .../internal/cli/NewGfshParserJUnitTest.java    |   72 +
 .../cli/annotations/CliArgumentJUnitTest.java   |  154 --
 .../cli/commands/CliCommandTestBase.java        |   90 +-
 .../commands/HelpCommandsIntegrationTest.java   |  142 --
 .../cli/parser/ParserUtilsJUnitTest.java        |   81 -
 .../preprocessor/PreprocessorJUnitTest.java     |  296 ----
 .../PreprocessorUtilsJUnitTest.java             |  121 --
 .../shell/GfshExecutionStrategyJUnitTest.java   |   21 +-
 72 files changed, 1461 insertions(+), 8900 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/geode/blob/ce9e138c/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandManager.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandManager.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandManager.java
index 4400445..35b3071 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandManager.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandManager.java
@@ -14,68 +14,112 @@
  */
 package org.apache.geode.management.internal.cli;
 
+import static org.apache.geode.distributed.ConfigurationProperties.USER_COMMAND_PACKAGES;
+
 import org.apache.geode.distributed.ConfigurationProperties;
 import org.apache.geode.distributed.internal.DistributionConfig;
 import org.apache.geode.internal.ClassPathLoader;
-import org.apache.geode.management.cli.CliMetaData;
-import org.apache.geode.management.internal.cli.annotation.CliArgument;
-import org.apache.geode.management.internal.cli.help.CliTopic;
-import org.apache.geode.management.internal.cli.parser.*;
-import org.apache.geode.management.internal.cli.parser.jopt.JoptOptionParser;
 import org.apache.geode.management.internal.cli.util.ClasspathScanLoadHelper;
+import org.springframework.context.ApplicationContextAware;
 import org.springframework.shell.core.CommandMarker;
 import org.springframework.shell.core.Converter;
-import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
 import org.springframework.shell.core.annotation.CliCommand;
-import org.springframework.shell.core.annotation.CliOption;
 
 import java.io.IOException;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
-import java.util.*;
-import java.util.Map.Entry;
-
-import static org.apache.geode.distributed.ConfigurationProperties.*;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
 
 /**
+ *
+ * this only takes care of loading all available command markers and converters from the application
  * 
  * @since GemFire 7.0
  */
 public class CommandManager {
-  // 1. Load Commands, availability indicators - Take from GfshParser
-  // 2. Load Converters - Take from GfshParser
-  // 3. Load Result Converters - Add
-
-  private static final Object INSTANCE_LOCK = new Object();
-  private static CommandManager INSTANCE = null;
   public static final String USER_CMD_PACKAGES_PROPERTY =
       DistributionConfig.GEMFIRE_PREFIX + USER_COMMAND_PACKAGES;
   public static final String USER_CMD_PACKAGES_ENV_VARIABLE = "GEMFIRE_USER_COMMAND_PACKAGES";
+  private static final Object INSTANCE_LOCK = new Object();
+  private static CommandManager INSTANCE = null;
 
-  private Properties cacheProperties;
+  private final Map<String, Method> commands = new TreeMap<String, Method>();
+  private final Map<String, Annotation[]> annotations = new TreeMap<>();
+
+
+  /**
+   * List of converters which should be populated first before any command can be added
+   */
+  private final List<Converter<?>> converters = new ArrayList<Converter<?>>();
 
+  private final List<CommandMarker> commandMarkers = new ArrayList<>();
+  private Properties cacheProperties;
   private LogWrapper logWrapper;
 
-  private CommandManager(final boolean loadDefaultCommands, final Properties cacheProperties)
-      throws ClassNotFoundException, IOException {
+  private CommandManager(final Properties cacheProperties) {
     if (cacheProperties != null) {
       this.cacheProperties = cacheProperties;
     }
-
     logWrapper = LogWrapper.getInstance();
-    if (loadDefaultCommands) {
-      loadCommands();
+    loadCommands();
+  }
+
+  private static void raiseExceptionIfEmpty(Set<Class<?>> foundClasses, String errorFor)
+      throws IllegalStateException {
+    if (foundClasses == null || foundClasses.isEmpty()) {
+      throw new IllegalStateException(
+          "Required " + errorFor + " classes were not loaded. Check logs for errors.");
+    }
+  }
 
-      if (logWrapper.fineEnabled()) {
-        logWrapper.fine("Commands Loaded: " + commands.keySet());
-        logWrapper
-            .fine("Command Availability Indicators Loaded: " + availabilityIndicators.keySet());
-        logWrapper.fine("Converters Loaded: " + converters);
+  /**
+   * this is used when getting the instance from Gfsh VM. We are getting the user-command-package
+   * from system environment. used by Gfsh.
+   * 
+   * @return
+   * @throws ClassNotFoundException
+   * @throws IOException
+   */
+  public static CommandManager getInstance() throws ClassNotFoundException, IOException {
+    return getInstance(null);
+  }
+
+  /**
+   * this is used when getting the instance in a cache server. We are getting the
+   * user-command-package from distribution properties. used by CommandProcessor.
+   * 
+   * @param cacheProperties
+   * @return
+   * @throws ClassNotFoundException
+   * @throws IOException
+   */
+  public static CommandManager getInstance(Properties cacheProperties) {
+    synchronized (INSTANCE_LOCK) {
+      if (INSTANCE == null) {
+        INSTANCE = new CommandManager(cacheProperties);
       }
+      return INSTANCE;
     }
   }
 
-  private void loadUserCommands() throws ClassNotFoundException, IOException {
+  // For testing.
+  public static void clearInstance() {
+    synchronized (INSTANCE_LOCK) {
+      INSTANCE = null;
+    }
+  }
+
+  private void loadUserCommands() {
     final Set<String> userCommandPackages = new HashSet<String>();
 
     // Find by packages specified by the system property
@@ -124,10 +168,8 @@ public class CommandManager {
         raiseExceptionIfEmpty(foundClasses, "User Command");
       } catch (ClassNotFoundException e) {
         logWrapper.warning("Could not load User Commands due to " + e.getLocalizedMessage());
-        throw e;
       } catch (IOException e) {
         logWrapper.warning("Could not load User Commands due to " + e.getLocalizedMessage());
-        throw e;
       } catch (IllegalStateException e) {
         logWrapper.warning(e.getMessage(), e);
         throw e;
@@ -137,7 +179,7 @@ public class CommandManager {
 
   /**
    * Loads commands via {@link ServiceLoader} from {@link ClassPathLoader}.
-   * 
+   *
    * @since GemFire 8.1
    */
   private void loadPluginCommands() {
@@ -158,7 +200,7 @@ public class CommandManager {
     }
   }
 
-  private void loadCommands() throws ClassNotFoundException, IOException {
+  private void loadCommands() {
     loadUserCommands();
 
     loadPluginCommands();
@@ -166,6 +208,7 @@ public class CommandManager {
     // CommandMarkers
     Set<Class<?>> foundClasses = null;
     try {
+      // geode's commands
       foundClasses = ClasspathScanLoadHelper.loadAndGet(
           "org.apache.geode.management.internal.cli.commands", CommandMarker.class, true);
       for (Class<?> klass : foundClasses) {
@@ -177,12 +220,27 @@ public class CommandManager {
         }
       }
       raiseExceptionIfEmpty(foundClasses, "Commands");
+
+      // Spring shell's commands
+      foundClasses = ClasspathScanLoadHelper.loadAndGet("org.springframework.shell.commands",
+          CommandMarker.class, true);
+      for (Class<?> klass : foundClasses) {
+        if (ApplicationContextAware.class.isAssignableFrom(klass)) {
+          // skip the ApplicationContextAware commands. i.e. the HelpCommands
+          continue;
+        }
+        try {
+          add((CommandMarker) klass.newInstance());
+        } catch (Exception e) {
+          logWrapper.warning(
+              "Could not load Command from: " + klass + " due to " + e.getLocalizedMessage()); // continue
+        }
+      }
+      raiseExceptionIfEmpty(foundClasses, "Commands");
     } catch (ClassNotFoundException e) {
       logWrapper.warning("Could not load Commands due to " + e.getLocalizedMessage());
-      throw e;
     } catch (IOException e) {
       logWrapper.warning("Could not load Commands due to " + e.getLocalizedMessage());
-      throw e;
     } catch (IllegalStateException e) {
       logWrapper.warning(e.getMessage(), e);
       throw e;
@@ -201,26 +259,13 @@ public class CommandManager {
         }
       }
       raiseExceptionIfEmpty(foundClasses, "Converters");
-    } catch (ClassNotFoundException e) {
-      logWrapper.warning("Could not load Converters due to " + e.getLocalizedMessage());
-      throw e;
-    } catch (IOException e) {
-      logWrapper.warning("Could not load Converters due to " + e.getLocalizedMessage());
-      throw e;
-    } catch (IllegalStateException e) {
-      logWrapper.warning(e.getMessage(), e);
-      throw e;
-    }
 
-    // Roo's Converters
-    try {
+      // Spring shell's converters
       foundClasses = ClasspathScanLoadHelper.loadAndGet("org.springframework.shell.converters",
           Converter.class, true);
       for (Class<?> klass : foundClasses) {
         try {
-          if (!SHL_CONVERTERS_TOSKIP.contains(klass.getName())) {
-            add((Converter<?>) klass.newInstance());
-          }
+          add((Converter<?>) klass.newInstance());
         } catch (Exception e) {
           logWrapper.warning(
               "Could not load Converter from: " + klass + " due to " + e.getLocalizedMessage()); // continue
@@ -228,116 +273,26 @@ public class CommandManager {
       }
       raiseExceptionIfEmpty(foundClasses, "Basic Converters");
     } catch (ClassNotFoundException e) {
-      logWrapper.warning("Could not load Default Converters due to " + e.getLocalizedMessage());// TODO
-                                                                                                // -
-                                                                                                // Abhishek:
-                                                                                                // Should
-                                                                                                // these
-                                                                                                // converters
-                                                                                                // be
-                                                                                                // moved
-                                                                                                // in
-                                                                                                // GemFire?
-      throw e;
+      logWrapper.warning("Could not load Converters due to " + e.getLocalizedMessage());
     } catch (IOException e) {
-      logWrapper.warning("Could not load Default Converters due to " + e.getLocalizedMessage());// TODO
-                                                                                                // -
-                                                                                                // Abhishek:
-                                                                                                // Should
-                                                                                                // these
-                                                                                                // converters
-                                                                                                // be
-                                                                                                // moved
-                                                                                                // in
-                                                                                                // GemFire?
-      throw e;
+      logWrapper.warning("Could not load Converters due to " + e.getLocalizedMessage());
     } catch (IllegalStateException e) {
       logWrapper.warning(e.getMessage(), e);
       throw e;
     }
   }
 
-  private static void raiseExceptionIfEmpty(Set<Class<?>> foundClasses, String errorFor)
-      throws IllegalStateException {
-    if (foundClasses == null || foundClasses.isEmpty()) {
-      throw new IllegalStateException(
-          "Required " + errorFor + " classes were not loaded. Check logs for errors.");
-    }
-  }
-
-  public static CommandManager getInstance() throws ClassNotFoundException, IOException {
-    return getInstance(true);
-  }
-
-  public static CommandManager getInstance(Properties cacheProperties)
-      throws ClassNotFoundException, IOException {
-    return getInstance(true, cacheProperties);
-  }
-
-  // For testing.
-  public static void clearInstance() {
-    synchronized (INSTANCE_LOCK) {
-      INSTANCE = null;
-    }
-  }
-
-  // This method exists for test code use only ...
-  /* package */static CommandManager getInstance(boolean loadDefaultCommands)
-      throws ClassNotFoundException, IOException {
-    return getInstance(loadDefaultCommands, null);
-  }
-
-  private static CommandManager getInstance(boolean loadDefaultCommands, Properties cacheProperties)
-      throws ClassNotFoundException, IOException {
-    synchronized (INSTANCE_LOCK) {
-      if (INSTANCE == null) {
-        INSTANCE = new CommandManager(loadDefaultCommands, cacheProperties);
-      }
-      return INSTANCE;
-    }
-  }
-
-  public static CommandManager getExisting() {
-    // if (INSTANCE == null) {
-    // throw new IllegalStateException("CommandManager doesn't exist.");
-    // }
-    return INSTANCE;
+  public List<Converter<?>> getConverters() {
+    return converters;
   }
 
-  /** Skip some of the Converters from Spring Shell for our customization */
-  private static List<String> SHL_CONVERTERS_TOSKIP = new ArrayList<String>();
-  static {
-    // Over-ridden by cggm.internal.cli.converters.BooleanConverter
-    SHL_CONVERTERS_TOSKIP.add("org.springframework.shell.converters.BooleanConverter");
-    // Over-ridden by cggm.internal.cli.converters.EnumConverter
-    SHL_CONVERTERS_TOSKIP.add("org.springframework.shell.converters.EnumConverter");
+  public List<CommandMarker> getCommandMarkers() {
+    return commandMarkers;
   }
 
   /**
-   * List of converters which should be populated first before any command can be added
-   */
-  private final List<Converter<?>> converters = new ArrayList<Converter<?>>();
-
-  /**
-   * Map of command string and actual CommandTarget object
-   * 
-   * This map can also be implemented as a trie to support command abbreviation
-   */
-  private final Map<String, CommandTarget> commands = new TreeMap<String, CommandTarget>();
-
-  /**
-   * This method will store the all the availabilityIndicators
-   */
-  private final Map<String, AvailabilityTarget> availabilityIndicators =
-      new HashMap<String, AvailabilityTarget>();
-
-  /**
-   */
-  private final Map<String, CliTopic> topics = new TreeMap<String, CliTopic>();
-
-  /**
    * Method to add new Converter
-   * 
+   *
    * @param converter
    */
   public void add(Converter<?> converter) {
@@ -346,299 +301,25 @@ public class CommandManager {
 
   /**
    * Method to add new Commands to the parser
-   * 
+   *
    * @param commandMarker
    */
   public void add(CommandMarker commandMarker) {
-    // First we need to find out all the methods marked with
-    // Command annotation
-    Method[] methods = commandMarker.getClass().getMethods();
-    for (Method method : methods) {
-      if (method.getAnnotation(CliCommand.class) != null) {
-
-        //
-        // First Build the option parser
-        //
-
-        // Create the empty LinkedLists for storing the argument and
-        // options
-        LinkedList<Argument> arguments = new LinkedList<Argument>();
-        LinkedList<Option> options = new LinkedList<Option>();
-        // Also we need to create the OptionParser for each command
-        GfshOptionParser optionParser = getOptionParser();
-        // Now get all the parameters annotations of the method
-        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
-        // Also get the parameter Types
-        Class<?>[] parameterTypes = method.getParameterTypes();
-
-        int parameterNo = 0;
-
-        for (int i = 0; i < parameterAnnotations.length; i++) {
-          // Get all the annotations for this specific parameter
-          Annotation[] annotations = parameterAnnotations[i];
-          // Also get the parameter type for this parameter
-          Class<?> parameterType = parameterTypes[i];
-
-          boolean paramFound = false;
-          String valueSeparator = CliMetaData.ANNOTATION_NULL_VALUE;
-          for (Annotation annotation : annotations) {
-            if (annotation instanceof CliArgument) {
-              // Here we need to create the argument Object
-              Argument argumentToAdd =
-                  createArgument((CliArgument) annotation, parameterType, parameterNo);
-              arguments.add(argumentToAdd);
-              parameterNo++;
-            } else if (annotation instanceof CliOption) {
-              Option createdOption =
-                  createOption((CliOption) annotation, parameterType, parameterNo);
-              if (!CliMetaData.ANNOTATION_NULL_VALUE.equals(valueSeparator)) { // CliMetaData was
-                                                                               // found earlier
-                createdOption.setValueSeparator(valueSeparator);
-
-                // reset valueSeparator back to null
-                valueSeparator = CliMetaData.ANNOTATION_NULL_VALUE;
-              } else { // CliMetaData is yet to be found
-                paramFound = true;
-              }
-              options.add(createdOption);
-              parameterNo++;
-            } else if (annotation instanceof CliMetaData) {
-              valueSeparator = ((CliMetaData) annotation).valueSeparator();
-              if (!CliMetaData.ANNOTATION_NULL_VALUE.equals(valueSeparator)) {
-                if (paramFound) { // CliOption was detected earlier
-                  Option lastAddedOption = options.getLast();
-                  lastAddedOption.setValueSeparator(valueSeparator);
-                  // reset valueSeparator back to null
-                  valueSeparator = CliMetaData.ANNOTATION_NULL_VALUE;
-                } // param not found yet, store valueSeparator value
-              } else {
-                // reset valueSeparator back to null
-                valueSeparator = CliMetaData.ANNOTATION_NULL_VALUE;
-              }
-            }
-          }
-        }
-        optionParser.setArguments(arguments);
-        optionParser.setOptions(options);
-
-        //
-        // Now build the commandTarget
-        //
-
-        // First build the MethodTarget for the command Method
-        GfshMethodTarget gfshMethodTarget = new GfshMethodTarget(method, commandMarker);
-
-        // Fetch the value array from the cliCommand annotation
-        CliCommand cliCommand = method.getAnnotation(CliCommand.class);
-        String[] values = cliCommand.value();
-
-        // First string will point to the command
-        // rest of them will act as synonyms
-        String commandName = null;
-        String[] synonyms = null;
-        if (values.length > 1) {
-          synonyms = new String[values.length - 1];
-        }
-
-        commandName = values[0];
-
-        for (int j = 1; j < values.length; j++) {
-          synonyms[j - 1] = values[j];
-        }
-
-        // Create the commandTarget object
-        CommandTarget commandTarget = new CommandTarget(commandName, synonyms, gfshMethodTarget,
-            optionParser, null, cliCommand.help());
-
-        // Now for each string in values put an entry in the commands
-        // map
-        for (String string : values) {
-          if (commands.get(string) == null) {
-            commands.put(string, commandTarget);
-          } else {
-            // TODO Handle collision
-            logWrapper.info("Multiple commands configured with the same name: " + string);
-          }
-        }
-
-        if (CliUtil.isGfshVM()) {
-          CliMetaData commandMetaData = method.getAnnotation(CliMetaData.class);
-          if (commandMetaData != null) {
-            String[] relatedTopics = commandMetaData.relatedTopic();
-            // System.out.println("relatedTopic :: "+Arrays.toString(relatedTopics));
-            for (String topicName : relatedTopics) {
-              CliTopic topic = topics.get(topicName);
-              if (topic == null) {
-                topic = new CliTopic(topicName);
-                topics.put(topicName, topic);
-              }
-              topic.addCommandTarget(commandTarget);
-            }
-          }
-        }
-
-      } else if (method.getAnnotation(CliAvailabilityIndicator.class) != null) {
-        // Now add this availability Indicator to the list of
-        // availability Indicators
-        CliAvailabilityIndicator cliAvailabilityIndicator =
-            method.getAnnotation(CliAvailabilityIndicator.class);
-
-        // Create a AvailabilityTarget for this availability Indicator
-        AvailabilityTarget availabilityIndicator = new AvailabilityTarget(commandMarker, method);
-
-        String[] value = cliAvailabilityIndicator.value();
-        for (String string : value) {
-          availabilityIndicators.put(string, availabilityIndicator);
-        }
-
-      }
-    }
-    // Now we must update all the existing CommandTargets to add
-    // this availability Indicator if it applies to them
-    updateAvailabilityIndicators();
-  }
-
-
-  /**
-   * Will update all the references to availability Indicators for commands
-   * 
-   */
-  public void updateAvailabilityIndicators() {
-    for (String string : availabilityIndicators.keySet()) {
-      CommandTarget commandTarget = commands.get(string);
-      if (commandTarget != null) {
-        commandTarget.setAvailabilityIndicator(availabilityIndicators.get(string));
-      }
-    }
-  }
-
-  /**
-   * Creates a new {@link Option} instance
-   * 
-   * @param cliOption
-   * @param parameterType
-   * @param parameterNo
-   * @return Option
-   */
-  public Option createOption(CliOption cliOption, Class<?> parameterType, int parameterNo) {
-    Option option = new Option();
-
-    // First set the Option identifiers
-    List<String> synonyms = new ArrayList<String>();
-    for (String string : cliOption.key()) {
-      if (!option.setLongOption(string)) {
-        synonyms.add(string);
+    commandMarkers.add(commandMarker);
+    for (Method method : commandMarker.getClass().getMethods()) {
+      CliCommand cliCommand = method.getAnnotation(CliCommand.class);
+      if (cliCommand != null) {
+        commands.put(cliCommand.value()[0], method);
+        annotations.put(cliCommand.value()[0], method.getDeclaredAnnotations());
       }
     }
-    option.setSynonyms(synonyms);
-    if (!(option.getAggregate().size() > 0)) {
-      logWrapper.warning("Option should have a name");
-    }
-    // Set the option Help
-    option.setHelp(cliOption.help());
-
-    // Set whether the option is required or not
-    option.setRequired(cliOption.mandatory());
-
-    // Set the fields related to option value
-    option.setSystemProvided(cliOption.systemProvided());
-    option.setSpecifiedDefaultValue(cliOption.specifiedDefaultValue());
-    option.setUnspecifiedDefaultValue(cliOption.unspecifiedDefaultValue());
-
-    // Set the things which are useful for value conversion and
-    // auto-completion
-    option.setContext(cliOption.optionContext());
-    // Find the matching Converter<?> for this option
-    option.setConverter(getConverter(parameterType, option.getContext()));
-
-    option.setDataType(parameterType);
-    option.setParameterNo(parameterNo);
-    return option;
   }
 
-  /**
-   * Creates a new {@link Argument} instance
-   * 
-   * @param cliArgument
-   * @param parameterType
-   * @param parameterNo
-   * @return Argument
-   */
-  public Argument createArgument(CliArgument cliArgument, Class<?> parameterType, int parameterNo) {
-    Argument argument = new Argument();
-    argument.setArgumentName(cliArgument.name());
-    argument.setContext(cliArgument.argumentContext());
-    argument.setConverter(getConverter(parameterType, argument.getContext()));
-    argument.setHelp(cliArgument.help());
-    argument.setRequired(cliArgument.mandatory());
-    argument.setDataType(parameterType);
-    argument.setParameterNo(parameterNo);
-    argument.setUnspecifiedDefaultValue(cliArgument.unspecifiedDefaultValue());
-    argument.setSystemProvided(cliArgument.systemProvided());
-    return argument;
+  public Method getCommandMethod(String command) {
+    return commands.get(command);
   }
 
-  /**
-   * Looks for a matching {@link Converter}
-   * 
-   * @param parameterType
-   * @param context
-   * @return {@link Converter}
-   */
-  public Converter<?> getConverter(Class<?> parameterType, String context) {
-    for (Converter<?> converter : converters) {
-      if (converter.supports(parameterType, context)) {
-        return converter;
-      }
-    }
-    return null;
-  }
-
-  /**
-   * For the time being this method returns a {@link JoptOptionParser} object but in the future we
-   * can change which optionParser should be returned.
-   * 
-   * @return {@link GfshOptionParser}
-   */
-  private GfshOptionParser getOptionParser() {
-    return new JoptOptionParser();
-  }
-
-  /**
-   * @return the commands
-   */
-  public Map<String, CommandTarget> getCommands() {
-    return Collections.unmodifiableMap(commands);
-  }
-
-  AvailabilityTarget getAvailabilityIndicator(Object key) {
-    return availabilityIndicators.get(key);
-  }
-
-  public Set<String> getTopicNames() {
-    Set<String> topicsNames = topics.keySet();
-    return Collections.unmodifiableSet(topicsNames);
-  }
-
-  public List<CliTopic> getTopics() {
-    List<CliTopic> topicsList = new ArrayList<CliTopic>(topics.values());
-    return Collections.unmodifiableList(topicsList);
-  }
-
-  public CliTopic getTopic(String topicName) {
-    CliTopic foundTopic = topics.get(topicName);
-
-    if (foundTopic == null) {
-      Set<Entry<String, CliTopic>> entries = topics.entrySet();
-
-      for (Entry<String, CliTopic> entry : entries) {
-        if (entry.getKey().equalsIgnoreCase(topicName)) {
-          foundTopic = entry.getValue();
-          break;
-        }
-      }
-    }
-
-    return foundTopic;
+  public Set<String> getCommands() {
+    return commands.keySet();
   }
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/ce9e138c/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandResponseBuilder.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandResponseBuilder.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandResponseBuilder.java
index bda030d..3f8f20d 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandResponseBuilder.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/CommandResponseBuilder.java
@@ -14,6 +14,7 @@
  */
 package org.apache.geode.management.internal.cli;
 
+import org.apache.geode.management.cli.CliMetaData;
 import org.apache.geode.management.internal.cli.json.GfJsonException;
 import org.apache.geode.management.internal.cli.json.GfJsonObject;
 import org.apache.geode.management.internal.cli.remote.CommandExecutionContext;
@@ -24,8 +25,6 @@ import org.apache.geode.management.internal.cli.result.CommandResult;
  * @since GemFire 7.0
  */
 public class CommandResponseBuilder {
-  // Command Response Constants
-  private static final String NO_TOKEN_ACCESSOR = "__NULL__";
 
   public static CommandResponse prepareCommandResponse(String memberName, CommandResult result) {
     GfJsonObject content = null;
@@ -42,7 +41,7 @@ public class CommandResponseBuilder {
         getType(result), // contentType
         result.getStatus().getCode(), // status code
         "1/1", // page --- TODO - Abhishek - define a scrollable ResultData
-        NO_TOKEN_ACCESSOR, // tokenAccessor for next results
+        CliMetaData.ANNOTATION_NULL_VALUE, // tokenAccessor for next results
         getDebugInfo(result), // debugData
         result.getHeader(), // header
         content, // content

http://git-wip-us.apache.org/repos/asf/geode/blob/ce9e138c/geode-core/src/main/java/org/apache/geode/management/internal/cli/GfshParseResult.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/GfshParseResult.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/GfshParseResult.java
index d879e2d..d1e46a3 100755
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/GfshParseResult.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/GfshParseResult.java
@@ -14,17 +14,20 @@
  */
 package org.apache.geode.management.internal.cli;
 
+import org.apache.commons.lang.StringUtils;
+import org.apache.geode.management.cli.CliMetaData;
+import org.apache.geode.management.internal.cli.shell.GfshExecutionStrategy;
+import org.apache.geode.management.internal.cli.shell.OperationInvoker;
+import org.springframework.shell.core.annotation.CliCommand;
+import org.springframework.shell.core.annotation.CliOption;
+import org.springframework.shell.event.ParseResult;
+
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.springframework.shell.event.ParseResult;
-
-import org.apache.geode.management.cli.CliMetaData;
-import org.apache.geode.management.internal.cli.shell.GfshExecutionStrategy;
-import org.apache.geode.management.internal.cli.shell.OperationInvoker;
-
 /**
  * Immutable representation of the outcome of parsing a given shell line. * Extends
  * {@link ParseResult} to add a field to specify the command string that was input by the user.
@@ -41,7 +44,7 @@ import org.apache.geode.management.internal.cli.shell.OperationInvoker;
 public class GfshParseResult extends ParseResult {
   private String userInput;
   private String commandName;
-  private Map<String, String> paramValueStringMap;
+  private Map<String, String> paramValueStringMap = new HashMap<>();
 
   /**
    * Creates a GfshParseResult instance to represent parsing outcome.
@@ -52,12 +55,34 @@ public class GfshParseResult extends ParseResult {
    * @param userInput user specified commands string
    */
   protected GfshParseResult(final Method method, final Object instance, final Object[] arguments,
-      final String userInput, final String commandName,
-      final Map<String, String> parametersAsString) {
+      final String userInput) {
     super(method, instance, arguments);
-    this.userInput = userInput;
-    this.commandName = commandName;
-    this.paramValueStringMap = new HashMap<String, String>(parametersAsString);
+    this.userInput = userInput.trim();
+
+    CliCommand cliCommand = method.getAnnotation(CliCommand.class);
+    commandName = cliCommand.value()[0];
+
+    Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+    if (arguments == null) {
+      return;
+    }
+
+    for (int i = 0; i < arguments.length; i++) {
+      Object argument = arguments[i];
+      if (argument == null) {
+        continue;
+      }
+
+      CliOption cliOption = getCliOption(parameterAnnotations, i);
+
+      String argumentAsString;
+      if (argument instanceof Object[]) {
+        argumentAsString = StringUtils.join((Object[]) argument, ",");
+      } else {
+        argumentAsString = argument.toString();
+      }
+      paramValueStringMap.put(cliOption.key()[0], argumentAsString);
+    }
   }
 
   /**
@@ -67,7 +92,6 @@ public class GfshParseResult extends ParseResult {
     return userInput;
   }
 
-
   /**
    * @return the unmodifiable paramValueStringMap
    */
@@ -75,18 +99,17 @@ public class GfshParseResult extends ParseResult {
     return Collections.unmodifiableMap(paramValueStringMap);
   }
 
-  @Override
-  public String toString() {
-    StringBuilder builder = new StringBuilder();
-    builder.append(GfshParseResult.class.getSimpleName());
-    builder.append(" [method=").append(getMethod());
-    builder.append(", instance=").append(getInstance());
-    builder.append(", arguments=").append(CliUtil.arrayToString(getArguments()));
-    builder.append("]");
-    return builder.toString();
-  }
-
   public String getCommandName() {
     return commandName;
   }
+
+  private CliOption getCliOption(Annotation[][] parameterAnnotations, int index) {
+    Annotation[] annotations = parameterAnnotations[index];
+    for (Annotation annotation : annotations) {
+      if (annotation instanceof CliOption) {
+        return (CliOption) annotation;
+      }
+    }
+    return null;
+  }
 }