diff --git a/maven-cli/src/main/java/org/apache/maven/cling/MavenCling.java b/maven-cli/src/main/java/org/apache/maven/cling/MavenCling.java index 691f207fb53d..b8b204d5f470 100644 --- a/maven-cli/src/main/java/org/apache/maven/cling/MavenCling.java +++ b/maven-cli/src/main/java/org/apache/maven/cling/MavenCling.java @@ -29,7 +29,6 @@ import org.apache.maven.cling.invoker.mvn.DefaultMavenParser; import org.apache.maven.cling.invoker.mvn.local.DefaultLocalMavenInvoker; import org.apache.maven.jline.JLineMessageBuilderFactory; -import org.apache.maven.jline.MessageUtils; import org.codehaus.plexus.classworlds.ClassWorld; /** @@ -60,17 +59,6 @@ public MavenCling(ClassWorld classWorld) { super(classWorld); } - @Override - public int run(String[] args) throws IOException { - MessageUtils.systemInstall(); - MessageUtils.registerShutdownHook(); - try { - return super.run(args); - } finally { - MessageUtils.systemUninstall(); - } - } - @Override protected Invoker> createInvoker() { return new DefaultLocalMavenInvoker( diff --git a/maven-cli/src/main/java/org/apache/maven/cling/MavenEncCling.java b/maven-cli/src/main/java/org/apache/maven/cling/MavenEncCling.java index 72cb51ea2c76..488eb9eae44a 100644 --- a/maven-cli/src/main/java/org/apache/maven/cling/MavenEncCling.java +++ b/maven-cli/src/main/java/org/apache/maven/cling/MavenEncCling.java @@ -30,10 +30,7 @@ import org.apache.maven.cling.invoker.mvnenc.DefaultEncryptInvoker; import org.apache.maven.cling.invoker.mvnenc.DefaultEncryptParser; import org.apache.maven.jline.JLineMessageBuilderFactory; -import org.apache.maven.jline.MessageUtils; import org.codehaus.plexus.classworlds.ClassWorld; -import org.jline.terminal.Terminal; -import org.jline.terminal.TerminalBuilder; /** * Maven encrypt CLI "new-gen". @@ -55,8 +52,6 @@ public static int main(String[] args, ClassWorld world) throws IOException { return new MavenEncCling(world).run(args); } - private Terminal terminal; - public MavenEncCling() { super(); } @@ -65,24 +60,10 @@ public MavenEncCling(ClassWorld classWorld) { super(classWorld); } - @Override - public int run(String[] args) throws IOException { - terminal = TerminalBuilder.builder().build(); - MessageUtils.systemInstall(terminal); - MessageUtils.registerShutdownHook(); - try { - return super.run(args); - } finally { - MessageUtils.systemUninstall(); - } - } - @Override protected Invoker createInvoker() { - return new DefaultEncryptInvoker(ProtoLookup.builder() - .addMapping(ClassWorld.class, classWorld) - .addMapping(Terminal.class, terminal) - .build()); + return new DefaultEncryptInvoker( + ProtoLookup.builder().addMapping(ClassWorld.class, classWorld).build()); } @Override diff --git a/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java b/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java index d38077238dd0..881d2d7cdfee 100644 --- a/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java +++ b/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java @@ -405,6 +405,7 @@ protected void helpOrVersionAndMayExit(C context) throws Exception { R invokerRequest = context.invokerRequest; if (invokerRequest.options().help().isPresent()) { invokerRequest.options().displayHelp(context.invokerRequest.parserRequest(), context.terminal.writer()); + context.terminal.writer().flush(); throw new ExitException(0); } if (invokerRequest.options().showVersionAndExit().isPresent()) { @@ -413,6 +414,7 @@ protected void helpOrVersionAndMayExit(C context) throws Exception { } else { context.terminal.writer().println(CLIReportingUtils.showVersion()); } + context.terminal.writer().flush(); throw new ExitException(0); } } diff --git a/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/DefaultEncryptInvoker.java b/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/DefaultEncryptInvoker.java index 82566bbe3f75..65583ee217bf 100644 --- a/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/DefaultEncryptInvoker.java +++ b/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/DefaultEncryptInvoker.java @@ -73,11 +73,8 @@ public void addInHeader(AttributedStyle style, String text) { } } - private final Terminal terminal; - public DefaultEncryptInvoker(ProtoLookup protoLookup) { super(protoLookup); - this.terminal = protoLookup.lookup(Terminal.class); } @Override @@ -101,29 +98,34 @@ protected void lookup(LocalContext context) { public static final int CANCELED = 3; // user canceled protected int doExecute(LocalContext context) throws Exception { - if (!context.interactive) { - System.out.println("This tool works only in interactive mode!"); - System.out.println("Tool purpose is to configure password management on developer workstations."); - System.out.println( - "Note: Generated configuration can be moved/copied to headless environments, if configured as such."); - return BAD_OPERATION; - } - - context.header = new ArrayList<>(); - context.style = new AttributedStyle(); - context.addInHeader( - context.style.italic().bold().foreground(Colors.rgbColor("green")), - "Maven Encryption " + CLIReportingUtils.showVersionMinimal()); - context.addInHeader("Tool for secure password management on workstations."); - context.addInHeader("This tool is part of Apache Maven 4 distribution."); - context.addInHeader(""); try { + if (!context.interactive) { + context.terminal.writer().println("This tool works only in interactive mode!"); + context.terminal + .writer() + .println("Tool purpose is to configure password management on developer workstations."); + context.terminal + .writer() + .println( + "Note: Generated configuration can be moved/copied to headless environments, if configured as such."); + return BAD_OPERATION; + } + + context.header = new ArrayList<>(); + context.style = new AttributedStyle(); + context.addInHeader( + context.style.italic().bold().foreground(Colors.rgbColor("green")), + "Maven Encryption " + CLIReportingUtils.showVersionMinimal()); + context.addInHeader("Tool for secure password management on workstations."); + context.addInHeader("This tool is part of Apache Maven 4 distribution."); + context.addInHeader(""); + Thread executeThread = Thread.currentThread(); - terminal.handle(Terminal.Signal.INT, signal -> executeThread.interrupt()); + context.terminal.handle(Terminal.Signal.INT, signal -> executeThread.interrupt()); ConsolePrompt.UiConfig config; - if (terminal.getType().equals(Terminal.TYPE_DUMB) - || terminal.getType().equals(Terminal.TYPE_DUMB_COLOR)) { - System.out.println(terminal.getName() + ": " + terminal.getType()); + if (context.terminal.getType().equals(Terminal.TYPE_DUMB) + || context.terminal.getType().equals(Terminal.TYPE_DUMB_COLOR)) { + context.terminal.writer().println(context.terminal.getName() + ": " + context.terminal.getType()); throw new IllegalStateException("Dumb terminal detected.\nThis tool requires real terminal to work!\n" + "Note: On Windows Jansi or JNA library must be included in classpath."); } else if (OSUtils.IS_WINDOWS) { @@ -133,8 +135,9 @@ protected int doExecute(LocalContext context) throws Exception { } config.setCancellableFirstPrompt(true); - context.reader = LineReaderBuilder.builder().terminal(terminal).build(); - context.prompt = new ConsolePrompt(context.reader, terminal, config); + context.reader = + LineReaderBuilder.builder().terminal(context.terminal).build(); + context.prompt = new ConsolePrompt(context.reader, context.terminal, config); if (context.invokerRequest.options().goals().isEmpty() || context.invokerRequest.options().goals().get().size() != 1) { @@ -150,22 +153,25 @@ protected int doExecute(LocalContext context) throws Exception { return goal.execute(context); } catch (InterruptedException | InterruptedIOException | UserInterruptException e) { - System.out.println("Goal canceled by user."); + context.terminal.writer().println("Goal canceled by user."); return CANCELED; } catch (Exception e) { if (context.invokerRequest.options().showErrors().orElse(false)) { - context.logger.error(e.getMessage(), e); + context.terminal.writer().println(e.getMessage()); + e.printStackTrace(context.terminal.writer()); } else { - context.logger.error(e.getMessage()); + context.terminal.writer().println(e.getMessage()); } return ERROR; + } finally { + context.terminal.writer().flush(); } } protected int badGoalsErrorMessage(String message, LocalContext context) { - System.out.println(message); - System.out.println("Supported goals are: " + String.join(", ", context.goals.keySet())); - System.out.println("Use -h to display help."); + context.terminal.writer().println(message); + context.terminal.writer().println("Supported goals are: " + String.join(", ", context.goals.keySet())); + context.terminal.writer().println("Use -h to display help."); return BAD_OPERATION; } } diff --git a/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/ConfiguredGoalSupport.java b/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/ConfiguredGoalSupport.java index 5719a816fc3a..efd4792f5c95 100644 --- a/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/ConfiguredGoalSupport.java +++ b/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/ConfiguredGoalSupport.java @@ -38,55 +38,65 @@ protected ConfiguredGoalSupport(MessageBuilderFactory messageBuilderFactory, Sec @Override public int execute(DefaultEncryptInvoker.LocalContext context) throws Exception { - if (!validateConfiguration()) { - logger.error(messageBuilderFactory - .builder() - .error("Maven Encryption is not configured, run `mvnenc init` first.") - .build()); + if (!validateConfiguration(context)) { + context.terminal + .writer() + .println(messageBuilderFactory + .builder() + .error("Maven Encryption is not configured, run `mvnenc init` first.") + .build()); return ERROR; } return doExecute(context); } - protected boolean validateConfiguration() { + protected boolean validateConfiguration(DefaultEncryptInvoker.LocalContext context) { SecDispatcher.ValidationResponse response = secDispatcher.validateConfiguration(); - if (!response.isValid() || logger.isDebugEnabled()) { - dumpResponse("", response); + if (!response.isValid() || context.invokerRequest.options().verbose().orElse(false)) { + dumpResponse(context, "", response); } return response.isValid(); } - protected void dumpResponse(String indent, SecDispatcher.ValidationResponse response) { - logger.info( - response.isValid() - ? messageBuilderFactory - .builder() - .success("{}Configuration validation of {}: {}") - .build() - : messageBuilderFactory - .builder() - .failure("{}Configuration validation of {}: {}") - .build(), - indent, - response.getSource(), - response.isValid() ? "VALID" : "INVALID"); + protected void dumpResponse( + DefaultEncryptInvoker.LocalContext context, String indent, SecDispatcher.ValidationResponse response) { + context.terminal + .writer() + .println(messageBuilderFactory + .builder() + .format( + response.isValid() + ? messageBuilderFactory + .builder() + .success("%sConfiguration validation of %s: %s") + .build() + : messageBuilderFactory + .builder() + .failure("%sConfiguration validation of %s: %s") + .build(), + indent, + response.getSource(), + response.isValid() ? "VALID" : "INVALID")); for (Map.Entry> entry : response.getReport().entrySet()) { - Consumer consumer = - s -> logger.info(messageBuilderFactory.builder().info(s).build()); + Consumer consumer = s -> context.terminal + .writer() + .println(messageBuilderFactory.builder().info(s).build()); if (entry.getKey() == SecDispatcher.ValidationResponse.Level.ERROR) { - consumer = s -> - logger.error(messageBuilderFactory.builder().error(s).build()); + consumer = s -> context.terminal + .writer() + .println(messageBuilderFactory.builder().error(s).build()); } else if (entry.getKey() == SecDispatcher.ValidationResponse.Level.WARNING) { - consumer = s -> - logger.warn(messageBuilderFactory.builder().warning(s).build()); + consumer = s -> context.terminal + .writer() + .println(messageBuilderFactory.builder().warning(s).build()); } for (String line : entry.getValue()) { consumer.accept(indent + " " + line); } } for (SecDispatcher.ValidationResponse subsystem : response.getSubsystems()) { - dumpResponse(indent + " ", subsystem); + dumpResponse(context, indent + " ", subsystem); } } diff --git a/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Decrypt.java b/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Decrypt.java index 6c437c96767b..43be1949e5a7 100644 --- a/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Decrypt.java +++ b/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Decrypt.java @@ -44,10 +44,10 @@ public Decrypt(MessageBuilderFactory messageBuilderFactory, SecDispatcher secDis protected int doExecute(DefaultEncryptInvoker.LocalContext context) throws Exception { String encrypted = context.reader.readLine("Enter the password to decrypt: "); if (secDispatcher.isAnyEncryptedString(encrypted)) { - logger.info(secDispatcher.decrypt(encrypted)); + context.terminal.writer().println(secDispatcher.decrypt(encrypted)); return OK; } else { - logger.error("Malformed encrypted string"); + context.terminal.writer().println(messageBuilderFactory.builder().error("Malformed encrypted string")); return BAD_OPERATION; } } diff --git a/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Diag.java b/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Diag.java index 01d4680ac92b..1f85bbed48b5 100644 --- a/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Diag.java +++ b/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Diag.java @@ -41,7 +41,7 @@ public Diag(MessageBuilderFactory messageBuilderFactory, SecDispatcher secDispat @Override protected int doExecute(DefaultEncryptInvoker.LocalContext context) { - dumpResponse("", secDispatcher.validateConfiguration()); + dumpResponse(context, "", secDispatcher.validateConfiguration()); return OK; } } diff --git a/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Encrypt.java b/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Encrypt.java index c17a5bd53ffd..a3fce98d61d0 100644 --- a/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Encrypt.java +++ b/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Encrypt.java @@ -42,7 +42,7 @@ public Encrypt(MessageBuilderFactory messageBuilderFactory, SecDispatcher secDis @Override protected int doExecute(DefaultEncryptInvoker.LocalContext context) throws Exception { String cleartext = context.reader.readLine("Enter the password to encrypt: ", '*'); - logger.info(secDispatcher.encrypt(cleartext, null)); + context.terminal.writer().println(secDispatcher.encrypt(cleartext, null)); return OK; } } diff --git a/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/GoalSupport.java b/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/GoalSupport.java index 8a8b43ebb92a..c2ac1ab76804 100644 --- a/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/GoalSupport.java +++ b/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/GoalSupport.java @@ -23,14 +23,11 @@ import org.apache.maven.api.services.MessageBuilderFactory; import org.apache.maven.cling.invoker.mvnenc.Goal; import org.codehaus.plexus.components.secdispatcher.SecDispatcher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * The support class for goal implementations. */ public abstract class GoalSupport implements Goal { - protected final Logger logger = LoggerFactory.getLogger(getClass()); protected final MessageBuilderFactory messageBuilderFactory; protected final SecDispatcher secDispatcher; diff --git a/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Init.java b/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Init.java index cd21e4abc2bc..0a98d6c0b194 100644 --- a/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Init.java +++ b/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Init.java @@ -71,9 +71,13 @@ public int execute(DefaultEncryptInvoker.LocalContext context) throws Exception boolean yes = context.invokerRequest.options().yes().orElse(false); if (configExists() && !force) { - System.out.println(messageBuilderFactory - .builder() - .error("Error: configuration exist. Use --force if you want to reset existing configuration.")); + context.terminal + .writer() + .println( + messageBuilderFactory + .builder() + .error( + "Error: configuration exist. Use --force if you want to reset existing configuration.")); return BAD_OPERATION; } @@ -89,11 +93,13 @@ public int execute(DefaultEncryptInvoker.LocalContext context) throws Exception throw new InterruptedException(); } if (NONE.equals(result.get("defaultDispatcher").getResult())) { - logger.warn(messageBuilderFactory - .builder() - .warning( - "Maven4 SecDispatcher disabled; Maven3 fallback may still work, use `mvnenc diag` to check") - .build()); + context.terminal + .writer() + .println(messageBuilderFactory + .builder() + .warning( + "Maven4 SecDispatcher disabled; Maven3 fallback may still work, use `mvnenc diag` to check") + .build()); secDispatcher.writeConfiguration(config); return OK; } @@ -177,16 +183,20 @@ public void complete( context.header, confirmPrompt(prompt.getPromptBuilder()).build()); ConfirmResult confirm = (ConfirmResult) result.get("confirm"); if (confirm.getConfirmed() == ConfirmChoice.ConfirmationValue.YES) { - logger.info(messageBuilderFactory - .builder() - .info("Writing out the configuration...") - .build()); + context.terminal + .writer() + .println(messageBuilderFactory + .builder() + .info("Writing out the configuration...") + .build()); secDispatcher.writeConfiguration(config); } else { - logger.warn(messageBuilderFactory - .builder() - .warning("Values not accepted; not saving configuration.") - .build()); + context.terminal + .writer() + .println(messageBuilderFactory + .builder() + .warning("Values not accepted; not saving configuration.") + .build()); return BAD_OPERATION; } }