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