diff --git a/beeline/pom.xml b/beeline/pom.xml index af67b00f0d7f..1bc1a77aa1e9 100644 --- a/beeline/pom.xml +++ b/beeline/pom.xml @@ -80,7 +80,7 @@ jackson-core - jline + org.jline jline @@ -114,6 +114,11 @@ + + org.apache.hadoop + hadoop-hdfs + test + org.apache.thrift libthrift diff --git a/beeline/src/java/org/apache/hive/beeline/AbstractCommandHandler.java b/beeline/src/java/org/apache/hive/beeline/AbstractCommandHandler.java index 7fc3f958f5dc..579df9f79b62 100644 --- a/beeline/src/java/org/apache/hive/beeline/AbstractCommandHandler.java +++ b/beeline/src/java/org/apache/hive/beeline/AbstractCommandHandler.java @@ -26,8 +26,8 @@ import java.util.LinkedList; import java.util.List; -import jline.console.completer.Completer; -import jline.console.completer.NullCompleter; +import org.jline.reader.Completer; +import org.jline.reader.impl.completer.NullCompleter; /** * An abstract implementation of CommandHandler. diff --git a/beeline/src/java/org/apache/hive/beeline/BeeLine.java b/beeline/src/java/org/apache/hive/beeline/BeeLine.java index 33d13013049d..b268da08d848 100644 --- a/beeline/src/java/org/apache/hive/beeline/BeeLine.java +++ b/beeline/src/java/org/apache/hive/beeline/BeeLine.java @@ -28,6 +28,7 @@ import java.io.EOFException; import java.io.File; import java.io.FileInputStream; +import java.io.IOError; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -87,7 +88,6 @@ import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.hive.conf.Constants; import org.apache.hadoop.hive.conf.HiveConf; @@ -100,6 +100,7 @@ import org.apache.hive.beeline.hs2connection.HS2ConnectionFileUtils; import org.apache.hive.beeline.hs2connection.HiveSiteHS2ConnectionFileParser; import org.apache.hive.beeline.hs2connection.UserHS2ConnectionFileParser; +import org.apache.hive.common.util.MatchingStringsCompleter; import org.apache.hive.common.util.ShutdownHookManager; import org.apache.hive.common.util.HiveStringUtils; import org.apache.hive.jdbc.HiveConnection; @@ -110,11 +111,19 @@ import com.google.common.annotations.VisibleForTesting; -import jline.console.ConsoleReader; -import jline.console.completer.Completer; -import jline.console.completer.FileNameCompleter; -import jline.console.completer.StringsCompleter; -import jline.console.history.FileHistory; +import org.jline.reader.Completer; +import org.jline.reader.EndOfFileException; +import org.jline.reader.History; +import org.jline.reader.LineReader; +import org.jline.reader.LineReaderBuilder; +import org.jline.reader.impl.DefaultParser; +import org.jline.reader.impl.LineReaderImpl; +import org.jline.reader.impl.history.DefaultHistory; +import org.jline.terminal.Terminal; +import org.jline.terminal.TerminalBuilder; + +import static org.jline.builtins.Completers.FileNameCompleter; + /** * A console SQL shell with command completion. @@ -151,14 +160,14 @@ public class BeeLine implements Closeable { private OutputFile recordOutputFile = null; private PrintStream outputStream = new PrintStream(System.out, true); private PrintStream errorStream = new PrintStream(System.err, true); - private InputStream inputStream = System.in; - private ConsoleReader consoleReader; + private LineReader currentReader; + private LineReader lineReader; private List batch = null; private final Reflector reflector = new Reflector(this); private String dbName = null; private String currentDatabase = null; - private FileHistory history; + private History history; // Indicates if this instance of beeline is running in compatibility mode, or beeline mode private boolean isBeeLine = true; @@ -204,7 +213,7 @@ public class BeeLine implements Closeable { new ReflectiveCommandHandler(this, new String[] {"quit", "done", "exit"}, null), new ReflectiveCommandHandler(this, new String[] {"connect", "open"}, - new Completer[] {new StringsCompleter(getConnectionURLExamples())}), + new Completer[] {new MatchingStringsCompleter(getConnectionURLExamples())}), new ReflectiveCommandHandler(this, new String[] {"describe"}, new Completer[] {new TableNameCompletor(this)}), new ReflectiveCommandHandler(this, new String[] {"indexes"}, @@ -233,7 +242,7 @@ public class BeeLine implements Closeable { null), new ReflectiveCommandHandler(this, new String[] {"metadata"}, new Completer[] { - new StringsCompleter(getMetadataMethodNames())}), + new MatchingStringsCompleter(getMetadataMethodNames())}), new ReflectiveCommandHandler(this, new String[] {"nativesql"}, null), new ReflectiveCommandHandler(this, new String[] {"dbinfo"}, @@ -263,9 +272,9 @@ public class BeeLine implements Closeable { new ReflectiveCommandHandler(this, new String[] {"closeall"}, null), new ReflectiveCommandHandler(this, new String[] {"isolation"}, - new Completer[] {new StringsCompleter(getIsolationLevels())}), + new Completer[] {new MatchingStringsCompleter(getIsolationLevels())}), new ReflectiveCommandHandler(this, new String[] {"outputformat"}, - new Completer[] {new StringsCompleter( + new Completer[] {new MatchingStringsCompleter( formats.keySet().toArray(new String[0]))}), new ReflectiveCommandHandler(this, new String[] {"autocommit"}, null), @@ -309,9 +318,9 @@ public class BeeLine implements Closeable { static { try { - Class.forName("jline.console.ConsoleReader"); + Class.forName("org.jline.reader.LineReader"); } catch (Throwable t) { - throw new ExceptionInInitializerError("jline-missing"); + throw new ExceptionInInitializerError("jline3-missing"); } } @@ -400,7 +409,7 @@ public class BeeLine implements Closeable { .withLongOpt("help") .withDescription("Display this message") .create('h')); - + // -getUrlsFromBeelineSite options.addOption(OptionBuilder .withLongOpt("getUrlsFromBeelineSite") @@ -433,7 +442,6 @@ public class BeeLine implements Closeable { .create()); } - static Manifest getManifest() throws IOException { URL base = BeeLine.class.getResource("/META-INF/MANIFEST.MF"); URLConnection c = base.openConnection(); @@ -443,7 +451,6 @@ static Manifest getManifest() throws IOException { return null; } - String getManifestAttribute(String name) { try { Manifest m = getManifest(); @@ -553,11 +560,13 @@ public static void mainWithInputRedirection(String[] args, InputStream inputStre BeeLine beeLine = new BeeLine(); try { int status = beeLine.begin(args, inputStream); + System.out.println("after beeline.begin"); if (!Boolean.getBoolean(BeeLineOpts.PROPERTY_NAME_EXIT)) { System.exit(status); } } finally { + System.out.println("mainWithInputRedirection ends, called finally"); beeLine.close(); } } @@ -569,19 +578,16 @@ public BeeLine() { public BeeLine(boolean isBeeLine) { this.isBeeLine = isBeeLine; this.signalHandler = new SunSignalHandler(this); - this.shutdownHook = new Runnable() { - @Override - public void run() { - try { - if (history != null) { - history.setMaxSize(getOpts().getMaxHistoryRows()); - history.flush(); - } - } catch (IOException e) { - error(e); - } finally { - close(); + this.shutdownHook = () -> { + info("Running shutdown hook"); + try { + if (history != null) { + history.save(); } + } catch (IOException e) { + error(e); + } finally { + close(); } }; } @@ -863,7 +869,7 @@ private boolean connectUsingArgs(BeelineParser beelineParser, CommandLine cl) { getOpts().setHelpAsked(true); return true; } - + if (cl.hasOption("getUrlsFromBeelineSite")) { printBeelineSiteUrls(); getOpts().setBeelineSiteUrlsAsked(true); @@ -937,8 +943,8 @@ private boolean connectUsingArgs(BeelineParser beelineParser, CommandLine cl) { String propertyFile = cl.getOptionValue("property-file"); if (propertyFile != null) { try { - this.consoleReader = new ConsoleReader(); - } catch (IOException e) { + this.lineReader = LineReaderBuilder.builder().build(); + } catch (IOError e) { handleException(e); } if (!dispatch("!properties " + propertyFile)) { @@ -980,7 +986,7 @@ private void printBeelineSiteUrls() { } } } - + private boolean isZkBasedUrl(String urlFromBeelineSite) { String zkJdbcUriParam = ("serviceDiscoveryMode=zooKeeper").toLowerCase(); if (urlFromBeelineSite.toLowerCase().contains(zkJdbcUriParam)) { @@ -1116,11 +1122,12 @@ public int begin(String[] args, InputStream inputStream, boolean keepHistory) th //add shutdown hook to cleanup the beeline for smooth exit addBeelineShutdownHook(); - //this method also initializes the consoleReader which is + //this method also initializes the lineReader which is //needed by initArgs for certain execution paths - ConsoleReader reader = initializeConsoleReader(inputStream); + initializeLineReader(); if (isBeeLine) { int code = initArgs(args); + info("initArgs returns: " + code); if (code != 0) { return code; } @@ -1146,7 +1153,16 @@ public int begin(String[] args, InputStream inputStream, boolean keepHistory) th } catch (Exception e) { // ignore } - return execute(reader, false); + return startListening(); + } + + /** + * This method is called when the begin phase is finished and beeline is about to prepare for interactive commands. + * @return the return code of commands + */ + protected int startListening() { + this.currentReader = lineReader; + return execute(lineReader, false); } /* @@ -1294,6 +1310,7 @@ int runInit() { } } } + info(String.format("initialized, exit: %s, executionResult: %d", exit, executionResult)); return executionResult; } @@ -1350,7 +1367,7 @@ private int executeFile(String fileName) { } fileStream = fs.open(path); } - return execute(initializeConsoleReader(fileStream), !getOpts().getForce()); + return execute(getFileLineReader(fileStream), !getOpts().getForce()); } catch (Throwable t) { handleException(t); return ERRNO_OTHER; @@ -1359,16 +1376,19 @@ private int executeFile(String fileName) { } } - private int execute(ConsoleReader reader, boolean exitOnError) { + private int execute(LineReader reader, boolean exitOnError) { + System.out.println("Execute with line reader"); int lastExecutionResult = ERRNO_OK; Character mask = (System.getProperty("jline.terminal", "").equals("jline.UnsupportedTerminal")) ? null - : ConsoleReader.NULL_MASK; + : LineReaderImpl.NULL_MASK; + String line; while (!exit) { try { + info("trying to parse next line"); // Execute one instruction; terminate on executing a script if there is an error // in silent mode, prevent the query and prompt being echoed back to terminal - String line = (getOpts().isSilent() && getOpts().getScriptFile() != null) ? reader + line = (getOpts().isSilent() && getOpts().getScriptFile() != null) ? reader .readLine(null, mask) : reader.readLine(getPrompt()); // trim line @@ -1384,7 +1404,18 @@ private int execute(ConsoleReader reader, boolean exitOnError) { } else if (line != null) { lastExecutionResult = ERRNO_OK; } - + } catch (EndOfFileException t) { + info("EndOfFileException caught"); + /* + * If you're reading from a normal file (not from standard input or a terminal), JLine might raise an + * EndOfFileException when it reaches the end of the file. JLine uses readLine() for reading input, and it + * expects the input source to provide data interactively. When reading from a file, it might misinterpret + * the EOF condition. + * It's unlikely that this catch-and-return-OK block masks a real issue. + * In interactive usage, EndOfFileException is not triggered, and in script file mode (-f), + * any potential corruption would typically surface as a failing command. + */ + return lastExecutionResult; } catch (Throwable t) { handleException(t); return ERRNO_OTHER; @@ -1403,48 +1434,80 @@ private void setupHistory() throws IOException { return; } - this.history = new FileHistory(new File(getOpts().getHistoryFile())); + this.history = new DefaultHistory(); } private void addBeelineShutdownHook() throws IOException { // add shutdown hook to flush the history to history file and it also close all open connections + info("Add shutdown hook"); ShutdownHookManager.addShutdownHook(getShutdownHook()); } - public ConsoleReader initializeConsoleReader(InputStream inputStream) throws IOException { - if (inputStream != null) { - // ### NOTE: fix for sf.net bug 879425. - // Working around an issue in jline-2.1.2, see https://github.com/jline/jline/issues/10 - // by appending a newline to the end of inputstream - InputStream inputStreamAppendedNewline = new SequenceInputStream(inputStream, - new ByteArrayInputStream((new String("\n")).getBytes())); - consoleReader = new ConsoleReader(inputStreamAppendedNewline, getErrorStream()); - consoleReader.setCopyPasteDetection(true); // jline will detect if is regular character - } else { - consoleReader = new ConsoleReader(getInputStream(), getErrorStream()); - } + public LineReader getFileLineReader(InputStream inputStream) throws IOException { + final LineReaderBuilder builder = LineReaderBuilder.builder(); + defaultParser(builder); - //disable the expandEvents for the purpose of backward compatibility - consoleReader.setExpandEvents(false); + Terminal terminal = buildTerminal(prepareInputStream(inputStream)); + builder.terminal(terminal); + + this.currentReader = builder.build(); + return currentReader; + } + + public void initializeLineReader() throws IOException { + final LineReaderBuilder builder = LineReaderBuilder.builder(); + defaultParser(builder); + + Terminal terminal = buildTerminal(null); + builder.terminal(terminal); try { // now set the output for the history if (this.history != null) { - consoleReader.setHistory(this.history); - } else { - consoleReader.setHistoryEnabled(false); + builder.history(this.history); + builder.variable(LineReader.HISTORY_FILE, new File(getOpts().getHistoryFile())); + builder.variable(LineReader.HISTORY_FILE_SIZE, getOpts().getMaxHistoryRows()); + // in-memory keep more data, but at least 500 entries + builder.variable(LineReader.HISTORY_SIZE, Math.max(500, 3 * getOpts().getMaxHistoryRows())); } } catch (Exception e) { handleException(e); } - if (inputStream instanceof FileInputStream || inputStream instanceof FSDataInputStream) { - // from script.. no need to load history and no need of completer, either - return consoleReader; + builder.completer(new BeeLineCompleter(this)); + lineReader = builder.build(); + lineReader.unsetOpt(LineReader.Option.HISTORY_TIMESTAMPED); + + if (this.history != null) { + this.history.attach(lineReader); } + } - consoleReader.addCompleter(new BeeLineCompleter(this)); - return consoleReader; + private void defaultParser(LineReaderBuilder builder) { + // In JLine3, special characters (e.g., backslash) are handled by the terminal by default. + // This is not desired: we want to send the query string to HS2 exactly as entered, without interpretation. + DefaultParser parser = new DefaultParser(); + parser.setEscapeChars(new char[]{}); + builder.parser(parser); + } + + private InputStream prepareInputStream(InputStream inputStream) { + if (inputStream != null) { + inputStream = new SequenceInputStream(inputStream, + new ByteArrayInputStream((new String("\n")).getBytes())); + } + return inputStream; + } + + protected Terminal buildTerminal(InputStream inputStream) throws IOException { + if (inputStream != null) { // typically when there is a file script to read from + info("Build terminal on stream"); + return TerminalBuilder.builder().streams(inputStream, getErrorStream()).build(); + } else { // no input stream, normal operation: proper behavior needs a system terminal + // system terminal can only be created with system streams + info("Build terminal on system in/err"); + return TerminalBuilder.builder().system(true).dumb(false).streams(System.in, System.err).build(); + } } void usage() { @@ -1495,13 +1558,12 @@ boolean dispatch(String line) { } line = HiveStringUtils.removeComments(line); + line = line.trim(); - if (line.trim().length() == 0) { + if (line.length() == 0) { return true; } - line = line.trim(); - // save it to the current script, if any if (scriptOutputFile != null) { scriptOutputFile.addLine(line); @@ -2493,16 +2555,12 @@ PrintStream getErrorStream() { return errorStream; } - InputStream getInputStream() { - return inputStream; - } - - ConsoleReader getConsoleReader() { - return consoleReader; + LineReader getLineReader() { + return lineReader; } - void setConsoleReader(ConsoleReader reader) { - this.consoleReader = reader; + LineReader getCurrentReader(){ + return currentReader; } List getBatch() { diff --git a/beeline/src/java/org/apache/hive/beeline/BeeLineCommandCompleter.java b/beeline/src/java/org/apache/hive/beeline/BeeLineCommandCompleter.java index 44bfc9fa61b3..8583b998af7a 100644 --- a/beeline/src/java/org/apache/hive/beeline/BeeLineCommandCompleter.java +++ b/beeline/src/java/org/apache/hive/beeline/BeeLineCommandCompleter.java @@ -21,10 +21,10 @@ import java.util.LinkedList; import java.util.List; -import jline.console.completer.AggregateCompleter; -import jline.console.completer.Completer; -import jline.console.completer.NullCompleter; -import jline.console.completer.StringsCompleter; +import org.apache.hive.common.util.MatchingStringsCompleter; +import org.jline.reader.Completer; +import org.jline.reader.impl.completer.AggregateCompleter; +import org.jline.reader.impl.completer.NullCompleter; class BeeLineCommandCompleter extends AggregateCompleter { public BeeLineCommandCompleter(Iterable handlers) { @@ -32,21 +32,21 @@ public BeeLineCommandCompleter(Iterable handlers) { } public static List getCompleters(Iterable handlers){ - List completers = new LinkedList(); + List completers = new LinkedList<>(); for (CommandHandler handler : handlers) { String[] commandNames = handler.getNames(); if (commandNames != null) { for (String commandName : commandNames) { - List compl = new LinkedList(); - compl.add(new StringsCompleter(BeeLine.COMMAND_PREFIX + commandName)); + List compl = new LinkedList<>(); + compl.add(new MatchingStringsCompleter(BeeLine.COMMAND_PREFIX + commandName)); compl.addAll(Arrays.asList(handler.getParameterCompleters())); compl.add(new NullCompleter()); // last param no complete - completers.add(new AggregateCompleter(compl.toArray(new Completer[compl.size()]))); + completers.add(new AggregateCompleter(compl.toArray(new Completer[0]))); } } } return completers; } -} \ No newline at end of file +} diff --git a/beeline/src/java/org/apache/hive/beeline/BeeLineCompleter.java b/beeline/src/java/org/apache/hive/beeline/BeeLineCompleter.java index 9213bcf76781..0f1e7971836e 100644 --- a/beeline/src/java/org/apache/hive/beeline/BeeLineCompleter.java +++ b/beeline/src/java/org/apache/hive/beeline/BeeLineCompleter.java @@ -24,7 +24,10 @@ import java.util.List; -import jline.console.completer.Completer; +import org.jline.reader.Candidate; +import org.jline.reader.Completer; +import org.jline.reader.LineReader; +import org.jline.reader.ParsedLine; /** * Completor for BeeLine. It dispatches to sub-completors based on the @@ -42,17 +45,15 @@ class BeeLineCompleter implements Completer { } @Override - public int complete(String buf, int pos, List cand) { - if (buf != null && buf.startsWith(BeeLine.COMMAND_PREFIX) - && !buf.startsWith(BeeLine.COMMAND_PREFIX + "all") - && !buf.startsWith(BeeLine.COMMAND_PREFIX + "sql")) { - return beeLine.getCommandCompletor().complete(buf, pos, cand); + public void complete(LineReader reader, ParsedLine line, List candidates) { + if (line != null && line.line().startsWith(BeeLine.COMMAND_PREFIX) + && !line.line().startsWith(BeeLine.COMMAND_PREFIX + "all") + && !line.line().startsWith(BeeLine.COMMAND_PREFIX + "sql")) { + beeLine.getCommandCompletor().complete(reader, line, candidates); } else { if (beeLine.getDatabaseConnection() != null && beeLine.getDatabaseConnection().getSQLCompleter() != null) { - return beeLine.getDatabaseConnection().getSQLCompleter().complete(buf, pos, cand); - } else { - return -1; + beeLine.getDatabaseConnection().getSQLCompleter().complete(reader, line, candidates); } } } -} \ No newline at end of file +} diff --git a/beeline/src/java/org/apache/hive/beeline/BeeLineOpts.java b/beeline/src/java/org/apache/hive/beeline/BeeLineOpts.java index 04ebab7df2e4..72eaf6e8e7cf 100644 --- a/beeline/src/java/org/apache/hive/beeline/BeeLineOpts.java +++ b/beeline/src/java/org/apache/hive/beeline/BeeLineOpts.java @@ -22,6 +22,15 @@ */ package org.apache.hive.beeline; +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hive.common.util.MatchingStringsCompleter; +import org.jline.reader.Candidate; +import org.jline.reader.Completer; +import org.jline.reader.LineReader; +import org.jline.reader.ParsedLine; +import org.jline.terminal.Terminal; +import org.jline.terminal.TerminalBuilder; + import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -41,13 +50,6 @@ import java.util.Set; import java.util.TreeSet; -import jline.Terminal; -import jline.TerminalFactory; -import jline.console.completer.Completer; -import jline.console.completer.StringsCompleter; -import jline.console.history.MemoryHistory; -import org.apache.hadoop.hive.conf.HiveConf; - public class BeeLineOpts implements Completer { public static final int DEFAULT_MAX_WIDTH = 80; public static final int DEFAULT_MAX_HEIGHT = 80; @@ -86,7 +88,6 @@ public class BeeLineOpts implements Completer { private boolean showElapsedTime = true; private boolean entireLineAsCommand = false; private String numberFormat = "default"; - private final Terminal terminal = TerminalFactory.get(); private int maxWidth = DEFAULT_MAX_WIDTH; private int maxHeight = DEFAULT_MAX_HEIGHT; private int maxColumnWidth = DEFAULT_MAX_COLUMN_WIDTH; @@ -106,7 +107,7 @@ public class BeeLineOpts implements Completer { private final File rcFile = new File(saveDir(), "beeline.properties"); private String historyFile = new File(saveDir(), "history").getAbsolutePath(); - private int maxHistoryRows = MemoryHistory.DEFAULT_MAX_SIZE; + private int maxHistoryRows = 500; // as in MemoryHistory of JLine 2 private String scriptFile = null; private String[] initFiles = null; @@ -152,11 +153,17 @@ public String get(String envVar) { public BeeLineOpts(BeeLine beeLine, Properties props) { this.beeLine = beeLine; - if (terminal.getWidth() > 0) { - maxWidth = terminal.getWidth(); - } - if (terminal.getHeight() > 0) { - maxHeight = terminal.getHeight(); + try { + Terminal terminal = TerminalBuilder.terminal(); + if (terminal.getWidth() > 0) { + maxWidth = terminal.getWidth(); + } + if (terminal.getHeight() > 0) { + maxHeight = terminal.getHeight(); + } + terminal.close(); + } catch(IOException e) { + // nothing to do } loadProperties(props); } @@ -195,12 +202,11 @@ public File saveDir() { @Override - public int complete(String buf, int pos, List cand) { + public void complete(LineReader reader, ParsedLine line, List candidates) { try { - return new StringsCompleter(propertyNames()).complete(buf, pos, cand); + new MatchingStringsCompleter(propertyNames()).complete(reader, line, candidates); } catch (Exception e) { beeLine.handleException(e); - return -1; } } @@ -742,4 +748,3 @@ public static void setEnv(Env envToUse){ env = envToUse; } } - diff --git a/beeline/src/java/org/apache/hive/beeline/BooleanCompleter.java b/beeline/src/java/org/apache/hive/beeline/BooleanCompleter.java index 6ab007dd05e0..d2976695d1a4 100644 --- a/beeline/src/java/org/apache/hive/beeline/BooleanCompleter.java +++ b/beeline/src/java/org/apache/hive/beeline/BooleanCompleter.java @@ -17,15 +17,14 @@ */ package org.apache.hive.beeline; -import jline.console.completer.StringsCompleter; +import org.apache.hive.common.util.MatchingStringsCompleter; /** * JLine completor boolean value (true/false) */ -class BooleanCompleter extends StringsCompleter { +class BooleanCompleter extends MatchingStringsCompleter { public BooleanCompleter(){ - super(new String[] {"true", "false"}); + super("true", "false"); } - -} \ No newline at end of file +} diff --git a/beeline/src/java/org/apache/hive/beeline/CommandHandler.java b/beeline/src/java/org/apache/hive/beeline/CommandHandler.java index 18fcfc40b228..7751cfe04349 100644 --- a/beeline/src/java/org/apache/hive/beeline/CommandHandler.java +++ b/beeline/src/java/org/apache/hive/beeline/CommandHandler.java @@ -22,7 +22,7 @@ */ package org.apache.hive.beeline; -import jline.console.completer.Completer; +import org.jline.reader.Completer; /** * A generic command to be executed. Execution of the command @@ -80,4 +80,4 @@ interface CommandHandler { * @return */ public Throwable getLastException(); -} \ No newline at end of file +} diff --git a/beeline/src/java/org/apache/hive/beeline/Commands.java b/beeline/src/java/org/apache/hive/beeline/Commands.java index 42cc87c1bb60..9a7da9ab5e41 100644 --- a/beeline/src/java/org/apache/hive/beeline/Commands.java +++ b/beeline/src/java/org/apache/hive/beeline/Commands.java @@ -48,6 +48,7 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.ListIterator; import java.util.Map; import java.util.Properties; import java.util.Set; @@ -67,6 +68,8 @@ import org.apache.hive.jdbc.Utils; import org.apache.hive.jdbc.Utils.JdbcConnectionParams; import org.apache.hive.jdbc.logs.InPlaceUpdateStream; +import org.jline.reader.History; +import org.jline.reader.impl.LineReaderImpl; public class Commands { @@ -186,13 +189,9 @@ public boolean addlocaldriverjar(String line) { } public boolean history(String line) { - Iterator hist = beeLine.getConsoleReader().getHistory().entries(); - String[] tmp; - while(hist.hasNext()){ - tmp = hist.next().toString().split(":", 2); - tmp[0] = Integer.toString(Integer.parseInt(tmp[0]) + 1); - beeLine.output(beeLine.getColorBuffer().pad(tmp[0], 6) - .append(":" + tmp[1])); + for (History.Entry entry : beeLine.getLineReader().getHistory()) { + beeLine.output(beeLine.getColorBuffer().pad(Integer.toString(entry.index() + 1), 6) + .append(": " + entry.line())); } return true; } @@ -291,7 +290,7 @@ public boolean dropall(String line) { return beeLine.error(beeLine.loc("no-current-connection")); } try { - if (!(beeLine.getConsoleReader().readLine(beeLine.loc("really-drop-all")).equals("y"))) { + if (!(beeLine.getLineReader().readLine(beeLine.loc("really-drop-all")).equals("y"))) { return beeLine.error("abort-drop-all"); } @@ -1090,7 +1089,7 @@ private boolean showReport() { public String handleMultiLineCmd(String line) throws IOException { line = HiveStringUtils.removeComments(line); Character mask = (System.getProperty("jline.terminal", "").equals("jline.UnsupportedTerminal")) ? null - : jline.console.ConsoleReader.NULL_MASK; + : LineReaderImpl.NULL_MASK; while (isMultiLine(line) && beeLine.getOpts().isAllowMultiLineCommand()) { StringBuilder prompt = new StringBuilder(beeLine.getPrompt()); @@ -1103,14 +1102,14 @@ public String handleMultiLineCmd(String line) throws IOException { } String extra; //avoid NPE below if for some reason -e argument has multi-line command - if (beeLine.getConsoleReader() == null) { + if (beeLine.getCurrentReader() == null) { throw new RuntimeException("Console reader not initialized. This could happen when there " + "is a multi-line command using -e option and which requires further reading from console"); } if (beeLine.getOpts().isSilent() && beeLine.getOpts().getScriptFile() != null) { - extra = beeLine.getConsoleReader().readLine(null, mask); + extra = beeLine.getCurrentReader().readLine(null, mask); } else { - extra = beeLine.getConsoleReader().readLine(prompt.toString()); + extra = beeLine.getCurrentReader().readLine(prompt.toString()); } if (extra == null) { //it happens when using -f and the line of cmds does not end with ; @@ -1515,6 +1514,7 @@ public boolean properties(String line) throws Exception { public boolean connect(String line) throws Exception { + beeLine.info("Connect: line: " + line); String example = "Usage: connect [driver]" + BeeLine.getSeparator(); @@ -1663,11 +1663,11 @@ public boolean connect(Properties props) throws IOException { && !JdbcConnectionParams.AUTH_SSO_BROWSER_MODE.equals(auth)) { String urlForPrompt = url.substring(0, url.contains(";") ? url.indexOf(';') : url.length()); if (username == null) { - username = beeLine.getConsoleReader().readLine("Enter username for " + urlForPrompt + ": "); + username = beeLine.getCurrentReader().readLine("Enter username for " + urlForPrompt + ": "); } props.setProperty(JdbcConnectionParams.AUTH_USER, username); if (password == null) { - password = beeLine.getConsoleReader().readLine("Enter password for " + urlForPrompt + ": ", + password = beeLine.getCurrentReader().readLine("Enter password for " + urlForPrompt + ": ", new Character('*')); } props.setProperty(JdbcConnectionParams.AUTH_PASSWD, password); @@ -1963,7 +1963,7 @@ public boolean manual(String line) throws IOException { // silly little pager if (index % (beeLine.getOpts().getMaxHeight() - 1) == 0) { - String ret = beeLine.getConsoleReader().readLine(beeLine.loc("enter-for-more")); + String ret = beeLine.getLineReader().readLine(beeLine.loc("enter-for-more")); if (ret != null && ret.startsWith("q")) { break; } diff --git a/beeline/src/java/org/apache/hive/beeline/DatabaseConnection.java b/beeline/src/java/org/apache/hive/beeline/DatabaseConnection.java index 129fc2eb9cc9..1fe21fbd3caf 100644 --- a/beeline/src/java/org/apache/hive/beeline/DatabaseConnection.java +++ b/beeline/src/java/org/apache/hive/beeline/DatabaseConnection.java @@ -39,8 +39,8 @@ import org.apache.hive.jdbc.HiveConnection; -import jline.console.completer.ArgumentCompleter; -import jline.console.completer.Completer; +import org.jline.reader.Completer; +import org.jline.reader.impl.completer.ArgumentCompleter; class DatabaseConnection { private static final String HIVE_VAR_PREFIX = "hivevar:"; @@ -79,24 +79,7 @@ void setCompletions(boolean skipmeta) throws SQLException, IOException { : getDatabaseMetaData().getExtraNameCharacters(); // setup the completer for the database - sqlCompleter = new ArgumentCompleter( - new ArgumentCompleter.AbstractArgumentDelimiter() { - // delimiters for SQL statements are any - // non-letter-or-number characters, except - // underscore and characters that are specified - // by the database to be valid name identifiers. - @Override - public boolean isDelimiterChar(CharSequence buffer, int pos) { - char c = buffer.charAt(pos); - if (Character.isWhitespace(c)) { - return true; - } - return !(Character.isLetterOrDigit(c)) - && c != '_' - && extraNameCharacters.indexOf(c) == -1; - } - }, - new SQLCompleter(SQLCompleter.getSQLCompleters(beeLine, skipmeta))); + sqlCompleter = new ArgumentCompleter(new SQLCompleter(SQLCompleter.getSQLCompleters(beeLine, skipmeta))); // not all argument elements need to hold true ((ArgumentCompleter) sqlCompleter).setStrict(false); } diff --git a/beeline/src/java/org/apache/hive/beeline/ReflectiveCommandHandler.java b/beeline/src/java/org/apache/hive/beeline/ReflectiveCommandHandler.java index a37ee8914200..6fbda4c670dc 100644 --- a/beeline/src/java/org/apache/hive/beeline/ReflectiveCommandHandler.java +++ b/beeline/src/java/org/apache/hive/beeline/ReflectiveCommandHandler.java @@ -22,9 +22,9 @@ */ package org.apache.hive.beeline; -import jline.console.completer.Completer; - import org.apache.hadoop.fs.shell.Command; +import org.jline.reader.Completer; + /** * A {@link Command} implementation that uses reflection to diff --git a/beeline/src/java/org/apache/hive/beeline/SQLCompleter.java b/beeline/src/java/org/apache/hive/beeline/SQLCompleter.java index b40b3a50636a..bd5985ff3017 100644 --- a/beeline/src/java/org/apache/hive/beeline/SQLCompleter.java +++ b/beeline/src/java/org/apache/hive/beeline/SQLCompleter.java @@ -30,11 +30,11 @@ import java.util.StringTokenizer; import java.util.TreeSet; -import jline.console.completer.StringsCompleter; +import org.apache.hive.common.util.MatchingStringsCompleter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -class SQLCompleter extends StringsCompleter { +class SQLCompleter extends MatchingStringsCompleter { private static final Logger LOG = LoggerFactory.getLogger(SQLCompleter.class.getName()); diff --git a/beeline/src/java/org/apache/hive/beeline/TableNameCompletor.java b/beeline/src/java/org/apache/hive/beeline/TableNameCompletor.java index 1eefe1788262..23b91f803729 100644 --- a/beeline/src/java/org/apache/hive/beeline/TableNameCompletor.java +++ b/beeline/src/java/org/apache/hive/beeline/TableNameCompletor.java @@ -24,8 +24,11 @@ import java.util.List; -import jline.console.completer.Completer; -import jline.console.completer.StringsCompleter; +import org.apache.hive.common.util.MatchingStringsCompleter; +import org.jline.reader.Candidate; +import org.jline.reader.Completer; +import org.jline.reader.LineReader; +import org.jline.reader.ParsedLine; class TableNameCompletor implements Completer { private final BeeLine beeLine; @@ -38,11 +41,11 @@ class TableNameCompletor implements Completer { } @Override - public int complete(String buf, int pos, List cand) { - if (beeLine.getDatabaseConnection() == null) { - return -1; + public void complete(LineReader reader, ParsedLine line, List candidates) { + final DatabaseConnection connection = beeLine.getDatabaseConnection(); + if (connection != null) { + new MatchingStringsCompleter(beeLine.getDatabaseConnection().getTableNames(true)) + .complete(reader, line, candidates); } - return new StringsCompleter(beeLine.getDatabaseConnection().getTableNames(true)) - .complete(buf, pos, cand); } -} \ No newline at end of file +} diff --git a/beeline/src/java/org/apache/hive/beeline/cli/HiveCli.java b/beeline/src/java/org/apache/hive/beeline/cli/HiveCli.java index 73d7aad64fb3..186763be5c33 100644 --- a/beeline/src/java/org/apache/hive/beeline/cli/HiveCli.java +++ b/beeline/src/java/org/apache/hive/beeline/cli/HiveCli.java @@ -31,11 +31,15 @@ public static void main(String[] args) throws IOException { } public int runWithArgs(String[] cmd, InputStream inputStream) throws IOException { - beeLine = new BeeLine(false); + beeLine = createBeeline(); try { return beeLine.begin(cmd, inputStream); } finally { beeLine.close(); } } + + protected BeeLine createBeeline() { + return new BeeLine(false); + } } diff --git a/beeline/src/test/org/apache/hive/beeline/BeeLineForTest.java b/beeline/src/test/org/apache/hive/beeline/BeeLineForTest.java new file mode 100644 index 000000000000..273a67b83bbf --- /dev/null +++ b/beeline/src/test/org/apache/hive/beeline/BeeLineForTest.java @@ -0,0 +1,40 @@ +/* + * 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.hive.beeline; + +import java.io.IOException; +import java.io.InputStream; + +import org.jline.terminal.Terminal; +import org.jline.terminal.impl.DumbTerminal; + +public class BeeLineForTest extends BeeLine { + + public BeeLineForTest() { + this(true); + } + + public BeeLineForTest(boolean isBeeLine) { + super(isBeeLine); + } + + protected Terminal buildTerminal(InputStream inputStream) throws IOException { + return new DumbTerminal(inputStream, getOutputStream()); + } +} diff --git a/beeline/src/test/org/apache/hive/beeline/TestBeeLineHistory.java b/beeline/src/test/org/apache/hive/beeline/TestBeeLineHistory.java index c8f4d4e42e55..bdcd1dbee582 100644 --- a/beeline/src/test/org/apache/hive/beeline/TestBeeLineHistory.java +++ b/beeline/src/test/org/apache/hive/beeline/TestBeeLineHistory.java @@ -62,7 +62,7 @@ public void testNumHistories() throws Exception { Method method = beeline.getClass().getDeclaredMethod("setupHistory"); method.setAccessible(true); method.invoke(beeline); - beeline.initializeConsoleReader(null); + beeline.initializeLineReader(); beeline.dispatch("!history"); String output = os.toString("UTF-8"); int numHistories = output.split("\n").length; @@ -80,7 +80,7 @@ public void testHistory() throws Exception { Method method = beeline.getClass().getDeclaredMethod("setupHistory"); method.setAccessible(true); method.invoke(beeline); - beeline.initializeConsoleReader(null); + beeline.initializeLineReader(); beeline.dispatch("!history"); String output = os.toString("UTF-8"); String[] tmp = output.split("\n"); diff --git a/beeline/src/test/org/apache/hive/beeline/TestBeelineArgParsing.java b/beeline/src/test/org/apache/hive/beeline/TestBeelineArgParsing.java index 9f1036247182..a7eeb916f67e 100644 --- a/beeline/src/test/org/apache/hive/beeline/TestBeelineArgParsing.java +++ b/beeline/src/test/org/apache/hive/beeline/TestBeelineArgParsing.java @@ -70,7 +70,7 @@ public TestBeelineArgParsing(String connectionString, String driverClazzName, St this.defaultSupported = defaultSupported; } - public class TestBeeline extends BeeLine { + public static class TestBeeline extends BeeLine { String connectArgs = null; List properties = new ArrayList(); diff --git a/beeline/src/test/org/apache/hive/beeline/cli/HiveCliForTest.java b/beeline/src/test/org/apache/hive/beeline/cli/HiveCliForTest.java new file mode 100644 index 000000000000..aa8198533299 --- /dev/null +++ b/beeline/src/test/org/apache/hive/beeline/cli/HiveCliForTest.java @@ -0,0 +1,28 @@ +/* + * 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.hive.beeline.cli; + +import org.apache.hive.beeline.BeeLine; +import org.apache.hive.beeline.BeeLineForTest; + +public class HiveCliForTest extends HiveCli { + + protected BeeLine createBeeline() { + return new BeeLineForTest(false); + } +} diff --git a/beeline/src/test/org/apache/hive/beeline/cli/TestHiveCli.java b/beeline/src/test/org/apache/hive/beeline/cli/TestHiveCli.java index a8378d914356..c8bc5ab03c93 100644 --- a/beeline/src/test/org/apache/hive/beeline/cli/TestHiveCli.java +++ b/beeline/src/test/org/apache/hive/beeline/cli/TestHiveCli.java @@ -36,6 +36,7 @@ import java.io.OutputStream; import java.io.PrintStream; import java.net.URISyntaxException; +import java.nio.charset.Charset; public class TestHiveCli { private static final Logger LOG = LoggerFactory.getLogger(TestHiveCli.class.getName()); @@ -248,7 +249,7 @@ private void executeCMD(String[] args, String input, int retCode) { int ret = 0; try { if (input != null) { - inputStream = IOUtils.toInputStream(input); + inputStream = IOUtils.toInputStream(input, Charset.defaultCharset()); } ret = cli.runWithArgs(args, inputStream); } catch (Throwable e) { @@ -293,9 +294,9 @@ public static void init(){ @Before public void setup() throws IOException, URISyntaxException { System.setProperty("datanucleus.schema.autoCreateAll", "true"); - cli = new HiveCli(); - initFromFile(); + cli = new HiveCliForTest(); redirectOutputStream(); + initFromFile(); } private void redirectOutputStream() { diff --git a/cli/pom.xml b/cli/pom.xml index 485b9a87020e..00135fad80a1 100644 --- a/cli/pom.xml +++ b/cli/pom.xml @@ -82,7 +82,7 @@ test - jline + org.jline jline @@ -121,6 +121,10 @@ hadoop-mapreduce-client-core true + + org.apache.logging.log4j + log4j-1.2-api + org.apache.hbase diff --git a/cli/src/java/org/apache/hadoop/hive/cli/CliDriver.java b/cli/src/java/org/apache/hadoop/hive/cli/CliDriver.java index 92be54934aeb..32ebfd45fa64 100644 --- a/cli/src/java/org/apache/hadoop/hive/cli/CliDriver.java +++ b/cli/src/java/org/apache/hadoop/hive/cli/CliDriver.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package org.apache.hadoop.hive.cli; + package org.apache.hadoop.hive.cli; import static org.apache.hadoop.hive.shims.HadoopShims.USER_ID; import static org.apache.hadoop.util.StringUtils.stringifyException; @@ -73,25 +73,26 @@ import org.apache.hadoop.hive.shims.ShimLoader; import org.apache.hadoop.io.IOUtils; import org.apache.hive.common.util.HiveStringUtils; +import org.apache.hive.common.util.MatchingStringsCompleter; import org.apache.hive.common.util.ShutdownHookManager; +import org.jline.reader.Candidate; +import org.jline.reader.Completer; +import org.jline.reader.History; +import org.jline.reader.LineReader; +import org.jline.reader.LineReaderBuilder; +import org.jline.reader.ParsedLine; +import org.jline.reader.impl.DefaultParser; +import org.jline.reader.impl.completer.ArgumentCompleter; +import org.jline.reader.impl.history.DefaultHistory; +import org.jline.terminal.Terminal; +import org.jline.terminal.Terminal.Signal; +import org.jline.terminal.Terminal.SignalHandler; +import org.jline.terminal.TerminalBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Splitter; -import jline.console.ConsoleReader; -import jline.console.completer.ArgumentCompleter; -import jline.console.completer.ArgumentCompleter.AbstractArgumentDelimiter; -import jline.console.completer.ArgumentCompleter.ArgumentDelimiter; -import jline.console.completer.Completer; -import jline.console.completer.StringsCompleter; -import jline.console.history.FileHistory; -import jline.console.history.History; -import jline.console.history.PersistentHistory; -import sun.misc.Signal; -import sun.misc.SignalHandler; - - /** * CliDriver. * @@ -106,7 +107,7 @@ public class CliDriver { public static final String HIVERCFILE = ".hiverc"; private final LogHelper console; - protected ConsoleReader reader; + protected LineReader reader; private Configuration conf; public CliDriver() { @@ -373,8 +374,8 @@ public CommandProcessorResponse processLine(String line, boolean allowInterrupti if (allowInterrupting) { // Remember all threads that were running at the time we started line processing. // Hook up the custom Ctrl+C handler while processing this line - interruptSignal = new Signal("INT"); - oldSignal = Signal.handle(interruptSignal, new SignalHandler() { + interruptSignal = Terminal.Signal.INT; + oldSignal = reader.getTerminal().handle(interruptSignal, new SignalHandler() { private boolean interruptRequested; @Override @@ -436,8 +437,8 @@ public void handle(Signal signal) { return lastRet; } finally { // Once we are done processing the line, restore the old handler - if (oldSignal != null && interruptSignal != null) { - Signal.handle(interruptSignal, oldSignal); + if (oldSignal != null) { + reader.getTerminal().handle(interruptSignal, oldSignal); } } } @@ -589,7 +590,7 @@ public void processSelectDatabase(CliSessionState ss) throws IOException, Comman public static Completer[] getCommandCompleter() { // StringsCompleter matches against a pre-defined wordlist // We start with an empty wordlist and build it up - List candidateStrings = new ArrayList(); + List candidateStrings = new ArrayList<>(); // We add Hive function names // For functions that aren't infix operators, we add an open @@ -608,23 +609,11 @@ public static Completer[] getCommandCompleter() { candidateStrings.add(s.toLowerCase()); } - StringsCompleter strCompleter = new StringsCompleter(candidateStrings); - - // Because we use parentheses in addition to whitespace - // as a keyword delimiter, we need to define a new ArgumentDelimiter - // that recognizes parenthesis as a delimiter. - ArgumentDelimiter delim = new AbstractArgumentDelimiter() { - @Override - public boolean isDelimiterChar(CharSequence buffer, int pos) { - char c = buffer.charAt(pos); - return (Character.isWhitespace(c) || c == '(' || c == ')' || - c == '[' || c == ']'); - } - }; + Completer strCompleter = new MatchingStringsCompleter(candidateStrings); // The ArgumentCompletor allows us to match multiple tokens // in the same line. - final ArgumentCompleter argCompleter = new ArgumentCompleter(delim, strCompleter); + final ArgumentCompleter argCompleter = new ArgumentCompleter(strCompleter); // By default ArgumentCompletor is in "strict" mode meaning // a token is only auto-completed if all prior tokens // match. We don't want that since there are valid tokens @@ -636,19 +625,16 @@ public boolean isDelimiterChar(CharSequence buffer, int pos) { // the opening parenthesis is unnecessary (and uncommon) in Hive. // We stack a custom Completor on top of our ArgumentCompletor // to reverse this. - Completer customCompletor = new Completer () { - @Override - public int complete (String buffer, int offset, List completions) { - List comp = completions; - int ret = argCompleter.complete(buffer, offset, completions); - // ConsoleReader will do the substitution if and only if there - // is exactly one valid completion, so we ignore other cases. - if (completions.size() == 1) { - if (comp.get(0).endsWith("( ")) { - comp.set(0, comp.get(0).trim()); - } + Completer customCompletor = (reader, line, candidates) -> { + argCompleter.complete(reader, line, candidates); + candidates.forEach(System.out::println); + // ConsoleReader will do the substitution if and only if there + // is exactly one valid completion, so we ignore other cases. + if (candidates.size() == 1) { + String candidateStr = candidates.get(0).value(); + if (candidateStr.endsWith("( ")) { + candidates.set(0, new Candidate(candidateStr.trim())); } - return ret; } }; @@ -657,61 +643,55 @@ public int complete (String buffer, int offset, List completions) { vars.add(conf.varname); } - StringsCompleter confCompleter = new StringsCompleter(vars) { + Completer confCompleter = new MatchingStringsCompleter(vars) { @Override - public int complete(final String buffer, final int cursor, final List clist) { - int result = super.complete(buffer, cursor, clist); - if (clist.isEmpty() && cursor > 1 && buffer.charAt(cursor - 1) == '=') { - HiveConf.ConfVars var = HiveConf.getConfVars(buffer.substring(0, cursor - 1)); + public void complete(LineReader reader, ParsedLine line, List candidates) { + super.complete(reader, line, candidates); + final int cursor = line.cursor(); + if (candidates.isEmpty() && cursor > 1 && line.word().charAt(cursor - 1) == '=') { + HiveConf.ConfVars var = HiveConf.getConfVars(line.word().substring(0, cursor - 1)); if (var == null) { - return result; + return; } if (var.getValidator() instanceof Validator.StringSet) { Validator.StringSet validator = (Validator.StringSet)var.getValidator(); - clist.addAll(validator.getExpected()); + validator.getExpected().stream().map(Candidate::new).forEach(candidates::add); } else if (var.getValidator() != null) { - clist.addAll(Arrays.asList(var.getValidator().toDescription(), "")); + candidates.add(new Candidate(var.getValidator().toDescription())); } else { - clist.addAll(Arrays.asList("Expects " + var.typeString() + " type value", "")); + candidates.add(new Candidate("Expects " + var.typeString() + " type value")); } - return cursor; + return; } - if (clist.size() > DELIMITED_CANDIDATE_THRESHOLD) { - Set delimited = new LinkedHashSet(); - for (CharSequence candidate : clist) { + if (candidates.size() > DELIMITED_CANDIDATE_THRESHOLD) { + Set delimited = new LinkedHashSet<>(); + for (Candidate candidate : candidates) { Iterator it = Splitter.on(".").split( - candidate.subSequence(cursor, candidate.length())).iterator(); + candidate.value().subSequence(cursor, candidate.value().length())).iterator(); if (it.hasNext()) { String next = it.next(); if (next.isEmpty()) { next = "."; } - candidate = buffer != null ? buffer.substring(0, cursor) + next : next; + candidate = new Candidate(line.line() != null ? line.line().substring(0, cursor) + next : next); } delimited.add(candidate); } - clist.clear(); - clist.addAll(delimited); + candidates.clear(); + candidates.addAll(delimited); } - return result; } }; - StringsCompleter setCompleter = new StringsCompleter("set") { - @Override - public int complete(String buffer, int cursor, List clist) { - return buffer != null && buffer.equals("set") ? super.complete(buffer, cursor, clist) : -1; - } - }; + Completer setCompleter = new MatchingStringsCompleter("set"); ArgumentCompleter propCompleter = new ArgumentCompleter(setCompleter, confCompleter) { @Override - public int complete(String buffer, int offset, List completions) { - int ret = super.complete(buffer, offset, completions); - if (completions.size() == 1) { - completions.set(0, ((String)completions.get(0)).trim()); + public void complete(LineReader reader, ParsedLine line, List candidates) { + super.complete(reader, line, candidates); + if (candidates.size() == 1) { + candidates.set(0, new Candidate(candidates.get(0).value().trim())); } - return ret; } }; return new Completer[] {propCompleter, customCompletor}; @@ -855,7 +835,7 @@ private CommandProcessorResponse executeDriver(CliSessionState ss, HiveConf conf console.printInfo(HiveConf.generateMrDeprecationWarning()); } - setupConsoleReader(); + setupLineReader(); String line; CommandProcessorResponse response = new CommandProcessorResponse(); @@ -888,15 +868,12 @@ private CommandProcessorResponse executeDriver(CliSessionState ss, HiveConf conf return response; } - private void setupCmdHistory() { + private String setupCmdHistory() { final String HISTORYFILE = ".hivehistory"; String historyDirectory = System.getProperty("user.home"); - PersistentHistory history = null; try { if ((new File(historyDirectory)).exists()) { - String historyFile = historyDirectory + File.separator + HISTORYFILE; - history = new FileHistory(new File(historyFile)); - reader.setHistory(history); + return historyDirectory + File.separator + HISTORYFILE; } else { System.err.println("WARNING: Directory for Hive history file: " + historyDirectory + " does not exist. History will not be available during this session."); @@ -905,32 +882,48 @@ private void setupCmdHistory() { System.err.println("WARNING: Encountered an error while trying to initialize Hive's " + "history file. History will not be available during this session."); System.err.println(e.getMessage()); + return null; } // add shutdown hook to flush the history to history file - ShutdownHookManager.addShutdownHook(new Runnable() { - @Override - public void run() { - History h = reader.getHistory(); - if (h instanceof FileHistory) { - try { - ((FileHistory) h).flush(); - } catch (IOException e) { - System.err.println("WARNING: Failed to write command history file: " + e.getMessage()); - } - } + ShutdownHookManager.addShutdownHook(() -> { + History h = reader.getHistory(); + try { + h.save(); + } catch (IOException e) { + System.err.println("WARNING: Failed to write command history file: " + e.getMessage()); } }); + return null; } - protected void setupConsoleReader() throws IOException { - reader = new ConsoleReader(); - reader.setExpandEvents(false); - reader.setBellEnabled(false); - for (Completer completer : getCommandCompleter()) { - reader.addCompleter(completer); + protected void setupLineReader() throws IOException { + LineReaderBuilder builder = LineReaderBuilder.builder(); + builder.variable(LineReader.BELL_STYLE, "audible"); + Arrays.stream(getCommandCompleter()).forEach(builder::completer); + builder.terminal(TerminalBuilder.terminal()); + builder.parser(getDefaultParser()); + builder.history(new DefaultHistory()); + + String historyFile = setupCmdHistory(); + if (historyFile != null) { + builder.variable(LineReader.HISTORY_FILE, historyFile); } - setupCmdHistory(); + reader = builder.build(); + } + + static DefaultParser getDefaultParser() { + return new DefaultParser() { + @Override + public boolean isDelimiterChar(CharSequence buffer, int pos) { + // Because we use parentheses in addition to whitespace + // as a keyword delimiter, we need to define a new ArgumentDelimiter + // that recognizes parenthesis as a delimiter. + final char c = buffer.charAt(pos); + return (Character.isWhitespace(c) || c == '(' || c == ')' || + c == '[' || c == ']'); + } + }; } /** @@ -970,5 +963,4 @@ private static String spacesForString(String s) { public void setHiveVariables(Map hiveVariables) { SessionState.get().setHiveVariables(hiveVariables); } - } diff --git a/cli/src/test/org/apache/hadoop/hive/cli/TestCliDriverMethods.java b/cli/src/test/org/apache/hadoop/hive/cli/TestCliDriverMethods.java index df0cdc52291c..23456e203eb5 100644 --- a/cli/src/test/org/apache/hadoop/hive/cli/TestCliDriverMethods.java +++ b/cli/src/test/org/apache/hadoop/hive/cli/TestCliDriverMethods.java @@ -29,7 +29,6 @@ import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileWriter; import java.io.IOException; import java.io.PrintStream; import java.lang.reflect.Field; @@ -40,11 +39,6 @@ import java.util.List; import java.util.Map; -import jline.console.ConsoleReader; -import jline.console.completer.ArgumentCompleter; -import jline.console.completer.Completer; - - import org.apache.commons.io.FileUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hive.common.io.SessionStream; @@ -57,6 +51,9 @@ import org.apache.hadoop.hive.ql.QueryState; import org.apache.hadoop.hive.ql.processors.CommandProcessorException; import org.apache.hadoop.hive.ql.processors.CommandProcessorResponse; +import org.jline.reader.Candidate; +import org.jline.reader.Completer; +import org.jline.reader.impl.completer.ArgumentCompleter; import org.junit.Test; import static org.junit.Assert.assertTrue; @@ -145,7 +142,7 @@ public void testThatCliDriverDoesNotStripComments() throws Exception { CliDriver cliDriver = new CliDriver(); // issue a command with bad options cliDriver.processCmd("!ls --abcdefghijklmnopqrstuvwxyz123456789"); - assertTrue("Comments with '--; should not have been stripped, so command should fail", false); + fail("Comments with '--; should not have been stripped, so command should fail"); } catch (CommandProcessorException e) { // this is expected to happen } finally { @@ -168,8 +165,6 @@ public void testThatCliDriverDoesNotStripComments() throws Exception { * Schema to throw against test * @return Output that would have been sent to the user * @throws CommandProcessorException - * @throws CommandNeedRetryException - * won't actually be thrown */ private PrintStream headerPrintingTestDriver(Schema mockSchema) throws CommandProcessorException { CliDriver cliDriver = new CliDriver(); @@ -206,21 +201,25 @@ public void testGetCommandCompletor() { Completer[] completors = CliDriver.getCommandCompleter(); assertEquals(2, completors.length); assertTrue(completors[0] instanceof ArgumentCompleter); - assertTrue(completors[1] instanceof Completer); + assertNotNull(completors[1]); - List testList = Arrays.asList(")"); - completors[1].complete("fdsdfsdf", 0, testList); - assertEquals(")", testList.get(0)); - testList=new ArrayList(); - completors[1].complete("len", 0, testList); - assertTrue(testList.get(0).toString().endsWith("length(")); + final List candidates1 = new ArrayList<>(); + candidates1.add(new Candidate(")")); + completors[1].complete(null, CliDriver.getDefaultParser().parse("fdsdfsdf", 0), candidates1); + assertEquals(")", candidates1.get(0).value()); - testList=new ArrayList(); - completors[0].complete("set f", 0, testList); - assertEquals("set", testList.get(0)); + final List candidates2 = new ArrayList<>(); + completors[1].complete(null, CliDriver.getDefaultParser().parse("length", 0), candidates2); + System.out.printf("--- --> %s%n", candidates2.get(0).value()); + assertTrue(candidates2.get(0).value().endsWith("length(")); + final List candidates3 = new ArrayList<>(); + completors[0].complete(null, CliDriver.getDefaultParser().parse("set f", 0), candidates3); + assertEquals("set", candidates3.get(0).value()); } + + @Test public void testRun() throws Exception { // clean history @@ -242,7 +241,7 @@ public void testRun() throws Exception { String[] args = {}; try { - new FakeCliDriver(configuration).run(args); + new FakeCliDriver().run(args); assertTrue(dataOut.toString(), dataOut.toString().contains("test message")); assertTrue(dataErr.toString(), dataErr.toString().contains("Hive history file=")); assertTrue(dataErr.toString(), dataErr.toString().contains("File: fakeFile is not a file.")); @@ -420,68 +419,9 @@ private static void setEnv(String key, String value) throws Exception { } private static class FakeCliDriver extends CliDriver { - - private HiveConf conf; - - public FakeCliDriver(HiveConf configuration) { - this.conf = configuration; - } - - @Override - protected void setupConsoleReader() throws IOException { - reader = new FakeConsoleReader(); - } - - protected HiveConf getConf() { - return conf; - } - } - - private static class FakeConsoleReader extends ConsoleReader { - private int counter = 0; - File temp = null; - - public FakeConsoleReader() throws IOException { - super(); - - } - @Override - public String readLine(String prompt) throws IOException { - FileWriter writer; - switch (counter++) { - case 0: - return "!echo test message;"; - case 1: - temp = File.createTempFile("hive", "test"); - temp.deleteOnExit(); - return "source " + temp.getAbsolutePath() + ";"; - case 2: - temp = File.createTempFile("hive", "test"); - temp.deleteOnExit(); - writer = new FileWriter(temp); - writer.write("bla bla bla"); - writer.close(); - return "list file file://" + temp.getAbsolutePath() + ";"; - case 3: - return "!echo "; - case 4: - return "test message;"; - case 5: - return "source fakeFile;"; - case 6: - temp = File.createTempFile("hive", "test"); - temp.deleteOnExit(); - writer = new FileWriter(temp); - writer.write("source fakeFile;"); - writer.close(); - return "list file file://" + temp.getAbsolutePath() + ";"; - - - // drop table over10k; - default: - return null; - } + protected void setupLineReader() throws IOException { + reader = null; } } diff --git a/common/pom.xml b/common/pom.xml index a38f5d0d51af..b28c7da157fb 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -82,7 +82,7 @@ - jline + org.jline jline @@ -109,6 +109,11 @@ org.eclipse.jetty jetty-webapp + + org.fusesource.jansi + jansi + 1.18 + joda-time joda-time diff --git a/common/src/java/org/apache/hive/common/util/MatchingStringsCompleter.java b/common/src/java/org/apache/hive/common/util/MatchingStringsCompleter.java new file mode 100644 index 000000000000..0bda53514e0e --- /dev/null +++ b/common/src/java/org/apache/hive/common/util/MatchingStringsCompleter.java @@ -0,0 +1,73 @@ +/* + * 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.hive.common.util; + +import org.jline.reader.Candidate; +import org.jline.reader.Completer; +import org.jline.reader.LineReader; +import org.jline.reader.ParsedLine; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; + +/** + * A matching string Completer based on JLine's StringCompleter + */ +public class MatchingStringsCompleter implements Completer { + protected SortedSet candidateStrings = new TreeSet<>(); + + public MatchingStringsCompleter() { + // empty + } + + public MatchingStringsCompleter(String... strings) { + this(Arrays.asList(strings)); + } + + public MatchingStringsCompleter(Iterable strings) { + strings.forEach(candidateStrings::add); + } + + public MatchingStringsCompleter(Candidate... candidates) { + Arrays.stream(candidates).map(Candidate::value).forEach(candidateStrings::add); + } + + public Collection getStrings() { + return candidateStrings; + } + + @Override + public void complete(LineReader reader, ParsedLine line, List candidates) { + assert candidates != null; + + if (line == null) { + candidateStrings.stream().map(Candidate::new).forEach(candidates::add); + } else { + for (String match : this.candidateStrings.tailSet(line.word())) { + if (!match.startsWith(line.word())) { + break; + } + candidates.add(new Candidate(match)); + } + } + } +} diff --git a/hcatalog/hcatalog-pig-adapter/pom.xml b/hcatalog/hcatalog-pig-adapter/pom.xml index 472636d234ed..62b40bc0c8ba 100644 --- a/hcatalog/hcatalog-pig-adapter/pom.xml +++ b/hcatalog/hcatalog-pig-adapter/pom.xml @@ -30,6 +30,8 @@ Hive HCatalog Pig Adapter ../.. + + 3.25.0 @@ -123,9 +125,9 @@ test - jline + org.jline jline - 0.9.94 + ${jline.version} test diff --git a/itests/hive-unit/pom.xml b/itests/hive-unit/pom.xml index 9b52e53def96..87fdab6360b6 100644 --- a/itests/hive-unit/pom.xml +++ b/itests/hive-unit/pom.xml @@ -152,6 +152,13 @@ hive-beeline test + + org.apache.hive + hive-beeline + ${project.version} + tests + test + org.apache.hadoop hadoop-distcp diff --git a/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestBeeLineWithArgs.java b/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestBeeLineWithArgs.java index 08626809fb8b..a3f1380109b6 100644 --- a/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestBeeLineWithArgs.java +++ b/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestBeeLineWithArgs.java @@ -158,10 +158,9 @@ public static void postTests() { * @return The stderr and stdout from running the script * @throws Throwable */ - static String testCommandLineScript(List argList, InputStream inputStream, - OutStream streamType) + static String testCommandLineScript(List argList, OutStream streamType) throws Throwable { - BeeLine beeLine = new BeeLine(); + BeeLine beeLine = getBeeLineForTest(); ByteArrayOutputStream os = new ByteArrayOutputStream(); PrintStream beelineOutputStream = new PrintStream(os); switch (streamType) { @@ -175,13 +174,37 @@ static String testCommandLineScript(List argList, InputStream inputStrea throw new RuntimeException("Unexpected outstream type " + streamType); } String[] args = argList.toArray(new String[argList.size()]); - beeLine.begin(args, inputStream); + beeLine.begin(args, null); beeLine.close(); beelineOutputStream.close(); String output = os.toString("UTF8"); return output; } + /* + * Creates a BeeLineForTest that simply quits after the init/script runs. Waits 500ms for the prompt to be printed. + */ + private static BeeLineForTest getBeeLineForTest() { + return new BeeLineForTest() { + @Override + protected int startListening() { + Thread taskThread = new Thread(() -> { + super.startListening(); + }); + + taskThread.start(); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + taskThread.interrupt(); + return 0; + } + }; + } + /** * Attempt to execute a simple script file with the -f and -i option to * BeeLine to test for presence of an expected pattern in the output (stdout @@ -266,8 +289,8 @@ public Tuple apply(Tuple tuple) { boolean matches = m.matches(); if (patternToMatch.shouldMatch != matches) { //failed - fail("Output" + output + " should" + (patternToMatch.shouldMatch ? "" : " not") + - " contain " + patternToMatch.pattern.pattern()); + fail(String.format("Output (mode: %s) '%s' should %s contain '%s'", mode, output, + (patternToMatch.shouldMatch ? "" : " not"), patternToMatch.pattern.pattern())); } } } @@ -281,18 +304,16 @@ enum Modes { INIT { @Override String output(File scriptFile, List argList, OutStream streamType) throws Throwable { - List copy = new ArrayList<>(argList); - copy.add("-i"); - copy.add(scriptFile.getAbsolutePath()); - return testCommandLineScript(copy, new StringBufferInputStream("!quit\n"), streamType); + List finalArgs = new ArrayList<>(argList); + finalArgs.addAll(Arrays.asList("-i", scriptFile.getAbsolutePath())); + return testCommandLineScript(finalArgs, streamType); } }, SCRIPT { @Override String output(File scriptFile, List argList, OutStream streamType) throws Throwable { - List copy = new ArrayList<>(argList); - copy.add("-f"); - copy.add(scriptFile.getAbsolutePath()); - return testCommandLineScript(copy, null, streamType); + List finalArgs = new ArrayList<>(argList); + finalArgs.addAll(Arrays.asList("-f", scriptFile.getAbsolutePath())); + return testCommandLineScript(finalArgs, streamType); } }; @@ -314,11 +335,10 @@ abstract String output(File scriptFile, List argList, OutStream streamTy private void testCommandEnclosedQuery(String enclosedQuery, String expectedPattern, boolean shouldMatch, List argList, OutStream out) throws Throwable { - List copy = new ArrayList(argList); - copy.add("-e"); - copy.add(enclosedQuery); + List finalArgs = new ArrayList(argList); + finalArgs.addAll(Arrays.asList("-e", enclosedQuery)); - String output = testCommandLineScript(copy, null, out); + String output = testCommandLineScript(finalArgs, out); boolean matches = output.contains(expectedPattern); if (shouldMatch != matches) { //failed @@ -484,7 +504,7 @@ public void testNullNonEmpty() throws Throwable { public void testGetVariableValue() throws Throwable { final String SCRIPT_TEXT = "set env:TERM;"; final String EXPECTED_PATTERN = "env:TERM"; - testScriptFile(SCRIPT_TEXT, getBaseArgs(miniHS2.getBaseJdbcURL()), OutStream.ERR, EXPECTED_PATTERN, true); + testScriptFile(SCRIPT_TEXT, getBaseArgs(miniHS2.getBaseJdbcURL()), OutStream.OUT, EXPECTED_PATTERN, true); } /** @@ -707,7 +727,7 @@ public void testNegativeScriptFile() throws Throwable { argList.add(scriptFile.getAbsolutePath()); try { - String output = testCommandLineScript(argList, null, OutStream.OUT); + String output = testCommandLineScript(argList, OutStream.OUT); if (output.contains(EXPECTED_PATTERN)) { fail("Output: " + output + " Negative pattern: " + EXPECTED_PATTERN); } @@ -1027,10 +1047,7 @@ public void testSelectQueryWithNonEscapedSemiColon() throws Throwable { } /** - * Attempt to execute a simple script file with the usage of user & password variables in URL. - * Test for presence of an expected pattern - * in the output (stdout or stderr), fail if not found - * Print PASSED or FAILED + * Attempts to execute a simple script file and verifies that the database name appears in the prompt as expected. */ @Test public void testShowDbInPrompt() throws Throwable { @@ -1041,7 +1058,7 @@ public void testShowDbInPrompt() throws Throwable { argList.add(miniHS2.getBaseJdbcURL() + ";user=hivetest;password=hive"); String SCRIPT_TEXT = "select current_user();"; - testScriptFile(SCRIPT_TEXT, argList, OutStream.ERR, EXPECTED_PATTERN, true); + testScriptFile(SCRIPT_TEXT, argList, OutStream.OUT, EXPECTED_PATTERN, true); } @Test diff --git a/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestHplSqlViaBeeLine.java b/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestHplSqlViaBeeLine.java index f1374663e9b2..60e9bf7d1dec 100644 --- a/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestHplSqlViaBeeLine.java +++ b/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestHplSqlViaBeeLine.java @@ -1413,10 +1413,10 @@ private void testScriptFile(String scriptText, List argList, String expe try (PrintStream os = new PrintStream(new FileOutputStream(scriptFile))) { os.print(scriptText); } - List copy = new ArrayList<>(argList); - copy.add("-f"); - copy.add(scriptFile.getAbsolutePath()); - String output = testCommandLineScript(copy, null, outStream); + List finalArgs = new ArrayList<>(argList); + finalArgs.addAll(Arrays.asList("-f", scriptFile.getAbsolutePath())); + + String output = testCommandLineScript(finalArgs, outStream); if (scriptText.equals("SELECT UNIX_TIMESTAMP()")) { Pattern pattern = Pattern.compile("\\|\\s*(\\d+)\\s*\\|"); Matcher matcher = pattern.matcher(output); diff --git a/itests/util/pom.xml b/itests/util/pom.xml index b6b52df4e1e3..ac81f10ff3ce 100644 --- a/itests/util/pom.xml +++ b/itests/util/pom.xml @@ -122,6 +122,10 @@ hive-llap-server tests + + org.apache.hive + hive-jdbc + org.apache.hadoop hadoop-common diff --git a/llap-server/src/java/org/apache/hadoop/hive/llap/cli/service/LlapServiceCommandLine.java b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/service/LlapServiceCommandLine.java index af5874db2985..aca398ed89e5 100644 --- a/llap-server/src/java/org/apache/hadoop/hive/llap/cli/service/LlapServiceCommandLine.java +++ b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/service/LlapServiceCommandLine.java @@ -21,8 +21,6 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; -import jline.TerminalFactory; - import java.util.Arrays; import java.util.Properties; import java.util.Set; @@ -36,6 +34,7 @@ import org.apache.commons.cli.ParseException; import org.apache.hadoop.hive.conf.HiveConf.ConfVars; import org.apache.hadoop.hive.llap.log.LogHelpers; +import org.jline.terminal.TerminalBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.hadoop.util.StringUtils.TraditionalBinaryPrefix; @@ -401,7 +400,7 @@ private static void printUsage() { HelpFormatter hf = new HelpFormatter(); try { int width = hf.getWidth(); - int jlineWidth = TerminalFactory.get().getWidth(); + int jlineWidth = TerminalBuilder.terminal().getWidth(); width = Math.min(160, Math.max(jlineWidth, width)); hf.setWidth(width); } catch (Throwable t) { // Ignore diff --git a/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/LlapStatusServiceCommandLine.java b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/LlapStatusServiceCommandLine.java index bee50791a3a6..25f10b4a8fd0 100644 --- a/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/LlapStatusServiceCommandLine.java +++ b/llap-server/src/java/org/apache/hadoop/hive/llap/cli/status/LlapStatusServiceCommandLine.java @@ -21,8 +21,6 @@ import java.util.Arrays; import java.util.Properties; -import jline.TerminalFactory; - import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.GnuParser; import org.apache.commons.cli.HelpFormatter; @@ -30,6 +28,7 @@ import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; +import org.jline.terminal.TerminalBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -238,7 +237,7 @@ private static void printUsage() { HelpFormatter hf = new HelpFormatter(); try { int width = hf.getWidth(); - int jlineWidth = TerminalFactory.get().getWidth(); + int jlineWidth = TerminalBuilder.terminal().getWidth(); width = Math.min(160, Math.max(jlineWidth, width)); hf.setWidth(width); } catch (Throwable t) { // Ignore diff --git a/pom.xml b/pom.xml index 62fe839c0088..6afb6474efec 100644 --- a/pom.xml +++ b/pom.xml @@ -160,7 +160,8 @@ 1.5.4 9.4.57.v20241219 1.19.4 - 2.14.6 + + 3.25.0 2.0.2 2.13.0 6.0.0 @@ -453,7 +454,7 @@ ${javolution.version} - jline + org.jline jline ${jline.version} diff --git a/standalone-metastore/metastore-server/pom.xml b/standalone-metastore/metastore-server/pom.xml index bdd754044eef..132c5669f86e 100644 --- a/standalone-metastore/metastore-server/pom.xml +++ b/standalone-metastore/metastore-server/pom.xml @@ -309,7 +309,7 @@ sqlline - jline + org.jline jline diff --git a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/tools/metatool/HiveMetaToolCommandLine.java b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/tools/metatool/HiveMetaToolCommandLine.java index 031d5475e945..50787338263e 100644 --- a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/tools/metatool/HiveMetaToolCommandLine.java +++ b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/tools/metatool/HiveMetaToolCommandLine.java @@ -27,10 +27,10 @@ import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; +import org.jline.terminal.TerminalBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import jline.TerminalFactory; class HiveMetaToolCommandLine { private static final Logger LOGGER = LoggerFactory.getLogger(HiveMetaToolCommandLine.class.getName()); @@ -214,7 +214,7 @@ private static void printUsage() { HelpFormatter hf = new HelpFormatter(); try { int width = hf.getWidth(); - int jlineWidth = TerminalFactory.get().getWidth(); + int jlineWidth = TerminalBuilder.terminal().getWidth(); width = Math.min(160, Math.max(jlineWidth, width)); hf.setWidth(width); } catch (Throwable t) { // Ignore diff --git a/standalone-metastore/pom.xml b/standalone-metastore/pom.xml index 5ddf56416e12..95d609330f1c 100644 --- a/standalone-metastore/pom.xml +++ b/standalone-metastore/pom.xml @@ -97,7 +97,8 @@ 3.25.5 1.72.0 1.9.0 - 2.14.6 + + 3.25.0 4.0.4 4.1.0-SNAPSHOT 1.9.4 @@ -333,9 +334,15 @@ sqlline sqlline ${sqlline.version} + + + org.jline + * + + - jline + org.jline jline ${jline.version}