diff --git a/pom.xml b/pom.xml
index 6f891496459..e6d7f28d65b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -470,7 +470,7 @@
4.1.119.Final
9.4.57.v20241219
2.15.2
- 2.14.6
+ 3.25.1
1.1.10.5
2.0.0
1.60
@@ -651,7 +651,7 @@
${jackson.version}
- jline
+ org.jline
jline
${jline.version}
diff --git a/zookeeper-assembly/pom.xml b/zookeeper-assembly/pom.xml
index 31353467d76..ab417b9ed22 100755
--- a/zookeeper-assembly/pom.xml
+++ b/zookeeper-assembly/pom.xml
@@ -100,7 +100,7 @@
jackson-databind
- jline
+ org.jline
jline
diff --git a/zookeeper-contrib/zookeeper-contrib-fatjar/pom.xml b/zookeeper-contrib/zookeeper-contrib-fatjar/pom.xml
index 9a378a5ffad..48f3182b5b3 100755
--- a/zookeeper-contrib/zookeeper-contrib-fatjar/pom.xml
+++ b/zookeeper-contrib/zookeeper-contrib-fatjar/pom.xml
@@ -79,7 +79,7 @@
jackson-databind
- jline
+ org.jline
jline
diff --git a/zookeeper-server/pom.xml b/zookeeper-server/pom.xml
index 878ef02072e..33c900f74d5 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..67288e18070 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/JLineZNodeCompleter.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/JLineZNodeCompleter.java
@@ -20,44 +20,41 @@
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;
+import org.jline.utils.AttributedString;
class JLineZNodeCompleter implements Completer {
- private ZooKeeper zk;
+ private final ZooKeeper zk;
public JLineZNodeCompleter(ZooKeeper zk) {
this.zk = zk;
}
- @SuppressWarnings({"unchecked", "rawtypes"})
- public int complete(String buffer, int cursor, List candidates) {
+ @Override
+ public void complete(LineReader lineReader, ParsedLine commandLine, List candidates) {
// Guarantee that the final token is the one we're expanding
- buffer = buffer.substring(0, cursor);
- String token = "";
- if (!buffer.endsWith(" ")) {
- String[] tokens = buffer.split(" ");
- if (tokens.length != 0) {
- token = tokens[tokens.length - 1];
- }
- }
+ String token = commandLine.words().get(commandLine.words().size() - 1);
if (token.startsWith("/")) {
- return completeZNode(buffer, token, candidates);
+ completeZNode(token, candidates);
+ } else {
+ completeCommand(token, candidates);
}
- return completeCommand(buffer, token, candidates);
}
- private int completeCommand(String buffer, String token, List candidates) {
+ private void completeCommand(String token, List candidates) {
for (String cmd : ZooKeeperMain.getCommands()) {
if (cmd.startsWith(token)) {
- candidates.add(cmd);
+ candidates.add(createCandidate(cmd));
}
}
- return buffer.lastIndexOf(" ") + 1;
}
- private int completeZNode(String buffer, String token, List candidates) {
+ private void completeZNode(String token, List candidates) {
String path = token;
int idx = path.lastIndexOf("/") + 1;
String prefix = path.substring(idx);
@@ -67,16 +64,17 @@ private int completeZNode(String buffer, String token, List candidates)
List children = zk.getChildren(dir, false);
for (String child : children) {
if (child.startsWith(prefix)) {
- candidates.add(child);
+ String zNode = dir + (idx == 1 ? "" : "/") + child;
+ candidates.add(createCandidate(zNode));
}
}
- } catch (InterruptedException e) {
- return 0;
- } catch (KeeperException e) {
- return 0;
+ } catch (InterruptedException | KeeperException e) {
+ return;
}
Collections.sort(candidates);
- return candidates.size() == 0 ? buffer.length() : buffer.lastIndexOf("/") + 1;
}
+ private static Candidate createCandidate(String cmd) {
+ return new Candidate(AttributedString.stripAnsi(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 4ee378fac05..04385d5043e 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java
@@ -310,20 +310,18 @@ void run() throws IOException, InterruptedException {
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");
+ Class> readerC = Class.forName("org.jline.reader.LineReader");
+ Class> completerC = Class.forName("org.apache.zookeeper.JLineZNodeCompleter");
System.out.println("JLine support is enabled");
- Object console = consoleC.getConstructor().newInstance();
-
- Object completor = completorC.getConstructor(ZooKeeper.class).newInstance(zk);
- Method addCompletor = consoleC.getMethod("addCompleter", Class.forName("jline.console.completer.Completer"));
- addCompletor.invoke(console, completor);
+ Object completer = completerC.getConstructor(ZooKeeper.class).newInstance(zk);
+ Object terminal = createTerminal();
+ Object reader = createLineReader(terminal, completer);
String line;
- Method readLine = consoleC.getMethod("readLine", String.class);
- while ((line = (String) readLine.invoke(console, getPrompt())) != null) {
+ Method readLine = readerC.getMethod("readLine", String.class);
+ while ((line = (String) readLine.invoke(reader, getPrompt())) != null) {
executeLine(line);
}
} catch (ClassNotFoundException
@@ -352,6 +350,26 @@ void run() throws IOException, InterruptedException {
ServiceUtils.requestSystemExit(exitCode);
}
+ private static Object createTerminal() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+ Class> terminalBuilderC = Class.forName("org.jline.terminal.TerminalBuilder");
+ Method terminalBuilderMethod = terminalBuilderC.getMethod("builder");
+ Object terminalBuilder = terminalBuilderMethod.invoke(null);
+ Method terminalBuildMethod = terminalBuilderC.getMethod("build");
+ return terminalBuildMethod.invoke(terminalBuilder);
+ }
+
+ private static Object createLineReader(Object terminal, Object completer) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+ Class> readerBuilderC = Class.forName("org.jline.reader.LineReaderBuilder");
+ Method readerBuilderMethod = readerBuilderC.getMethod("builder");
+ Object readerBuilder = readerBuilderMethod.invoke(null);
+ Method setTerminalMethod = readerBuilderC.getMethod("terminal", Class.forName("org.jline.terminal.Terminal"));
+ setTerminalMethod.invoke(readerBuilder, terminal);
+ Method setCompleterMethod = readerBuilderC.getMethod("completer", Class.forName("org.jline.reader.Completer"));
+ setCompleterMethod.invoke(readerBuilder, completer);
+ Method readerBuildMethod = readerBuilderC.getMethod("build");
+ return readerBuildMethod.invoke(readerBuilder);
+ }
+
public void executeLine(String line) throws InterruptedException, IOException {
if (!line.equals("")) {
cl.parseCommand(line);
diff --git a/zookeeper-server/src/main/resources/LICENSE.txt b/zookeeper-server/src/main/resources/LICENSE.txt
index 384713a645f..54d94d5b9af 100644
--- a/zookeeper-server/src/main/resources/LICENSE.txt
+++ b/zookeeper-server/src/main/resources/LICENSE.txt
@@ -206,9 +206,9 @@ This distribution bundles javacc, which is available under the
3-clause BSD License. For details, see a copy of the license in
lib/javacc.LICENSE.txt
-This distribution bundles jline 2.14.6, which is available under the
-2-clause BSD License. For details, see a copy of the license in
-lib/jline-2.14.6.LICENSE.txt
+This distribution bundles jline 3.25.1, which is available under the
+3-clause BSD License. For details, see a copy of the license in
+lib/jline-3.25.1.LICENSE.txt
This distribution bundles SLF4J 1.7.30, which is available under the MIT
License. For details, see a copy of the license in
diff --git a/zookeeper-server/src/main/resources/lib/jline-2.14.6.LICENSE.txt b/zookeeper-server/src/main/resources/lib/jline-3.25.1.LICENSE.txt
similarity index 90%
rename from zookeeper-server/src/main/resources/lib/jline-2.14.6.LICENSE.txt
rename to zookeeper-server/src/main/resources/lib/jline-3.25.1.LICENSE.txt
index 4ac9522bd8c..ed9503f23c2 100644
--- a/zookeeper-server/src/main/resources/lib/jline-2.14.6.LICENSE.txt
+++ b/zookeeper-server/src/main/resources/lib/jline-3.25.1.LICENSE.txt
@@ -1,7 +1,7 @@
-Copyright (c) 2002-2012, the original author or authors.
+Copyright (c) 2002-2023, 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
@@ -31,5 +31,4 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-OF THE POSSIBILITY OF SUCH DAMAGE.
-
+OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/server/ClientSSLReloadTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/server/ClientSSLReloadTest.java
index f9996c827bd..5c51cc4d0fc 100644
--- a/zookeeper-server/src/test/java/org/apache/zookeeper/server/ClientSSLReloadTest.java
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/server/ClientSSLReloadTest.java
@@ -25,7 +25,6 @@
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import jline.internal.Log;
import org.apache.commons.io.FileUtils;
import org.apache.zookeeper.PortAssignment;
import org.apache.zookeeper.WatchedEvent;
@@ -150,7 +149,7 @@ public void certficateReloadTest() throws Exception {
assertTrue(l.await(10, TimeUnit.SECONDS));
}
- Log.info("Updating keyStore & trustStore files !!!!");
+ LOG.info("Updating keyStore & trustStore files !!!!");
// Update the keyStoreFile1 and trustStoreFile1 files in the filesystem with keyStoreFile2 & trustStoreFile2
FileUtils.writeStringToFile(keyStoreFile1, FileUtils.readFileToString(keyStoreFile2, StandardCharsets.US_ASCII), StandardCharsets.US_ASCII, false);
FileUtils.writeStringToFile(trustStoreFile1, FileUtils.readFileToString(trustStoreFile2, StandardCharsets.US_ASCII), StandardCharsets.US_ASCII, false);