Package com.cloudera.flume.shell

Source Code of com.cloudera.flume.shell.CommandBuilder

/**
* Licensed to Cloudera, Inc. under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  Cloudera, Inc. 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 com.cloudera.flume.shell;

import java.util.ArrayList;

import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.tree.CommonTree;
import org.apache.commons.lang.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.cloudera.flume.master.Command;
import com.cloudera.flume.shell.antlr.FlumeShellLexer;
import com.cloudera.flume.shell.antlr.FlumeShellParser;

/**
* Builds a command object from a string. Needed for sane command line parsing.
*
* Unquoted tokens can contain alphanumeric, '.',':','_', or '-'. Tokens
* enclosed in '"' will be java string unescaped. Tokens enclosed in ''' (single
* quotes) are not unescaped at all and concontain any char except for '''.
* Exceptions are thrown if quotes are not properly matched or invalid chars
* present in unquoted tokens. .
*/
public class CommandBuilder {
  public static final Logger LOG = LoggerFactory.getLogger(CommandBuilder.class);

  enum ASTNODE {
    CMD, DQUOTE, SQUOTE, STRING
  };

  /**
   * This hooks a particular string to the lexer. From there it creates a parser
   * that can be started from different entities. The lexer and language are
   * case sensitive.
   */
  static FlumeShellParser getShellCmdParser(String s) {
    FlumeShellLexer lexer = new FlumeShellLexer(new ANTLRStringStream(s));
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    return new FlumeShellParser(tokens);
  }

  static CommonTokenStream getTokenStream(String s) {
    FlumeShellLexer lexer = new FlumeShellLexer(new ANTLRStringStream(s));
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    return tokens;
  }

  static String toString(CommonTree literal) {
    ASTNODE type = ASTNODE.valueOf(literal.getText());
    switch (type) {
    case SQUOTE:
      // remove single quotes
      String sq = literal.getChild(0).getText();
      sq = sq.substring(1, sq.length() - 1);
      return sq;

    case DQUOTE:
      // remove double quotes and unescape
      String dq = literal.getChild(0).getText();
      dq = dq.substring(1, dq.length() - 1);
      return StringEscapeUtils.unescapeJava(dq);

    case STRING:
      // just return string
      return literal.getChild(0).getText();
    default:
      throw new IllegalStateException("illegal parse!");
    }
  }

  /**
   * This takes a single string and parses it into a Command.
   */
  public static Command parseLine(String s) throws RecognitionException {
    try {
      CommonTree cmd = (CommonTree) getShellCmdParser(s).line().getTree();
      CommonTree ast = (CommonTree) cmd.getChild(0);
      String command = toString(ast);
      cmd.deleteChild(0);
      ArrayList<String> lst = new ArrayList<String>();
      for (int i = 0; i < cmd.getChildCount(); i++) {
        String tok = toString((CommonTree) cmd.getChild(i));
        lst.add(tok);
      }
      return new Command(command, lst.toArray(new String[0]));

    } catch (RecognitionException e) {
      LOG.debug("Failed to parse line, '" + s + "' because of "
          + e.getMessage(), e);
      throw e;
    } catch (RuntimeException rex) {
      // right now lexer errors are RTE's
      LOG
          .debug("Failed to lex '" + s + "' because of " + rex.getMessage(),
              rex);
      throw new CommandLineException(rex);
    }
  }
}
TOP

Related Classes of com.cloudera.flume.shell.CommandBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.