This is an automated email from the ASF dual-hosted git repository.

cstamas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven.git


The following commit(s) were added to refs/heads/master by this push:
     new 5b7a6de55a [MNG-8421] Move all of logging setup to LookupInvoker; 
mvnenc IT (#1964)
5b7a6de55a is described below

commit 5b7a6de55aede5f0f92b13de1f5aeac9b8436329
Author: Tamas Cservenak <ta...@cservenak.net>
AuthorDate: Thu Dec 12 09:43:12 2024 +0100

    [MNG-8421] Move all of logging setup to LookupInvoker; mvnenc IT (#1964)
    
    Currently mvnenc is unable to log to file (-l) as logging setup is 
incomplete, move all of this logic to LookupInvoker. Also, create prompt in 
mvnenc only when needed. Finally, implement needed changes to support mvnenc 
ITs and add mvnenc IT.
    
    Other changes:
    * get rid of `distributionFileName` dirty hack, is remnant from old ITs
    * fix CI re removal of that above and use of site that is brain-dead
    
    ---
    
    https://issues.apache.org/jira/browse/MNG-8421
---
 .github/workflows/maven.yml                        | 21 +++++--
 apache-maven/pom.xml                               |  5 --
 .../apache/maven/cling/invoker/LookupContext.java  |  3 +
 .../apache/maven/cling/invoker/LookupInvoker.java  | 20 ++++++
 .../maven/cling/invoker/mvn/MavenContext.java      |  2 -
 .../maven/cling/invoker/mvn/MavenInvoker.java      | 25 --------
 .../maven/cling/invoker/mvnenc/EncryptContext.java |  2 -
 .../maven/cling/invoker/mvnenc/EncryptInvoker.java | 23 ++-----
 .../mvnenc/goals/ConfiguredGoalSupport.java        | 58 ++++++++---------
 .../maven/cling/invoker/mvnenc/goals/Diag.java     |  9 ++-
 .../maven/cling/invoker/mvnenc/goals/Init.java     | 29 +++++----
 impl/maven-executor/pom.xml                        | 29 ++++++---
 .../executor/embedded/EmbeddedMavenExecutor.java   | 51 ++++++++++++---
 .../maven/cling/executor/internal/HelperImpl.java  |  4 +-
 .../cling/executor/MavenExecutorTestSupport.java   | 19 ++++++
 its/core-it-suite/pom.xml                          |  4 +-
 .../it/MavenITmng8421MavenEncryptionTest.java      | 73 ++++++++++++++++++++++
 .../org/apache/maven/it/TestSuiteOrdering.java     |  1 +
 .../src/test/resources/mng-8421/home1/readme.txt   |  1 +
 .../mng-8421/home2/.m2/settings-security.xml       | 25 ++++++++
 .../mng-8421/home2/.m2/settings-security4.xml      | 42 +++++++++++++
 .../src/test/resources/mng-8421/home2/readme.txt   |  1 +
 .../main/java/org/apache/maven/it/Verifier.java    | 15 ++++-
 23 files changed, 336 insertions(+), 126 deletions(-)

diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index f00bc6f0c1..92153927f5 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -56,7 +56,7 @@ jobs:
 
       - name: Build Maven distributions
         shell: bash
-        run: ./mvnw verify -e -B -V -DdistributionFileName=apache-maven 
-Dmaven.repo.local=$HOME/.m2/repository/cached
+        run: ./mvnw verify -e -B -V 
-Dmaven.repo.local=$HOME/.m2/repository/cached
 
       - name: List contents of target directory
         shell: bash
@@ -117,9 +117,14 @@ jobs:
         run: |
           mkdir -p maven-local
           if [ "${{ runner.os }}" = "Windows" ]; then
-            unzip maven-dist/apache-maven-bin.zip -d maven-local
+            unzip maven-dist/apache-maven-*-bin.zip -d maven-local
+            # Get the name of the extracted directory
+            MAVEN_DIR=$(ls maven-local)
+            # Move contents up one level
+            mv "maven-local/$MAVEN_DIR"/* maven-local/
+            rm -r "maven-local/$MAVEN_DIR"
           else
-            tar xzf maven-dist/apache-maven-bin.tar.gz -C maven-local 
--strip-components 1
+            tar xzf maven-dist/apache-maven-*-bin.tar.gz -C maven-local 
--strip-components 1
           fi
           echo "MAVEN_HOME=$PWD/maven-local" >> $GITHUB_ENV
           echo "$PWD/maven-local/bin" >> $GITHUB_PATH
@@ -133,9 +138,13 @@ jobs:
             maven-${{ runner.os }}-full-
             maven-${{ runner.os }}-
 
+      - name: Build with downloaded Maven
+        shell: bash
+        run: mvn verify -e -B -V -Dmaven.repo.local=$HOME/.m2/repository/cached
+
       - name: Build site with downloaded Maven
         shell: bash
-        run: mvn verify site -e -B -V -Preporting 
-Dmaven.repo.local=$HOME/.m2/repository/cached
+        run: mvn site -e -B -V -Preporting 
-Dmaven.repo.local=$HOME/.m2/repository/cached
 
   integration-tests:
     needs: initial-build
@@ -172,14 +181,14 @@ jobs:
         run: |
           mkdir -p maven-local
           if [ "${{ runner.os }}" = "Windows" ]; then
-            unzip maven-dist/apache-maven-bin.zip -d maven-local
+            unzip maven-dist/apache-maven-*-bin.zip -d maven-local
             # Get the name of the extracted directory
             MAVEN_DIR=$(ls maven-local)
             # Move contents up one level
             mv "maven-local/$MAVEN_DIR"/* maven-local/
             rm -r "maven-local/$MAVEN_DIR"
           else
-            tar xzf maven-dist/apache-maven-bin.tar.gz -C maven-local 
--strip-components 1
+            tar xzf maven-dist/apache-maven-*-bin.tar.gz -C maven-local 
--strip-components 1
           fi
           echo "MAVEN_HOME=$PWD/maven-local" >> $GITHUB_ENV
           echo "$PWD/maven-local/bin" >> $GITHUB_PATH
diff --git a/apache-maven/pom.xml b/apache-maven/pom.xml
index cb7a32de41..39cc762fa2 100644
--- a/apache-maven/pom.xml
+++ b/apache-maven/pom.xml
@@ -32,10 +32,6 @@ under the License.
   <name>Apache Maven Distribution</name>
   <description>The Apache Maven distribution, source and binary, in zip and 
tar.gz formats.</description>
 
-  <properties>
-    
<distributionFileName>${distributionId}-${project.version}</distributionFileName>
-  </properties>
-
   <dependencies>
     <dependency>
       <groupId>org.apache.maven</groupId>
@@ -162,7 +158,6 @@ under the License.
   </pluginRepositories>
 
   <build>
-    <finalName>${distributionFileName}</finalName>
     <plugins>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
diff --git 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupContext.java
 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupContext.java
index 2b29f846ed..8c7fd1df5f 100644
--- 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupContext.java
+++ 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupContext.java
@@ -35,6 +35,7 @@ import org.apache.maven.api.cli.Logger;
 import org.apache.maven.api.services.Lookup;
 import org.apache.maven.api.settings.Settings;
 import org.apache.maven.cling.logging.Slf4jConfiguration;
+import org.apache.maven.logging.BuildEventListener;
 import org.jline.terminal.Terminal;
 import org.slf4j.ILoggerFactory;
 
@@ -86,6 +87,8 @@ public class LookupContext implements AutoCloseable {
     public ContainerCapsule containerCapsule;
     public Lookup lookup;
 
+    public BuildEventListener buildEventListener;
+
     // paths user can override from CLI, and we need to set on MavenExReq
     public Path installationSettingsPath;
     public Path projectSettingsPath;
diff --git 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java
 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java
index 8c6aab340c..48c4c56c0a 100644
--- 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java
+++ 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java
@@ -69,7 +69,10 @@ import org.apache.maven.execution.MavenExecutionRequest;
 import org.apache.maven.internal.impl.SettingsUtilsV4;
 import org.apache.maven.jline.FastTerminal;
 import org.apache.maven.jline.MessageUtils;
+import org.apache.maven.logging.BuildEventListener;
 import org.apache.maven.logging.LoggingOutputStream;
+import org.apache.maven.logging.ProjectBuildLogAppender;
+import org.apache.maven.logging.SimpleBuildEventListener;
 import org.apache.maven.logging.api.LogLevelRecorder;
 import org.apache.maven.slf4j.MavenSimpleLogger;
 import org.jline.terminal.Terminal;
@@ -228,6 +231,23 @@ public abstract class LookupInvoker<C extends 
LookupContext> implements Invoker
         context.slf4jConfiguration.setRootLoggerLevel(context.loggerLevel);
         // else fall back to default log level specified in conf
         // see https://issues.apache.org/jira/browse/MNG-2570
+
+        // Create the build log appender; also sets MavenSimpleLogger sink
+        ProjectBuildLogAppender projectBuildLogAppender =
+                new 
ProjectBuildLogAppender(determineBuildEventListener(context));
+        context.closeables.add(projectBuildLogAppender);
+    }
+
+    protected BuildEventListener determineBuildEventListener(C context) {
+        if (context.buildEventListener == null) {
+            context.buildEventListener = 
doDetermineBuildEventListener(context);
+        }
+        return context.buildEventListener;
+    }
+
+    protected BuildEventListener doDetermineBuildEventListener(C context) {
+        Consumer<String> writer = determineWriter(context);
+        return new SimpleBuildEventListener(writer);
     }
 
     protected void createTerminal(C context) {
diff --git 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/MavenContext.java
 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/MavenContext.java
index c533b601ac..18f61aea36 100644
--- 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/MavenContext.java
+++ 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/MavenContext.java
@@ -22,7 +22,6 @@ import org.apache.maven.Maven;
 import org.apache.maven.api.cli.InvokerRequest;
 import org.apache.maven.cling.invoker.LookupContext;
 import org.apache.maven.eventspy.internal.EventSpyDispatcher;
-import org.apache.maven.logging.BuildEventListener;
 
 @SuppressWarnings("VisibilityModifier")
 public class MavenContext extends LookupContext {
@@ -30,7 +29,6 @@ public class MavenContext extends LookupContext {
         super(invokerRequest);
     }
 
-    public BuildEventListener buildEventListener;
     public EventSpyDispatcher eventSpyDispatcher;
     public Maven maven;
 
diff --git 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/MavenInvoker.java
 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/MavenInvoker.java
index 5e75e96b6f..667fc55623 100644
--- 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/MavenInvoker.java
+++ 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/MavenInvoker.java
@@ -27,7 +27,6 @@ import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.function.Consumer;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -68,11 +67,8 @@ import org.apache.maven.execution.ProfileActivation;
 import org.apache.maven.execution.ProjectActivation;
 import org.apache.maven.jline.MessageUtils;
 import org.apache.maven.lifecycle.LifecycleExecutionException;
-import org.apache.maven.logging.BuildEventListener;
 import org.apache.maven.logging.LoggingExecutionListener;
 import org.apache.maven.logging.MavenTransferListener;
-import org.apache.maven.logging.ProjectBuildLogAppender;
-import org.apache.maven.logging.SimpleBuildEventListener;
 import org.apache.maven.project.MavenProject;
 import org.codehaus.plexus.PlexusContainer;
 import org.eclipse.aether.DefaultRepositoryCache;
@@ -149,27 +145,6 @@ public abstract class MavenInvoker<C extends MavenContext> 
extends LookupInvoker
         }
     }
 
-    @Override
-    protected void configureLogging(C context) throws Exception {
-        super.configureLogging(context);
-        // Create the build log appender
-        ProjectBuildLogAppender projectBuildLogAppender =
-                new 
ProjectBuildLogAppender(determineBuildEventListener(context));
-        context.closeables.add(projectBuildLogAppender);
-    }
-
-    protected BuildEventListener determineBuildEventListener(C context) {
-        if (context.buildEventListener == null) {
-            context.buildEventListener = 
doDetermineBuildEventListener(context);
-        }
-        return context.buildEventListener;
-    }
-
-    protected BuildEventListener doDetermineBuildEventListener(C context) {
-        Consumer<String> writer = determineWriter(context);
-        return new SimpleBuildEventListener(writer);
-    }
-
     @Override
     protected void customizeSettingsRequest(C context, SettingsBuilderRequest 
settingsBuilderRequest) throws Exception {
         if (context.eventSpyDispatcher != null) {
diff --git 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/EncryptContext.java
 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/EncryptContext.java
index 41845f48d2..7f1e97abcb 100644
--- 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/EncryptContext.java
+++ 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/EncryptContext.java
@@ -23,7 +23,6 @@ import java.util.Map;
 
 import org.apache.maven.api.cli.InvokerRequest;
 import org.apache.maven.cling.invoker.LookupContext;
-import org.jline.consoleui.prompt.ConsolePrompt;
 import org.jline.reader.LineReader;
 import org.jline.utils.AttributedString;
 import org.jline.utils.AttributedStringBuilder;
@@ -40,7 +39,6 @@ public class EncryptContext extends LookupContext {
     public List<AttributedString> header;
     public AttributedStyle style;
     public LineReader reader;
-    public ConsolePrompt prompt;
 
     public void addInHeader(String text) {
         addInHeader(AttributedStyle.DEFAULT, text);
diff --git 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/EncryptInvoker.java
 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/EncryptInvoker.java
index 6ad5b0cbd4..1c52752377 100644
--- 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/EncryptInvoker.java
+++ 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/EncryptInvoker.java
@@ -26,13 +26,11 @@ import org.apache.maven.api.cli.mvnenc.EncryptOptions;
 import org.apache.maven.cling.invoker.LookupInvoker;
 import org.apache.maven.cling.invoker.ProtoLookup;
 import org.apache.maven.cling.utils.CLIReportingUtils;
-import org.jline.consoleui.prompt.ConsolePrompt;
 import org.jline.reader.LineReaderBuilder;
 import org.jline.reader.UserInterruptException;
 import org.jline.terminal.Terminal;
 import org.jline.utils.AttributedStyle;
 import org.jline.utils.Colors;
-import org.jline.utils.OSUtils;
 
 /**
  * mvnenc invoker implementation.
@@ -76,17 +74,9 @@ public class EncryptInvoker extends 
LookupInvoker<EncryptContext> {
 
             Thread executeThread = Thread.currentThread();
             context.terminal.handle(Terminal.Signal.INT, signal -> 
executeThread.interrupt());
-            ConsolePrompt.UiConfig config;
-            if (OSUtils.IS_WINDOWS) {
-                config = new ConsolePrompt.UiConfig(">", "( )", "(x)", "( )");
-            } else {
-                config = new ConsolePrompt.UiConfig("❯", "◯ ", "◉ ", "◯ ");
-            }
-            config.setCancellableFirstPrompt(true);
 
             context.reader =
                     
LineReaderBuilder.builder().terminal(context.terminal).build();
-            context.prompt = new ConsolePrompt(context.reader, 
context.terminal, config);
 
             EncryptOptions options = (EncryptOptions) 
context.invokerRequest.options();
             if (options.goals().isEmpty() || options.goals().get().size() != 
1) {
@@ -102,14 +92,13 @@ public class EncryptInvoker extends 
LookupInvoker<EncryptContext> {
 
             return goal.execute(context);
         } catch (InterruptedException | InterruptedIOException | 
UserInterruptException e) {
-            context.terminal.writer().println("Goal canceled by user.");
+            context.logger.error("Goal canceled by user.");
             return CANCELED;
         } catch (Exception e) {
             if (context.invokerRequest.options().showErrors().orElse(false)) {
-                context.terminal.writer().println(e.getMessage());
-                e.printStackTrace(context.terminal.writer());
+                context.logger.error(e.getMessage(), e);
             } else {
-                context.terminal.writer().println(e.getMessage());
+                context.logger.error(e.getMessage());
             }
             return ERROR;
         } finally {
@@ -118,9 +107,9 @@ public class EncryptInvoker extends 
LookupInvoker<EncryptContext> {
     }
 
     protected int badGoalsErrorMessage(String message, EncryptContext context) 
{
-        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.");
+        context.logger.error(message);
+        context.logger.error("Supported goals are: " + String.join(", ", 
context.goals.keySet()));
+        context.logger.error("Use -h to display help.");
         return BAD_OPERATION;
     }
 }
diff --git 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/ConfiguredGoalSupport.java
 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/ConfiguredGoalSupport.java
index fc9a51ad84..a3647a1f6b 100644
--- 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/ConfiguredGoalSupport.java
+++ 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/ConfiguredGoalSupport.java
@@ -39,12 +39,10 @@ public abstract class ConfiguredGoalSupport extends 
GoalSupport {
     @Override
     public int execute(EncryptContext context) throws Exception {
         if (!validateConfiguration(context)) {
-            context.terminal
-                    .writer()
-                    .println(messageBuilderFactory
-                            .builder()
-                            .error("Maven Encryption is not configured, run 
`mvnenc init` first.")
-                            .build());
+            context.logger.error(messageBuilderFactory
+                    .builder()
+                    .error("Maven Encryption is not configured, run `mvnenc 
init` first.")
+                    .build());
             return ERROR;
         }
         return doExecute(context);
@@ -59,36 +57,32 @@ public abstract class ConfiguredGoalSupport extends 
GoalSupport {
     }
 
     protected void dumpResponse(EncryptContext 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"));
+        context.logger.info(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")
+                .build());
         for (Map.Entry<SecDispatcher.ValidationResponse.Level, List<String>> 
entry :
                 response.getReport().entrySet()) {
-            Consumer<String> consumer = s -> context.terminal
-                    .writer()
-                    .println(messageBuilderFactory.builder().info(s).build());
+            Consumer<String> consumer = s ->
+                    
context.logger.info(messageBuilderFactory.builder().info(s).build());
             if (entry.getKey() == 
SecDispatcher.ValidationResponse.Level.ERROR) {
-                consumer = s -> context.terminal
-                        .writer()
-                        
.println(messageBuilderFactory.builder().error(s).build());
+                consumer = s -> context.logger.error(
+                        messageBuilderFactory.builder().error(s).build());
             } else if (entry.getKey() == 
SecDispatcher.ValidationResponse.Level.WARNING) {
-                consumer = s -> context.terminal
-                        .writer()
-                        
.println(messageBuilderFactory.builder().warning(s).build());
+                consumer = s -> context.logger.warn(
+                        messageBuilderFactory.builder().warning(s).build());
             }
             for (String line : entry.getValue()) {
                 consumer.accept(indent + "  " + line);
diff --git 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Diag.java
 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Diag.java
index 700ed47bc3..f6271d15cb 100644
--- 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Diag.java
+++ 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Diag.java
@@ -29,7 +29,7 @@ import 
org.codehaus.plexus.components.secdispatcher.SecDispatcher;
 import static org.apache.maven.cling.invoker.mvnenc.EncryptInvoker.OK;
 
 /**
- * The "diag" goal.
+ * The "diag" goal. It should always run, despite it overrides configured goal 
support.
  */
 @Singleton
 @Named("diag")
@@ -40,8 +40,13 @@ public class Diag extends ConfiguredGoalSupport {
     }
 
     @Override
-    protected int doExecute(EncryptContext context) {
+    public int execute(EncryptContext context) {
         dumpResponse(context, "", secDispatcher.validateConfiguration());
         return OK;
     }
+
+    @Override
+    protected int doExecute(EncryptContext context) throws Exception {
+        throw new IllegalStateException("Cannot reach here");
+    }
 }
diff --git 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Init.java
 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Init.java
index 7dfd1fba5f..ddaeed2846 100644
--- 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Init.java
+++ 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/goals/Init.java
@@ -45,6 +45,7 @@ import org.jline.reader.Completer;
 import org.jline.reader.LineReader;
 import org.jline.reader.ParsedLine;
 import org.jline.utils.Colors;
+import org.jline.utils.OSUtils;
 
 import static 
org.apache.maven.cling.invoker.mvnenc.EncryptInvoker.BAD_OPERATION;
 import static org.apache.maven.cling.invoker.mvnenc.EncryptInvoker.OK;
@@ -64,26 +65,30 @@ public class Init extends InteractiveGoalSupport {
 
     @Override
     public int doExecute(EncryptContext context) throws Exception {
-        
context.addInHeader(context.style.italic().bold().foreground(Colors.rgbColor("yellow")),
 "goal: init");
-        context.addInHeader("");
-
-        ConsolePrompt prompt = context.prompt;
-
         EncryptOptions options = (EncryptOptions) 
context.invokerRequest.options();
         boolean force = options.force().orElse(false);
         boolean yes = options.yes().orElse(false);
 
         if (configExists() && !force) {
-            context.terminal
-                    .writer()
-                    .println(
-                            messageBuilderFactory
-                                    .builder()
-                                    .error(
-                                            "Error: configuration exist. Use 
--force if you want to reset existing configuration."));
+            context.logger.error(messageBuilderFactory
+                    .builder()
+                    .error("Error: configuration exist. Use --force if you 
want to reset existing configuration.")
+                    .build());
             return BAD_OPERATION;
         }
 
+        
context.addInHeader(context.style.italic().bold().foreground(Colors.rgbColor("yellow")),
 "goal: init");
+        context.addInHeader("");
+
+        ConsolePrompt.UiConfig promptConfig;
+        if (OSUtils.IS_WINDOWS) {
+            promptConfig = new ConsolePrompt.UiConfig(">", "( )", "(x)", "( 
)");
+        } else {
+            promptConfig = new ConsolePrompt.UiConfig("❯", "◯ ", "◉ ", "◯ ");
+        }
+        promptConfig.setCancellableFirstPrompt(true);
+        ConsolePrompt prompt = new ConsolePrompt(context.reader, 
context.terminal, promptConfig);
+
         SettingsSecurity config = secDispatcher.readConfiguration(true);
 
         // reset config
diff --git a/impl/maven-executor/pom.xml b/impl/maven-executor/pom.xml
index 4e1060714b..73e76d9819 100644
--- a/impl/maven-executor/pom.xml
+++ b/impl/maven-executor/pom.xml
@@ -35,7 +35,7 @@ under the License.
 
   <properties>
     <maven3version>3.9.9</maven3version>
-    <maven4version>4.0.0-rc-1</maven4version>
+    <maven4version>${project.version}</maven4version>
   </properties>
 
   <dependencies>
@@ -55,6 +55,14 @@ under the License.
       <artifactId>junit-jupiter-params</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>apache-maven</artifactId>
+      <version>${project.version}</version>
+      <classifier>bin</classifier>
+      <type>zip</type>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
@@ -64,7 +72,17 @@ under the License.
         <artifactId>maven-dependency-plugin</artifactId>
         <executions>
           <execution>
-            <id>prepare-maven-distros</id>
+            <id>prepare-maven4-distro</id>
+            <goals>
+              <goal>unpack-dependencies</goal>
+            </goals>
+            <phase>generate-test-resources</phase>
+            <configuration>
+              <includeArtifactIds>apache-maven</includeArtifactIds>
+            </configuration>
+          </execution>
+          <execution>
+            <id>prepare-maven3-distro</id>
             <goals>
               <goal>unpack</goal>
             </goals>
@@ -78,13 +96,6 @@ under the License.
                   <classifier>bin</classifier>
                   <type>zip</type>
                 </artifactItem>
-                <artifactItem>
-                  <groupId>org.apache.maven</groupId>
-                  <artifactId>apache-maven</artifactId>
-                  <version>${maven4version}</version>
-                  <classifier>bin</classifier>
-                  <type>zip</type>
-                </artifactItem>
               </artifactItems>
             </configuration>
           </execution>
diff --git 
a/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/embedded/EmbeddedMavenExecutor.java
 
b/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/embedded/EmbeddedMavenExecutor.java
index 32b936a448..0bbacf9f66 100644
--- 
a/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/embedded/EmbeddedMavenExecutor.java
+++ 
b/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/embedded/EmbeddedMavenExecutor.java
@@ -34,6 +34,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Properties;
 import java.util.Set;
@@ -54,6 +55,9 @@ import static java.util.Objects.requireNonNull;
  * long as instance of this class is not closed. Subsequent execution requests 
over same installation home are cached.
  */
 public class EmbeddedMavenExecutor implements Executor {
+    protected static final Map<String, String> MAIN_CLASSES =
+            Map.of("mvn", "org.apache.maven.cling.MavenCling", "mvnenc", 
"org.apache.maven.cling.MavenEncCling");
+
     protected static final class Context {
         private final URLClassLoader bootClassLoader;
         private final String version;
@@ -62,7 +66,7 @@ public class EmbeddedMavenExecutor implements Executor {
         private final ClassLoader tccl;
         private final Function<ExecutorRequest, Integer> exec;
 
-        public Context(
+        private Context(
                 URLClassLoader bootClassLoader,
                 String version,
                 Object classWorld,
@@ -78,13 +82,38 @@ public class EmbeddedMavenExecutor implements Executor {
         }
     }
 
+    protected static class Key {
+        private final Path installationDirectory;
+        private final String command;
+
+        private Key(Path installationDirectory, String command) {
+            this.installationDirectory = installationDirectory;
+            this.command = command;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+            Key key = (Key) o;
+            return Objects.equals(installationDirectory, 
key.installationDirectory)
+                    && Objects.equals(command, key.command);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(installationDirectory, command);
+        }
+    }
+
     protected final boolean cacheContexts;
     protected final AtomicBoolean closed;
     protected final PrintStream originalStdout;
     protected final PrintStream originalStderr;
     protected final Properties originalProperties;
     protected final ClassLoader originalClassLoader;
-    protected final ConcurrentHashMap<Path, Context> contexts;
+    protected final ConcurrentHashMap<Key, Context> contexts;
 
     public EmbeddedMavenExecutor() {
         this(true);
@@ -163,8 +192,10 @@ public class EmbeddedMavenExecutor implements Executor {
 
     protected Context mayCreate(ExecutorRequest executorRequest) {
         Path mavenHome = 
ExecutorRequest.getCanonicalPath(executorRequest.installationDirectory());
+        String command = executorRequest.command();
+        Key key = new Key(mavenHome, command);
         if (cacheContexts) {
-            return contexts.computeIfAbsent(mavenHome, k -> 
doCreate(mavenHome, executorRequest));
+            return contexts.computeIfAbsent(key, k -> doCreate(mavenHome, 
executorRequest));
         } else {
             return doCreate(mavenHome, executorRequest);
         }
@@ -172,9 +203,9 @@ public class EmbeddedMavenExecutor implements Executor {
 
     protected Context doCreate(Path mavenHome, ExecutorRequest 
executorRequest) {
         if (!Files.isDirectory(mavenHome)) {
-            throw new IllegalArgumentException("Installation directory must 
point to existing directory");
+            throw new IllegalArgumentException("Installation directory must 
point to existing directory: " + mavenHome);
         }
-        if (!Objects.equals(executorRequest.command(), ExecutorRequest.MVN)) {
+        if (!MAIN_CLASSES.containsKey(executorRequest.command())) {
             throw new IllegalArgumentException(
                     getClass().getSimpleName() + " does not support command " 
+ executorRequest.command());
         }
@@ -187,7 +218,8 @@ public class EmbeddedMavenExecutor implements Executor {
         Path boot = mavenHome.resolve("boot");
         Path m2conf = mavenHome.resolve("bin/m2.conf");
         if (!Files.isDirectory(boot) || !Files.isRegularFile(m2conf)) {
-            throw new IllegalArgumentException("Installation directory does 
not point to Maven installation");
+            throw new IllegalArgumentException(
+                    "Installation directory does not point to Maven 
installation: " + mavenHome);
         }
 
         Properties properties = prepareProperties(executorRequest);
@@ -220,6 +252,10 @@ public class EmbeddedMavenExecutor implements Executor {
 
             if (version.startsWith("3.")) {
                 // 3.x
+                if (!ExecutorRequest.MVN.equals(executorRequest.command())) {
+                    throw new 
IllegalArgumentException(getClass().getSimpleName() + "w/ mvn3 does not support 
command "
+                            + executorRequest.command());
+                }
                 Constructor<?> newMavenCli = 
cliClass.getConstructor(classWorld.getClass());
                 Object mavenCli = newMavenCli.newInstance(classWorld);
                 Class<?>[] parameterTypes = {String[].class, String.class, 
PrintStream.class, PrintStream.class};
@@ -284,7 +320,8 @@ public class EmbeddedMavenExecutor implements Executor {
         properties.setProperty("maven.home", mavenHome.toString());
         properties.setProperty(
                 "maven.multiModuleProjectDirectory", request.cwd().toString());
-        properties.setProperty("maven.mainClass", 
"org.apache.maven.cling.MavenCling");
+        String mainClass = requireNonNull(MAIN_CLASSES.get(request.command()), 
"mainClass");
+        properties.setProperty("maven.mainClass", mainClass);
         properties.setProperty(
                 "library.jline.path", 
mavenHome.resolve("lib/jline-native").toString());
         // TODO: is this needed?
diff --git 
a/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/internal/HelperImpl.java
 
b/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/internal/HelperImpl.java
index d78a9161a1..e33af152bc 100644
--- 
a/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/internal/HelperImpl.java
+++ 
b/impl/maven-executor/src/main/java/org/apache/maven/cling/executor/internal/HelperImpl.java
@@ -22,7 +22,6 @@ import java.nio.file.Path;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.maven.api.annotations.Nullable;
@@ -112,8 +111,7 @@ public class HelperImpl implements ExecutorHelper {
     }
 
     private Executor getExecutorByRequest(ExecutorRequest request) {
-        if (Objects.equals(request.command(), ExecutorRequest.MVN)
-                && 
request.environmentVariables().orElse(Collections.emptyMap()).isEmpty()
+        if 
(request.environmentVariables().orElse(Collections.emptyMap()).isEmpty()
                 && 
request.jvmArguments().orElse(Collections.emptyList()).isEmpty()) {
             return getExecutor(Mode.EMBEDDED, request);
         } else {
diff --git 
a/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/MavenExecutorTestSupport.java
 
b/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/MavenExecutorTestSupport.java
index 0bf1b30f6a..42c6171a21 100644
--- 
a/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/MavenExecutorTestSupport.java
+++ 
b/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/MavenExecutorTestSupport.java
@@ -35,6 +35,25 @@ import org.junit.jupiter.api.io.TempDir;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 public abstract class MavenExecutorTestSupport {
+    @Test
+    void mvnenc(
+            @TempDir(cleanup = CleanupMode.ON_SUCCESS) Path cwd,
+            @TempDir(cleanup = CleanupMode.ON_SUCCESS) Path userHome)
+            throws Exception {
+        String logfile = "m4.log";
+        execute(
+                cwd.resolve(logfile),
+                List.of(mvn4ExecutorRequestBuilder()
+                        .command("mvnenc")
+                        .cwd(cwd)
+                        .userHomeDirectory(userHome)
+                        .argument("diag")
+                        .argument("-l")
+                        .argument(logfile)
+                        .build()));
+        System.out.println(Files.readString(cwd.resolve(logfile)));
+    }
+
     @Disabled("JUnit on Windows fails to clean up as mvn3 seems does not close 
log file properly")
     @Test
     void dump3(
diff --git a/its/core-it-suite/pom.xml b/its/core-it-suite/pom.xml
index 87c8a91f5f..b236580ac0 100644
--- a/its/core-it-suite/pom.xml
+++ b/its/core-it-suite/pom.xml
@@ -715,7 +715,7 @@ under the License.
                     <unzip dest="${mavenHome}" 
src="${project.build.directory}/maven-bin.zip">
                       <globmapper from="apache-maven-${mavenVersion}/*" 
handledirsep="true" to="*" />
                     </unzip>
-                    <chmod dir="${mavenHome}/bin" includes="mvn,mvnDebug" 
perm="ugo+rx" />
+                    <chmod dir="${mavenHome}/bin" 
includes="mvn,mvnDebug,mvnenc" perm="ugo+rx" />
                   </target>
                 </configuration>
               </execution>
@@ -758,7 +758,7 @@ under the License.
                     <unzip dest="${mavenHome}" src="${mavenDistro}">
                       <regexpmapper from="^([^/]+)/(.*)$" handledirsep="true" 
to="\2" />
                     </unzip>
-                    <chmod dir="${mavenHome}/bin" includes="mvn,mvnDebug" 
perm="ugo+rx" />
+                    <chmod dir="${mavenHome}/bin" 
includes="mvn,mvnDebug,mvnenc" perm="ugo+rx" />
                   </target>
                 </configuration>
               </execution>
diff --git 
a/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITmng8421MavenEncryptionTest.java
 
b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITmng8421MavenEncryptionTest.java
new file mode 100644
index 0000000000..8fdcffaf8e
--- /dev/null
+++ 
b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITmng8421MavenEncryptionTest.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.it;
+
+import java.nio.file.Path;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * This is a test set for <a 
href="https://issues.apache.org/jira/browse/MNG-8421";>MNG-8421</a>.
+ */
+class MavenITmng8421MavenEncryptionTest extends 
AbstractMavenIntegrationTestCase {
+
+    MavenITmng8421MavenEncryptionTest() {
+        super("[4.0.0-rc-2-SNAPSHOT,)");
+    }
+
+    /**
+     *  Verify that empty home causes diag output as expected.
+     */
+    @Test
+    void testEmptyHome() throws Exception {
+        Path basedir = 
extractResources("/mng-8421").getAbsoluteFile().toPath();
+
+        Path home = basedir.resolve("home1");
+
+        Verifier verifier = newVerifier(basedir.toString());
+        verifier.setLogFileName("home1.txt");
+        verifier.setUserHomeDirectory(home);
+        verifier.setExecutable("mvnenc");
+        verifier.addCliArgument("diag");
+        verifier.execute();
+        verifier.verifyTextInLog("[ERROR]");
+        verifier.verifyTextInLog("No configuration file found");
+        verifier.verifyTextInLog("settings-security4.xml");
+    }
+
+    /**
+     *  Verify that set-upo home causes diag output as expected.
+     */
+    @Test
+    void testSetupHome() throws Exception {
+        Path basedir = 
extractResources("/mng-8421").getAbsoluteFile().toPath();
+
+        Path home = basedir.resolve("home2");
+
+        Verifier verifier = newVerifier(basedir.toString());
+        verifier.setLogFileName("home2.txt");
+        verifier.setUserHomeDirectory(home);
+        verifier.setExecutable("mvnenc");
+        verifier.addCliArgument("diag");
+        verifier.execute();
+        verifier.verifyErrorFreeLog();
+        verifier.verifyTextInLog("[INFO] Configuration validation of 
MavenSecDispatcher: VALID");
+        verifier.verifyTextInLog("[WARNING]       Configured environment 
variable not exist");
+    }
+}
diff --git 
a/its/core-it-suite/src/test/java/org/apache/maven/it/TestSuiteOrdering.java 
b/its/core-it-suite/src/test/java/org/apache/maven/it/TestSuiteOrdering.java
index 79d20af271..ac5b592a86 100644
--- a/its/core-it-suite/src/test/java/org/apache/maven/it/TestSuiteOrdering.java
+++ b/its/core-it-suite/src/test/java/org/apache/maven/it/TestSuiteOrdering.java
@@ -100,6 +100,7 @@ public class TestSuiteOrdering implements ClassOrderer {
          * the tests are to finishing. Newer tests are also more likely to 
fail, so this is
          * a fail fast technique as well.
          */
+        suite.addTestSuite(MavenITmng8421MavenEncryptionTest.class);
         suite.addTestSuite(MavenITmng8400CanonicalMavenHomeTest.class);
         suite.addTestSuite(MavenITmng8385PropertyContributoSPITest.class);
         suite.addTestSuite(MavenITmng8383UnknownTypeDependenciesTest.class);
diff --git a/its/core-it-suite/src/test/resources/mng-8421/home1/readme.txt 
b/its/core-it-suite/src/test/resources/mng-8421/home1/readme.txt
new file mode 100644
index 0000000000..c33570fdcb
--- /dev/null
+++ b/its/core-it-suite/src/test/resources/mng-8421/home1/readme.txt
@@ -0,0 +1 @@
+This is an empty home
\ No newline at end of file
diff --git 
a/its/core-it-suite/src/test/resources/mng-8421/home2/.m2/settings-security.xml 
b/its/core-it-suite/src/test/resources/mng-8421/home2/.m2/settings-security.xml
new file mode 100644
index 0000000000..ee2e241583
--- /dev/null
+++ 
b/its/core-it-suite/src/test/resources/mng-8421/home2/.m2/settings-security.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<settingsSecurity>
+  <!-- created with Maven 3.9.9: "masterpassword" -->
+  <master>{biSS3+PaKIMH9acY9wBZjfuzSTrkkrXjgDa7jWvW+ew=}</master>
+</settingsSecurity>
\ No newline at end of file
diff --git 
a/its/core-it-suite/src/test/resources/mng-8421/home2/.m2/settings-security4.xml
 
b/its/core-it-suite/src/test/resources/mng-8421/home2/.m2/settings-security4.xml
new file mode 100644
index 0000000000..a1b2a049ac
--- /dev/null
+++ 
b/its/core-it-suite/src/test/resources/mng-8421/home2/.m2/settings-security4.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<settingsSecurity 
xmlns="http://codehaus-plexus.github.io/plexus-sec-dispatcher/4.0.0";
+                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+                  
xsi:schemaLocation="http://codehaus-plexus.github.io/plexus-sec-dispatcher/4.0.0
 https://codehaus-plexus.github.io/xsd/plexus-sec-dispatcher-4.0.0.xsd";>
+  <modelVersion>4.0</modelVersion>
+  <defaultDispatcher>master</defaultDispatcher>
+  <configurations>
+    <configuration>
+      <name>master</name>
+      <properties>
+        <property>
+          <name>source</name>
+          <value>env:MAVEN_MASTER_PASSWORD</value>
+        </property>
+        <property>
+          <name>cipher</name>
+          <value>AES/GCM/NoPadding</value>
+        </property>
+      </properties>
+    </configuration>
+  </configurations>
+</settingsSecurity>
diff --git a/its/core-it-suite/src/test/resources/mng-8421/home2/readme.txt 
b/its/core-it-suite/src/test/resources/mng-8421/home2/readme.txt
new file mode 100644
index 0000000000..01f0e09e25
--- /dev/null
+++ b/its/core-it-suite/src/test/resources/mng-8421/home2/readme.txt
@@ -0,0 +1 @@
+This is fully setup home
\ No newline at end of file
diff --git 
a/its/core-it-support/maven-it-helper/src/main/java/org/apache/maven/it/Verifier.java
 
b/its/core-it-support/maven-it-helper/src/main/java/org/apache/maven/it/Verifier.java
index 1755bf14a1..7e74123d9f 100644
--- 
a/its/core-it-support/maven-it-helper/src/main/java/org/apache/maven/it/Verifier.java
+++ 
b/its/core-it-support/maven-it-helper/src/main/java/org/apache/maven/it/Verifier.java
@@ -92,7 +92,7 @@ public class Verifier {
 
     private final Path tempBasedir; // empty basedir for queries
 
-    private final Path userHomeDirectory;
+    private Path userHomeDirectory;
 
     private final List<String> defaultCliArguments;
 
@@ -102,6 +102,8 @@ public class Verifier {
 
     private final List<String> cliArguments = new ArrayList<>();
 
+    private String executable = ExecutorRequest.MVN;
+
     private boolean autoClean = true;
 
     private boolean forkJvm = false;
@@ -144,8 +146,16 @@ public class Verifier {
         }
     }
 
+    public void setUserHomeDirectory(Path userHomeDirectory) {
+        this.userHomeDirectory = requireNonNull(userHomeDirectory);
+    }
+
     public String getExecutable() {
-        return ExecutorRequest.MVN;
+        return executable;
+    }
+
+    public void setExecutable(String executable) {
+        this.executable = requireNonNull(executable);
     }
 
     public void execute() throws VerificationException {
@@ -221,6 +231,7 @@ public class Verifier {
         try {
             ExecutorRequest.Builder builder = executorHelper
                     .executorRequest()
+                    .command(executable)
                     .cwd(basedir)
                     .userHomeDirectory(userHomeDirectory)
                     .arguments(args);


Reply via email to