/*
 * 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.cli;

import javax.xml.stream.XMLStreamException;

import java.io.Console;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.Map.Entry;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import com.google.inject.AbstractModule;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.UnrecognizedOptionException;
import org.apache.maven.BuildAbort;
import org.apache.maven.InternalErrorException;
import org.apache.maven.Maven;
import org.apache.maven.api.services.MessageBuilder;
import org.apache.maven.api.services.MessageBuilderFactory;
import org.apache.maven.building.FileSource;
import org.apache.maven.building.Problem;
import org.apache.maven.building.Source;
import org.apache.maven.cli.configuration.ConfigurationProcessor;
import org.apache.maven.cli.configuration.SettingsXmlConfigurationProcessor;
import org.apache.maven.cli.event.DefaultEventSpyContext;
import org.apache.maven.cli.event.ExecutionEventLogger;
import org.apache.maven.cli.internal.BootstrapCoreExtensionManager;
import org.apache.maven.cli.internal.extension.io.CoreExtensionsStaxReader;
import org.apache.maven.cli.internal.extension.model.CoreExtension;
import org.apache.maven.cli.logging.Slf4jConfiguration;
import org.apache.maven.cli.logging.Slf4jConfigurationFactory;
import org.apache.maven.cli.logging.Slf4jLoggerManager;
import org.apache.maven.cli.logging.Slf4jStdoutLogger;
import org.apache.maven.cli.transfer.*;
import org.apache.maven.eventspy.internal.EventSpyDispatcher;
import org.apache.maven.exception.DefaultExceptionHandler;
import org.apache.maven.exception.ExceptionHandler;
import org.apache.maven.exception.ExceptionSummary;
import org.apache.maven.execution.DefaultMavenExecutionRequest;
import org.apache.maven.execution.ExecutionListener;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionRequestPopulationException;
import org.apache.maven.execution.MavenExecutionRequestPopulator;
import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.execution.ProfileActivation;
import org.apache.maven.execution.ProjectActivation;
import org.apache.maven.execution.scope.internal.MojoExecutionScope;
import org.apache.maven.execution.scope.internal.MojoExecutionScopeModule;
import org.apache.maven.extension.internal.CoreExports;
import org.apache.maven.extension.internal.CoreExtensionEntry;
import org.apache.maven.jline.JLineMessageBuilderFactory;
import org.apache.maven.jline.MessageUtils;
import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.logwrapper.LogLevelRecorder;
import org.apache.maven.logwrapper.MavenSlf4jWrapperFactory;
import org.apache.maven.model.building.ModelProcessor;
import org.apache.maven.model.root.RootLocator;
import org.apache.maven.project.MavenProject;
import org.apache.maven.properties.internal.EnvironmentUtils;
import org.apache.maven.properties.internal.SystemProperties;
import org.apache.maven.session.scope.internal.SessionScope;
import org.apache.maven.session.scope.internal.SessionScopeModule;
import org.apache.maven.toolchain.building.DefaultToolchainsBuildingRequest;
import org.apache.maven.toolchain.building.ToolchainsBuilder;
import org.apache.maven.toolchain.building.ToolchainsBuildingResult;
import org.codehaus.plexus.ContainerConfiguration;
import org.codehaus.plexus.DefaultContainerConfiguration;
import org.codehaus.plexus.DefaultPlexusContainer;
import org.codehaus.plexus.PlexusConstants;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.interpolation.AbstractValueSource;
import org.codehaus.plexus.interpolation.BasicInterpolator;
import org.codehaus.plexus.interpolation.StringSearchInterpolator;
import org.codehaus.plexus.logging.LoggerManager;
import org.eclipse.aether.DefaultRepositoryCache;
import org.eclipse.aether.transfer.TransferListener;
import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
import org.sonatype.plexus.components.sec.dispatcher.SecUtil;
import org.sonatype.plexus.components.sec.dispatcher.model.SettingsSecurity;

import static java.util.Comparator.comparing;
import static org.apache.maven.cli.CLIManager.BATCH_MODE;
import static org.apache.maven.cli.CLIManager.COLOR;
import static org.apache.maven.cli.CLIManager.FORCE_INTERACTIVE;
import static org.apache.maven.cli.CLIManager.NON_INTERACTIVE;
import static org.apache.maven.cli.ResolveFile.resolveFile;

// TODO push all common bits back to plexus cli and prepare for transition to Guice. We don't need 50 ways to make CLIs

/**
 */
public class MavenCli {
    public static final String LOCAL_REPO_PROPERTY = "maven.repo.local";

    public static final String MULTIMODULE_PROJECT_DIRECTORY = "maven.multiModuleProjectDirectory";

    public static final String USER_HOME = System.getProperty("user.home");

    public static final File USER_MAVEN_CONFIGURATION_HOME = new File(USER_HOME, ".m2");

    public static final File DEFAULT_USER_TOOLCHAINS_FILE = new File(USER_MAVEN_CONFIGURATION_HOME, "toolchains.xml");

    public static final File DEFAULT_GLOBAL_TOOLCHAINS_FILE =
            new File(System.getProperty("maven.conf"), "toolchains.xml");

    private static final String EXT_CLASS_PATH = "maven.ext.class.path";

    private static final String EXTENSIONS_FILENAME = "extensions.xml";

    private static final String MVN_EXTENSIONS_FILENAME = ".mvn/" + EXTENSIONS_FILENAME;

    private static final String MVN_MAVEN_CONFIG = ".mvn/maven.config";

    public static final String STYLE_COLOR_PROPERTY = "style.color";

    private ClassWorld classWorld;

    private LoggerManager plexusLoggerManager;

    private ILoggerFactory slf4jLoggerFactory;

    private Logger slf4jLogger;

    private EventSpyDispatcher eventSpyDispatcher;

    private ModelProcessor modelProcessor;

    private Maven maven;

    private MavenExecutionRequestPopulator executionRequestPopulator;

    private ToolchainsBuilder toolchainsBuilder;

    private DefaultSecDispatcher dispatcher;

    private Map<String, ConfigurationProcessor> configurationProcessors;

    private CLIManager cliManager;

    private MessageBuilderFactory messageBuilderFactory;

    private static final Pattern NEXT_LINE = Pattern.compile("\r?\n");

    public MavenCli() {
        this(null);
    }

    // This supports painless invocation by the Verifier during embedded execution of the core ITs
    public MavenCli(ClassWorld classWorld) {
        this.classWorld = classWorld;
        this.messageBuilderFactory = new JLineMessageBuilderFactory();
    }

    public static void main(String[] args) {
        int result = main(args, null);

        System.exit(result);
    }

    public static int main(String[] args, ClassWorld classWorld) {
        MavenCli cli = new MavenCli();

        MessageUtils.systemInstall();
        MessageUtils.registerShutdownHook();
        int result = cli.doMain(new CliRequest(args, classWorld));
        MessageUtils.systemUninstall();

        return result;
    }

    // TODO need to externalize CliRequest
    public static int doMain(String[] args, ClassWorld classWorld) {
        MavenCli cli = new MavenCli();
        return cli.doMain(new CliRequest(args, classWorld));
    }

    /**
     * This supports painless invocation by the Verifier during embedded execution of the core ITs.
     * See <a href="http://maven.apache.org/shared/maven-verifier/xref/org/apache/maven/it/Embedded3xLauncher.html">
     * <code>Embedded3xLauncher</code> in <code>maven-verifier</code></a>
     *
     * @param args CLI args
     * @param workingDirectory working directory
     * @param stdout stdout
     * @param stderr stderr
     * @return return code
     */
    public int doMain(String[] args, String workingDirectory, PrintStream stdout, PrintStream stderr) {
        PrintStream oldout = System.out;
        PrintStream olderr = System.err;

        final Set<String> realms;
        if (classWorld != null) {
            realms = new HashSet<>();
            for (ClassRealm realm : classWorld.getRealms()) {
                realms.add(realm.getId());
            }
        } else {
            realms = Collections.emptySet();
        }

        try {
            if (stdout != null) {
                System.setOut(stdout);
            }
            if (stderr != null) {
                System.setErr(stderr);
            }

            CliRequest cliRequest = new CliRequest(args, classWorld);
            cliRequest.workingDirectory = workingDirectory;

            return doMain(cliRequest);
        } finally {
            if (classWorld != null) {
                for (ClassRealm realm : new ArrayList<>(classWorld.getRealms())) {
                    String realmId = realm.getId();
                    if (!realms.contains(realmId)) {
                        try {
                            classWorld.disposeRealm(realmId);
                        } catch (NoSuchRealmException ignored) {
                            // can't happen
                        }
                    }
                }
            }
            System.setOut(oldout);
            System.setErr(olderr);
        }
    }

    // TODO need to externalize CliRequest
    public int doMain(CliRequest cliRequest) {
        PlexusContainer localContainer = null;
        try {
            initialize(cliRequest);
            cli(cliRequest);
            properties(cliRequest);
            logging(cliRequest);
            informativeCommands(cliRequest);
            version(cliRequest);
            localContainer = container(cliRequest);
            commands(cliRequest);
            configure(cliRequest);
            toolchains(cliRequest);
            populateRequest(cliRequest);
            encryption(cliRequest);
            return execute(cliRequest);
        } catch (ExitException e) {
            return e.exitCode;
        } catch (UnrecognizedOptionException e) {
            // pure user error, suppress stack trace
            return 1;
        } catch (BuildAbort e) {
            CLIReportingUtils.showError(slf4jLogger, "ABORTED", e, cliRequest.showErrors);

            return 2;
        } catch (Exception e) {
            CLIReportingUtils.showError(slf4jLogger, "Error executing Maven.", e, cliRequest.showErrors);

            return 1;
        } finally {
            if (localContainer != null) {
                localContainer.dispose();
            }
        }
    }

    void initialize(CliRequest cliRequest) throws ExitException {
        if (cliRequest.workingDirectory == null) {
            cliRequest.workingDirectory = System.getProperty("user.dir");
        }

        if (cliRequest.multiModuleProjectDirectory == null) {
            String basedirProperty = System.getProperty(MULTIMODULE_PROJECT_DIRECTORY);
            if (basedirProperty == null) {
                System.err.format("-D%s system property is not set.", MULTIMODULE_PROJECT_DIRECTORY);
                throw new ExitException(1);
            }
            File basedir = new File(basedirProperty);
            try {
                cliRequest.multiModuleProjectDirectory = basedir.getCanonicalFile();
            } catch (IOException e) {
                cliRequest.multiModuleProjectDirectory = basedir.getAbsoluteFile();
            }
        }

        // We need to locate the top level project which may be pointed at using
        // the -f/--file option.  However, the command line isn't parsed yet, so
        // we need to iterate through the args to find it and act upon it.
        Path topDirectory = Paths.get(cliRequest.workingDirectory);
        boolean isAltFile = false;
        for (String arg : cliRequest.args) {
            if (isAltFile) {
                // this is the argument following -f/--file
                Path path = topDirectory.resolve(stripLeadingAndTrailingQuotes(arg));
                if (Files.isDirectory(path)) {
                    topDirectory = path;
                } else if (Files.isRegularFile(path)) {
                    topDirectory = path.getParent();
                    if (!Files.isDirectory(topDirectory)) {
                        System.err.println("Directory " + topDirectory
                                + " extracted from the -f/--file command-line argument " + arg + " does not exist");
                        throw new ExitException(1);
                    }
                } else {
                    System.err.println(
                            "POM file " + arg + " specified with the -f/--file command line argument does not exist");
                    throw new ExitException(1);
                }
                break;
            } else {
                // Check if this is the -f/--file option
                isAltFile = arg.equals("-f") || arg.equals("--file");
            }
        }
        topDirectory = getCanonicalPath(topDirectory);
        cliRequest.topDirectory = topDirectory;
        // We're very early in the process, and we don't have the container set up yet,
        // so we rely on the JDK services to eventually look up a custom RootLocator.
        // This is used to compute {@code session.rootDirectory} but all {@code project.rootDirectory}
        // properties will be computed through the RootLocator found in the container.
        RootLocator rootLocator =
                ServiceLoader.load(RootLocator.class).iterator().next();
        cliRequest.rootDirectory = rootLocator.findRoot(topDirectory);

        //
        // Make sure the Maven home directory is an absolute path to save us from confusion with say drive-relative
        // Windows paths.
        //
        String mavenHome = System.getProperty("maven.home");

        if (mavenHome != null) {
            System.setProperty("maven.home", new File(mavenHome).getAbsolutePath());
        }
    }

    void cli(CliRequest cliRequest) throws Exception {
        //
        // Parsing errors can happen during the processing of the arguments and we prefer not having to check if
        // the logger is null and construct this so we can use an SLF4J logger everywhere.
        //
        slf4jLogger = new Slf4jStdoutLogger();

        cliManager = new CLIManager();

        CommandLine mavenConfig = null;
        try {
            File configFile = new File(cliRequest.multiModuleProjectDirectory, MVN_MAVEN_CONFIG);

            if (configFile.isFile()) {
                try (Stream<String> lines = Files.lines(configFile.toPath(), Charset.defaultCharset())) {
                    String[] args = lines.filter(arg -> !arg.isEmpty() && !arg.startsWith("#"))
                            .toArray(String[]::new);
                    mavenConfig = cliManager.parse(args);
                    List<?> unrecognized = mavenConfig.getArgList();
                    if (!unrecognized.isEmpty()) {
                        // This file can only contain options, not args (goals or phases)
                        throw new ParseException("Unrecognized maven.config file entries: " + unrecognized);
                    }
                }
            }
        } catch (ParseException e) {
            System.err.println("Unable to parse maven.config file options: " + e.getMessage());
            cliManager.displayHelp(System.out);
            throw e;
        }

        try {
            CommandLine mavenCli = cliManager.parse(cliRequest.args);
            if (mavenConfig == null) {
                cliRequest.commandLine = mavenCli;
            } else {
                cliRequest.commandLine = cliMerge(mavenConfig, mavenCli);
            }
        } catch (ParseException e) {
            System.err.println("Unable to parse command line options: " + e.getMessage());
            cliManager.displayHelp(System.out);
            throw e;
        }

        // check for presence of unsupported command line options
        try {
            if (cliRequest.commandLine.hasOption("llr")) {
                throw new UnrecognizedOptionException("Option '-llr' is not supported starting with Maven 3.9.1");
            }
        } catch (ParseException e) {
            System.err.println("Unsupported options: " + e.getMessage());
            cliManager.displayHelp(System.out);
            throw e;
        }
    }

    private void informativeCommands(CliRequest cliRequest) throws ExitException {
        if (cliRequest.commandLine.hasOption(CLIManager.HELP)) {
            cliManager.displayHelp(System.out);
            throw new ExitException(0);
        }

        if (cliRequest.commandLine.hasOption(CLIManager.VERSION)) {
            if (cliRequest.commandLine.hasOption(CLIManager.QUIET)) {
                System.out.println(CLIReportingUtils.showVersionMinimal());
            } else {
                System.out.println(CLIReportingUtils.showVersion());
            }
            throw new ExitException(0);
        }

        if (cliRequest.rootDirectory == null) {
            slf4jLogger.info(RootLocator.UNABLE_TO_FIND_ROOT_PROJECT_MESSAGE);
        }
    }

    private CommandLine cliMerge(CommandLine mavenConfig, CommandLine mavenCli) {
        CommandLine.Builder commandLineBuilder = new CommandLine.Builder();

        // the args are easy, CLI only since maven.config file can only contain options
        for (String arg : mavenCli.getArgs()) {
            commandLineBuilder.addArg(arg);
        }

        /* Although this looks wrong in terms of order Commons CLI stores the value of options in
         * an array and when a value is potentionally overriden it is added to the array. The single
         * arg option value is retrieved and instead of returning values[values.length-1] it returns
         * values[0] which means that the original value instead of the overridden one is returned
         * (first wins). With properties values are truely overriden since at the end a map is used
         * to merge which means last wins.
         *
         * TODO Report this behavioral bug with Commons CLI
         */
        // now add all options, except for user properties with CLI first then maven.config file
        List<Option> setPropertyOptions = new ArrayList<>();
        for (Option opt : mavenCli.getOptions()) {
            if (String.valueOf(CLIManager.SET_USER_PROPERTY).equals(opt.getOpt())) {
                setPropertyOptions.add(opt);
            } else {
                commandLineBuilder.addOption(opt);
            }
        }
        for (Option opt : mavenConfig.getOptions()) {
            commandLineBuilder.addOption(opt);
        }
        // finally add the CLI user properties
        for (Option opt : setPropertyOptions) {
            commandLineBuilder.addOption(opt);
        }
        return commandLineBuilder.build();
    }

    /**
     * configure logging
     */
    void logging(CliRequest cliRequest) {
        // LOG LEVEL
        CommandLine commandLine = cliRequest.commandLine;
        cliRequest.verbose = commandLine.hasOption(CLIManager.VERBOSE) || commandLine.hasOption(CLIManager.DEBUG);
        cliRequest.quiet = !cliRequest.verbose && commandLine.hasOption(CLIManager.QUIET);
        cliRequest.showErrors = cliRequest.verbose || commandLine.hasOption(CLIManager.ERRORS);

        // LOG COLOR
        String styleColor = cliRequest.getUserProperties().getProperty(STYLE_COLOR_PROPERTY, "auto");
        styleColor = commandLine.getOptionValue(COLOR, styleColor);
        if ("always".equals(styleColor) || "yes".equals(styleColor) || "force".equals(styleColor)) {
            MessageUtils.setColorEnabled(true);
        } else if ("never".equals(styleColor) || "no".equals(styleColor) || "none".equals(styleColor)) {
            MessageUtils.setColorEnabled(false);
        } else if (!"auto".equals(styleColor) && !"tty".equals(styleColor) && !"if-tty".equals(styleColor)) {
            throw new IllegalArgumentException(
                    "Invalid color configuration value '" + styleColor + "'. Supported are 'auto', 'always', 'never'.");
        } else {
            boolean isBatchMode = !commandLine.hasOption(FORCE_INTERACTIVE)
                    && (commandLine.hasOption(BATCH_MODE) || commandLine.hasOption(NON_INTERACTIVE));
            if (isBatchMode || commandLine.hasOption(CLIManager.LOG_FILE)) {
                MessageUtils.setColorEnabled(false);
            }
        }

        slf4jLoggerFactory = LoggerFactory.getILoggerFactory();
        Slf4jConfiguration slf4jConfiguration = Slf4jConfigurationFactory.getConfiguration(slf4jLoggerFactory);

        if (cliRequest.verbose) {
            cliRequest.request.setLoggingLevel(MavenExecutionRequest.LOGGING_LEVEL_DEBUG);
            slf4jConfiguration.setRootLoggerLevel(Slf4jConfiguration.Level.DEBUG);
        } else if (cliRequest.quiet) {
            cliRequest.request.setLoggingLevel(MavenExecutionRequest.LOGGING_LEVEL_ERROR);
            slf4jConfiguration.setRootLoggerLevel(Slf4jConfiguration.Level.ERROR);
        }
        // else fall back to default log level specified in conf
        // see https://issues.apache.org/jira/browse/MNG-2570

        // LOG STREAMS
        if (commandLine.hasOption(CLIManager.LOG_FILE)) {
            File logFile = new File(commandLine.getOptionValue(CLIManager.LOG_FILE));
            logFile = resolveFile(logFile, cliRequest.workingDirectory);

            // redirect stdout and stderr to file
            try {
                PrintStream ps = new PrintStream(new FileOutputStream(logFile));
                System.setOut(ps);
                System.setErr(ps);
            } catch (FileNotFoundException e) {
                //
                // Ignore
                //
            }
        }

        slf4jConfiguration.activate();

        plexusLoggerManager = new Slf4jLoggerManager();
        slf4jLogger = slf4jLoggerFactory.getLogger(this.getClass().getName());

        if (commandLine.hasOption(CLIManager.FAIL_ON_SEVERITY)) {
            String logLevelThreshold = commandLine.getOptionValue(CLIManager.FAIL_ON_SEVERITY);

            if (slf4jLoggerFactory instanceof MavenSlf4jWrapperFactory) {
                LogLevelRecorder logLevelRecorder = new LogLevelRecorder(logLevelThreshold);
                ((MavenSlf4jWrapperFactory) slf4jLoggerFactory).setLogLevelRecorder(logLevelRecorder);
                slf4jLogger.info("Enabled to break the build on log level {}.", logLevelThreshold);
            } else {
                slf4jLogger.warn(
                        "Expected LoggerFactory to be of type '{}', but found '{}' instead. "
                                + "The --fail-on-severity flag will not take effect.",
                        MavenSlf4jWrapperFactory.class.getName(),
                        slf4jLoggerFactory.getClass().getName());
            }
        }

        if (commandLine.hasOption(CLIManager.DEBUG)) {
            slf4jLogger.warn("The option '--debug' is deprecated and may be repurposed as Java debug"
                    + " in a future version. Use -X/--verbose instead.");
        }
    }

    private void version(CliRequest cliRequest) {
        if (cliRequest.verbose || cliRequest.commandLine.hasOption(CLIManager.SHOW_VERSION)) {
            System.out.println(CLIReportingUtils.showVersion());
        }
    }

    private void commands(CliRequest cliRequest) {
        if (cliRequest.showErrors) {
            slf4jLogger.info("Error stacktraces are turned on.");
        }

        if (MavenExecutionRequest.CHECKSUM_POLICY_WARN.equals(cliRequest.request.getGlobalChecksumPolicy())) {
            slf4jLogger.info("Disabling strict checksum verification on all artifact downloads.");
        } else if (MavenExecutionRequest.CHECKSUM_POLICY_FAIL.equals(cliRequest.request.getGlobalChecksumPolicy())) {
            slf4jLogger.info("Enabling strict checksum verification on all artifact downloads.");
        }

        if (slf4jLogger.isDebugEnabled()) {
            slf4jLogger.debug("Message scheme: {}", (MessageUtils.isColorEnabled() ? "color" : "plain"));
            if (MessageUtils.isColorEnabled()) {
                MessageBuilder buff = MessageUtils.builder();
                buff.a("Message styles: ");
                buff.trace("trace").a(' ');
                buff.debug("debug").a(' ');
                buff.info("info").a(' ');
                buff.warning("warning").a(' ');
                buff.error("error").a(' ');
                buff.success("success").a(' ');
                buff.failure("failure").a(' ');
                buff.strong("strong").a(' ');
                buff.mojo("mojo").a(' ');
                buff.project("project");
                slf4jLogger.debug(buff.toString());
            }
        }
    }

    // Needed to make this method package visible to make writing a unit test possible
    // Maybe it's better to move some of those methods to separate class (SoC).
    void properties(CliRequest cliRequest) throws Exception {
        Properties paths = new Properties();
        if (cliRequest.topDirectory != null) {
            paths.put("session.topDirectory", cliRequest.topDirectory.toString());
        }
        if (cliRequest.rootDirectory != null) {
            paths.put("session.rootDirectory", cliRequest.rootDirectory.toString());
        }

        populateProperties(cliRequest.commandLine, paths, cliRequest.systemProperties, cliRequest.userProperties);

        // now that we have properties, interpolate all arguments
        BasicInterpolator interpolator =
                createInterpolator(paths, cliRequest.systemProperties, cliRequest.userProperties);
        CommandLine.Builder commandLineBuilder = new CommandLine.Builder();
        for (Option option : cliRequest.commandLine.getOptions()) {
            if (!String.valueOf(CLIManager.SET_USER_PROPERTY).equals(option.getOpt())) {
                List<String> values = option.getValuesList();
                for (ListIterator<String> it = values.listIterator(); it.hasNext(); ) {
                    it.set(interpolator.interpolate(it.next()));
                }
            }
            commandLineBuilder.addOption(option);
        }
        for (String arg : cliRequest.commandLine.getArgList()) {
            commandLineBuilder.addArg(interpolator.interpolate(arg));
        }
        cliRequest.commandLine = commandLineBuilder.build();
    }

    PlexusContainer container(CliRequest cliRequest) throws Exception {
        if (cliRequest.classWorld == null) {
            cliRequest.classWorld =
                    new ClassWorld("plexus.core", Thread.currentThread().getContextClassLoader());
        }

        ClassRealm coreRealm = cliRequest.classWorld.getClassRealm("plexus.core");
        if (coreRealm == null) {
            coreRealm = cliRequest.classWorld.getRealms().iterator().next();
        }

        List<File> extClassPath = parseExtClasspath(cliRequest);

        CoreExtensionEntry coreEntry = CoreExtensionEntry.discoverFrom(coreRealm);
        List<CoreExtensionEntry> extensions =
                loadCoreExtensions(cliRequest, coreRealm, coreEntry.getExportedArtifacts());

        ClassRealm containerRealm = setupContainerRealm(cliRequest.classWorld, coreRealm, extClassPath, extensions);

        ContainerConfiguration cc = new DefaultContainerConfiguration()
                .setClassWorld(cliRequest.classWorld)
                .setRealm(containerRealm)
                .setClassPathScanning(PlexusConstants.SCANNING_INDEX)
                .setAutoWiring(true)
                .setJSR250Lifecycle(true)
                .setName("maven");

        Set<String> exportedArtifacts = new HashSet<>(coreEntry.getExportedArtifacts());
        Set<String> exportedPackages = new HashSet<>(coreEntry.getExportedPackages());
        for (CoreExtensionEntry extension : extensions) {
            exportedArtifacts.addAll(extension.getExportedArtifacts());
            exportedPackages.addAll(extension.getExportedPackages());
        }

        final CoreExports exports = new CoreExports(containerRealm, exportedArtifacts, exportedPackages);

        DefaultPlexusContainer container = new DefaultPlexusContainer(cc, new AbstractModule() {
            @Override
            protected void configure() {
                bind(ILoggerFactory.class).toInstance(slf4jLoggerFactory);
                bind(CoreExports.class).toInstance(exports);
                bind(MessageBuilderFactory.class).toInstance(messageBuilderFactory);
            }
        });

        // NOTE: To avoid inconsistencies, we'll use the TCCL exclusively for lookups
        container.setLookupRealm(null);
        Thread.currentThread().setContextClassLoader(container.getContainerRealm());

        container.setLoggerManager(plexusLoggerManager);

        AbstractValueSource extensionSource = new AbstractValueSource(false) {
            @Override
            public Object getValue(String expression) {
                Object value = cliRequest.userProperties.getProperty(expression);
                if (value == null) {
                    value = cliRequest.systemProperties.getProperty(expression);
                }
                return value;
            }
        };
        for (CoreExtensionEntry extension : extensions) {
            container.discoverComponents(
                    extension.getClassRealm(),
                    new SessionScopeModule(container.lookup(SessionScope.class)),
                    new MojoExecutionScopeModule(container.lookup(MojoExecutionScope.class)),
                    new ExtensionConfigurationModule(extension, extensionSource));
        }

        customizeContainer(container);

        container.getLoggerManager().setThresholds(cliRequest.request.getLoggingLevel());

        eventSpyDispatcher = container.lookup(EventSpyDispatcher.class);

        DefaultEventSpyContext eventSpyContext = new DefaultEventSpyContext();
        Map<String, Object> data = eventSpyContext.getData();
        data.put("plexus", container);
        data.put("workingDirectory", cliRequest.workingDirectory);
        data.put("systemProperties", cliRequest.systemProperties);
        data.put("userProperties", cliRequest.userProperties);
        data.put("versionProperties", CLIReportingUtils.getBuildProperties());
        eventSpyDispatcher.init(eventSpyContext);

        // refresh logger in case container got customized by spy
        slf4jLogger = slf4jLoggerFactory.getLogger(this.getClass().getName());

        maven = container.lookup(Maven.class);

        executionRequestPopulator = container.lookup(MavenExecutionRequestPopulator.class);

        modelProcessor = createModelProcessor(container);

        configurationProcessors = container.lookupMap(ConfigurationProcessor.class);

        toolchainsBuilder = container.lookup(ToolchainsBuilder.class);

        dispatcher = (DefaultSecDispatcher) container.lookup(SecDispatcher.class, "maven");

        return container;
    }

    private List<CoreExtensionEntry> loadCoreExtensions(
            CliRequest cliRequest, ClassRealm containerRealm, Set<String> providedArtifacts) throws Exception {
        if (cliRequest.multiModuleProjectDirectory == null) {
            return Collections.emptyList();
        }

        File extensionsFile = new File(cliRequest.multiModuleProjectDirectory, MVN_EXTENSIONS_FILENAME);
        File userHomeExtensionsFile = new File(USER_MAVEN_CONFIGURATION_HOME, EXTENSIONS_FILENAME);

        List<CoreExtension> extensions = new ArrayList<>();
        if (extensionsFile.isFile()) {
            extensions.addAll(readCoreExtensionsDescriptor(extensionsFile));
        }
        if (userHomeExtensionsFile.isFile()) {
            extensions.addAll(readCoreExtensionsDescriptor(userHomeExtensionsFile));
        }

        if (extensions.isEmpty()) {
            return Collections.emptyList();
        }

        ContainerConfiguration cc = new DefaultContainerConfiguration() //
                .setClassWorld(cliRequest.classWorld) //
                .setRealm(containerRealm) //
                .setClassPathScanning(PlexusConstants.SCANNING_INDEX) //
                .setAutoWiring(true) //
                .setJSR250Lifecycle(true) //
                .setName("maven");

        DefaultPlexusContainer container = new DefaultPlexusContainer(cc, new AbstractModule() {
            @Override
            protected void configure() {
                bind(ILoggerFactory.class).toInstance(slf4jLoggerFactory);
            }
        });

        try {
            container.setLookupRealm(null);

            container.setLoggerManager(plexusLoggerManager);

            container.getLoggerManager().setThresholds(cliRequest.request.getLoggingLevel());

            Thread.currentThread().setContextClassLoader(container.getContainerRealm());

            executionRequestPopulator = container.lookup(MavenExecutionRequestPopulator.class);

            configurationProcessors = container.lookupMap(ConfigurationProcessor.class);

            configure(cliRequest);

            MavenExecutionRequest request = DefaultMavenExecutionRequest.copy(cliRequest.request);

            populateRequest(cliRequest, request);

            request = executionRequestPopulator.populateDefaults(request);

            BootstrapCoreExtensionManager resolver = container.lookup(BootstrapCoreExtensionManager.class);

            return Collections.unmodifiableList(resolver.loadCoreExtensions(request, providedArtifacts, extensions));

        } finally {
            executionRequestPopulator = null;
            container.dispose();
        }
    }

    private List<CoreExtension> readCoreExtensionsDescriptor(File extensionsFile)
            throws IOException, XMLStreamException {
        CoreExtensionsStaxReader parser = new CoreExtensionsStaxReader();

        try (InputStream is = Files.newInputStream(extensionsFile.toPath())) {
            return parser.read(is, true).getExtensions();
        }
    }

    private ClassRealm setupContainerRealm(
            ClassWorld classWorld, ClassRealm coreRealm, List<File> extClassPath, List<CoreExtensionEntry> extensions)
            throws Exception {
        if (!extClassPath.isEmpty() || !extensions.isEmpty()) {
            ClassRealm extRealm = classWorld.newRealm("maven.ext", null);

            extRealm.setParentRealm(coreRealm);

            slf4jLogger.debug("Populating class realm '{}'", extRealm.getId());

            for (File file : extClassPath) {
                slf4jLogger.debug("  included '{}'", file);

                extRealm.addURL(file.toURI().toURL());
            }

            for (CoreExtensionEntry entry : reverse(extensions)) {
                Set<String> exportedPackages = entry.getExportedPackages();
                ClassRealm realm = entry.getClassRealm();
                for (String exportedPackage : exportedPackages) {
                    extRealm.importFrom(realm, exportedPackage);
                }
                if (exportedPackages.isEmpty()) {
                    // sisu uses realm imports to establish component visibility
                    extRealm.importFrom(realm, realm.getId());
                }
            }

            return extRealm;
        }

        return coreRealm;
    }

    private static <T> List<T> reverse(List<T> list) {
        List<T> copy = new ArrayList<>(list);
        Collections.reverse(copy);
        return copy;
    }

    private List<File> parseExtClasspath(CliRequest cliRequest) {
        String extClassPath = cliRequest.userProperties.getProperty(EXT_CLASS_PATH);
        if (extClassPath == null) {
            extClassPath = cliRequest.systemProperties.getProperty(EXT_CLASS_PATH);
        }

        List<File> jars = new ArrayList<>();

        if (extClassPath != null && !extClassPath.isEmpty()) {
            for (String jar : extClassPath.split(File.pathSeparator)) {
                File file = resolveFile(new File(jar), cliRequest.workingDirectory);

                slf4jLogger.debug("  included '{}'", file);

                jars.add(file);
            }
        }

        return jars;
    }

    //
    // This should probably be a separate tool and not be baked into Maven.
    //
    private void encryption(CliRequest cliRequest) throws Exception {
        if (cliRequest.commandLine.hasOption(CLIManager.ENCRYPT_MASTER_PASSWORD)) {
            String passwd = cliRequest.commandLine.getOptionValue(CLIManager.ENCRYPT_MASTER_PASSWORD);

            if (passwd == null) {
                Console cons = System.console();
                char[] password = (cons == null) ? null : cons.readPassword("Master password: ");
                if (password != null) {
                    // Cipher uses Strings
                    passwd = String.copyValueOf(password);

                    // Sun/Oracle advises to empty the char array
                    java.util.Arrays.fill(password, ' ');
                }
            }

            DefaultPlexusCipher cipher = new DefaultPlexusCipher();

            System.out.println(cipher.encryptAndDecorate(passwd, DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION));

            throw new ExitException(0);
        } else if (cliRequest.commandLine.hasOption(CLIManager.ENCRYPT_PASSWORD)) {
            String passwd = cliRequest.commandLine.getOptionValue(CLIManager.ENCRYPT_PASSWORD);

            if (passwd == null) {
                Console cons = System.console();
                char[] password = (cons == null) ? null : cons.readPassword("Password: ");
                if (password != null) {
                    // Cipher uses Strings
                    passwd = String.copyValueOf(password);

                    // Sun/Oracle advises to empty the char array
                    java.util.Arrays.fill(password, ' ');
                }
            }

            String configurationFile = dispatcher.getConfigurationFile();

            if (configurationFile.startsWith("~")) {
                configurationFile = System.getProperty("user.home") + configurationFile.substring(1);
            }

            String file = System.getProperty(DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION, configurationFile);

            String master = null;

            SettingsSecurity sec = SecUtil.read(file, true);
            if (sec != null) {
                master = sec.getMaster();
            }

            if (master == null) {
                throw new IllegalStateException("Master password is not set in the setting security file: " + file);
            }

            DefaultPlexusCipher cipher = new DefaultPlexusCipher();
            String masterPasswd = cipher.decryptDecorated(master, DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION);
            System.out.println(cipher.encryptAndDecorate(passwd, masterPasswd));

            throw new ExitException(0);
        }
    }

    private int execute(CliRequest cliRequest) throws MavenExecutionRequestPopulationException {
        MavenExecutionRequest request = executionRequestPopulator.populateDefaults(cliRequest.request);

        if (cliRequest.request.getRepositoryCache() == null) {
            cliRequest.request.setRepositoryCache(new DefaultRepositoryCache());
        }

        eventSpyDispatcher.onEvent(request);

        MavenExecutionResult result = maven.execute(request);

        eventSpyDispatcher.onEvent(result);

        eventSpyDispatcher.close();

        if (result.hasExceptions()) {
            ExceptionHandler handler = new DefaultExceptionHandler();

            Map<String, String> references = new LinkedHashMap<>();

            List<MavenProject> failedProjects = new ArrayList<>();

            for (Throwable exception : result.getExceptions()) {
                ExceptionSummary summary = handler.handleException(exception);

                logSummary(summary, references, "", cliRequest.showErrors);

                if (exception instanceof LifecycleExecutionException) {
                    failedProjects.add(((LifecycleExecutionException) exception).getProject());
                }
            }

            slf4jLogger.error("");

            if (!cliRequest.showErrors) {
                slf4jLogger.error(
                        "To see the full stack trace of the errors, re-run Maven with the '{}' switch",
                        MessageUtils.builder().strong("-e"));
            }
            if (!slf4jLogger.isDebugEnabled()) {
                slf4jLogger.error(
                        "Re-run Maven using the '{}' switch to enable verbose output",
                        MessageUtils.builder().strong("-X"));
            }

            if (!references.isEmpty()) {
                slf4jLogger.error("");
                slf4jLogger.error("For more information about the errors and possible solutions"
                        + ", please read the following articles:");

                for (Map.Entry<String, String> entry : references.entrySet()) {
                    slf4jLogger.error("{} {}", MessageUtils.builder().strong(entry.getValue()), entry.getKey());
                }
            }

            if (result.canResume()) {
                logBuildResumeHint("mvn [args] -r");
            } else if (!failedProjects.isEmpty()) {
                List<MavenProject> sortedProjects = result.getTopologicallySortedProjects();

                // Sort the failedProjects list in the topologically sorted order.
                failedProjects.sort(comparing(sortedProjects::indexOf));

                MavenProject firstFailedProject = failedProjects.get(0);
                if (!firstFailedProject.equals(sortedProjects.get(0))) {
                    String resumeFromSelector = getResumeFromSelector(sortedProjects, firstFailedProject);
                    logBuildResumeHint("mvn [args] -rf " + resumeFromSelector);
                }
            }

            if (MavenExecutionRequest.REACTOR_FAIL_NEVER.equals(cliRequest.request.getReactorFailureBehavior())) {
                slf4jLogger.info("Build failures were ignored.");

                return 0;
            } else {
                return 1;
            }
        } else {
            return 0;
        }
    }

    private void logBuildResumeHint(String resumeBuildHint) {
        slf4jLogger.error("");
        slf4jLogger.error("After correcting the problems, you can resume the build with the command");
        slf4jLogger.error(MessageUtils.builder().a("  ").strong(resumeBuildHint).toString());
    }

    /**
     * A helper method to determine the value to resume the build with {@code -rf} taking into account the edge case
     *   where multiple modules in the reactor have the same artifactId.
     * <p>
     * {@code -rf :artifactId} will pick up the first module which matches, but when multiple modules in the reactor
     *   have the same artifactId, effective failed module might be later in build reactor.
     * This means that developer will either have to type groupId or wait for build execution of all modules which
     *   were fine, but they are still before one which reported errors.
     * <p>Then the returned value is {@code groupId:artifactId} when there is a name clash and
     * {@code :artifactId} if there is no conflict.
     * This method is made package-private for testing purposes.
     *
     * @param mavenProjects Maven projects which are part of build execution.
     * @param firstFailedProject The first project which has failed.
     * @return Value for -rf flag to resume build exactly from place where it failed ({@code :artifactId} in general
     * and {@code groupId:artifactId} when there is a name clash).
     */
    String getResumeFromSelector(List<MavenProject> mavenProjects, MavenProject firstFailedProject) {
        boolean hasOverlappingArtifactId = mavenProjects.stream()
                        .filter(project -> firstFailedProject.getArtifactId().equals(project.getArtifactId()))
                        .count()
                > 1;

        if (hasOverlappingArtifactId) {
            return firstFailedProject.getGroupId() + ":" + firstFailedProject.getArtifactId();
        }

        return ":" + firstFailedProject.getArtifactId();
    }

    private void logSummary(
            ExceptionSummary summary, Map<String, String> references, String indent, boolean showErrors) {
        String referenceKey = "";

        if (summary.getReference() != null && !summary.getReference().isEmpty()) {
            referenceKey =
                    references.computeIfAbsent(summary.getReference(), k -> "[Help " + (references.size() + 1) + "]");
        }

        String msg = summary.getMessage();

        if (referenceKey != null && !referenceKey.isEmpty()) {
            if (msg.indexOf('\n') < 0) {
                msg += " -> " + MessageUtils.builder().strong(referenceKey);
            } else {
                msg += "\n-> " + MessageUtils.builder().strong(referenceKey);
            }
        }

        String[] lines = NEXT_LINE.split(msg);
        String currentColor = "";

        for (int i = 0; i < lines.length; i++) {
            // add eventual current color inherited from previous line
            String line = currentColor + lines[i];

            // look for last ANSI escape sequence to check if nextColor
            Matcher matcher = LAST_ANSI_SEQUENCE.matcher(line);
            String nextColor = "";
            if (matcher.find()) {
                nextColor = matcher.group(1);
                if (ANSI_RESET.equals(nextColor)) {
                    // last ANSI escape code is reset: no next color
                    nextColor = "";
                }
            }

            // effective line, with indent and reset if end is colored
            line = indent + line + ("".equals(nextColor) ? "" : ANSI_RESET);

            if ((i == lines.length - 1) && (showErrors || (summary.getException() instanceof InternalErrorException))) {
                slf4jLogger.error(line, summary.getException());
            } else {
                slf4jLogger.error(line);
            }

            currentColor = nextColor;
        }

        indent += "  ";

        for (ExceptionSummary child : summary.getChildren()) {
            logSummary(child, references, indent, showErrors);
        }
    }

    private static final Pattern LAST_ANSI_SEQUENCE = Pattern.compile("(\u001B\\[[;\\d]*[ -/]*[@-~])[^\u001B]*$");

    private static final String ANSI_RESET = "\u001B\u005Bm";

    private void configure(CliRequest cliRequest) throws Exception {
        //
        // This is not ideal but there are events specifically for configuration from the CLI which I don't
        // believe are really valid but there are ITs which assert the right events are published so this
        // needs to be supported so the EventSpyDispatcher needs to be put in the CliRequest so that
        // it can be accessed by configuration processors.
        //
        cliRequest.request.setEventSpyDispatcher(eventSpyDispatcher);

        //
        // We expect at most 2 implementations to be available. The SettingsXmlConfigurationProcessor implementation
        // is always available in the core and likely always will be, but we may have another ConfigurationProcessor
        // present supplied by the user. The rule is that we only allow the execution of one ConfigurationProcessor.
        // If there is more than one then we execute the one supplied by the user, otherwise we execute the
        // default SettingsXmlConfigurationProcessor.
        //
        int userSuppliedConfigurationProcessorCount = configurationProcessors.size() - 1;

        if (userSuppliedConfigurationProcessorCount == 0) {
            //
            // Our settings.xml source is historically how we have configured Maven from the CLI so we are going to
            // have to honour its existence forever. So let's run it.
            //
            configurationProcessors.get(SettingsXmlConfigurationProcessor.HINT).process(cliRequest);
        } else if (userSuppliedConfigurationProcessorCount == 1) {
            //
            // Run the user supplied ConfigurationProcessor
            //
            for (Entry<String, ConfigurationProcessor> entry : configurationProcessors.entrySet()) {
                String hint = entry.getKey();
                if (!hint.equals(SettingsXmlConfigurationProcessor.HINT)) {
                    ConfigurationProcessor configurationProcessor = entry.getValue();
                    configurationProcessor.process(cliRequest);
                }
            }
        } else if (userSuppliedConfigurationProcessorCount > 1) {
            //
            // There are too many ConfigurationProcessors so we don't know which one to run so report the error.
            //
            StringBuilder sb = new StringBuilder(String.format(
                    "%nThere can only be one user supplied ConfigurationProcessor, there are %s:%n%n",
                    userSuppliedConfigurationProcessorCount));
            for (Entry<String, ConfigurationProcessor> entry : configurationProcessors.entrySet()) {
                String hint = entry.getKey();
                if (!hint.equals(SettingsXmlConfigurationProcessor.HINT)) {
                    ConfigurationProcessor configurationProcessor = entry.getValue();
                    sb.append(String.format(
                            "%s%n", configurationProcessor.getClass().getName()));
                }
            }
            throw new Exception(sb.toString());
        }
    }

    void toolchains(CliRequest cliRequest) throws Exception {
        File userToolchainsFile;

        if (cliRequest.commandLine.hasOption(CLIManager.ALTERNATE_USER_TOOLCHAINS)) {
            userToolchainsFile = new File(cliRequest.commandLine.getOptionValue(CLIManager.ALTERNATE_USER_TOOLCHAINS));
            userToolchainsFile = resolveFile(userToolchainsFile, cliRequest.workingDirectory);

            if (!userToolchainsFile.isFile()) {
                throw new FileNotFoundException(
                        "The specified user toolchains file does not exist: " + userToolchainsFile);
            }
        } else {
            userToolchainsFile = DEFAULT_USER_TOOLCHAINS_FILE;
        }

        File globalToolchainsFile;

        if (cliRequest.commandLine.hasOption(CLIManager.ALTERNATE_GLOBAL_TOOLCHAINS)) {
            globalToolchainsFile =
                    new File(cliRequest.commandLine.getOptionValue(CLIManager.ALTERNATE_GLOBAL_TOOLCHAINS));
            globalToolchainsFile = resolveFile(globalToolchainsFile, cliRequest.workingDirectory);

            if (!globalToolchainsFile.isFile()) {
                throw new FileNotFoundException(
                        "The specified global toolchains file does not exist: " + globalToolchainsFile);
            }
        } else {
            globalToolchainsFile = DEFAULT_GLOBAL_TOOLCHAINS_FILE;
        }

        cliRequest.request.setGlobalToolchainsFile(globalToolchainsFile);
        cliRequest.request.setUserToolchainsFile(userToolchainsFile);

        DefaultToolchainsBuildingRequest toolchainsRequest = new DefaultToolchainsBuildingRequest();
        if (globalToolchainsFile.isFile()) {
            toolchainsRequest.setGlobalToolchainsSource(new FileSource(globalToolchainsFile));
        }
        if (userToolchainsFile.isFile()) {
            toolchainsRequest.setUserToolchainsSource(new FileSource(userToolchainsFile));
        }

        eventSpyDispatcher.onEvent(toolchainsRequest);

        slf4jLogger.debug(
                "Reading global toolchains from '{}'",
                getLocation(toolchainsRequest.getGlobalToolchainsSource(), globalToolchainsFile));
        slf4jLogger.debug(
                "Reading user toolchains from '{}'",
                getLocation(toolchainsRequest.getUserToolchainsSource(), userToolchainsFile));

        ToolchainsBuildingResult toolchainsResult = toolchainsBuilder.build(toolchainsRequest);

        eventSpyDispatcher.onEvent(toolchainsResult);

        executionRequestPopulator.populateFromToolchains(cliRequest.request, toolchainsResult.getEffectiveToolchains());

        if (!toolchainsResult.getProblems().isEmpty() && slf4jLogger.isWarnEnabled()) {
            slf4jLogger.warn("");
            slf4jLogger.warn("Some problems were encountered while building the effective toolchains");

            for (Problem problem : toolchainsResult.getProblems()) {
                slf4jLogger.warn("{} @ {}", problem.getMessage(), problem.getLocation());
            }

            slf4jLogger.warn("");
        }
    }

    private Object getLocation(Source source, File defaultLocation) {
        if (source != null) {
            return source.getLocation();
        }
        return defaultLocation;
    }

    protected MavenExecutionRequest populateRequest(CliRequest cliRequest) {
        return populateRequest(cliRequest, cliRequest.request);
    }

    private MavenExecutionRequest populateRequest(CliRequest cliRequest, MavenExecutionRequest request) {
        slf4jLoggerFactory = LoggerFactory.getILoggerFactory();
        CommandLine commandLine = cliRequest.commandLine;
        String workingDirectory = cliRequest.workingDirectory;
        boolean quiet = cliRequest.quiet;
        boolean verbose = cliRequest.verbose;
        request.setShowErrors(cliRequest.showErrors); // default: false
        File baseDirectory = new File(workingDirectory, "").getAbsoluteFile();

        disableInteractiveModeIfNeeded(cliRequest, request);
        enableOnPresentOption(commandLine, CLIManager.SUPPRESS_SNAPSHOT_UPDATES, request::setNoSnapshotUpdates);
        request.setGoals(commandLine.getArgList());
        request.setReactorFailureBehavior(determineReactorFailureBehaviour(commandLine));
        disableOnPresentOption(commandLine, CLIManager.NON_RECURSIVE, request::setRecursive);
        enableOnPresentOption(commandLine, CLIManager.OFFLINE, request::setOffline);
        enableOnPresentOption(commandLine, CLIManager.UPDATE_SNAPSHOTS, request::setUpdateSnapshots);
        request.setGlobalChecksumPolicy(determineGlobalCheckPolicy(commandLine));
        request.setBaseDirectory(baseDirectory);
        request.setSystemProperties(cliRequest.systemProperties);
        request.setUserProperties(cliRequest.userProperties);
        request.setMultiModuleProjectDirectory(cliRequest.multiModuleProjectDirectory);
        request.setRootDirectory(cliRequest.rootDirectory);
        request.setTopDirectory(cliRequest.topDirectory);
        request.setPom(determinePom(commandLine, workingDirectory, baseDirectory));
        request.setTransferListener(determineTransferListener(quiet, verbose, commandLine, request));
        request.setExecutionListener(determineExecutionListener());

        if ((request.getPom() != null) && (request.getPom().getParentFile() != null)) {
            request.setBaseDirectory(request.getPom().getParentFile());
        }

        request.setResumeFrom(commandLine.getOptionValue(CLIManager.RESUME_FROM));
        enableOnPresentOption(commandLine, CLIManager.RESUME, request::setResume);
        request.setMakeBehavior(determineMakeBehavior(commandLine));
        boolean cacheNotFound = !commandLine.hasOption(CLIManager.CACHE_ARTIFACT_NOT_FOUND)
                || Boolean.parseBoolean(commandLine.getOptionValue(CLIManager.CACHE_ARTIFACT_NOT_FOUND));
        request.setCacheNotFound(cacheNotFound);
        request.setCacheTransferError(false);
        boolean strictArtifactDescriptorPolicy = commandLine.hasOption(CLIManager.STRICT_ARTIFACT_DESCRIPTOR_POLICY)
                && Boolean.parseBoolean(commandLine.getOptionValue(CLIManager.STRICT_ARTIFACT_DESCRIPTOR_POLICY));
        if (strictArtifactDescriptorPolicy) {
            request.setIgnoreMissingArtifactDescriptor(false);
            request.setIgnoreInvalidArtifactDescriptor(false);
        } else {
            request.setIgnoreMissingArtifactDescriptor(true);
            request.setIgnoreInvalidArtifactDescriptor(true);
        }
        enableOnPresentOption(
                commandLine, CLIManager.IGNORE_TRANSITIVE_REPOSITORIES, request::setIgnoreTransitiveRepositories);

        performProjectActivation(commandLine, request.getProjectActivation());
        performProfileActivation(commandLine, request.getProfileActivation());

        final String localRepositoryPath = determineLocalRepositoryPath(request);
        if (localRepositoryPath != null) {
            request.setLocalRepositoryPath(localRepositoryPath);
        }

        //
        // Builder, concurrency and parallelism
        //
        // We preserve the existing methods for builder selection which is to look for various inputs in the threading
        // configuration. We don't have an easy way to allow a pluggable builder to provide its own configuration
        // parameters but this is sufficient for now. Ultimately we want components like Builders to provide a way to
        // extend the command line to accept its own configuration parameters.
        //
        final String threadConfiguration = commandLine.getOptionValue(CLIManager.THREADS);

        if (threadConfiguration != null) {
            int degreeOfConcurrency = calculateDegreeOfConcurrency(threadConfiguration);
            if (degreeOfConcurrency > 1) {
                request.setBuilderId("multithreaded");
                request.setDegreeOfConcurrency(degreeOfConcurrency);
            }
        }

        //
        // Allow the builder to be overridden by the user if requested. The builders are now pluggable.
        //
        request.setBuilderId(commandLine.getOptionValue(CLIManager.BUILDER, request.getBuilderId()));

        return request;
    }

    private void disableInteractiveModeIfNeeded(final CliRequest cliRequest, final MavenExecutionRequest request) {
        CommandLine commandLine = cliRequest.getCommandLine();
        if (commandLine.hasOption(FORCE_INTERACTIVE)) {
            return;
        }

        if (commandLine.hasOption(BATCH_MODE) || commandLine.hasOption(NON_INTERACTIVE)) {
            request.setInteractiveMode(false);
        } else {
            boolean runningOnCI = isRunningOnCI(cliRequest.getSystemProperties());
            if (runningOnCI) {
                slf4jLogger.info(
                        "Making this build non-interactive, because the environment variable CI equals \"true\"."
                                + " Disable this detection by removing that variable or adding --force-interactive.");
                request.setInteractiveMode(false);
            }
        }
    }

    private static boolean isRunningOnCI(Properties systemProperties) {
        String ciEnv = systemProperties.getProperty("env.CI");
        return ciEnv != null && !"false".equals(ciEnv);
    }

    private String determineLocalRepositoryPath(final MavenExecutionRequest request) {
        String userDefinedLocalRepo = request.getUserProperties().getProperty(MavenCli.LOCAL_REPO_PROPERTY);
        if (userDefinedLocalRepo != null) {
            return userDefinedLocalRepo;
        }

        // TODO Investigate why this can also be a Java system property and not just a Maven user property like
        // other properties
        return request.getSystemProperties().getProperty(MavenCli.LOCAL_REPO_PROPERTY);
    }

    private File determinePom(final CommandLine commandLine, final String workingDirectory, final File baseDirectory) {
        String alternatePomFile = null;
        if (commandLine.hasOption(CLIManager.ALTERNATE_POM_FILE)) {
            alternatePomFile = commandLine.getOptionValue(CLIManager.ALTERNATE_POM_FILE);
        }

        File current = baseDirectory;
        if (alternatePomFile != null) {
            current = resolveFile(new File(alternatePomFile), workingDirectory);
        }

        if (modelProcessor != null) {
            return modelProcessor.locateExistingPom(current);
        } else {
            return current.isFile() ? current : null;
        }
    }

    // Visible for testing
    static void performProjectActivation(final CommandLine commandLine, final ProjectActivation projectActivation) {
        if (commandLine.hasOption(CLIManager.PROJECT_LIST)) {
            final String[] optionValues = commandLine.getOptionValues(CLIManager.PROJECT_LIST);

            if (optionValues == null || optionValues.length == 0) {
                return;
            }

            for (final String optionValue : optionValues) {
                for (String token : optionValue.split(",")) {
                    String selector = token.trim();
                    boolean active = true;
                    if (selector.charAt(0) == '-' || selector.charAt(0) == '!') {
                        active = false;
                        selector = selector.substring(1);
                    } else if (token.charAt(0) == '+') {
                        selector = selector.substring(1);
                    }

                    boolean optional = selector.charAt(0) == '?';
                    selector = selector.substring(optional ? 1 : 0);

                    projectActivation.addProjectActivation(selector, active, optional);
                }
            }
        }
    }

    // Visible for testing
    static void performProfileActivation(final CommandLine commandLine, final ProfileActivation profileActivation) {
        if (commandLine.hasOption(CLIManager.ACTIVATE_PROFILES)) {
            final String[] optionValues = commandLine.getOptionValues(CLIManager.ACTIVATE_PROFILES);

            if (optionValues == null || optionValues.length == 0) {
                return;
            }

            for (final String optionValue : optionValues) {
                for (String token : optionValue.split(",")) {
                    String profileId = token.trim();
                    boolean active = true;
                    if (profileId.charAt(0) == '-' || profileId.charAt(0) == '!') {
                        active = false;
                        profileId = profileId.substring(1);
                    } else if (token.charAt(0) == '+') {
                        profileId = profileId.substring(1);
                    }

                    boolean optional = profileId.charAt(0) == '?';
                    profileId = profileId.substring(optional ? 1 : 0);

                    profileActivation.addProfileActivation(profileId, active, optional);
                }
            }
        }
    }

    private ExecutionListener determineExecutionListener() {
        ExecutionListener executionListener = new ExecutionEventLogger(messageBuilderFactory);
        if (eventSpyDispatcher != null) {
            return eventSpyDispatcher.chainListener(executionListener);
        } else {
            return executionListener;
        }
    }

    private String determineReactorFailureBehaviour(final CommandLine commandLine) {
        if (commandLine.hasOption(CLIManager.FAIL_FAST)) {
            return MavenExecutionRequest.REACTOR_FAIL_FAST;
        } else if (commandLine.hasOption(CLIManager.FAIL_AT_END)) {
            return MavenExecutionRequest.REACTOR_FAIL_AT_END;
        } else if (commandLine.hasOption(CLIManager.FAIL_NEVER)) {
            return MavenExecutionRequest.REACTOR_FAIL_NEVER;
        } else {
            // this is the default behavior.
            return MavenExecutionRequest.REACTOR_FAIL_FAST;
        }
    }

    private TransferListener determineTransferListener(
            final boolean quiet,
            final boolean verbose,
            final CommandLine commandLine,
            final MavenExecutionRequest request) {
        boolean runningOnCI = isRunningOnCI(request.getSystemProperties());
        boolean quietCI = runningOnCI && !commandLine.hasOption(FORCE_INTERACTIVE);

        if (quiet || commandLine.hasOption(CLIManager.NO_TRANSFER_PROGRESS) || quietCI) {
            return new QuietMavenTransferListener();
        } else if (request.isInteractiveMode() && !commandLine.hasOption(CLIManager.LOG_FILE)) {
            //
            // If we're logging to a file then we don't want the console transfer listener as it will spew
            // download progress all over the place
            //
            return getConsoleTransferListener(verbose);
        } else {
            // default: batch mode which goes along with interactive
            return getBatchTransferListener();
        }
    }

    private String determineMakeBehavior(final CommandLine cl) {
        if (cl.hasOption(CLIManager.ALSO_MAKE) && !cl.hasOption(CLIManager.ALSO_MAKE_DEPENDENTS)) {
            return MavenExecutionRequest.REACTOR_MAKE_UPSTREAM;
        } else if (!cl.hasOption(CLIManager.ALSO_MAKE) && cl.hasOption(CLIManager.ALSO_MAKE_DEPENDENTS)) {
            return MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM;
        } else if (cl.hasOption(CLIManager.ALSO_MAKE) && cl.hasOption(CLIManager.ALSO_MAKE_DEPENDENTS)) {
            return MavenExecutionRequest.REACTOR_MAKE_BOTH;
        } else {
            return null;
        }
    }

    private String determineGlobalCheckPolicy(final CommandLine commandLine) {
        if (commandLine.hasOption(CLIManager.CHECKSUM_FAILURE_POLICY)) {
            return MavenExecutionRequest.CHECKSUM_POLICY_FAIL;
        } else if (commandLine.hasOption(CLIManager.CHECKSUM_WARNING_POLICY)) {
            return MavenExecutionRequest.CHECKSUM_POLICY_WARN;
        } else {
            return null;
        }
    }

    private void disableOnPresentOption(
            final CommandLine commandLine, final String option, final Consumer<Boolean> setting) {
        if (commandLine.hasOption(option)) {
            setting.accept(false);
        }
    }

    private void disableOnPresentOption(
            final CommandLine commandLine, final char option, final Consumer<Boolean> setting) {
        disableOnPresentOption(commandLine, String.valueOf(option), setting);
    }

    private void enableOnPresentOption(
            final CommandLine commandLine, final String option, final Consumer<Boolean> setting) {
        if (commandLine.hasOption(option)) {
            setting.accept(true);
        }
    }

    private void enableOnPresentOption(
            final CommandLine commandLine, final char option, final Consumer<Boolean> setting) {
        enableOnPresentOption(commandLine, String.valueOf(option), setting);
    }

    private void enableOnAbsentOption(
            final CommandLine commandLine, final char option, final Consumer<Boolean> setting) {
        if (!commandLine.hasOption(option)) {
            setting.accept(true);
        }
    }

    int calculateDegreeOfConcurrency(String threadConfiguration) {
        try {
            if (threadConfiguration.endsWith("C")) {
                String str = threadConfiguration.substring(0, threadConfiguration.length() - 1);
                float coreMultiplier = Float.parseFloat(str);

                if (coreMultiplier <= 0.0f) {
                    throw new IllegalArgumentException("Invalid threads core multiplier value: '" + threadConfiguration
                            + "'. Value must be positive.");
                }

                int procs = Runtime.getRuntime().availableProcessors();
                int threads = (int) (coreMultiplier * procs);
                return threads == 0 ? 1 : threads;
            } else {
                int threads = Integer.parseInt(threadConfiguration);
                if (threads <= 0) {
                    throw new IllegalArgumentException(
                            "Invalid threads value: '" + threadConfiguration + "'. Value must be positive.");
                }
                return threads;
            }
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("Invalid threads value: '" + threadConfiguration
                    + "'. Supported are int and float values ending with C.");
        }
    }

    // ----------------------------------------------------------------------
    // Properties handling
    // ----------------------------------------------------------------------

    static void populateProperties(
            CommandLine commandLine, Properties paths, Properties systemProperties, Properties userProperties)
            throws Exception {
        EnvironmentUtils.addEnvVars(systemProperties);

        // ----------------------------------------------------------------------
        // Options that are set on the command line become system properties
        // and therefore are set in the session properties. System properties
        // are most dominant.
        // ----------------------------------------------------------------------

        final Properties userSpecifiedProperties =
                commandLine.getOptionProperties(String.valueOf(CLIManager.SET_USER_PROPERTY));

        SystemProperties.addSystemProperties(systemProperties);

        // ----------------------------------------------------------------------
        // Properties containing info about the currently running version of Maven
        // These override any corresponding properties set on the command line
        // ----------------------------------------------------------------------

        Properties buildProperties = CLIReportingUtils.getBuildProperties();

        String mavenVersion = buildProperties.getProperty(CLIReportingUtils.BUILD_VERSION_PROPERTY);
        systemProperties.setProperty("maven.version", mavenVersion);

        String mavenBuildVersion = CLIReportingUtils.createMavenVersionString(buildProperties);
        systemProperties.setProperty("maven.build.version", mavenBuildVersion);

        BasicInterpolator interpolator =
                createInterpolator(paths, systemProperties, userProperties, userSpecifiedProperties);
        for (Map.Entry<Object, Object> e : userSpecifiedProperties.entrySet()) {
            String name = (String) e.getKey();
            String value = interpolator.interpolate((String) e.getValue());
            userProperties.setProperty(name, value);
            // ----------------------------------------------------------------------
            // I'm leaving the setting of system properties here as not to break
            // the SystemPropertyProfileActivator. This won't harm embedding. jvz.
            // ----------------------------------------------------------------------
            if (System.getProperty(name) == null) {
                System.setProperty(name, value);
            }
        }
    }

    private static BasicInterpolator createInterpolator(Properties... properties) {
        StringSearchInterpolator interpolator = new StringSearchInterpolator();
        interpolator.addValueSource(new AbstractValueSource(false) {
            @Override
            public Object getValue(String expression) {
                for (Properties props : properties) {
                    Object val = props.getProperty(expression);
                    if (val != null) {
                        return val;
                    }
                }
                return null;
            }
        });
        return interpolator;
    }

    private static String stripLeadingAndTrailingQuotes(String str) {
        final int length = str.length();
        if (length > 1
                && str.startsWith("\"")
                && str.endsWith("\"")
                && str.substring(1, length - 1).indexOf('"') == -1) {
            str = str.substring(1, length - 1);
        }

        return str;
    }

    private static Path getCanonicalPath(Path path) {
        try {
            return path.toRealPath();
        } catch (IOException e) {
            return getCanonicalPath(path.getParent()).resolve(path.getFileName());
        }
    }

    static class ExitException extends Exception {
        int exitCode;

        ExitException(int exitCode) {
            this.exitCode = exitCode;
        }
    }

    //
    // Customizations available via the CLI
    //

    protected TransferListener getConsoleTransferListener(boolean printResourceNames) {
        return new SimplexTransferListener(
                new ConsoleMavenTransferListener(messageBuilderFactory, System.out, printResourceNames));
    }

    protected TransferListener getBatchTransferListener() {
        return new Slf4jMavenTransferListener();
    }

    protected void customizeContainer(PlexusContainer container) {}

    protected ModelProcessor createModelProcessor(PlexusContainer container) throws ComponentLookupException {
        return container.lookup(ModelProcessor.class);
    }
}
