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