This is an automated email from the ASF dual-hosted git repository.
andor pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zookeeper.git
The following commit(s) were added to refs/heads/master by this push:
new 9dbd95836 ZOOKEEPER-3938: Upgrade JLine to 3.25.1
9dbd95836 is described below
commit 9dbd95836b2076023c899ffe3bef4e64881c4076
Author: Dávid Paksy <[email protected]>
AuthorDate: Wed Oct 1 01:24:50 2025 +0200
ZOOKEEPER-3938: Upgrade JLine to 3.25.1
Reviewers: anmolnar, ctubbsii, kezhuw
Author: PDavid
Closes #2318 from PDavid/ZOOKEEPER-3938-jline-upgrade
---
pom.xml | 4 +-
zookeeper-assembly/pom.xml | 2 +-
zookeeper-contrib/zookeeper-contrib-fatjar/pom.xml | 2 +-
zookeeper-server/pom.xml | 2 +-
.../org/apache/zookeeper/JLineZNodeCompleter.java | 46 +++++++++++-----------
.../java/org/apache/zookeeper/ZooKeeperMain.java | 32 +++++++++++----
zookeeper-server/src/main/resources/LICENSE.txt | 6 +--
...2.14.6.LICENSE.txt => jline-3.25.1.LICENSE.txt} | 7 ++--
.../zookeeper/server/ClientSSLReloadTest.java | 3 +-
9 files changed, 59 insertions(+), 45 deletions(-)
diff --git a/pom.xml b/pom.xml
index 01633810e..338921bd9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -562,7 +562,7 @@
<netty.version>4.1.127.Final</netty.version>
<jetty.version>9.4.57.v20241219</jetty.version>
<jackson.version>2.15.2</jackson.version>
- <jline.version>2.14.6</jline.version>
+ <jline.version>3.25.1</jline.version>
<snappy.version>1.1.10.5</snappy.version>
<kerby.version>2.0.0</kerby.version>
<bouncycastle.version>1.78</bouncycastle.version>
@@ -748,7 +748,7 @@
<version>${jackson.version}</version>
</dependency>
<dependency>
- <groupId>jline</groupId>
+ <groupId>org.jline</groupId>
<artifactId>jline</artifactId>
<version>${jline.version}</version>
</dependency>
diff --git a/zookeeper-assembly/pom.xml b/zookeeper-assembly/pom.xml
index 160f9e1b9..317233d6f 100644
--- a/zookeeper-assembly/pom.xml
+++ b/zookeeper-assembly/pom.xml
@@ -100,7 +100,7 @@
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
- <groupId>jline</groupId>
+ <groupId>org.jline</groupId>
<artifactId>jline</artifactId>
</dependency>
<dependency>
diff --git a/zookeeper-contrib/zookeeper-contrib-fatjar/pom.xml
b/zookeeper-contrib/zookeeper-contrib-fatjar/pom.xml
index f78a8fdce..3cf8a30b6 100644
--- a/zookeeper-contrib/zookeeper-contrib-fatjar/pom.xml
+++ b/zookeeper-contrib/zookeeper-contrib-fatjar/pom.xml
@@ -79,7 +79,7 @@
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
- <groupId>jline</groupId>
+ <groupId>org.jline</groupId>
<artifactId>jline</artifactId>
</dependency>
<dependency>
diff --git a/zookeeper-server/pom.xml b/zookeeper-server/pom.xml
index 495e48479..b2ecf1902 100644
--- a/zookeeper-server/pom.xml
+++ b/zookeeper-server/pom.xml
@@ -116,7 +116,7 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>jline</groupId>
+ <groupId>org.jline</groupId>
<artifactId>jline</artifactId>
<scope>provided</scope>
</dependency>
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 e55521400..67288e180 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<Candidate> 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<String>
candidates) {
+ private void completeCommand(String token, List<Candidate> 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<String>
candidates) {
+ private void completeZNode(String token, List<Candidate> 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<String> candidates)
List<String> 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 44851df1f..ca27348e1 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperMain.java
@@ -311,20 +311,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<?> 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 completer =
completerC.getConstructor(ZooKeeper.class).newInstance(zk);
- Method addCompleter = consoleC.getMethod("addCompleter",
Class.forName("jline.console.completer.Completer"));
- addCompleter.invoke(console, completer);
+ 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
@@ -353,6 +351,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 47ddded77..76741750a 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 2.0.13, 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 4ac9522bd..ed9503f23 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 c7e3c8d22..3589a21a8 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;
@@ -144,7 +143,7 @@ public void certificateReloadTest() 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);