diff --git a/pom.xml b/pom.xml
index b44967b126c..782a819ee31 100755
--- a/pom.xml
+++ b/pom.xml
@@ -439,7 +439,7 @@
9.4.24.v20191120
2.10.3
1.1.1
- 2.14.6
+ 3.16.0
1.1.7
2.0.0
1.60
@@ -635,7 +635,7 @@
- jline
+ org.jline
jline
${jline.version}
diff --git a/zookeeper-assembly/pom.xml b/zookeeper-assembly/pom.xml
index 8a2967fe616..4b6525e17cd 100755
--- a/zookeeper-assembly/pom.xml
+++ b/zookeeper-assembly/pom.xml
@@ -104,7 +104,7 @@
json-simple
- jline
+ org.jline
jline
diff --git a/zookeeper-contrib/zookeeper-contrib-fatjar/pom.xml b/zookeeper-contrib/zookeeper-contrib-fatjar/pom.xml
index 9a90dd7fc3c..9e38ab31c55 100755
--- a/zookeeper-contrib/zookeeper-contrib-fatjar/pom.xml
+++ b/zookeeper-contrib/zookeeper-contrib-fatjar/pom.xml
@@ -83,7 +83,7 @@
json-simple
- jline
+ org.jline
jline
diff --git a/zookeeper-server/pom.xml b/zookeeper-server/pom.xml
index 059f2fff0fb..b4355cf0d56 100755
--- a/zookeeper-server/pom.xml
+++ b/zookeeper-server/pom.xml
@@ -113,7 +113,7 @@
test
- jline
+ org.jline
jline
provided
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/JLineZNodeCompleter.java b/zookeeper-server/src/main/java/org/apache/zookeeper/JLineZNodeCompleter.java
index e55521400fa..e863f27c802 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/JLineZNodeCompleter.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/JLineZNodeCompleter.java
@@ -20,20 +20,21 @@
import java.util.Collections;
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;
class JLineZNodeCompleter implements Completer {
-
private ZooKeeper zk;
public JLineZNodeCompleter(ZooKeeper zk) {
this.zk = zk;
}
- @SuppressWarnings({"unchecked", "rawtypes"})
- public int complete(String buffer, int cursor, List candidates) {
- // Guarantee that the final token is the one we're expanding
- buffer = buffer.substring(0, cursor);
+ @Override
+ public void complete(LineReader reader, ParsedLine commandLine, List candidates) {
+ String buffer = commandLine.word().substring(0, commandLine.wordCursor());
String token = "";
if (!buffer.endsWith(" ")) {
String[] tokens = buffer.split(" ");
@@ -43,40 +44,38 @@ public int complete(String buffer, int cursor, List candidates) {
}
if (token.startsWith("/")) {
- return completeZNode(buffer, token, candidates);
- }
- return completeCommand(buffer, token, candidates);
- }
-
- private int completeCommand(String buffer, String token, List candidates) {
- for (String cmd : ZooKeeperMain.getCommands()) {
- if (cmd.startsWith(token)) {
- candidates.add(cmd);
- }
+ completeZNode(candidates, token);
+ } else {
+ completeCommand(candidates, token);
}
- return buffer.lastIndexOf(" ") + 1;
}
- private int completeZNode(String buffer, String token, List candidates) {
- String path = token;
- int idx = path.lastIndexOf("/") + 1;
- String prefix = path.substring(idx);
+ private void completeZNode(List candidates, String token) {
+ int idx = token.lastIndexOf("/") + 1;
+ String prefix = token.substring(idx);
try {
// Only the root path can end in a /, so strip it off every other prefix
- String dir = idx == 1 ? "/" : path.substring(0, idx - 1);
- List children = zk.getChildren(dir, false);
+ StringBuilder dir = new StringBuilder(idx == 1 ? "/" : token.substring(0, idx - 1));
+ List children = zk.getChildren(dir.toString(), false);
for (String child : children) {
if (child.startsWith(prefix)) {
- candidates.add(child);
+ if (!dir.toString().endsWith("/")) {
+ dir.append("/");
+ }
+ candidates.add(new Candidate(dir + child, child, null, null, null, null, true));
}
}
- } catch (InterruptedException e) {
- return 0;
- } catch (KeeperException e) {
- return 0;
+ } catch (InterruptedException | KeeperException e) {
+ // Ignore
}
Collections.sort(candidates);
- return candidates.size() == 0 ? buffer.length() : buffer.lastIndexOf("/") + 1;
}
+ private void completeCommand(List candidates, String token) {
+ for (String cmd : ZooKeeperMain.getCommands()) {
+ if (cmd.startsWith(token)) {
+ candidates.add(new Candidate(cmd, cmd, null, null, null, null, true));
+ }
+ }
+ }
}
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java b/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java
index ff8ce623286..cdfba365868 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java
@@ -18,11 +18,7 @@
package org.apache.zookeeper;
-import java.io.BufferedReader;
import java.io.IOException;
-import java.io.InputStreamReader;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -46,6 +42,12 @@
import org.apache.zookeeper.server.ExitCode;
import org.apache.zookeeper.server.quorum.QuorumPeerConfig;
import org.apache.zookeeper.util.ServiceUtils;
+import org.jline.reader.Completer;
+import org.jline.reader.LineReader;
+import org.jline.reader.LineReaderBuilder;
+import org.jline.reader.UserInterruptException;
+import org.jline.terminal.Terminal;
+import org.jline.terminal.TerminalBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -282,44 +284,21 @@ public ZooKeeperMain(ZooKeeper zk) {
void run() throws IOException, InterruptedException {
if (cl.getCommand() == null) {
System.out.println("Welcome to ZooKeeper!");
+ System.out.println("JLine support is enabled");
- boolean jlinemissing = false;
- // only use jline if it's in the classpath
- try {
- Class> consoleC = Class.forName("jline.console.ConsoleReader");
- Class> completorC = Class.forName("org.apache.zookeeper.JLineZNodeCompleter");
-
- System.out.println("JLine support is enabled");
-
- Object console = consoleC.getConstructor().newInstance();
+ Terminal terminal = TerminalBuilder.builder().system(true).build();
+ Completer znodeCompleter = new JLineZNodeCompleter(zk);
- Object completor = completorC.getConstructor(ZooKeeper.class).newInstance(zk);
- Method addCompletor = consoleC.getMethod("addCompleter", Class.forName("jline.console.completer.Completer"));
- addCompletor.invoke(console, completor);
+ LineReader lineReader = LineReaderBuilder.builder().terminal(terminal).completer(znodeCompleter).build();
- String line;
- Method readLine = consoleC.getMethod("readLine", String.class);
- while ((line = (String) readLine.invoke(console, getPrompt())) != null) {
- executeLine(line);
- }
- } catch (ClassNotFoundException
- | NoSuchMethodException
- | InvocationTargetException
- | IllegalAccessException
- | InstantiationException e
- ) {
- LOG.debug("Unable to start jline", e);
- jlinemissing = true;
- }
-
- if (jlinemissing) {
- System.out.println("JLine support is disabled");
- BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
-
- String line;
- while ((line = br.readLine()) != null) {
+ String line;
+ try {
+ while ((line = lineReader.readLine(getPrompt())) != null) {
executeLine(line);
}
+ } catch (UserInterruptException ex) {
+ // ignore exception
+ executeLine("quit");
}
} else {
// Command line args non-null. Run what was passed.
diff --git a/zookeeper-server/src/main/resources/lib/jline-2.14.6.LICENSE.txt b/zookeeper-server/src/main/resources/lib/jline-3.16.0.LICENSE.txt
similarity index 92%
rename from zookeeper-server/src/main/resources/lib/jline-2.14.6.LICENSE.txt
rename to zookeeper-server/src/main/resources/lib/jline-3.16.0.LICENSE.txt
index 4ac9522bd8c..7e11b67fba7 100644
--- a/zookeeper-server/src/main/resources/lib/jline-2.14.6.LICENSE.txt
+++ b/zookeeper-server/src/main/resources/lib/jline-3.16.0.LICENSE.txt
@@ -1,7 +1,7 @@
-Copyright (c) 2002-2012, the original author or authors.
+Copyright (c) 2002-2018, the original author or authors.
All rights reserved.
-http://www.opensource.org/licenses/bsd-license.php
+https://opensource.org/licenses/BSD-3-Clause
Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the following