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