1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.cling.invoker;
20
21 import java.io.FileNotFoundException;
22 import java.io.IOException;
23 import java.io.PrintWriter;
24 import java.nio.file.Files;
25 import java.nio.file.Path;
26 import java.util.ArrayList;
27 import java.util.HashSet;
28 import java.util.List;
29 import java.util.Locale;
30 import java.util.Map;
31 import java.util.Properties;
32 import java.util.function.Consumer;
33 import java.util.function.Function;
34
35 import org.apache.maven.api.Constants;
36 import org.apache.maven.api.ProtoSession;
37 import org.apache.maven.api.cli.Invoker;
38 import org.apache.maven.api.cli.InvokerException;
39 import org.apache.maven.api.cli.InvokerRequest;
40 import org.apache.maven.api.cli.Logger;
41 import org.apache.maven.api.cli.Options;
42 import org.apache.maven.api.services.BuilderProblem;
43 import org.apache.maven.api.services.Interpolator;
44 import org.apache.maven.api.services.Lookup;
45 import org.apache.maven.api.services.MavenException;
46 import org.apache.maven.api.services.MessageBuilder;
47 import org.apache.maven.api.services.SettingsBuilder;
48 import org.apache.maven.api.services.SettingsBuilderRequest;
49 import org.apache.maven.api.services.SettingsBuilderResult;
50 import org.apache.maven.api.services.Source;
51 import org.apache.maven.api.settings.Mirror;
52 import org.apache.maven.api.settings.Profile;
53 import org.apache.maven.api.settings.Proxy;
54 import org.apache.maven.api.settings.Repository;
55 import org.apache.maven.api.settings.Server;
56 import org.apache.maven.api.settings.Settings;
57 import org.apache.maven.api.spi.PropertyContributor;
58 import org.apache.maven.artifact.InvalidRepositoryException;
59 import org.apache.maven.artifact.repository.ArtifactRepository;
60 import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
61 import org.apache.maven.artifact.repository.MavenArtifactRepository;
62 import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
63 import org.apache.maven.bridge.MavenRepositorySystem;
64 import org.apache.maven.cling.invoker.spi.PropertyContributorsHolder;
65 import org.apache.maven.cling.logging.Slf4jConfiguration;
66 import org.apache.maven.cling.logging.Slf4jConfigurationFactory;
67 import org.apache.maven.cling.utils.CLIReportingUtils;
68 import org.apache.maven.execution.MavenExecutionRequest;
69 import org.apache.maven.internal.impl.SettingsUtilsV4;
70 import org.apache.maven.jline.FastTerminal;
71 import org.apache.maven.jline.MessageUtils;
72 import org.apache.maven.logging.BuildEventListener;
73 import org.apache.maven.logging.LoggingOutputStream;
74 import org.apache.maven.logging.ProjectBuildLogAppender;
75 import org.apache.maven.logging.SimpleBuildEventListener;
76 import org.apache.maven.logging.api.LogLevelRecorder;
77 import org.apache.maven.slf4j.MavenSimpleLogger;
78 import org.jline.terminal.Terminal;
79 import org.jline.terminal.TerminalBuilder;
80 import org.jline.terminal.impl.AbstractPosixTerminal;
81 import org.jline.terminal.spi.TerminalExt;
82 import org.slf4j.LoggerFactory;
83 import org.slf4j.spi.LocationAwareLogger;
84
85 import static java.util.Objects.requireNonNull;
86 import static org.apache.maven.cling.invoker.Utils.toMavenExecutionRequestLoggingLevel;
87 import static org.apache.maven.cling.invoker.Utils.toProperties;
88
89
90
91
92
93
94 public abstract class LookupInvoker<C extends LookupContext> implements Invoker {
95 protected final ProtoLookup protoLookup;
96
97 public LookupInvoker(ProtoLookup protoLookup) {
98 this.protoLookup = requireNonNull(protoLookup);
99 }
100
101 @Override
102 public int invoke(InvokerRequest invokerRequest) throws InvokerException {
103 requireNonNull(invokerRequest);
104
105 Properties oldProps = (Properties) System.getProperties().clone();
106 ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
107 try (C context = createContext(invokerRequest)) {
108 try {
109 if (context.containerCapsule != null
110 && context.containerCapsule.currentThreadClassLoader().isPresent()) {
111 Thread.currentThread()
112 .setContextClassLoader(context.containerCapsule
113 .currentThreadClassLoader()
114 .get());
115 }
116 return doInvoke(context);
117 } catch (InvokerException.ExitException e) {
118 return e.getExitCode();
119 } catch (Exception e) {
120 throw handleException(context, e);
121 }
122 } finally {
123 Thread.currentThread().setContextClassLoader(oldCL);
124 System.setProperties(oldProps);
125 }
126 }
127
128 protected int doInvoke(C context) throws Exception {
129 pushCoreProperties(context);
130 pushUserProperties(context);
131 validate(context);
132 prepare(context);
133 configureLogging(context);
134 createTerminal(context);
135 activateLogging(context);
136 helpOrVersionAndMayExit(context);
137 preCommands(context);
138 container(context);
139 postContainer(context);
140 pushUserProperties(context);
141 lookup(context);
142 init(context);
143 postCommands(context);
144 settings(context);
145 return execute(context);
146 }
147
148 protected InvokerException handleException(C context, Exception e) throws InvokerException {
149 boolean showStackTrace = context.invokerRequest.options().showErrors().orElse(false);
150 if (showStackTrace) {
151 context.logger.error(
152 "Error executing " + context.invokerRequest.parserRequest().commandName() + ".", e);
153 } else {
154 context.logger.error(
155 "Error executing " + context.invokerRequest.parserRequest().commandName() + ".");
156 context.logger.error(e.getMessage());
157 for (Throwable cause = e.getCause(); cause != null && cause != cause.getCause(); cause = cause.getCause()) {
158 context.logger.error("Caused by: " + cause.getMessage());
159 }
160 }
161 return new InvokerException(e.getMessage(), e);
162 }
163
164 protected abstract C createContext(InvokerRequest invokerRequest) throws InvokerException;
165
166 protected void pushCoreProperties(C context) throws Exception {
167 System.setProperty(
168 Constants.MAVEN_HOME,
169 context.invokerRequest.installationDirectory().toString());
170 }
171
172
173
174
175
176
177
178
179 protected void pushUserProperties(C context) throws Exception {
180 ProtoSession protoSession = context.protoSession;
181 HashSet<String> sys = new HashSet<>(protoSession.getSystemProperties().keySet());
182 if (context.pushedUserProperties == null) {
183 context.pushedUserProperties = new HashSet<>();
184 protoSession.getUserProperties().entrySet().stream()
185 .filter(k -> !sys.contains(k.getKey()))
186 .peek(k -> context.pushedUserProperties.add(k.getKey()))
187 .forEach(k -> System.setProperty(k.getKey(), k.getValue()));
188 } else {
189 protoSession.getUserProperties().entrySet().stream()
190 .filter(k -> context.pushedUserProperties.contains(k.getKey()) || !sys.contains(k.getKey()))
191 .forEach(k -> System.setProperty(k.getKey(), k.getValue()));
192 }
193 }
194
195 protected void validate(C context) throws Exception {}
196
197 protected void prepare(C context) throws Exception {}
198
199 protected void configureLogging(C context) throws Exception {
200
201 Options mavenOptions = context.invokerRequest.options();
202 Map<String, String> userProperties = context.protoSession.getUserProperties();
203 String styleColor = mavenOptions
204 .color()
205 .orElse(userProperties.getOrDefault(
206 Constants.MAVEN_STYLE_COLOR_PROPERTY, userProperties.getOrDefault("style.color", "auto")));
207 if ("always".equals(styleColor) || "yes".equals(styleColor) || "force".equals(styleColor)) {
208 context.coloredOutput = true;
209 } else if ("never".equals(styleColor) || "no".equals(styleColor) || "none".equals(styleColor)) {
210 context.coloredOutput = false;
211 } else if (!"auto".equals(styleColor) && !"tty".equals(styleColor) && !"if-tty".equals(styleColor)) {
212 throw new IllegalArgumentException(
213 "Invalid color configuration value '" + styleColor + "'. Supported are 'auto', 'always', 'never'.");
214 } else {
215 boolean isBatchMode = !mavenOptions.forceInteractive().orElse(false)
216 && mavenOptions.nonInteractive().orElse(false);
217 if (isBatchMode || mavenOptions.logFile().isPresent()) {
218 context.coloredOutput = false;
219 }
220 }
221
222 context.loggerFactory = LoggerFactory.getILoggerFactory();
223 context.slf4jConfiguration = Slf4jConfigurationFactory.getConfiguration(context.loggerFactory);
224
225 context.loggerLevel = Slf4jConfiguration.Level.INFO;
226 if (mavenOptions.verbose().orElse(false)) {
227 context.loggerLevel = Slf4jConfiguration.Level.DEBUG;
228 } else if (mavenOptions.quiet().orElse(false)) {
229 context.loggerLevel = Slf4jConfiguration.Level.ERROR;
230 }
231 context.slf4jConfiguration.setRootLoggerLevel(context.loggerLevel);
232
233
234
235
236 ProjectBuildLogAppender projectBuildLogAppender =
237 new ProjectBuildLogAppender(determineBuildEventListener(context));
238 context.closeables.add(projectBuildLogAppender);
239 }
240
241 protected BuildEventListener determineBuildEventListener(C context) {
242 if (context.buildEventListener == null) {
243 context.buildEventListener = doDetermineBuildEventListener(context);
244 }
245 return context.buildEventListener;
246 }
247
248 protected BuildEventListener doDetermineBuildEventListener(C context) {
249 Consumer<String> writer = determineWriter(context);
250 return new SimpleBuildEventListener(writer);
251 }
252
253 protected void createTerminal(C context) {
254 MessageUtils.systemInstall(
255 builder -> {
256 builder.streams(
257 context.invokerRequest.in().orElse(null),
258 context.invokerRequest.out().orElse(null));
259 builder.systemOutput(TerminalBuilder.SystemOutput.ForcedSysOut);
260
261
262
263 builder.exec(false);
264 if (context.coloredOutput != null) {
265 builder.color(context.coloredOutput);
266 }
267 },
268 terminal -> doConfigureWithTerminal(context, terminal));
269
270 context.terminal = MessageUtils.getTerminal();
271
272
273 context.closeables.add(MessageUtils::systemUninstall);
274 MessageUtils.registerShutdownHook();
275 if (context.coloredOutput != null) {
276 MessageUtils.setColorEnabled(context.coloredOutput);
277 }
278 }
279
280 protected void doConfigureWithTerminal(C context, Terminal terminal) {
281 Options options = context.invokerRequest.options();
282 if (options.rawStreams().isEmpty() || !options.rawStreams().get()) {
283 MavenSimpleLogger stdout = (MavenSimpleLogger) context.loggerFactory.getLogger("stdout");
284 MavenSimpleLogger stderr = (MavenSimpleLogger) context.loggerFactory.getLogger("stderr");
285 stdout.setLogLevel(LocationAwareLogger.INFO_INT);
286 stderr.setLogLevel(LocationAwareLogger.INFO_INT);
287 System.setOut(new LoggingOutputStream(s -> stdout.info("[stdout] " + s)).printStream());
288 System.setErr(new LoggingOutputStream(s -> stderr.warn("[stderr] " + s)).printStream());
289
290 }
291 }
292
293 protected Consumer<String> determineWriter(C context) {
294 if (context.writer == null) {
295 context.writer = doDetermineWriter(context);
296 }
297 return context.writer;
298 }
299
300 protected Consumer<String> doDetermineWriter(C context) {
301 Options options = context.invokerRequest.options();
302 if (options.logFile().isPresent()) {
303 Path logFile = context.cwdResolver.apply(options.logFile().get());
304 try {
305 PrintWriter printWriter = new PrintWriter(Files.newBufferedWriter(logFile), true);
306 context.closeables.add(printWriter);
307 return printWriter::println;
308 } catch (IOException e) {
309 throw new MavenException("Unable to redirect logging to " + logFile, e);
310 }
311 } else {
312
313
314 return msg -> {
315 PrintWriter pw = context.terminal.writer();
316 pw.println(msg);
317 pw.flush();
318 };
319 }
320 }
321
322 protected void activateLogging(C context) throws Exception {
323 InvokerRequest invokerRequest = context.invokerRequest;
324 Options mavenOptions = invokerRequest.options();
325
326 context.slf4jConfiguration.activate();
327 org.slf4j.Logger l = context.loggerFactory.getLogger(this.getClass().getName());
328 context.logger = (level, message, error) -> l.atLevel(org.slf4j.event.Level.valueOf(level.name()))
329 .setCause(error)
330 .log(message);
331
332 if (mavenOptions.failOnSeverity().isPresent()) {
333 String logLevelThreshold = mavenOptions.failOnSeverity().get();
334 if (context.loggerFactory instanceof LogLevelRecorder recorder) {
335 LogLevelRecorder.Level level =
336 switch (logLevelThreshold.toLowerCase(Locale.ENGLISH)) {
337 case "warn", "warning" -> LogLevelRecorder.Level.WARN;
338 case "error" -> LogLevelRecorder.Level.ERROR;
339 default -> throw new IllegalArgumentException(
340 logLevelThreshold
341 + " is not a valid log severity threshold. Valid severities are WARN/WARNING and ERROR.");
342 };
343 recorder.setMaxLevelAllowed(level);
344 context.logger.info("Enabled to break the build on log level " + logLevelThreshold + ".");
345 } else {
346 context.logger.warn("Expected LoggerFactory to be of type '" + LogLevelRecorder.class.getName()
347 + "', but found '"
348 + context.loggerFactory.getClass().getName() + "' instead. "
349 + "The --fail-on-severity flag will not take effect.");
350 }
351 }
352 }
353
354 protected void helpOrVersionAndMayExit(C context) throws Exception {
355 InvokerRequest invokerRequest = context.invokerRequest;
356 if (invokerRequest.options().help().isPresent()) {
357 Consumer<String> writer = determineWriter(context);
358 invokerRequest.options().displayHelp(context.invokerRequest.parserRequest(), writer);
359 throw new InvokerException.ExitException(0);
360 }
361 if (invokerRequest.options().showVersionAndExit().isPresent()) {
362 showVersion(context);
363 throw new InvokerException.ExitException(0);
364 }
365 }
366
367 protected void showVersion(C context) {
368 Consumer<String> writer = determineWriter(context);
369 InvokerRequest invokerRequest = context.invokerRequest;
370 if (invokerRequest.options().quiet().orElse(false)) {
371 writer.accept(CLIReportingUtils.showVersionMinimal());
372 } else if (invokerRequest.options().verbose().orElse(false)) {
373 writer.accept(CLIReportingUtils.showVersion(
374 ProcessHandle.current().info().commandLine().orElse(null), describe(context.terminal)));
375
376 } else {
377 writer.accept(CLIReportingUtils.showVersion());
378 }
379 }
380
381 protected String describe(Terminal terminal) {
382 if (terminal == null) {
383 return null;
384 }
385 if (terminal instanceof FastTerminal ft) {
386 terminal = ft.getTerminal();
387 }
388 List<String> subs = new ArrayList<>();
389 subs.add("type=" + terminal.getType());
390 if (terminal instanceof TerminalExt te) {
391 subs.add("provider=" + te.getProvider().name());
392 }
393 if (terminal instanceof AbstractPosixTerminal pt) {
394 subs.add("pty=" + pt.getPty().getClass().getName());
395 }
396 return terminal.getClass().getSimpleName() + " (" + String.join(", ", subs) + ")";
397 }
398
399 protected void preCommands(C context) throws Exception {
400 Options mavenOptions = context.invokerRequest.options();
401 boolean verbose = mavenOptions.verbose().orElse(false);
402 boolean version = mavenOptions.showVersion().orElse(false);
403 if (verbose || version) {
404 showVersion(context);
405 }
406 }
407
408 protected void container(C context) throws Exception {
409 context.containerCapsule = createContainerCapsuleFactory().createContainerCapsule(this, context);
410 context.closeables.add(context::closeContainer);
411 context.lookup = context.containerCapsule.getLookup();
412
413
414 org.slf4j.Logger l = context.loggerFactory.getLogger(this.getClass().getName());
415 context.logger = (level, message, error) -> l.atLevel(org.slf4j.event.Level.valueOf(level.name()))
416 .setCause(error)
417 .log(message);
418 }
419
420 protected ContainerCapsuleFactory<C> createContainerCapsuleFactory() {
421 return new PlexusContainerCapsuleFactory<>();
422 }
423
424 protected void postContainer(C context) throws Exception {
425 ProtoSession protoSession = context.protoSession;
426 for (PropertyContributor propertyContributor : context.lookup
427 .lookup(PropertyContributorsHolder.class)
428 .getPropertyContributors()
429 .values()) {
430 protoSession = protoSession.toBuilder()
431 .withUserProperties(propertyContributor.contribute(protoSession))
432 .build();
433 }
434 context.protoSession = protoSession;
435 }
436
437 protected void lookup(C context) throws Exception {}
438
439 protected void init(C context) throws Exception {}
440
441 protected void postCommands(C context) throws Exception {
442 InvokerRequest invokerRequest = context.invokerRequest;
443 Logger logger = context.logger;
444 if (invokerRequest.options().showErrors().orElse(false)) {
445 logger.info("Error stacktraces are turned on.");
446 }
447 if (context.invokerRequest.options().verbose().orElse(false)) {
448 logger.debug("Message scheme: " + (MessageUtils.isColorEnabled() ? "color" : "plain"));
449 if (MessageUtils.isColorEnabled()) {
450 MessageBuilder buff = MessageUtils.builder();
451 buff.a("Message styles: ");
452 buff.trace("trace").a(' ');
453 buff.debug("debug").a(' ');
454 buff.info("info").a(' ');
455 buff.warning("warning").a(' ');
456 buff.error("error").a(' ');
457 buff.success("success").a(' ');
458 buff.failure("failure").a(' ');
459 buff.strong("strong").a(' ');
460 buff.mojo("mojo").a(' ');
461 buff.project("project");
462 logger.debug(buff.toString());
463 }
464 }
465 }
466
467 protected void settings(C context) throws Exception {
468 settings(context, true, context.lookup.lookup(SettingsBuilder.class));
469 }
470
471
472
473
474
475
476
477
478
479 protected void settings(C context, boolean emitSettingsWarnings, SettingsBuilder settingsBuilder) throws Exception {
480 Options mavenOptions = context.invokerRequest.options();
481
482 Path userSettingsFile = null;
483 if (mavenOptions.altUserSettings().isPresent()) {
484 userSettingsFile =
485 context.cwdResolver.apply(mavenOptions.altUserSettings().get());
486
487 if (!Files.isRegularFile(userSettingsFile)) {
488 throw new FileNotFoundException("The specified user settings file does not exist: " + userSettingsFile);
489 }
490 } else {
491 String userSettingsFileStr =
492 context.protoSession.getUserProperties().get(Constants.MAVEN_USER_SETTINGS);
493 if (userSettingsFileStr != null) {
494 userSettingsFile = context.userResolver.apply(userSettingsFileStr);
495 }
496 }
497
498 Path projectSettingsFile = null;
499 if (mavenOptions.altProjectSettings().isPresent()) {
500 projectSettingsFile =
501 context.cwdResolver.apply(mavenOptions.altProjectSettings().get());
502
503 if (!Files.isRegularFile(projectSettingsFile)) {
504 throw new FileNotFoundException(
505 "The specified project settings file does not exist: " + projectSettingsFile);
506 }
507 } else {
508 String projectSettingsFileStr =
509 context.protoSession.getUserProperties().get(Constants.MAVEN_PROJECT_SETTINGS);
510 if (projectSettingsFileStr != null) {
511 projectSettingsFile = context.cwdResolver.apply(projectSettingsFileStr);
512 }
513 }
514
515 Path installationSettingsFile = null;
516 if (mavenOptions.altInstallationSettings().isPresent()) {
517 installationSettingsFile = context.cwdResolver.apply(
518 mavenOptions.altInstallationSettings().get());
519
520 if (!Files.isRegularFile(installationSettingsFile)) {
521 throw new FileNotFoundException(
522 "The specified installation settings file does not exist: " + installationSettingsFile);
523 }
524 } else {
525 String installationSettingsFileStr =
526 context.protoSession.getUserProperties().get(Constants.MAVEN_INSTALLATION_SETTINGS);
527 if (installationSettingsFileStr != null) {
528 installationSettingsFile = context.installationResolver.apply(installationSettingsFileStr);
529 }
530 }
531
532 context.installationSettingsPath = installationSettingsFile;
533 context.projectSettingsPath = projectSettingsFile;
534 context.userSettingsPath = userSettingsFile;
535
536 Function<String, String> interpolationSource = Interpolator.chain(
537 context.protoSession.getUserProperties()::get, context.protoSession.getSystemProperties()::get);
538 SettingsBuilderRequest settingsRequest = SettingsBuilderRequest.builder()
539 .session(context.protoSession)
540 .installationSettingsSource(
541 installationSettingsFile != null && Files.exists(installationSettingsFile)
542 ? Source.fromPath(installationSettingsFile)
543 : null)
544 .projectSettingsSource(
545 projectSettingsFile != null && Files.exists(projectSettingsFile)
546 ? Source.fromPath(projectSettingsFile)
547 : null)
548 .userSettingsSource(
549 userSettingsFile != null && Files.exists(userSettingsFile)
550 ? Source.fromPath(userSettingsFile)
551 : null)
552 .interpolationSource(interpolationSource)
553 .build();
554
555 customizeSettingsRequest(context, settingsRequest);
556
557 context.logger.debug("Reading installation settings from '" + installationSettingsFile + "'");
558 context.logger.debug("Reading project settings from '" + projectSettingsFile + "'");
559 context.logger.debug("Reading user settings from '" + userSettingsFile + "'");
560
561 SettingsBuilderResult settingsResult = settingsBuilder.build(settingsRequest);
562 customizeSettingsResult(context, settingsResult);
563
564 context.effectiveSettings = settingsResult.getEffectiveSettings();
565 context.interactive = mayDisableInteractiveMode(context, context.effectiveSettings.isInteractiveMode());
566 context.localRepositoryPath = localRepositoryPath(context);
567
568 if (emitSettingsWarnings && !settingsResult.getProblems().isEmpty()) {
569 context.logger.info("");
570 context.logger.info(
571 "Some problems were encountered while building the effective settings (use -X to see details)");
572
573 if (context.invokerRequest.options().verbose().orElse(false)) {
574 for (BuilderProblem problem : settingsResult.getProblems()) {
575 context.logger.warn(problem.getMessage() + " @ " + problem.getLocation());
576 }
577 }
578 context.logger.info("");
579 }
580 }
581
582 protected void customizeSettingsRequest(C context, SettingsBuilderRequest settingsBuilderRequest)
583 throws Exception {}
584
585 protected void customizeSettingsResult(C context, SettingsBuilderResult settingsBuilderResult) throws Exception {}
586
587 protected boolean mayDisableInteractiveMode(C context, boolean proposedInteractive) {
588 if (!context.invokerRequest.options().forceInteractive().orElse(false)) {
589 if (context.invokerRequest.options().nonInteractive().orElse(false)) {
590 return false;
591 } else {
592 boolean runningOnCI = isRunningOnCI(context);
593 if (runningOnCI) {
594 context.logger.info(
595 "Making this build non-interactive, because the environment variable CI equals \"true\"."
596 + " Disable this detection by removing that variable or adding --force-interactive.");
597 return false;
598 }
599 }
600 }
601 return proposedInteractive;
602 }
603
604 protected Path localRepositoryPath(C context) {
605
606 String userDefinedLocalRepo = context.protoSession.getUserProperties().get(Constants.MAVEN_REPO_LOCAL);
607 if (userDefinedLocalRepo == null) {
608 userDefinedLocalRepo = context.protoSession.getUserProperties().get(Constants.MAVEN_REPO_LOCAL);
609 if (userDefinedLocalRepo != null) {
610 context.logger.warn("The property '" + Constants.MAVEN_REPO_LOCAL
611 + "' has been set using a JVM system property which is deprecated. "
612 + "The property can be passed as a Maven argument or in the Maven project configuration file,"
613 + "usually located at ${session.rootDirectory}/.mvn/maven.properties.");
614 }
615 }
616 if (userDefinedLocalRepo != null) {
617 return context.cwdResolver.apply(userDefinedLocalRepo);
618 }
619
620 userDefinedLocalRepo = context.effectiveSettings.getLocalRepository();
621 if (userDefinedLocalRepo != null && !userDefinedLocalRepo.isEmpty()) {
622 return context.userResolver.apply(userDefinedLocalRepo);
623 }
624
625 return context.userResolver
626 .apply(context.protoSession.getUserProperties().get(Constants.MAVEN_USER_CONF))
627 .resolve("repository");
628 }
629
630 protected void populateRequest(C context, Lookup lookup, MavenExecutionRequest request) throws Exception {
631 populateRequestFromSettings(request, context.effectiveSettings);
632
633 Options options = context.invokerRequest.options();
634 request.setLoggingLevel(toMavenExecutionRequestLoggingLevel(context.loggerLevel));
635 request.setLocalRepositoryPath(context.localRepositoryPath.toFile());
636 request.setLocalRepository(createLocalArtifactRepository(context.localRepositoryPath));
637
638 request.setInteractiveMode(context.interactive);
639 request.setShowErrors(options.showErrors().orElse(false));
640 request.setBaseDirectory(context.invokerRequest.topDirectory().toFile());
641 request.setSystemProperties(toProperties(context.protoSession.getSystemProperties()));
642 request.setUserProperties(toProperties(context.protoSession.getUserProperties()));
643
644 request.setInstallationSettingsFile(
645 context.installationSettingsPath != null ? context.installationSettingsPath.toFile() : null);
646 request.setProjectSettingsFile(
647 context.projectSettingsPath != null ? context.projectSettingsPath.toFile() : null);
648 request.setUserSettingsFile(context.userSettingsPath != null ? context.userSettingsPath.toFile() : null);
649
650 request.setTopDirectory(context.invokerRequest.topDirectory());
651 if (context.invokerRequest.rootDirectory().isPresent()) {
652 request.setMultiModuleProjectDirectory(
653 context.invokerRequest.rootDirectory().get().toFile());
654 request.setRootDirectory(context.invokerRequest.rootDirectory().get());
655 }
656
657 request.addPluginGroup("org.apache.maven.plugins");
658 request.addPluginGroup("org.codehaus.mojo");
659 }
660
661
662
663
664 @Deprecated
665 private ArtifactRepository createLocalArtifactRepository(Path baseDirectory) {
666 DefaultRepositoryLayout layout = new DefaultRepositoryLayout();
667 ArtifactRepositoryPolicy blah = new ArtifactRepositoryPolicy(
668 true, ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, ArtifactRepositoryPolicy.CHECKSUM_POLICY_IGNORE);
669 return new MavenArtifactRepository(
670 "local", "file://" + baseDirectory.toUri().getRawPath(), layout, blah, blah);
671 }
672
673 protected void populateRequestFromSettings(MavenExecutionRequest request, Settings settings) throws Exception {
674 if (settings == null) {
675 return;
676 }
677 request.setOffline(settings.isOffline());
678 request.setInteractiveMode(settings.isInteractiveMode());
679 request.setPluginGroups(settings.getPluginGroups());
680 request.setLocalRepositoryPath(settings.getLocalRepository());
681 for (Server server : settings.getServers()) {
682 request.addServer(new org.apache.maven.settings.Server(server));
683 }
684
685
686
687
688
689
690
691
692
693
694
695
696
697 for (Proxy proxy : settings.getProxies()) {
698 if (!proxy.isActive()) {
699 continue;
700 }
701 request.addProxy(new org.apache.maven.settings.Proxy(proxy));
702 }
703
704
705
706
707
708
709
710
711
712 for (Mirror mirror : settings.getMirrors()) {
713 request.addMirror(new org.apache.maven.settings.Mirror(mirror));
714 }
715
716 for (Repository remoteRepository : settings.getRepositories()) {
717 try {
718 request.addRemoteRepository(MavenRepositorySystem.buildArtifactRepository(
719 new org.apache.maven.settings.Repository(remoteRepository)));
720 } catch (InvalidRepositoryException e) {
721
722 }
723 }
724
725 for (Repository pluginRepository : settings.getPluginRepositories()) {
726 try {
727 request.addPluginArtifactRepository(MavenRepositorySystem.buildArtifactRepository(
728 new org.apache.maven.settings.Repository(pluginRepository)));
729 } catch (InvalidRepositoryException e) {
730
731 }
732 }
733
734 request.setActiveProfiles(settings.getActiveProfiles());
735 for (Profile rawProfile : settings.getProfiles()) {
736 request.addProfile(
737 new org.apache.maven.model.Profile(SettingsUtilsV4.convertFromSettingsProfile(rawProfile)));
738
739 if (settings.getActiveProfiles().contains(rawProfile.getId())) {
740 List<Repository> remoteRepositories = rawProfile.getRepositories();
741 for (Repository remoteRepository : remoteRepositories) {
742 try {
743 request.addRemoteRepository(MavenRepositorySystem.buildArtifactRepository(
744 new org.apache.maven.settings.Repository(remoteRepository)));
745 } catch (InvalidRepositoryException e) {
746
747 }
748 }
749
750 List<Repository> pluginRepositories = rawProfile.getPluginRepositories();
751 for (Repository pluginRepository : pluginRepositories) {
752 try {
753 request.addPluginArtifactRepository(MavenRepositorySystem.buildArtifactRepository(
754 new org.apache.maven.settings.Repository(pluginRepository)));
755 } catch (InvalidRepositoryException e) {
756
757 }
758 }
759 }
760 }
761 }
762
763 protected int calculateDegreeOfConcurrency(String threadConfiguration) {
764 try {
765 if (threadConfiguration.endsWith("C")) {
766 String str = threadConfiguration.substring(0, threadConfiguration.length() - 1);
767 float coreMultiplier = Float.parseFloat(str);
768
769 if (coreMultiplier <= 0.0f) {
770 throw new IllegalArgumentException("Invalid threads core multiplier value: '" + threadConfiguration
771 + "'. Value must be positive.");
772 }
773
774 int procs = Runtime.getRuntime().availableProcessors();
775 int threads = (int) (coreMultiplier * procs);
776 return threads == 0 ? 1 : threads;
777 } else {
778 int threads = Integer.parseInt(threadConfiguration);
779 if (threads <= 0) {
780 throw new IllegalArgumentException(
781 "Invalid threads value: '" + threadConfiguration + "'. Value must be positive.");
782 }
783 return threads;
784 }
785 } catch (NumberFormatException e) {
786 throw new IllegalArgumentException("Invalid threads value: '" + threadConfiguration
787 + "'. Supported are int and float values ending with C.");
788 }
789 }
790
791 protected boolean isRunningOnCI(C context) {
792 String ciEnv = context.protoSession.getSystemProperties().get("env.CI");
793 return ciEnv != null && !"false".equals(ciEnv);
794 }
795
796 protected abstract int execute(C context) throws Exception;
797 }