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