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