From b6bddf2ceb75c4ba4df4332e0284a80123e3533b Mon Sep 17 00:00:00 2001 From: Stefan Oehme Date: Fri, 12 Sep 2025 13:04:52 +0200 Subject: [PATCH] Make prompting work in the daemon (#1303) The daemon was implementing the legacy plexus.interactivity Prompter interface, which Maven 4 no longer calls. Instead, it needs to implement the new maven.api Prompter interface. This also simplifies the code, since the legacy prompter handling is now done by Maven core and it delegates to the new interface if an old plugin uses it. Also, prompting was skipped on dumb terminals for some reason. This meant that prompting could not be tested with automated tests using ProcessBuilder. It also meant that piping input into mvnd on the terminal wouldn't work. This made it inconsistent with regular Maven, which supports promting on a dumb terminal. I've reactivated it, which makes the prompting integration tests for our Maven extension pass again. There was also a missing console flush before sending the response to the daemon, which could lead to inconsistent output, where the newline was sometimes printed before and sometimes after the next line from the daemon. Fixes #1292 --- .../common/logging/TerminalInputHandler.java | 1 + .../mvnd/common/logging/TerminalOutput.java | 4 -- .../mvnd/interactivity/DaemonPrompter.java | 43 +++++-------------- 3 files changed, 11 insertions(+), 37 deletions(-) diff --git a/common/src/main/java/org/mvndaemon/mvnd/common/logging/TerminalInputHandler.java b/common/src/main/java/org/mvndaemon/mvnd/common/logging/TerminalInputHandler.java index 2be40d88..c4071cbe 100644 --- a/common/src/main/java/org/mvndaemon/mvnd/common/logging/TerminalInputHandler.java +++ b/common/src/main/java/org/mvndaemon/mvnd/common/logging/TerminalInputHandler.java @@ -178,6 +178,7 @@ public class TerminalInputHandler implements AutoCloseable { break; } else if (c == '\n' || c == '\r') { terminal.writer().println(); + terminal.writer().flush(); daemonDispatch.accept(prompt.response(sb.toString())); break; } else if (c == 127) { // Backspace diff --git a/common/src/main/java/org/mvndaemon/mvnd/common/logging/TerminalOutput.java b/common/src/main/java/org/mvndaemon/mvnd/common/logging/TerminalOutput.java index bf322f67..ea416498 100644 --- a/common/src/main/java/org/mvndaemon/mvnd/common/logging/TerminalOutput.java +++ b/common/src/main/java/org/mvndaemon/mvnd/common/logging/TerminalOutput.java @@ -328,10 +328,6 @@ public class TerminalOutput implements ClientOutput { } case Message.PROMPT: { Message.Prompt prompt = (Message.Prompt) entry; - if (dumb) { - terminal.writer().println(""); - break; - } clearDisplay(); inputHandler.requestPrompt(prompt); break; diff --git a/daemon/src/main/java/org/mvndaemon/mvnd/interactivity/DaemonPrompter.java b/daemon/src/main/java/org/mvndaemon/mvnd/interactivity/DaemonPrompter.java index baff8a66..299a8c55 100644 --- a/daemon/src/main/java/org/mvndaemon/mvnd/interactivity/DaemonPrompter.java +++ b/daemon/src/main/java/org/mvndaemon/mvnd/interactivity/DaemonPrompter.java @@ -26,12 +26,9 @@ import java.util.List; import java.util.Objects; import java.util.UUID; +import org.apache.maven.api.services.Prompter; +import org.apache.maven.api.services.PrompterException; import org.apache.maven.logging.ProjectBuildLogAppender; -import org.codehaus.plexus.components.interactivity.AbstractInputHandler; -import org.codehaus.plexus.components.interactivity.InputHandler; -import org.codehaus.plexus.components.interactivity.OutputHandler; -import org.codehaus.plexus.components.interactivity.Prompter; -import org.codehaus.plexus.components.interactivity.PrompterException; import org.eclipse.sisu.Priority; import org.eclipse.sisu.Typed; import org.mvndaemon.mvnd.common.Message; @@ -41,39 +38,39 @@ import org.slf4j.LoggerFactory; @Named @Priority(20) -@Typed({Prompter.class, InputHandler.class, OutputHandler.class}) -public class DaemonPrompter extends AbstractInputHandler implements Prompter, InputHandler, OutputHandler { +@Typed({Prompter.class}) +public class DaemonPrompter implements Prompter { private static final Logger LOGGER = LoggerFactory.getLogger(DaemonPrompter.class); @Override - public String prompt(String message) throws PrompterException { + public String prompt(String message) { return prompt(message, null, null); } @Override - public String prompt(String message, String defaultReply) throws PrompterException { + public String prompt(String message, String defaultReply) { return prompt(message, null, defaultReply); } @Override - public String prompt(String message, List possibleValues) throws PrompterException { + public String prompt(String message, List possibleValues) { return prompt(message, possibleValues, null); } @Override @SuppressWarnings("unchecked") - public String prompt(String message, List possibleValues, String defaultReply) throws PrompterException { + public String prompt(String message, List possibleValues, String defaultReply) { return doPrompt(message, possibleValues, defaultReply, false); } @Override - public String promptForPassword(String message) throws PrompterException { + public String promptForPassword(String message) { return doPrompt(message, null, null, true); } @Override - public void showMessage(String message) throws PrompterException { + public void showMessage(String message) { try { doDisplay(message); } catch (IOException e) { @@ -81,26 +78,6 @@ public class DaemonPrompter extends AbstractInputHandler implements Prompter, In } } - @Override - public String readLine() throws IOException { - return doPrompt(null, false); - } - - @Override - public String readPassword() throws IOException { - return doPrompt(null, true); - } - - @Override - public void write(String line) throws IOException { - doDisplay(line); - } - - @Override - public void writeLine(String line) throws IOException { - doDisplay(line + "\n"); - } - String doPrompt(String message, List possibleValues, String defaultReply, boolean password) throws PrompterException { String formattedMessage = formatMessage(message, possibleValues, defaultReply);