pzygielo commented on code in PR #1750:
URL: https://github.com/apache/maven/pull/1750#discussion_r2040004749


##########
maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java:
##########
@@ -0,0 +1,654 @@
+/*
+ * 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.cling.invoker;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.function.Function;
+
+import org.apache.maven.api.Constants;
+import org.apache.maven.api.cli.Invoker;
+import org.apache.maven.api.cli.InvokerException;
+import org.apache.maven.api.cli.InvokerRequest;
+import org.apache.maven.api.cli.Logger;
+import org.apache.maven.api.cli.Options;
+import org.apache.maven.api.services.Lookup;
+import org.apache.maven.api.services.MessageBuilder;
+import org.apache.maven.artifact.InvalidRepositoryException;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
+import org.apache.maven.artifact.repository.MavenArtifactRepository;
+import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
+import org.apache.maven.bridge.MavenRepositorySystem;
+import org.apache.maven.cli.CLIReportingUtils;
+import org.apache.maven.cli.logging.Slf4jConfiguration;
+import org.apache.maven.cli.logging.Slf4jConfigurationFactory;
+import org.apache.maven.cli.transfer.ConsoleMavenTransferListener;
+import org.apache.maven.cli.transfer.QuietMavenTransferListener;
+import org.apache.maven.cli.transfer.SimplexTransferListener;
+import org.apache.maven.cli.transfer.Slf4jMavenTransferListener;
+import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.jline.MessageUtils;
+import org.apache.maven.logwrapper.LogLevelRecorder;
+import org.apache.maven.logwrapper.MavenSlf4jWrapperFactory;
+import org.apache.maven.settings.Mirror;
+import org.apache.maven.settings.Profile;
+import org.apache.maven.settings.Proxy;
+import org.apache.maven.settings.Repository;
+import org.apache.maven.settings.Server;
+import org.apache.maven.settings.Settings;
+import org.apache.maven.settings.SettingsUtils;
+import org.apache.maven.settings.building.DefaultSettingsBuildingRequest;
+import org.apache.maven.settings.building.SettingsBuilder;
+import org.apache.maven.settings.building.SettingsBuildingRequest;
+import org.apache.maven.settings.building.SettingsBuildingResult;
+import org.apache.maven.settings.building.SettingsProblem;
+import org.eclipse.aether.transfer.TransferListener;
+import org.slf4j.ILoggerFactory;
+import org.slf4j.LoggerFactory;
+
+import static java.util.Objects.requireNonNull;
+import static org.apache.maven.cling.invoker.Utils.toFile;
+import static 
org.apache.maven.cling.invoker.Utils.toMavenExecutionRequestLoggingLevel;
+import static org.apache.maven.cling.invoker.Utils.toProperties;
+
+/**
+ * Plexus invoker implementation, that boots up Plexus DI container. This 
class expects fully setup ClassWorld via constructor.
+ *
+ * @param <O> the options type
+ * @param <R> the request type
+ * @param <C> the context type
+ */
+public abstract class LookupInvoker<
+                O extends Options, R extends InvokerRequest<O>, C extends 
LookupInvoker.LookupInvokerContext<O, R, C>>
+        implements Invoker<R> {
+
+    @SuppressWarnings("VisibilityModifier")
+    public static class LookupInvokerContext<
+                    O extends Options, R extends InvokerRequest<O>, C extends 
LookupInvokerContext<O, R, C>>
+            implements AutoCloseable {
+        public final LookupInvoker<O, R, C> invoker;
+        public final ProtoLookup protoLookup;
+        public final R invokerRequest;
+        public final Function<String, Path> cwdResolver;
+        public final InputStream stdIn;
+        public final PrintWriter stdOut;
+        public final PrintWriter stdErr;
+
+        protected LookupInvokerContext(LookupInvoker<O, R, C> invoker, R 
invokerRequest) {
+            this.invoker = invoker;
+            this.protoLookup = invoker.protoLookup;
+            this.invokerRequest = requireNonNull(invokerRequest);
+            this.cwdResolver = s -> 
invokerRequest.cwd().resolve(s).normalize().toAbsolutePath();
+            this.stdIn = invokerRequest.in().orElse(System.in);
+            this.stdOut = new 
PrintWriter(invokerRequest.out().orElse(System.out), true);
+            this.stdErr = new 
PrintWriter(invokerRequest.err().orElse(System.err), true);
+            this.logger = invokerRequest.logger();
+        }
+
+        public Logger logger;
+        public ILoggerFactory loggerFactory;
+        public Slf4jConfiguration.Level loggerLevel;
+        public ContainerCapsule containerCapsule;
+        public Lookup lookup;
+        public SettingsBuilder settingsBuilder;
+
+        public boolean interactive;
+        public Path localRepositoryPath;
+        public Path installationSettingsPath;
+        public Path projectSettingsPath;
+        public Path userSettingsPath;
+        public Settings effectiveSettings;
+
+        @Override
+        public void close() throws InvokerException {
+            if (containerCapsule != null) {
+                containerCapsule.close();
+            }
+        }
+    }
+
+    protected final ProtoLookup protoLookup;
+
+    public LookupInvoker(ProtoLookup protoLookup) {
+        this.protoLookup = requireNonNull(protoLookup);
+    }
+
+    @Override
+    public int invoke(R invokerRequest) throws InvokerException {
+        requireNonNull(invokerRequest);
+
+        try (C context = createContext(invokerRequest)) {
+            try {
+                validate(context);
+                prepare(context);
+                logging(context);
+
+                if (invokerRequest.options().help().isPresent()) {
+                    
invokerRequest.options().displayHelp(context.invokerRequest.command(), 
context.stdOut);
+                    return 0;
+                }
+                if (invokerRequest.options().showVersionAndExit().isPresent()) 
{
+                    if (invokerRequest.options().quiet().orElse(false)) {
+                        
context.stdOut.println(CLIReportingUtils.showVersionMinimal());
+                    } else {
+                        
context.stdOut.println(CLIReportingUtils.showVersion());
+                    }
+                    return 0;
+                }
+
+                preCommands(context);
+                container(context);
+                lookup(context);
+                init(context);
+                postCommands(context);
+                settings(context);
+                return execute(context);
+            } catch (Exception e) {
+                throw handleException(context, e);
+            }
+        }
+    }
+
+    protected InvokerException handleException(LookupInvokerContext<O, R, C> 
context, Exception e)
+            throws InvokerException {
+        boolean showStackTrace = 
context.invokerRequest.options().showErrors().orElse(false);
+        if (showStackTrace) {
+            context.logger.error("Error executing Maven.", e);
+        } else {
+            context.logger.error("Error executing Maven.");
+            context.logger.error(e.getMessage());
+            for (Throwable cause = e.getCause(); cause != null && cause != 
cause.getCause(); cause = cause.getCause()) {
+                context.logger.error("Caused by: " + cause.getMessage());
+            }
+        }
+        return new InvokerException(e.getMessage(), e);
+    }
+
+    protected abstract C createContext(R invokerRequest) throws 
InvokerException;
+
+    protected void validate(C context) throws Exception {}
+
+    protected void prepare(C context) throws Exception {}
+
+    protected void logging(C context) throws Exception {
+        R invokerRequest = context.invokerRequest;
+        // LOG COLOR
+        Options mavenOptions = invokerRequest.options();
+        Map<String, String> userProperties = invokerRequest.userProperties();
+        String styleColor = mavenOptions
+                .color()
+                .orElse(userProperties.getOrDefault(
+                        Constants.MAVEN_STYLE_COLOR_PROPERTY, 
userProperties.getOrDefault("style.color", "auto")));
+        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 = 
!mavenOptions.forceInteractive().orElse(false)
+                    && mavenOptions.nonInteractive().orElse(false);
+            if (isBatchMode || mavenOptions.logFile().isPresent()) {
+                MessageUtils.setColorEnabled(false);
+            }
+        }
+
+        context.loggerFactory = LoggerFactory.getILoggerFactory();
+        Slf4jConfiguration slf4jConfiguration = 
Slf4jConfigurationFactory.getConfiguration(context.loggerFactory);
+
+        context.loggerLevel = Slf4jConfiguration.Level.INFO;
+        if (mavenOptions.verbose().orElse(false)) {
+            context.loggerLevel = Slf4jConfiguration.Level.DEBUG;
+        } else if (mavenOptions.quiet().orElse(false)) {
+            context.loggerLevel = Slf4jConfiguration.Level.ERROR;
+        }
+        slf4jConfiguration.setRootLoggerLevel(context.loggerLevel);
+        // else fall back to default log level specified in conf
+        // see https://issues.apache.org/jira/browse/MNG-2570
+
+        // LOG STREAMS
+        if (mavenOptions.logFile().isPresent()) {
+            Path logFile = 
context.cwdResolver.apply(mavenOptions.logFile().get());
+            // redirect stdout and stderr to file
+            try {
+                PrintStream ps = new 
PrintStream(Files.newOutputStream(logFile));
+                System.setOut(ps);
+                System.setErr(ps);
+            } catch (IOException e) {
+                throw new InvokerException("Cannot set up log " + 
e.getMessage(), e);
+            }
+        }
+
+        slf4jConfiguration.activate();
+        org.slf4j.Logger l = 
context.loggerFactory.getLogger(this.getClass().getName());
+        context.logger = (level, message, error) -> 
l.atLevel(org.slf4j.event.Level.valueOf(level.name()))
+                .setCause(error)
+                .log(message);
+
+        if (mavenOptions.failOnSeverity().isPresent()) {
+            String logLevelThreshold = mavenOptions.failOnSeverity().get();
+
+            if (context.loggerFactory instanceof MavenSlf4jWrapperFactory) {
+                LogLevelRecorder logLevelRecorder = new 
LogLevelRecorder(logLevelThreshold);
+                ((MavenSlf4jWrapperFactory) 
context.loggerFactory).setLogLevelRecorder(logLevelRecorder);
+                context.logger.info("Enabled to break the build on log level " 
+ logLevelThreshold + ".");
+            } else {
+                context.logger.warn("Expected LoggerFactory to be of type '" + 
MavenSlf4jWrapperFactory.class.getName()
+                        + "', but found '"
+                        + context.loggerFactory.getClass().getName() + "' 
instead. "
+                        + "The --fail-on-severity flag will not take effect.");
+            }
+        }
+    }
+
+    protected void preCommands(C context) throws Exception {
+        Options mavenOptions = context.invokerRequest.options();
+        if (mavenOptions.verbose().orElse(false) || 
mavenOptions.showVersion().orElse(false)) {
+            context.stdOut.println(CLIReportingUtils.showVersion());
+        }
+    }
+
+    protected void container(C context) throws Exception {
+        context.containerCapsule = 
createContainerCapsuleFactory().createContainerCapsule(context);
+        context.lookup = context.containerCapsule.getLookup();
+        context.settingsBuilder = context.lookup.lookup(SettingsBuilder.class);
+
+        // refresh logger in case container got customized by spy
+        org.slf4j.Logger l = 
context.loggerFactory.getLogger(this.getClass().getName());
+        context.logger = (level, message, error) -> 
l.atLevel(org.slf4j.event.Level.valueOf(level.name()))
+                .setCause(error)
+                .log(message);
+    }
+
+    protected ContainerCapsuleFactory<O, R, C> createContainerCapsuleFactory() 
{
+        return new PlexusContainerCapsuleFactory<>();
+    }
+
+    protected void lookup(C context) throws Exception {}
+
+    protected void init(C context) throws Exception {}
+
+    protected void postCommands(C context) throws Exception {
+        R invokerRequest = context.invokerRequest;
+        Logger logger = context.logger;
+        if (invokerRequest.options().showErrors().orElse(false)) {
+            logger.info("Error stacktraces are turned on.");
+        }
+        if (context.invokerRequest.options().verbose().orElse(false)) {
+            logger.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");
+                logger.debug(buff.toString());
+            }
+        }
+    }
+
+    protected void settings(C context) throws Exception {
+        settings(context, context.settingsBuilder);
+    }
+
+    protected void settings(C context, SettingsBuilder settingsBuilder) throws 
Exception {
+        Options mavenOptions = context.invokerRequest.options();
+        Path userSettingsFile = null;
+
+        if (mavenOptions.altUserSettings().isPresent()) {
+            userSettingsFile =
+                    
context.cwdResolver.apply(mavenOptions.altUserSettings().get());
+
+            if (!Files.isRegularFile(userSettingsFile)) {
+                throw new FileNotFoundException("The specified user settings 
file does not exist: " + userSettingsFile);
+            }
+        } else {
+            String userSettingsFileStr = 
context.invokerRequest.userProperties().get(Constants.MAVEN_USER_SETTINGS);
+            if (userSettingsFileStr != null) {
+                userSettingsFile = 
context.cwdResolver.apply(userSettingsFileStr);
+            }
+        }
+
+        Path projectSettingsFile = null;
+
+        if (mavenOptions.altProjectSettings().isPresent()) {
+            projectSettingsFile =
+                    
context.cwdResolver.apply(mavenOptions.altProjectSettings().get());
+
+            if (!Files.isRegularFile(projectSettingsFile)) {
+                throw new FileNotFoundException(
+                        "The specified project settings file does not exist: " 
+ projectSettingsFile);
+            }
+        } else {
+            String projectSettingsFileStr =
+                    
context.invokerRequest.userProperties().get(Constants.MAVEN_PROJECT_SETTINGS);
+            if (projectSettingsFileStr != null) {
+                projectSettingsFile = 
context.cwdResolver.apply(projectSettingsFileStr);
+            }
+        }
+
+        Path installationSettingsFile = null;
+
+        if (mavenOptions.altInstallationSettings().isPresent()) {
+            installationSettingsFile = context.cwdResolver.apply(
+                    mavenOptions.altInstallationSettings().get());
+
+            if (!Files.isRegularFile(installationSettingsFile)) {
+                throw new FileNotFoundException(
+                        "The specified installation settings file does not 
exist: " + installationSettingsFile);
+            }
+        } else {
+            String installationSettingsFileStr =
+                    
context.invokerRequest.userProperties().get(Constants.MAVEN_INSTALLATION_SETTINGS);
+            if (installationSettingsFileStr != null) {
+                installationSettingsFile = 
context.cwdResolver.apply(installationSettingsFileStr);
+            }
+        }
+
+        context.installationSettingsPath = installationSettingsFile;
+        context.projectSettingsPath = projectSettingsFile;
+        context.userSettingsPath = userSettingsFile;
+
+        SettingsBuildingRequest settingsRequest = new 
DefaultSettingsBuildingRequest();
+        
settingsRequest.setGlobalSettingsFile(toFile(installationSettingsFile));
+        settingsRequest.setProjectSettingsFile(toFile(projectSettingsFile));
+        settingsRequest.setUserSettingsFile(toFile(userSettingsFile));
+        
settingsRequest.setSystemProperties(toProperties(context.invokerRequest.systemProperties()));
+        Properties props = 
toProperties(context.invokerRequest.userProperties());
+        props.put(
+                "session.rootDirectory", 
context.invokerRequest.rootDirectory().toString());
+        props.put("session.topDirectory", 
context.invokerRequest.topDirectory().toString());
+
+        settingsRequest.setUserProperties(props);
+        customizeSettingsRequest(context, settingsRequest);
+
+        context.logger.debug("Reading installation settings from '"
+                + (settingsRequest.getGlobalSettingsSource() != null
+                        ? 
settingsRequest.getGlobalSettingsSource().getLocation()
+                        : settingsRequest.getGlobalSettingsFile())
+                + "'");
+        context.logger.debug("Reading project settings from '"
+                + (settingsRequest.getProjectSettingsSource() != null
+                        ? 
settingsRequest.getProjectSettingsSource().getLocation()
+                        : settingsRequest.getProjectSettingsFile())
+                + "'");
+        context.logger.debug("Reading user settings from '"
+                + (settingsRequest.getUserSettingsSource() != null
+                        ? settingsRequest.getUserSettingsSource().getLocation()
+                        : settingsRequest.getUserSettingsFile())
+                + "'");
+
+        SettingsBuildingResult settingsResult = 
settingsBuilder.build(settingsRequest);
+        customizeSettingsResult(context, settingsResult);
+
+        context.effectiveSettings = settingsResult.getEffectiveSettings();
+        context.interactive = mayDisableInteractiveMode(context, 
context.effectiveSettings.isInteractiveMode());
+        context.localRepositoryPath = localRepositoryPath(context);
+
+        if (!settingsResult.getProblems().isEmpty()) {
+            context.logger.warn("");
+            context.logger.warn("Some problems were encountered while building 
the effective settings");
+
+            for (SettingsProblem problem : settingsResult.getProblems()) {
+                context.logger.warn(problem.getMessage() + " @ " + 
problem.getLocation());
+            }
+            context.logger.warn("");
+        }
+    }
+
+    protected void customizeSettingsRequest(C context, SettingsBuildingRequest 
settingsBuildingRequest)
+            throws Exception {}
+
+    protected void customizeSettingsResult(C context, SettingsBuildingResult 
settingsBuildingResult) throws Exception {}
+
+    protected boolean mayDisableInteractiveMode(C context, boolean 
proposedInteractive) {
+        if 
(!context.invokerRequest.options().forceInteractive().orElse(false)) {
+            if 
(context.invokerRequest.options().nonInteractive().orElse(false)) {
+                return false;
+            } else {
+                boolean runningOnCI = isRunningOnCI(context);
+                if (runningOnCI) {
+                    context.logger.info(
+                            "Making this build non-interactive, because the 
environment variable CI equals \"true\"."

Review Comment:
   - Apparently since #869



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscr...@maven.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to