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