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