This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 6590f9f01898 chore: Fix commands using System.console() to work inside
camel shell
6590f9f01898 is described below
commit 6590f9f018987264d2fae934c92bdddf1433328a
Author: Guillaume Nodet <[email protected]>
AuthorDate: Tue May 26 08:29:27 2026 +0200
chore: Fix commands using System.console() to work inside camel shell
- Add EnvironmentHelper.getActiveTerminal()/setActiveTerminal() for sharing
the shell's JLine terminal
- Add EnvironmentHelper.readLine()/hasConsole()/isInteractiveTerminal()
that prefer the active terminal over System.console()
- Update Shell.java to set the active terminal during shell execution
- Update InfraRun and CommandHelper to use EnvironmentHelper instead of
System.console()
---
.../dsl/jbang/core/commands/CommandHelper.java | 12 ++++--
.../camel/dsl/jbang/core/commands/Debug.java | 9 ++---
.../apache/camel/dsl/jbang/core/commands/Init.java | 8 +++-
.../camel/dsl/jbang/core/commands/Shell.java | 3 ++
.../dsl/jbang/core/commands/infra/InfraRun.java | 7 ++--
.../dsl/jbang/core/common/EnvironmentHelper.java | 47 +++++++++++++++++++++-
6 files changed, 69 insertions(+), 17 deletions(-)
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CommandHelper.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CommandHelper.java
index 460ae9520cd1..1bf2b16ad5e6 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CommandHelper.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CommandHelper.java
@@ -17,6 +17,7 @@
package org.apache.camel.dsl.jbang.core.commands;
import java.io.IOException;
+import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -26,6 +27,7 @@ import java.util.stream.Stream;
import org.apache.camel.dsl.jbang.core.common.EnvironmentHelper;
import org.apache.camel.dsl.jbang.core.common.PathUtils;
import org.apache.camel.dsl.jbang.core.common.Printer;
+import org.jline.terminal.Terminal;
public final class CommandHelper {
@@ -93,8 +95,10 @@ public final class CommandHelper {
System.out.print(message + " [y/N] ");
System.out.flush();
try {
- // Do not use try-with-resources here: closing the Scanner would
close System.in
- Scanner scanner = new Scanner(System.in);
+ Terminal terminal = EnvironmentHelper.getActiveTerminal();
+ InputStream input = terminal != null ? terminal.input() :
System.in;
+ // Do not use try-with-resources here: closing the Scanner would
close the input stream
+ Scanner scanner = new Scanner(input);
String answer = scanner.nextLine().trim().toLowerCase();
return "y".equals(answer) || "yes".equals(answer);
} catch (Exception e) {
@@ -116,8 +120,8 @@ public final class CommandHelper {
@Override
public void run() {
- if (System.console() != null) {
- System.console().readLine();
+ String line = EnvironmentHelper.readLine();
+ if (line != null) {
listener.run();
}
}
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Debug.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Debug.java
index c1b1b56bc887..67812323163a 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Debug.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Debug.java
@@ -17,7 +17,6 @@
package org.apache.camel.dsl.jbang.core.commands;
import java.io.BufferedReader;
-import java.io.Console;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -41,6 +40,7 @@ import java.util.concurrent.atomic.AtomicReference;
import org.apache.camel.dsl.jbang.core.commands.action.MessageTableHelper;
import org.apache.camel.dsl.jbang.core.common.CamelCommandHelper;
import org.apache.camel.dsl.jbang.core.common.CommandLineHelper;
+import org.apache.camel.dsl.jbang.core.common.EnvironmentHelper;
import org.apache.camel.dsl.jbang.core.common.PathUtils;
import org.apache.camel.dsl.jbang.core.common.ProcessHelper;
import org.apache.camel.dsl.jbang.core.common.VersionHelper;
@@ -187,7 +187,6 @@ public class Debug extends Run {
// read log input
final AtomicBoolean quit = new AtomicBoolean();
- final Console c = System.console();
if (logLines > 0) {
Thread t = new Thread(() -> {
doReadLog(quit);
@@ -196,7 +195,7 @@ public class Debug extends Run {
}
// read CLI input from user
- Thread t2 = new Thread(() -> doRead(c, quit), "ReadCommand");
+ Thread t2 = new Thread(() -> doRead(quit), "ReadCommand");
t2.start();
do {
@@ -285,9 +284,9 @@ public class Debug extends Run {
} while (!quit.get());
}
- private void doRead(Console c, AtomicBoolean quit) {
+ private void doRead(AtomicBoolean quit) {
do {
- String line = c.readLine();
+ String line = EnvironmentHelper.readLine();
if (line != null) {
line = line.trim();
if ("q".equalsIgnoreCase(line) ||
"quit".equalsIgnoreCase(line) || "exit".equalsIgnoreCase(line)) {
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Init.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Init.java
index 00772ae1cfa4..da2d911daf10 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Init.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Init.java
@@ -34,6 +34,7 @@ import java.util.StringJoiner;
import org.apache.camel.CamelContext;
import org.apache.camel.dsl.jbang.core.commands.catalog.KameletCatalogHelper;
import org.apache.camel.dsl.jbang.core.common.CommandLineHelper;
+import org.apache.camel.dsl.jbang.core.common.EnvironmentHelper;
import org.apache.camel.dsl.jbang.core.common.ResourceDoesNotExist;
import org.apache.camel.dsl.jbang.core.common.VersionHelper;
import org.apache.camel.github.GistResourceResolver;
@@ -43,6 +44,7 @@ import org.apache.camel.spi.Resource;
import org.apache.camel.util.FileUtil;
import org.apache.camel.util.IOHelper;
import org.apache.commons.io.IOUtils;
+import org.jline.terminal.Terminal;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;
@@ -106,7 +108,7 @@ public class Init extends CamelCommand {
}
if (file == null) {
// try interactive picker if running in a TTY and not in CI
- if (System.console() != null && System.getenv("CI") == null) {
+ if (EnvironmentHelper.isInteractiveTerminal()) {
return interactivePicker();
}
printer().printErr("Missing required parameter: <file>");
@@ -309,7 +311,9 @@ public class Init extends CamelCommand {
pipeTemplates.add(new String[] { "init-pipe.yaml", "Pipe CR (source to
sink)", ".yaml" });
categories.put("Pipes and CRs", pipeTemplates);
- Scanner scanner = new Scanner(System.in);
+ Terminal activeTerminal = EnvironmentHelper.getActiveTerminal();
+ InputStream scannerInput = activeTerminal != null ?
activeTerminal.input() : System.in;
+ Scanner scanner = new Scanner(scannerInput);
// Step 1: Pick a category
printer().println("Select a template category:");
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Shell.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Shell.java
index da0427070077..7f406b61a6b9 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Shell.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Shell.java
@@ -99,8 +99,11 @@ public class Shell extends CamelCommand {
}
try (org.jline.shell.Shell shell = builder.build()) {
+ EnvironmentHelper.setActiveTerminal(shell.terminal());
printBanner(shell, camelVersion, colorEnabled);
shell.run();
+ } finally {
+ EnvironmentHelper.setActiveTerminal(null);
}
return 0;
}
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraRun.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraRun.java
index 4e1395de3fec..7aed979d3784 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraRun.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraRun.java
@@ -16,7 +16,6 @@
*/
package org.apache.camel.dsl.jbang.core.commands.infra;
-import java.io.Console;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
@@ -32,6 +31,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
import org.apache.camel.dsl.jbang.core.common.CommandLineHelper;
+import org.apache.camel.dsl.jbang.core.common.EnvironmentHelper;
import org.apache.camel.dsl.jbang.core.common.Printer;
import org.apache.camel.dsl.jbang.core.common.RuntimeUtil;
import org.apache.camel.main.download.DependencyDownloaderClassLoader;
@@ -226,15 +226,14 @@ public class InfraRun extends InfraBaseCommand {
final CountDownLatch latch = new CountDownLatch(1);
// running in foreground then wait for user to exit
- final Console c = System.console();
- if (c != null) {
+ if (EnvironmentHelper.isInteractiveTerminal()) {
if (!jsonOutput) {
printer().println("Press ENTER to stop the execution");
}
Thread t = new Thread(() -> {
boolean quit = false;
do {
- String line = c.readLine();
+ String line = EnvironmentHelper.readLine();
if (line != null) {
quit = true;
latch.countDown();
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/EnvironmentHelper.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/EnvironmentHelper.java
index e35385be27c2..034c59ba1914 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/EnvironmentHelper.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/EnvironmentHelper.java
@@ -16,6 +16,13 @@
*/
package org.apache.camel.dsl.jbang.core.common;
+import java.io.BufferedReader;
+import java.io.Console;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import org.jline.terminal.Terminal;
+
/**
* Helper for detecting environment characteristics such as CI environments,
color support, and interactive terminals.
*
@@ -32,9 +39,45 @@ package org.apache.camel.dsl.jbang.core.common;
*/
public final class EnvironmentHelper {
+ private static volatile Terminal activeTerminal;
+
private EnvironmentHelper() {
}
+ /**
+ * Sets the active JLine terminal. Called by the shell command to make the
terminal available to subcommands.
+ */
+ public static void setActiveTerminal(Terminal terminal) {
+ activeTerminal = terminal;
+ }
+
+ /**
+ * Returns the active JLine terminal, or null if not running inside the
shell.
+ */
+ public static Terminal getActiveTerminal() {
+ return activeTerminal;
+ }
+
+ /**
+ * Reads a single line from the best available input source: the active
JLine terminal if inside the shell,
+ * otherwise {@link System#console()}.
+ *
+ * @return the line read, or null if no input source is available or an
error occurs
+ */
+ public static String readLine() {
+ Terminal terminal = activeTerminal;
+ if (terminal != null) {
+ try {
+ BufferedReader reader = new BufferedReader(new
InputStreamReader(terminal.input()));
+ return reader.readLine();
+ } catch (IOException e) {
+ return null;
+ }
+ }
+ Console c = System.console();
+ return c != null ? c.readLine() : null;
+ }
+
/**
* Determines whether colored output should be enabled based on
environment variables and terminal capabilities.
*
@@ -59,7 +102,7 @@ public final class EnvironmentHelper {
if (getEnv("FORCE_COLOR") != null) {
return true;
}
- return System.console() != null;
+ return activeTerminal != null || System.console() != null;
}
/**
@@ -80,7 +123,7 @@ public final class EnvironmentHelper {
* @return true if the terminal supports interactive prompts
*/
public static boolean isInteractiveTerminal() {
- return System.console() != null && !isCIEnvironment();
+ return (activeTerminal != null || System.console() != null) &&
!isCIEnvironment();
}
// Visible for testing - allows overriding in tests