All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.geode.management.internal.cli.GfshParser Maven / Gradle / Ivy

Go to download

Apache Geode provides a database-like consistency model, reliable transaction processing and a shared-nothing architecture to maintain very low latency performance with high concurrency processing

There is a newer version: 1.15.1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package org.apache.geode.management.internal.cli;

import org.apache.commons.lang.StringUtils;
import org.apache.geode.management.cli.CommandProcessingException;
import org.apache.geode.management.internal.cli.exceptions.CliCommandMultiModeOptionException;
import org.apache.geode.management.internal.cli.exceptions.CliCommandOptionException;
import org.apache.geode.management.internal.cli.exceptions.CliException;
import org.apache.geode.management.internal.cli.exceptions.ExceptionHandler;
import org.apache.geode.management.internal.cli.help.format.NewHelp;
import org.apache.geode.management.internal.cli.help.utils.HelpUtils;
import org.apache.geode.management.internal.cli.i18n.CliStrings;
import org.apache.geode.management.internal.cli.modes.CommandModes;
import org.apache.geode.management.internal.cli.modes.CommandModes.CommandMode;
import org.apache.geode.management.internal.cli.parser.Argument;
import org.apache.geode.management.internal.cli.parser.AvailabilityTarget;
import org.apache.geode.management.internal.cli.parser.CommandTarget;
import org.apache.geode.management.internal.cli.parser.GfshMethodTarget;
import org.apache.geode.management.internal.cli.parser.MethodParameter;
import org.apache.geode.management.internal.cli.parser.Option;
import org.apache.geode.management.internal.cli.parser.OptionSet;
import org.apache.geode.management.internal.cli.parser.Parameter;
import org.apache.geode.management.internal.cli.parser.ParserUtils;
import org.apache.geode.management.internal.cli.parser.SyntaxConstants;
import org.apache.geode.management.internal.cli.parser.preprocessor.PreprocessorUtils;
import org.apache.geode.management.internal.cli.parser.preprocessor.TrimmedInput;
import org.apache.geode.management.internal.cli.shell.Gfsh;
import org.apache.geode.management.internal.cli.util.CLIConsoleBufferUtil;
import org.springframework.shell.core.AbstractShell;
import org.springframework.shell.core.Completion;
import org.springframework.shell.core.Converter;
import org.springframework.shell.core.MethodTarget;
import org.springframework.shell.core.Parser;
import org.springframework.shell.event.ParseResult;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.logging.Logger;
import java.util.regex.Pattern;

/**
 * Implementation of the {@link Parser} interface for GemFire SHell (gfsh) requirements.
 *
 * @since GemFire 7.0
 */
public class GfshParser implements Parser {

  public static final String LINE_SEPARATOR = System.getProperty("line.separator");

  // Constants used while finding command targets for help
  private final static Short EXACT_TARGET = (short) 0;
  private final static Short MATCHING_TARGETS = (short) 1;

  // Make use of LogWrapper
  private static final LogWrapper logWrapper = LogWrapper.getInstance();

  // private CliStringResourceBundle cliStringBundle;
  private CommandManager commandManager;

  /**
   * Used for warning messages
   */
  // TODO Investigating using GemFire logging.
  private final Logger consoleLogger;

  public GfshParser(CommandManager commandManager) {
    // cliStringBundle = new
    // CliStringResourceBundle("org/apache/geode/management/internal/cli/i18n/CliStringResourceBundle");
    this.commandManager = commandManager;
    if (CliUtil.isGfshVM()) {
      consoleLogger = Logger.getLogger(this.getClass().getCanonicalName());
    } else {
      consoleLogger = logWrapper.getLogger();
    }
  }

  // ///////////////// Parser interface Methods Start //////////////////////////
  // ////////////////////// Implemented Methods ////////////////////////////////

  /**
   * Populates a list of completion candidates. See {@link Parser#complete(String, int, List)} for
   * details.
   *
   * @param buffer
   * @param cursor
   * @param completionCandidates
   *
   * @return new cursor position
   */
  public int complete(String buffer, int cursor, List completionCandidates) {
    final List candidates = new ArrayList();
    final int result = completeAdvanced(buffer, cursor, candidates);
    for (final Completion completion : candidates) {
      completionCandidates.add(completion.getValue());
    }
    return result;
  }

  /**
   * Populates a list of completion candidates.
   *
   * @param buffer
   * @param cursor
   * @param completionCandidates
   *
   * @return new cursor position
   */
  public int completeAdvanced(String buffer, int cursor, List completionCandidates) {
    // Currently, support for auto-completion
    // in between is not supported, only if the
    // cursor is at the end

    if (cursor <= buffer.length() - 1
        && !PreprocessorUtils.containsOnlyWhiteSpaces(buffer.substring(cursor))
        || (ParserUtils.contains(buffer, SyntaxConstants.COMMAND_DELIMITER))) {
      return cursor;
    }

    int desiredCursorPosition = 0;

    try {
      TrimmedInput simpleTrim = PreprocessorUtils.simpleTrim(buffer);
      desiredCursorPosition += simpleTrim.getNoOfSpacesRemoved();
      List targets = locateTargets(simpleTrim.getString());
      if (targets.size() > 1) {
        String padding =
            desiredCursorPosition != 0 ? ParserUtils.getPadding(desiredCursorPosition) : "";
        // This means that what the user has entered matches
        // the beginning of many commands
        for (CommandTarget commandTarget : targets) {
          completionCandidates
              .add(new Completion(padding + commandTarget.getGfshMethodTarget().getKey()));
        }
      } else {
        if (targets.size() == 1) {
          CommandTarget commandTarget = targets.get(0);
          // Only one command matches but we still have to check
          // whether the user has properly entered it or not
          if (simpleTrim.getString().length() >= commandTarget.getGfshMethodTarget().getKey()
              .length()) {
            /* int position = */
            return completeParameters(commandTarget,
                desiredCursorPosition + commandTarget.getGfshMethodTarget().getKey().length(),
                commandTarget.getGfshMethodTarget().getRemainingBuffer(), cursor,
                completionCandidates);
            /*
             * updateCompletionCandidates(completionCandidates, buffer, position); return 0;
             */
          } else {
            String padding =
                desiredCursorPosition != 0 ? ParserUtils.getPadding(desiredCursorPosition) : "";
            // User has still not entered the command name properly,
            // we need to populate the completionCandidates list
            completionCandidates
                .add(new Completion(padding + commandTarget.getGfshMethodTarget().getKey()));
          }
        }
      }

    } catch (IllegalArgumentException e) {
      logWrapper.warning(CliUtil.stackTraceAsString(e));
    } catch (IllegalAccessException e) {
      logWrapper.warning(CliUtil.stackTraceAsString(e));
    } catch (InvocationTargetException e) {
      logWrapper.warning(CliUtil.stackTraceAsString(e));
    } catch (RuntimeException e) {
      logWrapper.warning(CliUtil.stackTraceAsString(e));
    }
    // Returning 0 for exceptions too. This will break the completors' loop in
    // jline.ConsoleReader.complete() & will return false
    return 0;
  }

  @SuppressWarnings("unused")
  private void updateCompletionCandidates(List completionCandidates, String buffer,
      int position) {
    List temp = new ArrayList();
    while (completionCandidates.size() > 0) {
      temp.add(completionCandidates.remove(0));
    }
    for (Completion completion : temp) {
      completionCandidates.add(new Completion(buffer.substring(0, position) + completion.getValue(),
          completion.getFormattedValue(), completion.getHeading(), completion.getOrder()));
    }
  }

  private int completeParameters(CommandTarget commandTarget, int cursorStart,
      String remainingBuffer, int cursor, List completionCandidates) {
    int desiredCursorPosition = cursorStart;
    // Factor for remainingBuffer
    boolean sizeReduced = false;
    // We need to work modify the flow according to the CliException
    // generated. For that we will need a reference to the Exception
    // CliException reference
    CliCommandOptionException coe = null;
    OptionSet userOptionSet = null;
    try {
      // We need to remove the space which separates command from the
      // parameters
      if (remainingBuffer.length() > 0) {
        remainingBuffer = remainingBuffer.substring(1);
        sizeReduced = true;
      }

      userOptionSet = commandTarget.getOptionParser().parse(remainingBuffer);
    } catch (CliException ce) {
      if (ce instanceof CliCommandOptionException) {
        coe = (CliCommandOptionException) ce;
        coe.setCommandTarget(commandTarget);
        userOptionSet = coe.getOptionSet();
      }
    }

    // Contains mandatory options which have not been specified
    List




© 2015 - 2024 Weber Informatics LLC | Privacy Policy