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

Reply via email to