This is an automated email from the ASF dual-hosted git repository.
andor pushed a commit to branch branch-3.8
in repository https://gitbox.apache.org/repos/asf/zookeeper.git
The following commit(s) were added to refs/heads/branch-3.8 by this push:
new 231e1f4b7 ZOOKEEPER-3938: Upgrade JLine to 3.25.1
231e1f4b7 is described below
commit 231e1f4b7a66ea4c274f6f09166e22afd0584be1
Author: Dávid Paksy <[email protected]>
AuthorDate: Tue Dec 2 22:57:27 2025 +0100
ZOOKEEPER-3938: Upgrade JLine to 3.25.1
Reviewers: anmolnar
Author: PDavid
Closes #2329 from PDavid/ZOOKEEPER-3938-jline-upgrade-branch-3.8
---
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 | 36 ++++++++++++-----
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, 61 insertions(+), 47 deletions(-)
diff --git a/pom.xml b/pom.xml
index 9d8db5f01..816e9ae2a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -470,7 +470,7 @@
<netty.version>4.1.119.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.60</bouncycastle.version>
@@ -651,7 +651,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 31353467d..ab417b9ed 100755
--- 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 9a378a5ff..48f3182b5 100755
--- 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 878ef0207..33c900f74 100755
--- a/zookeeper-server/pom.xml
+++ b/zookeeper-server/pom.xml
@@ -113,7 +113,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 4ee378fac..04385d504 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 384713a64..54d94d5b9 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 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 f9996c827..5c51cc4d0 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);