[MNG-8283] Make resident able to restore state (#1779)

And move all logic out of invoke. Also, parser and other improvements, mostly adding "extension points" in form of overridable protected method.

---

https://issues.apache.org/jira/browse/MNG-8283
This commit is contained in:
Tamas Cservenak 2024-10-05 15:57:15 +02:00 committed by GitHub
parent 20fe966770
commit e369ce5782
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 237 additions and 264 deletions

View File

@ -60,94 +60,91 @@ import static org.apache.maven.cling.invoker.Utils.stripLeadingAndTrailingQuotes
import static org.apache.maven.cling.invoker.Utils.toMap; import static org.apache.maven.cling.invoker.Utils.toMap;
public abstract class BaseParser<O extends Options, R extends InvokerRequest<O>> implements Parser<R> { public abstract class BaseParser<O extends Options, R extends InvokerRequest<O>> implements Parser<R> {
@SuppressWarnings("VisibilityModifier")
public static class LocalContext {
public final ParserRequest parserRequest;
public final Map<String, String> systemPropertiesOverrides;
public LocalContext(ParserRequest parserRequest) {
this.parserRequest = parserRequest;
this.systemPropertiesOverrides = new HashMap<>();
}
public Path cwd;
public Path installationDirectory;
public Path userHomeDirectory;
public Map<String, String> systemProperties;
public Map<String, String> userProperties;
public Path topDirectory;
public Path rootDirectory;
public List<CoreExtension> extensions;
public Options options;
public Map<String, String> extraInterpolationSource() {
Map<String, String> extra = new HashMap<>();
extra.put("session.topDirectory", topDirectory.toString());
extra.put("session.rootDirectory", rootDirectory.toString());
return extra;
}
}
@Override @Override
public R parse(ParserRequest parserRequest) throws ParserException, IOException { public R parse(ParserRequest parserRequest) throws ParserException, IOException {
requireNonNull(parserRequest); requireNonNull(parserRequest);
LocalContext context = new LocalContext(parserRequest);
// the basics // the basics
HashMap<String, String> overrides = new HashMap<>(); context.cwd = requireNonNull(getCwd(context));
Path cwd = requireNonNull(getCwd(parserRequest, overrides)); context.installationDirectory = requireNonNull(getInstallationDirectory(context));
Path installationDirectory = requireNonNull(getInstallationDirectory(parserRequest, overrides)); context.userHomeDirectory = requireNonNull(getUserHomeDirectory(context));
Path userHomeDirectory = requireNonNull(getUserHomeDirectory(parserRequest, overrides));
// top/root // top/root
Path topDirectory = requireNonNull(getTopDirectory(parserRequest, cwd)); context.topDirectory = requireNonNull(getTopDirectory(context));
Path rootDirectory = requireNonNull(getRootDirectory(parserRequest, cwd, topDirectory)); context.rootDirectory = requireNonNull(getRootDirectory(context));
// options // options
List<O> parsedOptions = parseCliOptions(rootDirectory, parserRequest.args()); List<O> parsedOptions = parseCliOptions(context);
// warn about deprecated options // warn about deprecated options
parsedOptions.forEach(o -> o.warnAboutDeprecatedOptions( parsedOptions.forEach(o -> o.warnAboutDeprecatedOptions(
parserRequest, new PrintWriter(parserRequest.out() != null ? parserRequest.out() : System.out, true))); parserRequest, new PrintWriter(parserRequest.out() != null ? parserRequest.out() : System.out, true)));
// assemble options if needed // assemble options if needed
O options = assembleOptions(parsedOptions); context.options = assembleOptions(parsedOptions);
// system and user properties // system and user properties
Map<String, String> systemProperties = populateSystemProperties(overrides); context.systemProperties = populateSystemProperties(context);
Map<String, String> paths = new HashMap<>(); context.userProperties = populateUserProperties(context);
paths.put("session.topDirectory", topDirectory.toString());
paths.put("session.rootDirectory", rootDirectory.toString());
Map<String, String> userProperties =
populateUserProperties(systemProperties, installationDirectory, paths, options);
// options: interpolate // options: interpolate
Options interpolatedOptions = options.interpolate(Arrays.asList(paths, systemProperties, userProperties)); context.options = context.options.interpolate(
Arrays.asList(context.extraInterpolationSource(), context.userProperties, context.systemProperties));
// core extensions // core extensions
ArrayList<CoreExtension> extensions = new ArrayList<>(); context.extensions = readCoreExtensionsDescriptor(context);
String installationExtensionsFile = userProperties.get(Constants.MAVEN_INSTALLATION_EXTENSIONS);
extensions.addAll(readCoreExtensionsDescriptor(installationExtensionsFile, installationDirectory));
String projectExtensionsFile = userProperties.get(Constants.MAVEN_PROJECT_EXTENSIONS); return getInvokerRequest(context);
extensions.addAll(readCoreExtensionsDescriptor(projectExtensionsFile, cwd));
String userExtensionsFile = userProperties.get(Constants.MAVEN_USER_EXTENSIONS);
extensions.addAll(readCoreExtensionsDescriptor(userExtensionsFile, userHomeDirectory));
return getInvokerRequest(
parserRequest,
cwd,
installationDirectory,
userHomeDirectory,
userProperties,
systemProperties,
topDirectory,
rootDirectory,
extensions,
interpolatedOptions);
} }
@SuppressWarnings("ParameterNumber") protected abstract R getInvokerRequest(LocalContext context);
protected abstract R getInvokerRequest(
ParserRequest parserRequest,
Path cwd,
Path installationDirectory,
Path userHomeDirectory,
Map<String, String> userProperties,
Map<String, String> systemProperties,
Path topDirectory,
Path rootDirectory,
ArrayList<CoreExtension> extensions,
Options options);
protected Path getCwd(ParserRequest parserRequest, Map<String, String> overrides) throws ParserException { protected Path getCwd(LocalContext context) throws ParserException {
if (parserRequest.cwd() != null) { if (context.parserRequest.cwd() != null) {
Path result = getCanonicalPath(parserRequest.cwd()); Path result = getCanonicalPath(context.parserRequest.cwd());
overrides.put("user.dir", result.toString()); context.systemPropertiesOverrides.put("user.dir", result.toString());
return result; return result;
} else { } else {
return getCanonicalPath(Paths.get(System.getProperty("user.dir"))); return getCanonicalPath(Paths.get(System.getProperty("user.dir")));
} }
} }
protected Path getInstallationDirectory(ParserRequest parserRequest, Map<String, String> overrides) protected Path getInstallationDirectory(LocalContext context) throws ParserException {
throws ParserException {
Path result; Path result;
if (parserRequest.mavenHome() != null) { if (context.parserRequest.mavenHome() != null) {
result = getCanonicalPath(parserRequest.mavenHome()); result = getCanonicalPath(context.parserRequest.mavenHome());
overrides.put(MAVEN_HOME, result.toString()); context.systemPropertiesOverrides.put(MAVEN_HOME, result.toString());
} else { } else {
String mavenHome = System.getProperty(Constants.MAVEN_HOME); String mavenHome = System.getProperty(Constants.MAVEN_HOME);
if (mavenHome == null) { if (mavenHome == null) {
@ -158,23 +155,22 @@ public abstract class BaseParser<O extends Options, R extends InvokerRequest<O>>
return result; return result;
} }
protected Path getUserHomeDirectory(ParserRequest parserRequest, Map<String, String> overrides) protected Path getUserHomeDirectory(LocalContext context) throws ParserException {
throws ParserException { if (context.parserRequest.userHome() != null) {
if (parserRequest.userHome() != null) { Path result = getCanonicalPath(context.parserRequest.userHome());
Path result = getCanonicalPath(parserRequest.userHome()); context.systemPropertiesOverrides.put("user.home", result.toString());
overrides.put("user.home", result.toString());
return result; return result;
} else { } else {
return getCanonicalPath(Paths.get(System.getProperty("user.home"))); return getCanonicalPath(Paths.get(System.getProperty("user.home")));
} }
} }
protected Path getTopDirectory(ParserRequest parserRequest, Path cwd) throws ParserException { protected Path getTopDirectory(LocalContext context) throws ParserException {
// We need to locate the top level project which may be pointed at using // We need to locate the top level project which may be pointed at using
// the -f/--file option. // the -f/--file option.
Path topDirectory = cwd; Path topDirectory = requireNonNull(context.cwd);
boolean isAltFile = false; boolean isAltFile = false;
for (String arg : parserRequest.args()) { for (String arg : context.parserRequest.args()) {
if (isAltFile) { if (isAltFile) {
// this is the argument following -f/--file // this is the argument following -f/--file
Path path = topDirectory.resolve(stripLeadingAndTrailingQuotes(arg)); Path path = topDirectory.resolve(stripLeadingAndTrailingQuotes(arg));
@ -199,32 +195,34 @@ public abstract class BaseParser<O extends Options, R extends InvokerRequest<O>>
return getCanonicalPath(topDirectory); return getCanonicalPath(topDirectory);
} }
protected Path getRootDirectory(ParserRequest parserRequest, Path cwd, Path topDirectory) throws ParserException { protected Path getRootDirectory(LocalContext context) throws ParserException {
RootLocator rootLocator = RootLocator rootLocator =
ServiceLoader.load(RootLocator.class).iterator().next(); ServiceLoader.load(RootLocator.class).iterator().next();
Path rootDirectory = rootLocator.findRoot(topDirectory); Path rootDirectory = rootLocator.findRoot(requireNonNull(context.topDirectory));
// TODO: multiModuleProjectDirectory vs rootDirectory? // TODO: multiModuleProjectDirectory vs rootDirectory?
// fallback if no root? otherwise make sure they are same? // fallback if no root? otherwise make sure they are same?
Path mmpd = System.getProperty("maven.multiModuleProjectDirectory") == null Path mmpd = System.getProperty("maven.multiModuleProjectDirectory") == null
? null ? null
: getCanonicalPath(cwd.resolve(requireNonNull( : getCanonicalPath(context.cwd.resolve(requireNonNull(
System.getProperty("maven.multiModuleProjectDirectory"), System.getProperty("maven.multiModuleProjectDirectory"),
"maven.multiModuleProjectDirectory is not set"))); "maven.multiModuleProjectDirectory is not set")));
if (rootDirectory == null) { if (rootDirectory == null) {
parserRequest.logger().warn(rootLocator.getNoRootMessage()); context.parserRequest.logger().warn(rootLocator.getNoRootMessage());
rootDirectory = requireNonNull( rootDirectory = requireNonNull(
mmpd, "maven.multiModuleProjectDirectory is not set and rootDirectory was not discovered"); mmpd, "maven.multiModuleProjectDirectory is not set and rootDirectory was not discovered");
} else { } else {
rootDirectory = getCanonicalPath(rootDirectory); rootDirectory = getCanonicalPath(rootDirectory);
if (mmpd != null && !Objects.equals(rootDirectory, mmpd)) { if (mmpd != null && !Objects.equals(rootDirectory, mmpd)) {
parserRequest.logger().warn("Project root directory and multiModuleProjectDirectory are not aligned"); context.parserRequest
.logger()
.warn("Project root directory and multiModuleProjectDirectory are not aligned");
} }
} }
return getCanonicalPath(rootDirectory); return getCanonicalPath(rootDirectory);
} }
protected Map<String, String> populateSystemProperties(Map<String, String> overrides) throws ParserException { protected Map<String, String> populateSystemProperties(LocalContext context) throws ParserException {
Properties systemProperties = new Properties(); Properties systemProperties = new Properties();
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
@ -248,18 +246,11 @@ public abstract class BaseParser<O extends Options, R extends InvokerRequest<O>>
systemProperties.setProperty("maven.build.version", mavenBuildVersion); systemProperties.setProperty("maven.build.version", mavenBuildVersion);
Map<String, String> result = toMap(systemProperties); Map<String, String> result = toMap(systemProperties);
if (overrides != null) { result.putAll(context.systemPropertiesOverrides);
result.putAll(overrides);
}
return result; return result;
} }
protected Map<String, String> populateUserProperties( protected Map<String, String> populateUserProperties(LocalContext context) throws ParserException, IOException {
Map<String, String> systemProperties,
Path installationDirectory,
Map<String, String> paths,
Options options)
throws ParserException, IOException {
Properties userProperties = new Properties(); Properties userProperties = new Properties();
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
@ -268,49 +259,65 @@ public abstract class BaseParser<O extends Options, R extends InvokerRequest<O>>
// are most dominant. // are most dominant.
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
Map<String, String> userSpecifiedProperties = options.userProperties().orElse(new HashMap<>()); Map<String, String> userSpecifiedProperties =
userProperties.putAll(userSpecifiedProperties); context.options.userProperties().orElse(new HashMap<>());
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Load config files // Load config files
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
Map<String, String> paths = context.extraInterpolationSource();
Function<String, String> callback = Function<String, String> callback =
or(paths::get, prefix("cli.", userSpecifiedProperties::get), systemProperties::get); or(paths::get, prefix("cli.", userSpecifiedProperties::get), context.systemProperties::get);
Path mavenConf; Path mavenConf;
if (systemProperties.get(MAVEN_INSTALLATION_CONF) != null) { if (context.systemProperties.get(MAVEN_INSTALLATION_CONF) != null) {
mavenConf = installationDirectory.resolve(systemProperties.get(MAVEN_INSTALLATION_CONF)); mavenConf = context.installationDirectory.resolve(context.systemProperties.get(MAVEN_INSTALLATION_CONF));
} else if (systemProperties.get("maven.conf") != null) { } else if (context.systemProperties.get("maven.conf") != null) {
mavenConf = installationDirectory.resolve(systemProperties.get("maven.conf")); mavenConf = context.installationDirectory.resolve(context.systemProperties.get("maven.conf"));
} else if (systemProperties.get(MAVEN_HOME) != null) { } else if (context.systemProperties.get(MAVEN_HOME) != null) {
mavenConf = installationDirectory mavenConf = context.installationDirectory
.resolve(systemProperties.get(MAVEN_HOME)) .resolve(context.systemProperties.get(MAVEN_HOME))
.resolve("conf"); .resolve("conf");
} else { } else {
mavenConf = installationDirectory.resolve(""); mavenConf = context.installationDirectory.resolve("");
} }
Path propertiesFile = mavenConf.resolve("maven.properties"); Path propertiesFile = mavenConf.resolve("maven.properties");
MavenPropertiesLoader.loadProperties(userProperties, propertiesFile, callback, false); MavenPropertiesLoader.loadProperties(userProperties, propertiesFile, callback, false);
// CLI specified properties are most dominant
userProperties.putAll(userSpecifiedProperties);
return toMap(userProperties); return toMap(userProperties);
} }
protected abstract List<O> parseCliOptions(Path rootDirectory, List<String> args) protected abstract List<O> parseCliOptions(LocalContext context) throws ParserException, IOException;
throws ParserException, IOException;
protected abstract O assembleOptions(List<O> parsedOptions); protected abstract O assembleOptions(List<O> parsedOptions);
protected List<CoreExtension> readCoreExtensionsDescriptor(String extensionsFile, Path cwd) protected List<CoreExtension> readCoreExtensionsDescriptor(LocalContext context)
throws ParserException, IOException {
ArrayList<CoreExtension> extensions = new ArrayList<>();
String installationExtensionsFile = context.userProperties.get(Constants.MAVEN_INSTALLATION_EXTENSIONS);
extensions.addAll(readCoreExtensionsDescriptorFromFile(
context.installationDirectory.resolve(installationExtensionsFile)));
String projectExtensionsFile = context.userProperties.get(Constants.MAVEN_PROJECT_EXTENSIONS);
extensions.addAll(readCoreExtensionsDescriptorFromFile(context.cwd.resolve(projectExtensionsFile)));
String userExtensionsFile = context.userProperties.get(Constants.MAVEN_USER_EXTENSIONS);
extensions.addAll(readCoreExtensionsDescriptorFromFile(context.userHomeDirectory.resolve(userExtensionsFile)));
return extensions;
}
protected List<CoreExtension> readCoreExtensionsDescriptorFromFile(Path extensionsFile)
throws ParserException, IOException { throws ParserException, IOException {
try { try {
if (extensionsFile != null) { if (extensionsFile != null && Files.exists(extensionsFile)) {
Path extensionsPath = cwd.resolve(extensionsFile); try (InputStream is = Files.newInputStream(extensionsFile)) {
if (Files.exists(extensionsPath)) {
try (InputStream is = Files.newInputStream(extensionsPath)) {
return new CoreExtensionsStaxReader().read(is, true).getExtensions(); return new CoreExtensionsStaxReader().read(is, true).getExtensions();
} }
} }
}
return List.of(); return List.of();
} catch (XMLStreamException e) { } catch (XMLStreamException e) {
throw new ParserException("Failed to parse extensions file: " + extensionsFile, e); throw new ParserException("Failed to parse extensions file: " + extensionsFile, e);

View File

@ -403,6 +403,10 @@ public abstract class CommonsCliOptions implements Options {
return commandLine; return commandLine;
} }
public org.apache.commons.cli.Options getOptions() {
return options;
}
public Set<Option> getUsedDeprecatedOptions() { public Set<Option> getUsedDeprecatedOptions() {
return usedDeprecatedOptions; return usedDeprecatedOptions;
} }

View File

@ -88,6 +88,19 @@ public abstract class LookupInvoker<
O extends Options, R extends InvokerRequest<O>, C extends LookupInvoker.LookupInvokerContext<O, R, C>> O extends Options, R extends InvokerRequest<O>, C extends LookupInvoker.LookupInvokerContext<O, R, C>>
implements Invoker<R> { implements Invoker<R> {
/**
* Exception for intentional exit: No message or anything will be displayed, just the
* carried exit code will be returned from {@link #invoke(InvokerRequest)} method.
*/
public static final class ExitException extends InvokerException {
private final int exitCode;
public ExitException(int exitCode) {
super("EXIT");
this.exitCode = exitCode;
}
}
@SuppressWarnings("VisibilityModifier") @SuppressWarnings("VisibilityModifier")
public static class LookupInvokerContext< public static class LookupInvokerContext<
O extends Options, R extends InvokerRequest<O>, C extends LookupInvokerContext<O, R, C>> O extends Options, R extends InvokerRequest<O>, C extends LookupInvokerContext<O, R, C>>
@ -124,6 +137,7 @@ public abstract class LookupInvoker<
public ILoggerFactory loggerFactory; public ILoggerFactory loggerFactory;
public Slf4jConfiguration slf4jConfiguration; public Slf4jConfiguration slf4jConfiguration;
public Slf4jConfiguration.Level loggerLevel; public Slf4jConfiguration.Level loggerLevel;
public ClassLoader currentThreadContextClassLoader;
public ContainerCapsule containerCapsule; public ContainerCapsule containerCapsule;
public Lookup lookup; public Lookup lookup;
public SettingsBuilder settingsBuilder; public SettingsBuilder settingsBuilder;
@ -153,36 +167,32 @@ public abstract class LookupInvoker<
public int invoke(R invokerRequest) throws InvokerException { public int invoke(R invokerRequest) throws InvokerException {
requireNonNull(invokerRequest); requireNonNull(invokerRequest);
Properties oldProps = (Properties) System.getProperties().clone();
ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
try (C context = createContext(invokerRequest)) { try (C context = createContext(invokerRequest)) {
Properties props = (Properties) System.getProperties().clone();
try { try {
HashSet<String> sys = if (context.currentThreadContextClassLoader != null) {
new HashSet<>(invokerRequest.systemProperties().keySet()); Thread.currentThread().setContextClassLoader(context.currentThreadContextClassLoader);
invokerRequest.userProperties().entrySet().stream() }
.filter(k -> !sys.contains(k.getKey())) return doInvoke(context);
.forEach(k -> System.setProperty(k.getKey(), k.getValue())); } catch (ExitException e) {
System.setProperty( return e.exitCode;
Constants.MAVEN_HOME, } catch (Exception e) {
invokerRequest.installationDirectory().toString()); throw handleException(context, e);
}
} finally {
Thread.currentThread().setContextClassLoader(oldCL);
System.setProperties(oldProps);
}
}
protected int doInvoke(C context) throws Exception {
pushProperties(context);
validate(context); validate(context);
prepare(context); prepare(context);
configureLogging(context); configureLogging(context);
activateLogging(context); activateLogging(context);
helpOrVersionAndMayExit(context);
if (invokerRequest.options().help().isPresent()) {
invokerRequest.options().displayHelp(context.invokerRequest.parserRequest(), 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); preCommands(context);
container(context); container(context);
lookup(context); lookup(context);
@ -190,12 +200,6 @@ public abstract class LookupInvoker<
postCommands(context); postCommands(context);
settings(context); settings(context);
return execute(context); return execute(context);
} catch (Exception e) {
throw handleException(context, e);
} finally {
System.setProperties(props);
}
}
} }
protected InvokerException handleException(LookupInvokerContext<O, R, C> context, Exception e) protected InvokerException handleException(LookupInvokerContext<O, R, C> context, Exception e)
@ -217,6 +221,16 @@ public abstract class LookupInvoker<
protected abstract C createContext(R invokerRequest) throws InvokerException; protected abstract C createContext(R invokerRequest) throws InvokerException;
protected void pushProperties(C context) throws Exception {
R invokerRequest = context.invokerRequest;
HashSet<String> sys = new HashSet<>(invokerRequest.systemProperties().keySet());
invokerRequest.userProperties().entrySet().stream()
.filter(k -> !sys.contains(k.getKey()))
.forEach(k -> System.setProperty(k.getKey(), k.getValue()));
System.setProperty(
Constants.MAVEN_HOME, invokerRequest.installationDirectory().toString());
}
protected void validate(C context) throws Exception {} protected void validate(C context) throws Exception {}
protected void prepare(C context) throws Exception {} protected void prepare(C context) throws Exception {}
@ -298,6 +312,22 @@ public abstract class LookupInvoker<
} }
} }
protected void helpOrVersionAndMayExit(C context) throws Exception {
R invokerRequest = context.invokerRequest;
if (invokerRequest.options().help().isPresent()) {
invokerRequest.options().displayHelp(context.invokerRequest.parserRequest(), context.stdOut);
throw new ExitException(0);
}
if (invokerRequest.options().showVersionAndExit().isPresent()) {
if (invokerRequest.options().quiet().orElse(false)) {
context.stdOut.println(CLIReportingUtils.showVersionMinimal());
} else {
context.stdOut.println(CLIReportingUtils.showVersion());
}
throw new ExitException(0);
}
}
protected void preCommands(C context) throws Exception { protected void preCommands(C context) throws Exception {
Options mavenOptions = context.invokerRequest.options(); Options mavenOptions = context.invokerRequest.options();
if (mavenOptions.verbose().orElse(false) || mavenOptions.showVersion().orElse(false)) { if (mavenOptions.verbose().orElse(false) || mavenOptions.showVersion().orElse(false)) {

View File

@ -57,6 +57,7 @@ import org.codehaus.plexus.PlexusConstants;
import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.classworlds.ClassWorld; import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.classworlds.realm.ClassRealm; import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.logging.LoggerManager;
import org.slf4j.ILoggerFactory; import org.slf4j.ILoggerFactory;
import static org.apache.maven.cling.invoker.Utils.toPlexusLoggingLevel; import static org.apache.maven.cling.invoker.Utils.toPlexusLoggingLevel;
@ -110,9 +111,10 @@ public class PlexusContainerCapsuleFactory<
// NOTE: To avoid inconsistencies, we'll use the TCCL exclusively for lookups // NOTE: To avoid inconsistencies, we'll use the TCCL exclusively for lookups
container.setLookupRealm(null); container.setLookupRealm(null);
context.currentThreadContextClassLoader = container.getContainerRealm();
Thread.currentThread().setContextClassLoader(container.getContainerRealm()); Thread.currentThread().setContextClassLoader(container.getContainerRealm());
container.setLoggerManager(new Slf4jLoggerManager()); container.setLoggerManager(createLoggerManager());
R invokerRequest = context.invokerRequest; R invokerRequest = context.invokerRequest;
Function<String, String> extensionSource = expression -> { Function<String, String> extensionSource = expression -> {
String value = invokerRequest.userProperties().get(expression); String value = invokerRequest.userProperties().get(expression);
@ -167,6 +169,10 @@ public class PlexusContainerCapsuleFactory<
}; };
} }
protected LoggerManager createLoggerManager() {
return new Slf4jLoggerManager();
}
protected void customizeContainerConfiguration(C context, ContainerConfiguration configuration) throws Exception {} protected void customizeContainerConfiguration(C context, ContainerConfiguration configuration) throws Exception {}
protected void customizeContainer(C context, PlexusContainer container) throws Exception {} protected void customizeContainer(C context, PlexusContainer container) throws Exception {}
@ -261,7 +267,7 @@ public class PlexusContainerCapsuleFactory<
ClassLoader oldCL = Thread.currentThread().getContextClassLoader(); ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
try { try {
container.setLookupRealm(null); container.setLookupRealm(null);
container.setLoggerManager(new Slf4jLoggerManager()); container.setLoggerManager(createLoggerManager());
container.getLoggerManager().setThresholds(toPlexusLoggingLevel(context.loggerLevel)); container.getLoggerManager().setThresholds(toPlexusLoggingLevel(context.loggerLevel));
Thread.currentThread().setContextClassLoader(container.getContainerRealm()); Thread.currentThread().setContextClassLoader(container.getContainerRealm());

View File

@ -24,13 +24,10 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.apache.maven.api.cli.Options; import org.apache.maven.api.cli.Options;
import org.apache.maven.api.cli.ParserException; import org.apache.maven.api.cli.ParserException;
import org.apache.maven.api.cli.ParserRequest;
import org.apache.maven.api.cli.extensions.CoreExtension;
import org.apache.maven.api.cli.mvn.MavenInvokerRequest; import org.apache.maven.api.cli.mvn.MavenInvokerRequest;
import org.apache.maven.api.cli.mvn.MavenOptions; import org.apache.maven.api.cli.mvn.MavenOptions;
import org.apache.maven.api.cli.mvn.MavenParser; import org.apache.maven.api.cli.mvn.MavenParser;
@ -38,27 +35,14 @@ import org.apache.maven.cling.invoker.BaseParser;
public abstract class BaseMavenParser<O extends MavenOptions, R extends MavenInvokerRequest<O>> extends BaseParser<O, R> public abstract class BaseMavenParser<O extends MavenOptions, R extends MavenInvokerRequest<O>> extends BaseParser<O, R>
implements MavenParser<R> { implements MavenParser<R> {
@SuppressWarnings("ParameterNumber")
@Override
protected abstract R getInvokerRequest(
ParserRequest parserRequest,
Path cwd,
Path installationDirectory,
Path userHomeDirectory,
Map<String, String> userProperties,
Map<String, String> systemProperties,
Path topDirectory,
Path rootDirectory,
ArrayList<CoreExtension> extensions,
Options options);
@Override @Override
protected List<O> parseCliOptions(Path rootDirectory, List<String> args) throws ParserException, IOException { protected List<O> parseCliOptions(LocalContext context) throws ParserException, IOException {
ArrayList<O> result = new ArrayList<>(); ArrayList<O> result = new ArrayList<>();
// CLI args // CLI args
result.add(parseMavenCliOptions(args)); result.add(parseMavenCliOptions(context.parserRequest.args()));
// maven.config; if exists // maven.config; if exists
Path mavenConfig = rootDirectory.resolve(".mvn/maven.config"); Path mavenConfig = context.rootDirectory.resolve(".mvn/maven.config");
if (Files.isRegularFile(mavenConfig)) { if (Files.isRegularFile(mavenConfig)) {
result.add(parseMavenConfigOptions(mavenConfig)); result.add(parseMavenConfigOptions(mavenConfig));
} }

View File

@ -18,49 +18,32 @@
*/ */
package org.apache.maven.cling.invoker.mvn; package org.apache.maven.cling.invoker.mvn;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import org.apache.commons.cli.ParseException; import org.apache.commons.cli.ParseException;
import org.apache.maven.api.cli.Options;
import org.apache.maven.api.cli.ParserException; import org.apache.maven.api.cli.ParserException;
import org.apache.maven.api.cli.ParserRequest;
import org.apache.maven.api.cli.extensions.CoreExtension;
import org.apache.maven.api.cli.mvn.MavenInvokerRequest; import org.apache.maven.api.cli.mvn.MavenInvokerRequest;
import org.apache.maven.api.cli.mvn.MavenOptions; import org.apache.maven.api.cli.mvn.MavenOptions;
import org.apache.maven.api.cli.mvn.MavenParser; import org.apache.maven.api.cli.mvn.MavenParser;
public class DefaultMavenParser extends BaseMavenParser<MavenOptions, MavenInvokerRequest<MavenOptions>> public class DefaultMavenParser extends BaseMavenParser<MavenOptions, MavenInvokerRequest<MavenOptions>>
implements MavenParser<MavenInvokerRequest<MavenOptions>> { implements MavenParser<MavenInvokerRequest<MavenOptions>> {
@SuppressWarnings("ParameterNumber")
@Override @Override
protected DefaultMavenInvokerRequest<MavenOptions> getInvokerRequest( protected DefaultMavenInvokerRequest<MavenOptions> getInvokerRequest(LocalContext context) {
ParserRequest parserRequest,
Path cwd,
Path installationDirectory,
Path userHomeDirectory,
Map<String, String> userProperties,
Map<String, String> systemProperties,
Path topDirectory,
Path rootDirectory,
ArrayList<CoreExtension> extensions,
Options options) {
return new DefaultMavenInvokerRequest<>( return new DefaultMavenInvokerRequest<>(
parserRequest, context.parserRequest,
cwd, context.cwd,
installationDirectory, context.installationDirectory,
userHomeDirectory, context.userHomeDirectory,
userProperties, context.userProperties,
systemProperties, context.systemProperties,
topDirectory, context.topDirectory,
rootDirectory, context.rootDirectory,
parserRequest.in(), context.parserRequest.in(),
parserRequest.out(), context.parserRequest.out(),
parserRequest.err(), context.parserRequest.err(),
extensions, context.extensions,
(MavenOptions) options); (MavenOptions) context.options);
} }
@Override @Override

View File

@ -19,15 +19,10 @@
package org.apache.maven.cling.invoker.mvn.forked; package org.apache.maven.cling.invoker.mvn.forked;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import org.apache.commons.cli.ParseException; import org.apache.commons.cli.ParseException;
import org.apache.maven.api.cli.Options;
import org.apache.maven.api.cli.ParserException; import org.apache.maven.api.cli.ParserException;
import org.apache.maven.api.cli.ParserRequest;
import org.apache.maven.api.cli.extensions.CoreExtension;
import org.apache.maven.api.cli.mvn.MavenOptions; import org.apache.maven.api.cli.mvn.MavenOptions;
import org.apache.maven.api.cli.mvn.forked.ForkedMavenInvokerRequest; import org.apache.maven.api.cli.mvn.forked.ForkedMavenInvokerRequest;
import org.apache.maven.api.cli.mvn.forked.ForkedMavenParser; import org.apache.maven.api.cli.mvn.forked.ForkedMavenParser;
@ -40,32 +35,22 @@ public class DefaultForkedMavenParser extends BaseMavenParser<MavenOptions, Fork
@SuppressWarnings("ParameterNumber") @SuppressWarnings("ParameterNumber")
@Override @Override
protected ForkedMavenInvokerRequest getInvokerRequest( protected ForkedMavenInvokerRequest getInvokerRequest(LocalContext context) {
ParserRequest parserRequest,
Path cwd,
Path installationDirectory,
Path userHomeDirectory,
Map<String, String> userProperties,
Map<String, String> systemProperties,
Path topDirectory,
Path rootDirectory,
ArrayList<CoreExtension> extensions,
Options options) {
return new DefaultForkedMavenInvokerRequest( return new DefaultForkedMavenInvokerRequest(
parserRequest, context.parserRequest,
cwd, context.cwd,
installationDirectory, context.installationDirectory,
userHomeDirectory, context.userHomeDirectory,
userProperties, context.userProperties,
systemProperties, context.systemProperties,
topDirectory, context.topDirectory,
rootDirectory, context.rootDirectory,
parserRequest.in(), context.parserRequest.in(),
parserRequest.out(), context.parserRequest.out(),
parserRequest.err(), context.parserRequest.err(),
extensions, context.extensions,
getJvmArguments(rootDirectory), getJvmArguments(context.rootDirectory),
(MavenOptions) options); (MavenOptions) context.options);
} }
protected List<String> getJvmArguments(Path rootDirectory) { protected List<String> getJvmArguments(Path rootDirectory) {

View File

@ -55,6 +55,9 @@ public class DefaultResidentMavenInvoker
} }
public LocalContext copy(MavenInvokerRequest<MavenOptions> invokerRequest) { public LocalContext copy(MavenInvokerRequest<MavenOptions> invokerRequest) {
if (invokerRequest == this.invokerRequest) {
return this;
}
LocalContext shadow = new LocalContext((DefaultResidentMavenInvoker) invoker, invokerRequest); LocalContext shadow = new LocalContext((DefaultResidentMavenInvoker) invoker, invokerRequest);
shadow.logger = logger; shadow.logger = logger;
@ -109,19 +112,7 @@ public class DefaultResidentMavenInvoker
@Override @Override
protected LocalContext createContext(MavenInvokerRequest<MavenOptions> invokerRequest) { protected LocalContext createContext(MavenInvokerRequest<MavenOptions> invokerRequest) {
return residentContext return residentContext
.computeIfAbsent(getContextId(invokerRequest), k -> { .computeIfAbsent(getContextId(invokerRequest), k -> new LocalContext(this, invokerRequest))
LocalContext master = new LocalContext(this, invokerRequest);
try {
validate(master);
prepare(master);
configureLogging(master);
container(master);
lookup(master);
return master;
} catch (Exception e) {
throw new InvokerException("Failed to init master context", e);
}
})
.copy(invokerRequest); .copy(invokerRequest);
} }
@ -133,7 +124,7 @@ public class DefaultResidentMavenInvoker
@Override @Override
protected void container(LocalContext context) throws Exception { protected void container(LocalContext context) throws Exception {
if (context.maven == null) { if (context.containerCapsule == null) {
super.container(context); super.container(context);
} }
} }

View File

@ -18,55 +18,38 @@
*/ */
package org.apache.maven.cling.invoker.mvnenc; package org.apache.maven.cling.invoker.mvnenc;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import org.apache.commons.cli.ParseException; import org.apache.commons.cli.ParseException;
import org.apache.maven.api.cli.Options;
import org.apache.maven.api.cli.ParserException; import org.apache.maven.api.cli.ParserException;
import org.apache.maven.api.cli.ParserRequest;
import org.apache.maven.api.cli.extensions.CoreExtension;
import org.apache.maven.api.cli.mvnenc.EncryptInvokerRequest; import org.apache.maven.api.cli.mvnenc.EncryptInvokerRequest;
import org.apache.maven.api.cli.mvnenc.EncryptOptions; import org.apache.maven.api.cli.mvnenc.EncryptOptions;
import org.apache.maven.api.cli.mvnenc.EncryptParser; import org.apache.maven.api.cli.mvnenc.EncryptParser;
import org.apache.maven.cling.invoker.BaseParser; import org.apache.maven.cling.invoker.BaseParser;
public class DefaultEncryptParser extends BaseParser<EncryptOptions, EncryptInvokerRequest> implements EncryptParser { public class DefaultEncryptParser extends BaseParser<EncryptOptions, EncryptInvokerRequest> implements EncryptParser {
@SuppressWarnings("ParameterNumber")
@Override @Override
protected EncryptInvokerRequest getInvokerRequest( protected EncryptInvokerRequest getInvokerRequest(LocalContext context) {
ParserRequest parserRequest,
Path cwd,
Path installationDirectory,
Path userHomeDirectory,
Map<String, String> userProperties,
Map<String, String> systemProperties,
Path topDirectory,
Path rootDirectory,
ArrayList<CoreExtension> extensions,
Options options) {
return new DefaultEncryptInvokerRequest( return new DefaultEncryptInvokerRequest(
parserRequest, context.parserRequest,
cwd, context.cwd,
installationDirectory, context.installationDirectory,
userHomeDirectory, context.userHomeDirectory,
userProperties, context.userProperties,
systemProperties, context.systemProperties,
topDirectory, context.topDirectory,
rootDirectory, context.rootDirectory,
parserRequest.in(), context.parserRequest.in(),
parserRequest.out(), context.parserRequest.out(),
parserRequest.err(), context.parserRequest.err(),
extensions, context.extensions,
options); context.options);
} }
@Override @Override
protected List<EncryptOptions> parseCliOptions(Path rootDirectory, List<String> args) throws ParserException { protected List<EncryptOptions> parseCliOptions(LocalContext context) throws ParserException {
return Collections.singletonList(parseEncryptCliOptions(args)); return Collections.singletonList(parseEncryptCliOptions(context.parserRequest.args()));
} }
protected CommonsCliEncryptOptions parseEncryptCliOptions(List<String> args) throws ParserException { protected CommonsCliEncryptOptions parseEncryptCliOptions(List<String> args) throws ParserException {