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