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