1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.cli;
20
21 import java.io.BufferedReader;
22 import java.io.Console;
23 import java.io.File;
24 import java.io.FileNotFoundException;
25 import java.io.FileOutputStream;
26 import java.io.IOException;
27 import java.io.PrintStream;
28 import java.nio.charset.StandardCharsets;
29 import java.nio.file.Files;
30 import java.nio.file.Path;
31 import java.nio.file.Paths;
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.HashSet;
35 import java.util.LinkedHashMap;
36 import java.util.List;
37 import java.util.ListIterator;
38 import java.util.Map;
39 import java.util.Map.Entry;
40 import java.util.Objects;
41 import java.util.Properties;
42 import java.util.ServiceLoader;
43 import java.util.Set;
44 import java.util.StringTokenizer;
45 import java.util.regex.Matcher;
46 import java.util.regex.Pattern;
47 import java.util.stream.Stream;
48
49 import com.google.inject.AbstractModule;
50 import org.apache.commons.cli.CommandLine;
51 import org.apache.commons.cli.Option;
52 import org.apache.commons.cli.ParseException;
53 import org.apache.commons.cli.UnrecognizedOptionException;
54 import org.apache.maven.BuildAbort;
55 import org.apache.maven.InternalErrorException;
56 import org.apache.maven.Maven;
57 import org.apache.maven.building.FileSource;
58 import org.apache.maven.building.Problem;
59 import org.apache.maven.building.Source;
60 import org.apache.maven.cli.configuration.ConfigurationProcessor;
61 import org.apache.maven.cli.configuration.SettingsXmlConfigurationProcessor;
62 import org.apache.maven.cli.event.DefaultEventSpyContext;
63 import org.apache.maven.cli.event.ExecutionEventLogger;
64 import org.apache.maven.cli.internal.BootstrapCoreExtensionManager;
65 import org.apache.maven.cli.internal.extension.model.CoreExtension;
66 import org.apache.maven.cli.internal.extension.model.io.xpp3.CoreExtensionsXpp3Reader;
67 import org.apache.maven.cli.logging.Slf4jConfiguration;
68 import org.apache.maven.cli.logging.Slf4jConfigurationFactory;
69 import org.apache.maven.cli.logging.Slf4jLoggerManager;
70 import org.apache.maven.cli.logging.Slf4jStdoutLogger;
71 import org.apache.maven.cli.transfer.ConsoleMavenTransferListener;
72 import org.apache.maven.cli.transfer.QuietMavenTransferListener;
73 import org.apache.maven.cli.transfer.SimplexTransferListener;
74 import org.apache.maven.cli.transfer.Slf4jMavenTransferListener;
75 import org.apache.maven.eventspy.internal.EventSpyDispatcher;
76 import org.apache.maven.exception.DefaultExceptionHandler;
77 import org.apache.maven.exception.ExceptionHandler;
78 import org.apache.maven.exception.ExceptionSummary;
79 import org.apache.maven.execution.DefaultMavenExecutionRequest;
80 import org.apache.maven.execution.ExecutionListener;
81 import org.apache.maven.execution.MavenExecutionRequest;
82 import org.apache.maven.execution.MavenExecutionRequestPopulationException;
83 import org.apache.maven.execution.MavenExecutionRequestPopulator;
84 import org.apache.maven.execution.MavenExecutionResult;
85 import org.apache.maven.execution.scope.internal.MojoExecutionScopeModule;
86 import org.apache.maven.extension.internal.CoreExports;
87 import org.apache.maven.extension.internal.CoreExtensionEntry;
88 import org.apache.maven.jline.MessageUtils;
89 import org.apache.maven.lifecycle.LifecycleExecutionException;
90 import org.apache.maven.message.MessageBuilder;
91 import org.apache.maven.model.building.ModelProcessor;
92 import org.apache.maven.model.interpolation.ModelInterpolator;
93 import org.apache.maven.model.root.RootLocator;
94 import org.apache.maven.project.MavenProject;
95 import org.apache.maven.properties.internal.EnvironmentUtils;
96 import org.apache.maven.properties.internal.SystemProperties;
97 import org.apache.maven.session.scope.internal.SessionScopeModule;
98 import org.apache.maven.toolchain.building.DefaultToolchainsBuildingRequest;
99 import org.apache.maven.toolchain.building.ToolchainsBuilder;
100 import org.apache.maven.toolchain.building.ToolchainsBuildingResult;
101 import org.codehaus.plexus.ContainerConfiguration;
102 import org.codehaus.plexus.DefaultContainerConfiguration;
103 import org.codehaus.plexus.DefaultPlexusContainer;
104 import org.codehaus.plexus.PlexusConstants;
105 import org.codehaus.plexus.PlexusContainer;
106 import org.codehaus.plexus.classworlds.ClassWorld;
107 import org.codehaus.plexus.classworlds.realm.ClassRealm;
108 import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
109 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
110 import org.codehaus.plexus.interpolation.AbstractValueSource;
111 import org.codehaus.plexus.interpolation.InterpolationException;
112 import org.codehaus.plexus.interpolation.StringSearchInterpolator;
113 import org.codehaus.plexus.logging.LoggerManager;
114 import org.codehaus.plexus.util.StringUtils;
115 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
116 import org.eclipse.aether.DefaultRepositoryCache;
117 import org.eclipse.aether.repository.RepositoryPolicy;
118 import org.eclipse.aether.transfer.TransferListener;
119 import org.slf4j.ILoggerFactory;
120 import org.slf4j.Logger;
121 import org.slf4j.LoggerFactory;
122 import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
123 import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
124 import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
125 import org.sonatype.plexus.components.sec.dispatcher.SecUtil;
126 import org.sonatype.plexus.components.sec.dispatcher.model.SettingsSecurity;
127
128 import static org.apache.maven.cli.CLIManager.COLOR;
129 import static org.apache.maven.cli.ResolveFile.resolveFile;
130 import static org.apache.maven.jline.MessageUtils.builder;
131
132
133
134
135
136
137 public class MavenCli {
138 public static final String LOCAL_REPO_PROPERTY = "maven.repo.local";
139
140 public static final String MULTIMODULE_PROJECT_DIRECTORY = "maven.multiModuleProjectDirectory";
141
142 public static final String USER_HOME = System.getProperty("user.home");
143
144 public static final File USER_MAVEN_CONFIGURATION_HOME = new File(USER_HOME, ".m2");
145
146 public static final File DEFAULT_USER_TOOLCHAINS_FILE = new File(USER_MAVEN_CONFIGURATION_HOME, "toolchains.xml");
147
148 public static final File DEFAULT_GLOBAL_TOOLCHAINS_FILE =
149 new File(System.getProperty("maven.conf"), "toolchains.xml");
150
151 private static final String EXT_CLASS_PATH = "maven.ext.class.path";
152
153 private static final String DOT_MVN = ".mvn";
154
155 private static final String PROJECT_EXTENSIONS_FILENAME = DOT_MVN + "/extensions.xml";
156
157 private static final File USER_EXTENSIONS_FILE = new File(USER_MAVEN_CONFIGURATION_HOME, "extensions.xml");
158
159 public static final File GLOBAL_EXTENSIONS_FILE = new File(System.getProperty("maven.conf"), "extensions.xml");
160
161 private static final String MVN_MAVEN_CONFIG = DOT_MVN + "/maven.config";
162
163
164
165
166
167
168
169 private static final String MAVEN_REPO_CENTRAL_ENV = "env.MAVEN_REPO_CENTRAL";
170
171 public static final String STYLE_COLOR_PROPERTY = "style.color";
172
173 private ClassWorld classWorld;
174
175 private LoggerManager plexusLoggerManager;
176
177 private ILoggerFactory slf4jLoggerFactory;
178
179 private Logger slf4jLogger;
180
181 private EventSpyDispatcher eventSpyDispatcher;
182
183 private ModelProcessor modelProcessor;
184
185 private Maven maven;
186
187 private MavenExecutionRequestPopulator executionRequestPopulator;
188
189 private ToolchainsBuilder toolchainsBuilder;
190
191 private DefaultSecDispatcher dispatcher;
192
193 private Map<String, ConfigurationProcessor> configurationProcessors;
194
195 private CLIManager cliManager;
196
197 private static final Pattern NEXT_LINE = Pattern.compile("\r?\n");
198
199 public MavenCli() {
200 this(null);
201 }
202
203
204 public MavenCli(ClassWorld classWorld) {
205 this.classWorld = classWorld;
206 }
207
208 public static void main(String[] args) {
209 int result = main(args, null);
210
211 System.exit(result);
212 }
213
214 public static int main(String[] args, ClassWorld classWorld) {
215 MavenCli cli = new MavenCli();
216
217 MessageUtils.systemInstall();
218 MessageUtils.registerShutdownHook();
219 int result = cli.doMain(new CliRequest(args, classWorld));
220 MessageUtils.systemUninstall();
221
222 return result;
223 }
224
225
226 public static int doMain(String[] args, ClassWorld classWorld) {
227 MavenCli cli = new MavenCli();
228 return cli.doMain(new CliRequest(args, classWorld));
229 }
230
231
232
233
234
235
236 public int doMain(String[] args, String workingDirectory, PrintStream stdout, PrintStream stderr) {
237 PrintStream oldout = System.out;
238 PrintStream olderr = System.err;
239
240 final Set<String> realms;
241 if (classWorld != null) {
242 realms = new HashSet<>();
243 for (ClassRealm realm : classWorld.getRealms()) {
244 realms.add(realm.getId());
245 }
246 } else {
247 realms = Collections.emptySet();
248 }
249
250 try {
251 if (stdout != null) {
252 MessageUtils.awaitTerminalInitialization();
253 System.setOut(stdout);
254 }
255 if (stderr != null) {
256 MessageUtils.awaitTerminalInitialization();
257 System.setErr(stderr);
258 }
259
260 CliRequest cliRequest = new CliRequest(args, classWorld);
261 cliRequest.workingDirectory = workingDirectory;
262
263 return doMain(cliRequest);
264 } finally {
265 if (classWorld != null) {
266 for (ClassRealm realm : new ArrayList<>(classWorld.getRealms())) {
267 String realmId = realm.getId();
268 if (!realms.contains(realmId)) {
269 try {
270 classWorld.disposeRealm(realmId);
271 } catch (NoSuchRealmException ignored) {
272
273 }
274 }
275 }
276 }
277 System.setOut(oldout);
278 System.setErr(olderr);
279 }
280 }
281
282
283 public int doMain(CliRequest cliRequest) {
284 PlexusContainer localContainer = null;
285 try {
286 initialize(cliRequest);
287 cli(cliRequest);
288 properties(cliRequest);
289 setupGuiceClassLoading();
290 logging(cliRequest);
291 informativeCommands(cliRequest);
292 version(cliRequest);
293 localContainer = container(cliRequest);
294 commands(cliRequest);
295 configure(cliRequest);
296 toolchains(cliRequest);
297 populateRequest(cliRequest);
298 encryption(cliRequest);
299 return execute(cliRequest);
300 } catch (ExitException e) {
301 return e.exitCode;
302 } catch (UnrecognizedOptionException e) {
303
304 return 1;
305 } catch (BuildAbort e) {
306 CLIReportingUtils.showError(slf4jLogger, "ABORTED", e, cliRequest.showErrors);
307
308 return 2;
309 } catch (Exception e) {
310 CLIReportingUtils.showError(slf4jLogger, "Error executing Maven.", e, cliRequest.showErrors);
311
312 return 1;
313 } finally {
314 if (localContainer != null) {
315 localContainer.dispose();
316 }
317 }
318 }
319
320 void initialize(CliRequest cliRequest) throws ExitException {
321 if (cliRequest.workingDirectory == null) {
322 cliRequest.workingDirectory = System.getProperty("user.dir");
323 }
324
325 if (cliRequest.multiModuleProjectDirectory == null) {
326 String basedirProperty = System.getProperty(MULTIMODULE_PROJECT_DIRECTORY);
327 if (basedirProperty == null) {
328 System.err.format("-D%s system property is not set.", MULTIMODULE_PROJECT_DIRECTORY);
329 throw new ExitException(1);
330 }
331 File basedir = basedirProperty != null ? new File(basedirProperty) : new File("");
332 try {
333 cliRequest.multiModuleProjectDirectory = basedir.getCanonicalFile();
334 } catch (IOException e) {
335 cliRequest.multiModuleProjectDirectory = basedir.getAbsoluteFile();
336 }
337 }
338
339
340
341
342 Path topDirectory = Paths.get(cliRequest.workingDirectory);
343 boolean isAltFile = false;
344 for (String arg : cliRequest.args) {
345 if (isAltFile) {
346
347 Path path = topDirectory.resolve(stripLeadingAndTrailingQuotes(arg));
348 if (Files.isDirectory(path)) {
349 topDirectory = path;
350 } else if (Files.isRegularFile(path)) {
351 topDirectory = path.getParent();
352 if (!Files.isDirectory(topDirectory)) {
353 System.err.println("Directory " + topDirectory
354 + " extracted from the -f/--file command-line argument " + arg + " does not exist");
355 throw new ExitException(1);
356 }
357 } else {
358 System.err.println(
359 "POM file " + arg + " specified with the -f/--file command line argument does not exist");
360 throw new ExitException(1);
361 }
362 break;
363 } else {
364
365 isAltFile = arg.equals("-f") || arg.equals("--file");
366 }
367 }
368 topDirectory = getCanonicalPath(topDirectory);
369 cliRequest.request.setTopDirectory(topDirectory);
370
371
372
373
374 RootLocator rootLocator =
375 ServiceLoader.load(RootLocator.class).iterator().next();
376 cliRequest.request.setRootDirectory(rootLocator.findRoot(topDirectory));
377
378
379
380
381
382 String mavenHome = System.getProperty("maven.home");
383
384 if (mavenHome != null) {
385 System.setProperty("maven.home", new File(mavenHome).getAbsolutePath());
386 }
387 }
388
389 void cli(CliRequest cliRequest) throws Exception {
390
391
392
393
394 slf4jLogger = new Slf4jStdoutLogger();
395
396 cliManager = new CLIManager();
397
398 CommandLine mavenConfig = null;
399 try {
400 File configFile = new File(cliRequest.multiModuleProjectDirectory, MVN_MAVEN_CONFIG);
401
402 if (configFile.isFile()) {
403 try (Stream<String> lines = Files.lines(configFile.toPath(), StandardCharsets.UTF_8)) {
404 String[] args = lines.filter(arg -> !arg.isEmpty() && !arg.startsWith("#"))
405 .toArray(String[]::new);
406 mavenConfig = cliManager.parse(args);
407 List<?> unrecognized = mavenConfig.getArgList();
408 if (!unrecognized.isEmpty()) {
409
410 throw new ParseException("Unrecognized maven.config file entries: " + unrecognized);
411 }
412 }
413 }
414 } catch (ParseException e) {
415 System.err.println("Unable to parse maven.config file options: " + e.getMessage());
416 cliManager.displayHelp(System.out);
417 throw e;
418 }
419
420 try {
421 CommandLine mavenCli = cliManager.parse(cliRequest.args);
422 if (mavenConfig == null) {
423 cliRequest.commandLine = mavenCli;
424 } else {
425 cliRequest.commandLine = cliMerge(mavenConfig, mavenCli);
426 }
427 } catch (ParseException e) {
428 System.err.println("Unable to parse command line options: " + e.getMessage());
429 cliManager.displayHelp(System.out);
430 throw e;
431 }
432
433
434 try {
435 if (cliRequest.commandLine.hasOption("llr")) {
436 throw new UnrecognizedOptionException("Option '-llr' is not supported starting with Maven 3.9.1");
437 }
438 } catch (ParseException e) {
439 System.err.println("Unsupported options: " + e.getMessage());
440 cliManager.displayHelp(System.out);
441 throw e;
442 }
443 }
444
445 private void informativeCommands(CliRequest cliRequest) throws ExitException {
446 if (cliRequest.commandLine.hasOption(CLIManager.HELP)) {
447 cliManager.displayHelp(System.out);
448 throw new ExitException(0);
449 }
450
451 if (cliRequest.commandLine.hasOption(CLIManager.VERSION)) {
452 if (cliRequest.commandLine.hasOption(CLIManager.QUIET)) {
453 System.out.println(CLIReportingUtils.showVersionMinimal());
454 } else {
455 System.out.println(CLIReportingUtils.showVersion());
456 }
457 throw new ExitException(0);
458 }
459 }
460
461 private CommandLine cliMerge(CommandLine mavenConfig, CommandLine mavenCli) {
462 CommandLine.Builder commandLineBuilder = new CommandLine.Builder();
463
464
465 for (String arg : mavenCli.getArgs()) {
466 commandLineBuilder.addArg(arg);
467 }
468
469
470
471
472
473
474
475
476
477
478
479 List<Option> setPropertyOptions = new ArrayList<>();
480 for (Option opt : mavenCli.getOptions()) {
481 if (String.valueOf(CLIManager.SET_USER_PROPERTY).equals(opt.getOpt())) {
482 setPropertyOptions.add(opt);
483 } else {
484 commandLineBuilder.addOption(opt);
485 }
486 }
487 for (Option opt : mavenConfig.getOptions()) {
488 commandLineBuilder.addOption(opt);
489 }
490
491 for (Option opt : setPropertyOptions) {
492 commandLineBuilder.addOption(opt);
493 }
494 return commandLineBuilder.build();
495 }
496
497
498
499
500
501 void setupGuiceClassLoading() {
502 if (System.getProperty("guice_custom_class_loading", "").trim().isEmpty()) {
503 System.setProperty("guice_custom_class_loading", "CHILD");
504 }
505 }
506
507
508
509
510 void logging(CliRequest cliRequest) {
511
512 cliRequest.debug = cliRequest.commandLine.hasOption(CLIManager.DEBUG);
513 cliRequest.quiet = !cliRequest.debug && cliRequest.commandLine.hasOption(CLIManager.QUIET);
514 cliRequest.showErrors = cliRequest.debug || cliRequest.commandLine.hasOption(CLIManager.ERRORS);
515
516 slf4jLoggerFactory = LoggerFactory.getILoggerFactory();
517 Slf4jConfiguration slf4jConfiguration = Slf4jConfigurationFactory.getConfiguration(slf4jLoggerFactory);
518
519 if (cliRequest.debug) {
520 cliRequest.request.setLoggingLevel(MavenExecutionRequest.LOGGING_LEVEL_DEBUG);
521 slf4jConfiguration.setRootLoggerLevel(Slf4jConfiguration.Level.DEBUG);
522 } else if (cliRequest.quiet) {
523 cliRequest.request.setLoggingLevel(MavenExecutionRequest.LOGGING_LEVEL_ERROR);
524 slf4jConfiguration.setRootLoggerLevel(Slf4jConfiguration.Level.ERROR);
525 }
526
527
528
529
530 String styleColor = cliRequest.getUserProperties().getProperty(STYLE_COLOR_PROPERTY, "auto");
531 styleColor = cliRequest.commandLine.getOptionValue(COLOR, styleColor);
532 if ("always".equals(styleColor) || "yes".equals(styleColor) || "force".equals(styleColor)) {
533 MessageUtils.setColorEnabled(true);
534 } else if ("never".equals(styleColor) || "no".equals(styleColor) || "none".equals(styleColor)) {
535 MessageUtils.setColorEnabled(false);
536 } else if (!"auto".equals(styleColor) && !"tty".equals(styleColor) && !"if-tty".equals(styleColor)) {
537 throw new IllegalArgumentException(
538 "Invalid color configuration value '" + styleColor + "'. Supported are 'auto', 'always', 'never'.");
539 } else if (cliRequest.commandLine.hasOption(CLIManager.BATCH_MODE)
540 || cliRequest.commandLine.hasOption(CLIManager.LOG_FILE)) {
541 MessageUtils.setColorEnabled(false);
542 } else {
543
544 if (MessageUtils.getTerminal() != null
545 && MessageUtils.getTerminal().getType().startsWith("dumb")) {
546 MessageUtils.setColorEnabled(false);
547 }
548 }
549
550
551 if (cliRequest.commandLine.hasOption(CLIManager.LOG_FILE)) {
552 File logFile = new File(cliRequest.commandLine.getOptionValue(CLIManager.LOG_FILE));
553 logFile = resolveFile(logFile, cliRequest.workingDirectory);
554
555
556
557
558 MessageUtils.awaitTerminalInitialization();
559
560
561 try {
562 PrintStream ps = new PrintStream(new FileOutputStream(logFile));
563 System.setOut(ps);
564 System.setErr(ps);
565 } catch (FileNotFoundException e) {
566
567
568
569 }
570 }
571
572 slf4jConfiguration.activate();
573
574 plexusLoggerManager = new Slf4jLoggerManager();
575 slf4jLogger = slf4jLoggerFactory.getLogger(this.getClass().getName());
576 }
577
578 private void version(CliRequest cliRequest) {
579 if (cliRequest.debug || cliRequest.commandLine.hasOption(CLIManager.SHOW_VERSION)) {
580 System.out.println(CLIReportingUtils.showVersion());
581 }
582 }
583
584 private void commands(CliRequest cliRequest) {
585 if (cliRequest.showErrors) {
586 slf4jLogger.info("Error stacktraces are turned on.");
587 }
588
589 if (MavenExecutionRequest.CHECKSUM_POLICY_WARN.equals(cliRequest.request.getGlobalChecksumPolicy())) {
590 slf4jLogger.info("Disabling strict checksum verification on all artifact downloads.");
591 } else if (MavenExecutionRequest.CHECKSUM_POLICY_FAIL.equals(cliRequest.request.getGlobalChecksumPolicy())) {
592 slf4jLogger.info("Enabling strict checksum verification on all artifact downloads.");
593 }
594
595 if (slf4jLogger.isDebugEnabled()) {
596 slf4jLogger.debug("Message scheme: {}", (MessageUtils.isColorEnabled() ? "color" : "plain"));
597 slf4jLogger.debug("Message terminal: {}", MessageUtils.getTerminal());
598 if (MessageUtils.isColorEnabled()) {
599 MessageBuilder buff = builder();
600 buff.a("Message styles: ");
601 buff.a(builder().trace("trace")).a(' ');
602 buff.a(builder().debug("debug")).a(' ');
603 buff.a(builder().info("info")).a(' ');
604 buff.a(builder().warning("warning")).a(' ');
605 buff.a(builder().error("error")).a(' ');
606 buff.success("success").a(' ');
607 buff.failure("failure").a(' ');
608 buff.strong("strong").a(' ');
609 buff.mojo("mojo").a(' ');
610 buff.project("project");
611 slf4jLogger.debug(buff.toString());
612 }
613 }
614 }
615
616
617
618 void properties(CliRequest cliRequest) throws ExitException {
619 try {
620 populateProperties(cliRequest, cliRequest.systemProperties, cliRequest.userProperties);
621
622 StringSearchInterpolator interpolator =
623 createInterpolator(cliRequest, cliRequest.systemProperties, cliRequest.userProperties);
624 CommandLine.Builder commandLineBuilder = new CommandLine.Builder();
625 for (Option option : cliRequest.commandLine.getOptions()) {
626 if (!String.valueOf(CLIManager.SET_USER_PROPERTY).equals(option.getOpt())) {
627 List<String> values = option.getValuesList();
628 for (ListIterator<String> it = values.listIterator(); it.hasNext(); ) {
629 it.set(interpolator.interpolate(it.next()));
630 }
631 }
632 commandLineBuilder.addOption(option);
633 }
634 for (String arg : cliRequest.commandLine.getArgList()) {
635 commandLineBuilder.addArg(interpolator.interpolate(arg));
636 }
637 cliRequest.commandLine = commandLineBuilder.build();
638 } catch (InterpolationException e) {
639 String message = "ERROR: Could not interpolate properties and/or arguments: " + e.getMessage();
640 System.err.println(message);
641 throw new ExitException(1);
642 } catch (IllegalUseOfUndefinedProperty e) {
643 String message = "ERROR: Illegal use of undefined property: " + e.property;
644 System.err.println(message);
645 try {
646 cliRequest.request.getRootDirectory();
647 } catch (IllegalStateException ex) {
648 System.err.println();
649 System.err.println(RootLocator.UNABLE_TO_FIND_ROOT_PROJECT_MESSAGE);
650 }
651 throw new ExitException(1);
652 }
653 }
654
655 PlexusContainer container(CliRequest cliRequest) throws Exception {
656 if (cliRequest.classWorld == null) {
657 cliRequest.classWorld =
658 new ClassWorld("plexus.core", Thread.currentThread().getContextClassLoader());
659 }
660
661 ClassRealm coreRealm = cliRequest.classWorld.getClassRealm("plexus.core");
662 if (coreRealm == null) {
663 coreRealm = cliRequest.classWorld.getRealms().iterator().next();
664 }
665
666 List<File> extClassPath = parseExtClasspath(cliRequest);
667
668 CoreExtensionEntry coreEntry = CoreExtensionEntry.discoverFrom(coreRealm);
669 List<CoreExtensionEntry> extensions =
670 loadCoreExtensions(cliRequest, coreRealm, coreEntry.getExportedArtifacts());
671
672 ClassRealm containerRealm = setupContainerRealm(cliRequest.classWorld, coreRealm, extClassPath, extensions);
673
674 ContainerConfiguration cc = new DefaultContainerConfiguration()
675 .setClassWorld(cliRequest.classWorld)
676 .setRealm(containerRealm)
677 .setClassPathScanning(PlexusConstants.SCANNING_INDEX)
678 .setAutoWiring(true)
679 .setJSR250Lifecycle(true)
680 .setName("maven");
681
682 Set<String> exportedArtifacts = new HashSet<>(coreEntry.getExportedArtifacts());
683 Set<String> exportedPackages = new HashSet<>(coreEntry.getExportedPackages());
684 for (CoreExtensionEntry extension : extensions) {
685 exportedArtifacts.addAll(extension.getExportedArtifacts());
686 exportedPackages.addAll(extension.getExportedPackages());
687 }
688
689 final CoreExports exports = new CoreExports(containerRealm, exportedArtifacts, exportedPackages);
690
691 DefaultPlexusContainer container = new DefaultPlexusContainer(cc, new AbstractModule() {
692 @Override
693 protected void configure() {
694 bind(ILoggerFactory.class).toInstance(slf4jLoggerFactory);
695 bind(CoreExports.class).toInstance(exports);
696 }
697 });
698
699
700 container.setLookupRealm(null);
701 Thread.currentThread().setContextClassLoader(container.getContainerRealm());
702
703 container.setLoggerManager(plexusLoggerManager);
704
705 for (CoreExtensionEntry extension : extensions) {
706 container.discoverComponents(
707 extension.getClassRealm(),
708 new SessionScopeModule(container),
709 new MojoExecutionScopeModule(container));
710 }
711
712 customizeContainer(container);
713
714 container.getLoggerManager().setThresholds(cliRequest.request.getLoggingLevel());
715
716 eventSpyDispatcher = container.lookup(EventSpyDispatcher.class);
717
718 DefaultEventSpyContext eventSpyContext = new DefaultEventSpyContext();
719 Map<String, Object> data = eventSpyContext.getData();
720 data.put("plexus", container);
721 data.put("workingDirectory", cliRequest.workingDirectory);
722 data.put("systemProperties", cliRequest.systemProperties);
723 data.put("userProperties", cliRequest.userProperties);
724 data.put("versionProperties", CLIReportingUtils.getBuildProperties());
725 eventSpyDispatcher.init(eventSpyContext);
726
727
728 slf4jLogger = slf4jLoggerFactory.getLogger(this.getClass().getName());
729
730 maven = container.lookup(Maven.class);
731
732 executionRequestPopulator = container.lookup(MavenExecutionRequestPopulator.class);
733
734 modelProcessor = createModelProcessor(container);
735
736 configurationProcessors = container.lookupMap(ConfigurationProcessor.class);
737
738 toolchainsBuilder = container.lookup(ToolchainsBuilder.class);
739
740 dispatcher = (DefaultSecDispatcher) container.lookup(SecDispatcher.class, "maven");
741
742 return container;
743 }
744
745 private List<CoreExtensionEntry> loadCoreExtensions(
746 CliRequest cliRequest, ClassRealm containerRealm, Set<String> providedArtifacts) throws Exception {
747 if (cliRequest.multiModuleProjectDirectory == null) {
748 return Collections.emptyList();
749 }
750
751 File projectExtensionsFile = new File(cliRequest.multiModuleProjectDirectory, PROJECT_EXTENSIONS_FILENAME);
752 if (!projectExtensionsFile.isFile() && !USER_EXTENSIONS_FILE.isFile() && !GLOBAL_EXTENSIONS_FILE.isFile()) {
753 return Collections.emptyList();
754 }
755
756 List<CoreExtension> projectExtensions = null;
757 List<CoreExtension> userExtensions = null;
758 List<CoreExtension> globalExtensions = null;
759 if (projectExtensionsFile.isFile()) {
760 projectExtensions = readCoreExtensionsDescriptor(projectExtensionsFile.toPath());
761 }
762 if (USER_EXTENSIONS_FILE.isFile()) {
763 userExtensions = readCoreExtensionsDescriptor(USER_EXTENSIONS_FILE.toPath());
764 }
765 if (GLOBAL_EXTENSIONS_FILE.isFile()) {
766 globalExtensions = readCoreExtensionsDescriptor(GLOBAL_EXTENSIONS_FILE.toPath());
767 }
768
769 if ((projectExtensions == null || projectExtensions.isEmpty())
770 && (userExtensions == null || userExtensions.isEmpty())
771 && (globalExtensions == null || globalExtensions.isEmpty())) {
772 return Collections.emptyList();
773 }
774
775 Map<Path, List<CoreExtension>> configuredCoreExtensions = new LinkedHashMap<>();
776 if (projectExtensions != null && !projectExtensions.isEmpty()) {
777 configuredCoreExtensions.put(projectExtensionsFile.toPath(), projectExtensions);
778 }
779 if (userExtensions != null && !userExtensions.isEmpty()) {
780 configuredCoreExtensions.put(USER_EXTENSIONS_FILE.toPath(), userExtensions);
781 }
782 if (globalExtensions != null && !globalExtensions.isEmpty()) {
783 configuredCoreExtensions.put(GLOBAL_EXTENSIONS_FILE.toPath(), globalExtensions);
784 }
785
786 List<CoreExtension> extensions = selectCoreExtensions(configuredCoreExtensions);
787
788 ContainerConfiguration cc = new DefaultContainerConfiguration()
789 .setClassWorld(cliRequest.classWorld)
790 .setRealm(containerRealm)
791 .setClassPathScanning(PlexusConstants.SCANNING_INDEX)
792 .setAutoWiring(true)
793 .setJSR250Lifecycle(true)
794 .setName("maven");
795
796 DefaultPlexusContainer container = new DefaultPlexusContainer(cc, new AbstractModule() {
797 @Override
798 protected void configure() {
799 bind(ILoggerFactory.class).toInstance(slf4jLoggerFactory);
800 }
801 });
802
803 try {
804 container.setLookupRealm(null);
805
806 container.setLoggerManager(plexusLoggerManager);
807
808 container.getLoggerManager().setThresholds(cliRequest.request.getLoggingLevel());
809
810 Thread.currentThread().setContextClassLoader(container.getContainerRealm());
811
812 executionRequestPopulator = container.lookup(MavenExecutionRequestPopulator.class);
813
814 configurationProcessors = container.lookupMap(ConfigurationProcessor.class);
815
816 configure(cliRequest);
817
818 MavenExecutionRequest request = DefaultMavenExecutionRequest.copy(cliRequest.request);
819
820 request = populateRequest(cliRequest, request);
821
822 request = executionRequestPopulator.populateDefaults(request);
823
824 BootstrapCoreExtensionManager resolver = container.lookup(BootstrapCoreExtensionManager.class);
825
826 return Collections.unmodifiableList(resolver.loadCoreExtensions(request, providedArtifacts, extensions));
827
828 } finally {
829 executionRequestPopulator = null;
830 container.dispose();
831 }
832 }
833
834 private List<CoreExtension> readCoreExtensionsDescriptor(Path extensionsFile)
835 throws IOException, XmlPullParserException {
836 CoreExtensionsXpp3Reader parser = new CoreExtensionsXpp3Reader();
837 try (BufferedReader is = Files.newBufferedReader(extensionsFile, StandardCharsets.UTF_8)) {
838 return parser.read(is).getExtensions();
839 }
840 }
841
842 private List<CoreExtension> selectCoreExtensions(Map<Path, List<CoreExtension>> configuredCoreExtensions) {
843 slf4jLogger.debug("Configured core extensions (in precedence order):");
844 for (Map.Entry<Path, List<CoreExtension>> source : configuredCoreExtensions.entrySet()) {
845 slf4jLogger.debug("* Source file: {}", source.getKey());
846 for (CoreExtension extension : source.getValue()) {
847 slf4jLogger.debug(" - {} -> {}", extension.getId(), source.getKey());
848 }
849 }
850
851 LinkedHashMap<String, CoreExtension> selectedExtensions = new LinkedHashMap<>();
852 List<String> conflicts = new ArrayList<>();
853 for (Map.Entry<Path, List<CoreExtension>> coreExtensions : configuredCoreExtensions.entrySet()) {
854 for (CoreExtension coreExtension : coreExtensions.getValue()) {
855 String key = coreExtension.getGroupId() + ":" + coreExtension.getArtifactId();
856 CoreExtension conflict = selectedExtensions.putIfAbsent(key, coreExtension);
857 if (conflict != null && !Objects.equals(coreExtension.getVersion(), conflict.getVersion())) {
858 conflicts.add(String.format(
859 "Conflicting extension %s: %s vs %s in %s",
860 key, coreExtension.getVersion(), conflict.getVersion(), coreExtensions.getKey()));
861 }
862 }
863 }
864 if (!conflicts.isEmpty()) {
865 slf4jLogger.warn("Found {} extension conflict(s):", conflicts.size());
866 for (String conflict : conflicts) {
867 slf4jLogger.warn("* {}", conflict);
868 }
869 slf4jLogger.warn("");
870 slf4jLogger.warn(
871 "Order of core extensions precedence is project > user > installation. Selected extensions are:");
872 for (CoreExtension extension : selectedExtensions.values()) {
873 slf4jLogger.warn("* {}", extension.getId());
874 }
875 }
876
877 slf4jLogger.debug("Selected core extensions (in loading order):");
878 for (CoreExtension source : selectedExtensions.values()) {
879 slf4jLogger.debug("* {}: ", source.getId());
880 }
881 return new ArrayList<>(selectedExtensions.values());
882 }
883
884 private ClassRealm setupContainerRealm(
885 ClassWorld classWorld, ClassRealm coreRealm, List<File> extClassPath, List<CoreExtensionEntry> extensions)
886 throws Exception {
887 if (!extClassPath.isEmpty() || !extensions.isEmpty()) {
888 ClassRealm extRealm = classWorld.newRealm("maven.ext", null);
889
890 extRealm.setParentRealm(coreRealm);
891
892 slf4jLogger.debug("Populating class realm {}", extRealm.getId());
893
894 for (File file : extClassPath) {
895 slf4jLogger.debug(" Included {}", file);
896
897 extRealm.addURL(file.toURI().toURL());
898 }
899
900 for (CoreExtensionEntry entry : reverse(extensions)) {
901 Set<String> exportedPackages = entry.getExportedPackages();
902 ClassRealm realm = entry.getClassRealm();
903 for (String exportedPackage : exportedPackages) {
904 extRealm.importFrom(realm, exportedPackage);
905 }
906 if (exportedPackages.isEmpty()) {
907
908 extRealm.importFrom(realm, realm.getId());
909 }
910 }
911
912 return extRealm;
913 }
914
915 return coreRealm;
916 }
917
918 private static <T> List<T> reverse(List<T> list) {
919 List<T> copy = new ArrayList<>(list);
920 Collections.reverse(copy);
921 return copy;
922 }
923
924 private List<File> parseExtClasspath(CliRequest cliRequest) {
925 String extClassPath = cliRequest.userProperties.getProperty(EXT_CLASS_PATH);
926 if (extClassPath == null) {
927 extClassPath = cliRequest.systemProperties.getProperty(EXT_CLASS_PATH);
928 }
929
930 List<File> jars = new ArrayList<>();
931
932 if (StringUtils.isNotEmpty(extClassPath)) {
933 for (String jar : StringUtils.split(extClassPath, File.pathSeparator)) {
934 File file = resolveFile(new File(jar), cliRequest.workingDirectory);
935
936 slf4jLogger.debug(" Included {}", file);
937
938 jars.add(file);
939 }
940 }
941
942 return jars;
943 }
944
945
946
947
948 private void encryption(CliRequest cliRequest) throws Exception {
949 if (cliRequest.commandLine.hasOption(CLIManager.ENCRYPT_MASTER_PASSWORD)) {
950 String passwd = cliRequest.commandLine.getOptionValue(CLIManager.ENCRYPT_MASTER_PASSWORD);
951
952 if (passwd == null) {
953 Console cons = System.console();
954 char[] password = (cons == null) ? null : cons.readPassword("Master password: ");
955 if (password != null) {
956
957 passwd = String.copyValueOf(password);
958
959
960 java.util.Arrays.fill(password, ' ');
961 }
962 }
963
964 DefaultPlexusCipher cipher = new DefaultPlexusCipher();
965
966 System.out.println(cipher.encryptAndDecorate(passwd, DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION));
967
968 throw new ExitException(0);
969 } else if (cliRequest.commandLine.hasOption(CLIManager.ENCRYPT_PASSWORD)) {
970 String passwd = cliRequest.commandLine.getOptionValue(CLIManager.ENCRYPT_PASSWORD);
971
972 if (passwd == null) {
973 Console cons = System.console();
974 char[] password = (cons == null) ? null : cons.readPassword("Password: ");
975 if (password != null) {
976
977 passwd = String.copyValueOf(password);
978
979
980 java.util.Arrays.fill(password, ' ');
981 }
982 }
983
984 String configurationFile = dispatcher.getConfigurationFile();
985
986 if (configurationFile.startsWith("~")) {
987 configurationFile = System.getProperty("user.home") + configurationFile.substring(1);
988 }
989
990 String file = System.getProperty(DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION, configurationFile);
991
992 String master = null;
993
994 SettingsSecurity sec = SecUtil.read(file, true);
995 if (sec != null) {
996 master = sec.getMaster();
997 }
998
999 if (master == null) {
1000 throw new IllegalStateException("Master password is not set in the setting security file: " + file);
1001 }
1002
1003 DefaultPlexusCipher cipher = new DefaultPlexusCipher();
1004 String masterPasswd = cipher.decryptDecorated(master, DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION);
1005 System.out.println(cipher.encryptAndDecorate(passwd, masterPasswd));
1006
1007 throw new ExitException(0);
1008 }
1009 }
1010
1011 private int execute(CliRequest cliRequest) throws MavenExecutionRequestPopulationException {
1012 MavenExecutionRequest request = executionRequestPopulator.populateDefaults(cliRequest.request);
1013 request.setRepositoryCache(new DefaultRepositoryCache());
1014
1015 eventSpyDispatcher.onEvent(request);
1016
1017 MavenExecutionResult result = maven.execute(request);
1018
1019 eventSpyDispatcher.onEvent(result);
1020
1021 eventSpyDispatcher.close();
1022
1023 if (result.hasExceptions()) {
1024 ExceptionHandler handler = new DefaultExceptionHandler();
1025
1026 Map<String, String> references = new LinkedHashMap<>();
1027
1028 MavenProject project = null;
1029
1030 for (Throwable exception : result.getExceptions()) {
1031 ExceptionSummary summary = handler.handleException(exception);
1032
1033 logSummary(summary, references, "", cliRequest.showErrors);
1034
1035 if (project == null && exception instanceof LifecycleExecutionException) {
1036 project = ((LifecycleExecutionException) exception).getProject();
1037 }
1038 }
1039
1040 slf4jLogger.error("");
1041
1042 if (!cliRequest.showErrors) {
1043 slf4jLogger.error(
1044 "To see the full stack trace of the errors, re-run Maven with the {} switch.",
1045 builder().strong("-e"));
1046 }
1047 if (!slf4jLogger.isDebugEnabled()) {
1048 slf4jLogger.error(
1049 "Re-run Maven using the {} switch to enable full debug logging.",
1050 builder().strong("-X"));
1051 }
1052
1053 if (!references.isEmpty()) {
1054 slf4jLogger.error("");
1055 slf4jLogger.error("For more information about the errors and possible solutions"
1056 + ", please read the following articles:");
1057
1058 for (Map.Entry<String, String> entry : references.entrySet()) {
1059 slf4jLogger.error("{} {}", builder().strong(entry.getValue()), entry.getKey());
1060 }
1061 }
1062
1063 if (project != null
1064 && !project.equals(result.getTopologicallySortedProjects().get(0))) {
1065 slf4jLogger.error("");
1066 slf4jLogger.error("After correcting the problems, you can resume the build with the command");
1067 slf4jLogger.error(builder()
1068 .a(" ")
1069 .strong("mvn <args> -rf " + getResumeFrom(result.getTopologicallySortedProjects(), project))
1070 .toString());
1071 }
1072
1073 if (MavenExecutionRequest.REACTOR_FAIL_NEVER.equals(cliRequest.request.getReactorFailureBehavior())) {
1074 slf4jLogger.info("Build failures were ignored.");
1075
1076 return 0;
1077 } else {
1078 return 1;
1079 }
1080 } else {
1081 return 0;
1082 }
1083 }
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101 private String getResumeFrom(List<MavenProject> mavenProjects, MavenProject failedProject) {
1102 for (MavenProject buildProject : mavenProjects) {
1103 if (failedProject.getArtifactId().equals(buildProject.getArtifactId())
1104 && !failedProject.equals(buildProject)) {
1105 return failedProject.getGroupId() + ":" + failedProject.getArtifactId();
1106 }
1107 }
1108 return ":" + failedProject.getArtifactId();
1109 }
1110
1111 private void logSummary(
1112 ExceptionSummary summary, Map<String, String> references, String indent, boolean showErrors) {
1113 String referenceKey = "";
1114
1115 if (StringUtils.isNotEmpty(summary.getReference())) {
1116 referenceKey = references.get(summary.getReference());
1117 if (referenceKey == null) {
1118 referenceKey = "[Help " + (references.size() + 1) + "]";
1119 references.put(summary.getReference(), referenceKey);
1120 }
1121 }
1122
1123 String msg = summary.getMessage();
1124
1125 if (StringUtils.isNotEmpty(referenceKey)) {
1126 if (msg.indexOf('\n') < 0) {
1127 msg += " -> " + builder().strong(referenceKey);
1128 } else {
1129 msg += "\n-> " + builder().strong(referenceKey);
1130 }
1131 }
1132
1133 String[] lines = NEXT_LINE.split(msg);
1134 String currentColor = "";
1135
1136 for (int i = 0; i < lines.length; i++) {
1137
1138 String line = currentColor + lines[i];
1139
1140
1141 Matcher matcher = LAST_ANSI_SEQUENCE.matcher(line);
1142 String nextColor = "";
1143 if (matcher.find()) {
1144 nextColor = matcher.group(1);
1145 if (ANSI_RESET.equals(nextColor)) {
1146
1147 nextColor = "";
1148 }
1149 }
1150
1151
1152 line = indent + line + ("".equals(nextColor) ? "" : ANSI_RESET);
1153
1154 if ((i == lines.length - 1) && (showErrors || (summary.getException() instanceof InternalErrorException))) {
1155 slf4jLogger.error(line, summary.getException());
1156 } else {
1157 slf4jLogger.error(line);
1158 }
1159
1160 currentColor = nextColor;
1161 }
1162
1163 indent += " ";
1164
1165 for (ExceptionSummary child : summary.getChildren()) {
1166 logSummary(child, references, indent, showErrors);
1167 }
1168 }
1169
1170 private static final Pattern LAST_ANSI_SEQUENCE = Pattern.compile("(\u001B\\[[;\\d]*[ -/]*[@-~])[^\u001B]*$");
1171
1172 private static final String ANSI_RESET = "\u001B\u005Bm";
1173
1174 private void configure(CliRequest cliRequest) throws Exception {
1175
1176
1177
1178
1179
1180
1181 cliRequest.request.setEventSpyDispatcher(eventSpyDispatcher);
1182
1183
1184
1185
1186
1187
1188
1189
1190 int userSuppliedConfigurationProcessorCount = configurationProcessors.size() - 1;
1191
1192 if (userSuppliedConfigurationProcessorCount == 0) {
1193
1194
1195
1196
1197 configurationProcessors.get(SettingsXmlConfigurationProcessor.HINT).process(cliRequest);
1198 } else if (userSuppliedConfigurationProcessorCount == 1) {
1199
1200
1201
1202 for (Entry<String, ConfigurationProcessor> entry : configurationProcessors.entrySet()) {
1203 String hint = entry.getKey();
1204 if (!hint.equals(SettingsXmlConfigurationProcessor.HINT)) {
1205 ConfigurationProcessor configurationProcessor = entry.getValue();
1206 configurationProcessor.process(cliRequest);
1207 }
1208 }
1209 } else if (userSuppliedConfigurationProcessorCount > 1) {
1210
1211
1212
1213 StringBuilder sb = new StringBuilder(String.format(
1214 "\nThere can only be one user supplied ConfigurationProcessor, there are %s:\n\n",
1215 userSuppliedConfigurationProcessorCount));
1216 for (Entry<String, ConfigurationProcessor> entry : configurationProcessors.entrySet()) {
1217 String hint = entry.getKey();
1218 if (!hint.equals(SettingsXmlConfigurationProcessor.HINT)) {
1219 ConfigurationProcessor configurationProcessor = entry.getValue();
1220 sb.append(String.format(
1221 "%s\n", configurationProcessor.getClass().getName()));
1222 }
1223 }
1224 sb.append("\n");
1225 throw new Exception(sb.toString());
1226 }
1227 }
1228
1229 void toolchains(CliRequest cliRequest) throws Exception {
1230 File userToolchainsFile;
1231
1232 if (cliRequest.commandLine.hasOption(CLIManager.ALTERNATE_USER_TOOLCHAINS)) {
1233 userToolchainsFile = new File(cliRequest.commandLine.getOptionValue(CLIManager.ALTERNATE_USER_TOOLCHAINS));
1234 userToolchainsFile = resolveFile(userToolchainsFile, cliRequest.workingDirectory);
1235
1236 if (!userToolchainsFile.isFile()) {
1237 throw new FileNotFoundException(
1238 "The specified user toolchains file does not exist: " + userToolchainsFile);
1239 }
1240 } else {
1241 userToolchainsFile = DEFAULT_USER_TOOLCHAINS_FILE;
1242 }
1243
1244 File globalToolchainsFile;
1245
1246 if (cliRequest.commandLine.hasOption(CLIManager.ALTERNATE_GLOBAL_TOOLCHAINS)) {
1247 globalToolchainsFile =
1248 new File(cliRequest.commandLine.getOptionValue(CLIManager.ALTERNATE_GLOBAL_TOOLCHAINS));
1249 globalToolchainsFile = resolveFile(globalToolchainsFile, cliRequest.workingDirectory);
1250
1251 if (!globalToolchainsFile.isFile()) {
1252 throw new FileNotFoundException(
1253 "The specified global toolchains file does not exist: " + globalToolchainsFile);
1254 }
1255 } else {
1256 globalToolchainsFile = DEFAULT_GLOBAL_TOOLCHAINS_FILE;
1257 }
1258
1259 cliRequest.request.setGlobalToolchainsFile(globalToolchainsFile);
1260 cliRequest.request.setUserToolchainsFile(userToolchainsFile);
1261
1262 DefaultToolchainsBuildingRequest toolchainsRequest = new DefaultToolchainsBuildingRequest();
1263 if (globalToolchainsFile.isFile()) {
1264 toolchainsRequest.setGlobalToolchainsSource(new FileSource(globalToolchainsFile));
1265 }
1266 if (userToolchainsFile.isFile()) {
1267 toolchainsRequest.setUserToolchainsSource(new FileSource(userToolchainsFile));
1268 }
1269
1270 eventSpyDispatcher.onEvent(toolchainsRequest);
1271
1272 slf4jLogger.debug(
1273 "Reading global toolchains from {}",
1274 getLocation(toolchainsRequest.getGlobalToolchainsSource(), globalToolchainsFile));
1275 slf4jLogger.debug(
1276 "Reading user toolchains from {}",
1277 getLocation(toolchainsRequest.getUserToolchainsSource(), userToolchainsFile));
1278
1279 ToolchainsBuildingResult toolchainsResult = toolchainsBuilder.build(toolchainsRequest);
1280
1281 eventSpyDispatcher.onEvent(toolchainsResult);
1282
1283 executionRequestPopulator.populateFromToolchains(cliRequest.request, toolchainsResult.getEffectiveToolchains());
1284
1285 if (!toolchainsResult.getProblems().isEmpty() && slf4jLogger.isWarnEnabled()) {
1286 slf4jLogger.warn("");
1287 slf4jLogger.warn("Some problems were encountered while building the effective toolchains");
1288
1289 for (Problem problem : toolchainsResult.getProblems()) {
1290 slf4jLogger.warn("{} @ {}", problem.getMessage(), problem.getLocation());
1291 }
1292
1293 slf4jLogger.warn("");
1294 }
1295 }
1296
1297 private Object getLocation(Source source, File defaultLocation) {
1298 if (source != null) {
1299 return source.getLocation();
1300 }
1301 return defaultLocation;
1302 }
1303
1304 private MavenExecutionRequest populateRequest(CliRequest cliRequest) {
1305 return populateRequest(cliRequest, cliRequest.request);
1306 }
1307
1308 @SuppressWarnings("checkstyle:methodlength")
1309 private MavenExecutionRequest populateRequest(CliRequest cliRequest, MavenExecutionRequest request) {
1310 CommandLine commandLine = cliRequest.commandLine;
1311 String workingDirectory = cliRequest.workingDirectory;
1312 boolean quiet = cliRequest.quiet;
1313 boolean showErrors = cliRequest.showErrors;
1314
1315 String[] deprecatedOptions = {"up", "npu", "cpu", "npr"};
1316 for (String deprecatedOption : deprecatedOptions) {
1317 if (commandLine.hasOption(deprecatedOption)) {
1318 slf4jLogger.warn(
1319 "Command line option -{} is deprecated and will be removed in future Maven versions.",
1320 deprecatedOption);
1321 }
1322 }
1323
1324
1325
1326
1327
1328
1329 if (commandLine.hasOption(CLIManager.BATCH_MODE)) {
1330 request.setInteractiveMode(false);
1331 }
1332
1333 boolean noSnapshotUpdates = false;
1334 if (commandLine.hasOption(CLIManager.SUPRESS_SNAPSHOT_UPDATES)) {
1335 noSnapshotUpdates = true;
1336 }
1337
1338 boolean updateSnapshots = false;
1339 if (commandLine.hasOption(CLIManager.UPDATE_SNAPSHOTS)) {
1340 updateSnapshots = true;
1341 }
1342
1343 String artifactsUpdatePolicy = null;
1344 String metadataUpdatePolicy = null;
1345 if (commandLine.hasOption(CLIManager.UPDATE_ARTIFACTS)) {
1346 artifactsUpdatePolicy = RepositoryPolicy.UPDATE_POLICY_ALWAYS;
1347 }
1348 if (artifactsUpdatePolicy == null && commandLine.hasOption(CLIManager.ARTIFACTS_UPDATE_POLICY)) {
1349 artifactsUpdatePolicy = commandLine.getOptionValue(CLIManager.ARTIFACTS_UPDATE_POLICY);
1350 }
1351 if (commandLine.hasOption(CLIManager.UPDATE_METADATA)) {
1352 metadataUpdatePolicy = RepositoryPolicy.UPDATE_POLICY_ALWAYS;
1353 }
1354 if (metadataUpdatePolicy == null && commandLine.hasOption(CLIManager.METADATA_UPDATE_POLICY)) {
1355 metadataUpdatePolicy = commandLine.getOptionValue(CLIManager.METADATA_UPDATE_POLICY);
1356 }
1357
1358
1359
1360
1361
1362 List<String> goals = commandLine.getArgList();
1363
1364 boolean recursive = true;
1365
1366
1367 String reactorFailureBehaviour = MavenExecutionRequest.REACTOR_FAIL_FAST;
1368
1369 if (commandLine.hasOption(CLIManager.NON_RECURSIVE)) {
1370 recursive = false;
1371 }
1372
1373 if (commandLine.hasOption(CLIManager.FAIL_FAST)) {
1374 reactorFailureBehaviour = MavenExecutionRequest.REACTOR_FAIL_FAST;
1375 } else if (commandLine.hasOption(CLIManager.FAIL_AT_END)) {
1376 reactorFailureBehaviour = MavenExecutionRequest.REACTOR_FAIL_AT_END;
1377 } else if (commandLine.hasOption(CLIManager.FAIL_NEVER)) {
1378 reactorFailureBehaviour = MavenExecutionRequest.REACTOR_FAIL_NEVER;
1379 }
1380
1381 if (commandLine.hasOption(CLIManager.OFFLINE)) {
1382 request.setOffline(true);
1383 }
1384
1385 String globalChecksumPolicy = null;
1386
1387 if (commandLine.hasOption(CLIManager.CHECKSUM_FAILURE_POLICY)) {
1388 globalChecksumPolicy = MavenExecutionRequest.CHECKSUM_POLICY_FAIL;
1389 } else if (commandLine.hasOption(CLIManager.CHECKSUM_WARNING_POLICY)) {
1390 globalChecksumPolicy = MavenExecutionRequest.CHECKSUM_POLICY_WARN;
1391 }
1392
1393 File baseDirectory = new File(workingDirectory, "").getAbsoluteFile();
1394
1395
1396
1397
1398
1399 List<String> activeProfiles = new ArrayList<>();
1400
1401 List<String> inactiveProfiles = new ArrayList<>();
1402
1403 if (commandLine.hasOption(CLIManager.ACTIVATE_PROFILES)) {
1404 String[] profileOptionValues = commandLine.getOptionValues(CLIManager.ACTIVATE_PROFILES);
1405 if (profileOptionValues != null) {
1406 for (String profileOptionValue : profileOptionValues) {
1407 StringTokenizer profileTokens = new StringTokenizer(profileOptionValue, ",");
1408
1409 while (profileTokens.hasMoreTokens()) {
1410 String profileAction = profileTokens.nextToken().trim();
1411
1412 if (profileAction.startsWith("-") || profileAction.startsWith("!")) {
1413 inactiveProfiles.add(profileAction.substring(1));
1414 } else if (profileAction.startsWith("+")) {
1415 activeProfiles.add(profileAction.substring(1));
1416 } else {
1417 activeProfiles.add(profileAction);
1418 }
1419 }
1420 }
1421 }
1422 }
1423
1424 TransferListener transferListener;
1425
1426 if (quiet || cliRequest.commandLine.hasOption(CLIManager.NO_TRANSFER_PROGRESS)) {
1427 transferListener = new QuietMavenTransferListener();
1428 } else if (request.isInteractiveMode() && !cliRequest.commandLine.hasOption(CLIManager.LOG_FILE)) {
1429
1430
1431
1432
1433 transferListener = getConsoleTransferListener(cliRequest.commandLine.hasOption(CLIManager.DEBUG));
1434 } else {
1435 transferListener = getBatchTransferListener();
1436 }
1437
1438 ExecutionListener executionListener = new ExecutionEventLogger();
1439 if (eventSpyDispatcher != null) {
1440 executionListener = eventSpyDispatcher.chainListener(executionListener);
1441 }
1442
1443 String alternatePomFile = null;
1444 if (commandLine.hasOption(CLIManager.ALTERNATE_POM_FILE)) {
1445 alternatePomFile = commandLine.getOptionValue(CLIManager.ALTERNATE_POM_FILE);
1446 }
1447
1448 request.setBaseDirectory(baseDirectory)
1449 .setGoals(goals)
1450 .setSystemProperties(cliRequest.systemProperties)
1451 .setUserProperties(cliRequest.userProperties)
1452 .setReactorFailureBehavior(reactorFailureBehaviour)
1453 .setRecursive(recursive)
1454 .setShowErrors(showErrors)
1455 .addActiveProfiles(activeProfiles)
1456 .addInactiveProfiles(inactiveProfiles)
1457 .setExecutionListener(executionListener)
1458 .setTransferListener(transferListener)
1459 .setUpdateSnapshots(updateSnapshots)
1460 .setNoSnapshotUpdates(noSnapshotUpdates)
1461 .setArtifactsUpdatePolicy(artifactsUpdatePolicy)
1462 .setMetadataUpdatePolicy(metadataUpdatePolicy)
1463 .setGlobalChecksumPolicy(globalChecksumPolicy)
1464 .setMultiModuleProjectDirectory(cliRequest.multiModuleProjectDirectory);
1465
1466 if (alternatePomFile != null) {
1467 File pom = resolveFile(new File(alternatePomFile), workingDirectory);
1468 if (pom.isDirectory()) {
1469 pom = new File(pom, "pom.xml");
1470 }
1471
1472 request.setPom(pom);
1473 } else if (modelProcessor != null) {
1474 File pom = modelProcessor.locatePom(baseDirectory);
1475
1476 if (pom.isFile()) {
1477 request.setPom(pom);
1478 }
1479 }
1480
1481 if ((request.getPom() != null) && (request.getPom().getParentFile() != null)) {
1482 request.setBaseDirectory(request.getPom().getParentFile());
1483 }
1484
1485 if (commandLine.hasOption(CLIManager.RESUME_FROM)) {
1486 request.setResumeFrom(commandLine.getOptionValue(CLIManager.RESUME_FROM));
1487 }
1488
1489 if (commandLine.hasOption(CLIManager.PROJECT_LIST)) {
1490 String[] projectOptionValues = commandLine.getOptionValues(CLIManager.PROJECT_LIST);
1491
1492 List<String> inclProjects = new ArrayList<>();
1493 List<String> exclProjects = new ArrayList<>();
1494
1495 if (projectOptionValues != null) {
1496 for (String projectOptionValue : projectOptionValues) {
1497 StringTokenizer projectTokens = new StringTokenizer(projectOptionValue, ",");
1498
1499 while (projectTokens.hasMoreTokens()) {
1500 String projectAction = projectTokens.nextToken().trim();
1501
1502 if (projectAction.startsWith("-") || projectAction.startsWith("!")) {
1503 exclProjects.add(projectAction.substring(1));
1504 } else if (projectAction.startsWith("+")) {
1505 inclProjects.add(projectAction.substring(1));
1506 } else {
1507 inclProjects.add(projectAction);
1508 }
1509 }
1510 }
1511 }
1512
1513 request.setSelectedProjects(inclProjects);
1514 request.setExcludedProjects(exclProjects);
1515 }
1516
1517 if (commandLine.hasOption(CLIManager.ALSO_MAKE) && !commandLine.hasOption(CLIManager.ALSO_MAKE_DEPENDENTS)) {
1518 request.setMakeBehavior(MavenExecutionRequest.REACTOR_MAKE_UPSTREAM);
1519 } else if (!commandLine.hasOption(CLIManager.ALSO_MAKE)
1520 && commandLine.hasOption(CLIManager.ALSO_MAKE_DEPENDENTS)) {
1521 request.setMakeBehavior(MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM);
1522 } else if (commandLine.hasOption(CLIManager.ALSO_MAKE)
1523 && commandLine.hasOption(CLIManager.ALSO_MAKE_DEPENDENTS)) {
1524 request.setMakeBehavior(MavenExecutionRequest.REACTOR_MAKE_BOTH);
1525 }
1526
1527 String localRepoProperty = request.getUserProperties().getProperty(MavenCli.LOCAL_REPO_PROPERTY);
1528
1529
1530
1531 if (localRepoProperty == null) {
1532 localRepoProperty = request.getSystemProperties().getProperty(MavenCli.LOCAL_REPO_PROPERTY);
1533 }
1534
1535 if (localRepoProperty != null) {
1536 request.setLocalRepositoryPath(localRepoProperty);
1537 }
1538
1539 request.setCacheNotFound(true);
1540 request.setCacheTransferError(false);
1541 request.setIgnoreTransitiveRepositories(commandLine.hasOption(CLIManager.IGNORE_TRANSITIVE_REPOSITORIES));
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551 final String threadConfiguration =
1552 commandLine.hasOption(CLIManager.THREADS) ? commandLine.getOptionValue(CLIManager.THREADS) : null;
1553
1554 if (threadConfiguration != null) {
1555 int degreeOfConcurrency = calculateDegreeOfConcurrency(threadConfiguration);
1556 if (degreeOfConcurrency > 1) {
1557 request.setBuilderId("multithreaded");
1558 request.setDegreeOfConcurrency(degreeOfConcurrency);
1559 }
1560 }
1561
1562
1563
1564
1565 if (commandLine.hasOption(CLIManager.BUILDER)) {
1566 request.setBuilderId(commandLine.getOptionValue(CLIManager.BUILDER));
1567 }
1568
1569 return request;
1570 }
1571
1572 int calculateDegreeOfConcurrency(String originalThreadConfiguration) {
1573 String threadConfiguration = originalThreadConfiguration.trim();
1574 if (threadConfiguration.endsWith("C")) {
1575 threadConfiguration = threadConfiguration.substring(0, threadConfiguration.length() - 1);
1576
1577 try {
1578 float coreMultiplier = Float.parseFloat(threadConfiguration);
1579
1580 if (coreMultiplier <= 0.0f) {
1581 throw new IllegalArgumentException("Invalid threads core multiplier value: '" + threadConfiguration
1582 + "C'. Value must be positive.");
1583 }
1584
1585 int procs = Runtime.getRuntime().availableProcessors();
1586 int threads = (int) (coreMultiplier * procs);
1587 return threads == 0 ? 1 : threads;
1588 } catch (NumberFormatException e) {
1589 throw new IllegalArgumentException(
1590 "Invalid threads core multiplier value: '" + threadConfiguration
1591 + "C'. Supported are int and float values ending with C.",
1592 e);
1593 }
1594 } else {
1595 try {
1596 int threads = Integer.parseInt(threadConfiguration);
1597
1598 if (threads <= 0) {
1599 throw new IllegalArgumentException(
1600 "Invalid threads value: '" + threadConfiguration + "'. Value must be positive.");
1601 }
1602
1603 return threads;
1604 } catch (NumberFormatException e) {
1605 throw new IllegalArgumentException(
1606 "Invalid threads value: '" + threadConfiguration + "'. Supported are integer values.");
1607 }
1608 }
1609 }
1610
1611
1612
1613
1614
1615 static void populateProperties(CliRequest cliRequest, Properties systemProperties, Properties userProperties)
1616 throws InterpolationException {
1617
1618
1619
1620
1621
1622
1623
1624 Properties cliProperties = new Properties();
1625 if (cliRequest.commandLine.hasOption(CLIManager.SET_USER_PROPERTY)) {
1626 String[] defStrs = cliRequest.commandLine.getOptionValues(CLIManager.SET_USER_PROPERTY);
1627
1628 if (defStrs != null) {
1629 String name;
1630 String value;
1631 for (String property : defStrs) {
1632 int i = property.indexOf('=');
1633 if (i <= 0) {
1634 name = property.trim();
1635 value = "true";
1636 } else {
1637 name = property.substring(0, i).trim();
1638 value = property.substring(i + 1);
1639 }
1640 cliProperties.setProperty(name, value);
1641 }
1642 }
1643 }
1644
1645 EnvironmentUtils.addEnvVars(systemProperties);
1646 SystemProperties.addSystemProperties(systemProperties);
1647
1648
1649 if (systemProperties.containsKey(MAVEN_REPO_CENTRAL_ENV)) {
1650 systemProperties.put(
1651 ModelInterpolator.MAVEN_REPO_CENTRAL_KEY, systemProperties.getProperty(MAVEN_REPO_CENTRAL_ENV));
1652 }
1653
1654 StringSearchInterpolator interpolator = createInterpolator(cliRequest, cliProperties, systemProperties);
1655 for (Map.Entry<Object, Object> e : cliProperties.entrySet()) {
1656 String name = (String) e.getKey();
1657 String value = interpolator.interpolate((String) e.getValue());
1658 userProperties.setProperty(name, value);
1659 }
1660
1661 systemProperties.putAll(userProperties);
1662
1663
1664
1665
1666
1667 userProperties.forEach((k, v) -> System.setProperty((String) k, (String) v));
1668
1669
1670
1671
1672
1673
1674 Properties buildProperties = CLIReportingUtils.getBuildProperties();
1675
1676 String mavenVersion = buildProperties.getProperty(CLIReportingUtils.BUILD_VERSION_PROPERTY);
1677 systemProperties.setProperty("maven.version", mavenVersion);
1678
1679 String mavenBuildVersion = CLIReportingUtils.createMavenVersionString(buildProperties);
1680 systemProperties.setProperty("maven.build.version", mavenBuildVersion);
1681 }
1682
1683 protected static StringSearchInterpolator createInterpolator(CliRequest cliRequest, Properties... properties) {
1684 StringSearchInterpolator interpolator = new StringSearchInterpolator();
1685 interpolator.addValueSource(new AbstractValueSource(false) {
1686 @Override
1687 public Object getValue(String expression) {
1688 if ("session.topDirectory".equals(expression)) {
1689 Path topDirectory = cliRequest.request.getTopDirectory();
1690 if (topDirectory != null) {
1691 return topDirectory.toString();
1692 } else {
1693 throw new IllegalUseOfUndefinedProperty(expression);
1694 }
1695 } else if ("session.rootDirectory".equals(expression)) {
1696 try {
1697 return cliRequest.request.getRootDirectory();
1698 } catch (IllegalStateException e) {
1699 throw new IllegalUseOfUndefinedProperty(expression);
1700 }
1701 }
1702 return null;
1703 }
1704 });
1705 interpolator.addValueSource(new AbstractValueSource(false) {
1706 @Override
1707 public Object getValue(String expression) {
1708 for (Properties props : properties) {
1709 Object val = props.getProperty(expression);
1710 if (val != null) {
1711 return val;
1712 }
1713 }
1714 return null;
1715 }
1716 });
1717 return interpolator;
1718 }
1719
1720 private static String stripLeadingAndTrailingQuotes(String str) {
1721 final int length = str.length();
1722 if (length > 1
1723 && str.startsWith("\"")
1724 && str.endsWith("\"")
1725 && str.substring(1, length - 1).indexOf('"') == -1) {
1726 str = str.substring(1, length - 1);
1727 }
1728
1729 return str;
1730 }
1731
1732 private static Path getCanonicalPath(Path path) {
1733 try {
1734 return path.toRealPath();
1735 } catch (IOException e) {
1736 return getCanonicalPath(path.getParent()).resolve(path.getFileName());
1737 }
1738 }
1739
1740 static class ExitException extends Exception {
1741 int exitCode;
1742
1743 ExitException(int exitCode) {
1744 this.exitCode = exitCode;
1745 }
1746 }
1747
1748 static class IllegalUseOfUndefinedProperty extends IllegalArgumentException {
1749 final String property;
1750
1751 IllegalUseOfUndefinedProperty(String property) {
1752 this.property = property;
1753 }
1754 }
1755
1756
1757
1758
1759
1760 protected TransferListener getConsoleTransferListener(boolean printResourceNames) {
1761 return new SimplexTransferListener(new ConsoleMavenTransferListener(System.out, printResourceNames));
1762 }
1763
1764 protected TransferListener getBatchTransferListener() {
1765 return new Slf4jMavenTransferListener();
1766 }
1767
1768 protected void customizeContainer(PlexusContainer container) {}
1769
1770 protected ModelProcessor createModelProcessor(PlexusContainer container) throws ComponentLookupException {
1771 return container.lookup(ModelProcessor.class);
1772 }
1773 }