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 java.io.Console;
23 import java.io.File;
24 import java.io.FileNotFoundException;
25 import java.io.FileOutputStream;
26 import java.io.PrintStream;
27 import java.util.ArrayList;
28 import java.util.LinkedHashMap;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Properties;
32 import java.util.StringTokenizer;
33
34 import org.apache.commons.cli.CommandLine;
35 import org.apache.commons.cli.ParseException;
36 import org.apache.commons.cli.UnrecognizedOptionException;
37 import org.apache.maven.BuildAbort;
38 import org.apache.maven.InternalErrorException;
39 import org.apache.maven.Maven;
40 import org.apache.maven.cli.event.DefaultEventSpyContext;
41 import org.apache.maven.cli.event.ExecutionEventLogger;
42 import org.apache.maven.cli.logging.Slf4jConfiguration;
43 import org.apache.maven.cli.logging.Slf4jConfigurationFactory;
44 import org.apache.maven.cli.logging.Slf4jLoggerManager;
45 import org.apache.maven.cli.logging.Slf4jStdoutLogger;
46 import org.apache.maven.cli.transfer.ConsoleMavenTransferListener;
47 import org.apache.maven.cli.transfer.QuietMavenTransferListener;
48 import org.apache.maven.cli.transfer.Slf4jMavenTransferListener;
49 import org.apache.maven.eventspy.internal.EventSpyDispatcher;
50 import org.apache.maven.exception.DefaultExceptionHandler;
51 import org.apache.maven.exception.ExceptionHandler;
52 import org.apache.maven.exception.ExceptionSummary;
53 import org.apache.maven.execution.DefaultMavenExecutionRequest;
54 import org.apache.maven.execution.ExecutionListener;
55 import org.apache.maven.execution.MavenExecutionRequest;
56 import org.apache.maven.execution.MavenExecutionRequestPopulator;
57 import org.apache.maven.execution.MavenExecutionResult;
58 import org.apache.maven.lifecycle.LifecycleExecutionException;
59 import org.apache.maven.model.building.ModelProcessor;
60 import org.apache.maven.project.MavenProject;
61 import org.apache.maven.properties.internal.EnvironmentUtils;
62 import org.apache.maven.properties.internal.SystemProperties;
63 import org.apache.maven.settings.building.DefaultSettingsBuildingRequest;
64 import org.apache.maven.settings.building.SettingsBuilder;
65 import org.apache.maven.settings.building.SettingsBuildingRequest;
66 import org.apache.maven.settings.building.SettingsBuildingResult;
67 import org.apache.maven.settings.building.SettingsProblem;
68 import org.apache.maven.settings.building.SettingsSource;
69 import org.codehaus.plexus.ContainerConfiguration;
70 import org.codehaus.plexus.DefaultContainerConfiguration;
71 import org.codehaus.plexus.DefaultPlexusContainer;
72 import org.codehaus.plexus.PlexusConstants;
73 import org.codehaus.plexus.PlexusContainer;
74 import org.codehaus.plexus.classworlds.ClassWorld;
75 import org.codehaus.plexus.classworlds.realm.ClassRealm;
76 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
77 import org.codehaus.plexus.logging.LoggerManager;
78 import org.codehaus.plexus.util.StringUtils;
79 import org.eclipse.aether.transfer.TransferListener;
80 import org.slf4j.ILoggerFactory;
81 import org.slf4j.Logger;
82 import org.slf4j.LoggerFactory;
83 import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
84 import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
85 import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
86 import org.sonatype.plexus.components.sec.dispatcher.SecUtil;
87 import org.sonatype.plexus.components.sec.dispatcher.model.SettingsSecurity;
88
89 import com.google.inject.AbstractModule;
90
91
92
93
94
95
96
97 public class MavenCli
98 {
99 public static final String LOCAL_REPO_PROPERTY = "maven.repo.local";
100
101 public static final String THREADS_DEPRECATED = "maven.threads.experimental";
102
103 public static final String userHome = System.getProperty( "user.home" );
104
105 public static final File userMavenConfigurationHome = new File( userHome, ".m2" );
106
107 public static final File DEFAULT_USER_SETTINGS_FILE = new File( userMavenConfigurationHome, "settings.xml" );
108
109 public static final File DEFAULT_GLOBAL_SETTINGS_FILE =
110 new File( System.getProperty( "maven.home", System.getProperty( "user.dir", "" ) ), "conf/settings.xml" );
111
112 public static final File DEFAULT_USER_TOOLCHAINS_FILE = new File( userMavenConfigurationHome, "toolchains.xml" );
113
114 private static final String EXT_CLASS_PATH = "maven.ext.class.path";
115
116 private ClassWorld classWorld;
117
118 private LoggerManager plexusLoggerManager;
119
120 private ILoggerFactory slf4jLoggerFactory;
121
122 private Logger slf4jLogger;
123
124 private EventSpyDispatcher eventSpyDispatcher;
125
126 private ModelProcessor modelProcessor;
127
128 private Maven maven;
129
130 private MavenExecutionRequestPopulator executionRequestPopulator;
131
132 private SettingsBuilder settingsBuilder;
133
134 private DefaultSecDispatcher dispatcher;
135
136 public MavenCli()
137 {
138 this( null );
139 }
140
141
142 public MavenCli( ClassWorld classWorld )
143 {
144 this.classWorld = classWorld;
145 }
146
147 public static void main( String[] args )
148 {
149 int result = main( args, null );
150
151 System.exit( result );
152 }
153
154
155 public static int main( String[] args, ClassWorld classWorld )
156 {
157 MavenCli cli = new MavenCli();
158 return cli.doMain( new CliRequest( args, classWorld ) );
159 }
160
161
162 public static int doMain( String[] args, ClassWorld classWorld )
163 {
164 MavenCli cli = new MavenCli();
165 return cli.doMain( new CliRequest( args, classWorld ) );
166 }
167
168
169 public int doMain( String[] args, String workingDirectory, PrintStream stdout, PrintStream stderr )
170 {
171 PrintStream oldout = System.out;
172 PrintStream olderr = System.err;
173
174 try
175 {
176 if ( stdout != null )
177 {
178 System.setOut( stdout );
179 }
180 if ( stderr != null )
181 {
182 System.setErr( stderr );
183 }
184
185 CliRequest cliRequest = new CliRequest( args, classWorld );
186 cliRequest.workingDirectory = workingDirectory;
187
188 return doMain( cliRequest );
189 }
190 finally
191 {
192 System.setOut( oldout );
193 System.setErr( olderr );
194 }
195 }
196
197
198 public int doMain( CliRequest cliRequest )
199 {
200 PlexusContainer localContainer = null;
201 try
202 {
203 initialize( cliRequest );
204 cli( cliRequest );
205 logging( cliRequest );
206 version( cliRequest );
207 properties( cliRequest );
208 localContainer = container( cliRequest );
209 commands( cliRequest );
210 settings( cliRequest );
211 populateRequest( cliRequest );
212 encryption( cliRequest );
213 repository( cliRequest );
214 return execute( cliRequest );
215 }
216 catch ( ExitException e )
217 {
218 return e.exitCode;
219 }
220 catch ( UnrecognizedOptionException e )
221 {
222
223 return 1;
224 }
225 catch ( BuildAbort e )
226 {
227 CLIReportingUtils.showError( slf4jLogger, "ABORTED", e, cliRequest.showErrors );
228
229 return 2;
230 }
231 catch ( Exception e )
232 {
233 CLIReportingUtils.showError( slf4jLogger, "Error executing Maven.", e, cliRequest.showErrors );
234
235 return 1;
236 }
237 finally
238 {
239 if ( localContainer != null )
240 {
241 localContainer.dispose();
242 }
243 }
244 }
245
246 private void initialize( CliRequest cliRequest )
247 {
248 if ( cliRequest.workingDirectory == null )
249 {
250 cliRequest.workingDirectory = System.getProperty( "user.dir" );
251 }
252
253
254
255
256
257 String mavenHome = System.getProperty( "maven.home" );
258
259 if ( mavenHome != null )
260 {
261 System.setProperty( "maven.home", new File( mavenHome ).getAbsolutePath() );
262 }
263 }
264
265 private void cli( CliRequest cliRequest )
266 throws Exception
267 {
268
269
270
271
272 slf4jLogger = new Slf4jStdoutLogger();
273
274 CLIManager cliManager = new CLIManager();
275
276 try
277 {
278 cliRequest.commandLine = cliManager.parse( cliRequest.args );
279 }
280 catch ( ParseException e )
281 {
282 System.err.println( "Unable to parse command line options: " + e.getMessage() );
283 cliManager.displayHelp( System.out );
284 throw e;
285 }
286
287 if ( cliRequest.commandLine.hasOption( CLIManager.HELP ) )
288 {
289 cliManager.displayHelp( System.out );
290 throw new ExitException( 0 );
291 }
292
293 if ( cliRequest.commandLine.hasOption( CLIManager.VERSION ) )
294 {
295 System.out.println( CLIReportingUtils.showVersion() );
296 throw new ExitException( 0 );
297 }
298 }
299
300
301
302
303 private void logging( CliRequest cliRequest )
304 {
305 cliRequest.debug = cliRequest.commandLine.hasOption( CLIManager.DEBUG );
306 cliRequest.quiet = !cliRequest.debug && cliRequest.commandLine.hasOption( CLIManager.QUIET );
307 cliRequest.showErrors = cliRequest.debug || cliRequest.commandLine.hasOption( CLIManager.ERRORS );
308
309 slf4jLoggerFactory = LoggerFactory.getILoggerFactory();
310 Slf4jConfiguration slf4jConfiguration = Slf4jConfigurationFactory.getConfiguration( slf4jLoggerFactory );
311
312 if ( cliRequest.debug )
313 {
314 cliRequest.request.setLoggingLevel( MavenExecutionRequest.LOGGING_LEVEL_DEBUG );
315 slf4jConfiguration.setRootLoggerLevel( Slf4jConfiguration.Level.DEBUG );
316 }
317 else if ( cliRequest.quiet )
318 {
319 cliRequest.request.setLoggingLevel( MavenExecutionRequest.LOGGING_LEVEL_ERROR );
320 slf4jConfiguration.setRootLoggerLevel( Slf4jConfiguration.Level.ERROR );
321 }
322
323
324
325 if ( cliRequest.commandLine.hasOption( CLIManager.LOG_FILE ) )
326 {
327 File logFile = new File( cliRequest.commandLine.getOptionValue( CLIManager.LOG_FILE ) );
328 logFile = resolveFile( logFile, cliRequest.workingDirectory );
329
330
331 try
332 {
333 PrintStream ps = new PrintStream( new FileOutputStream( logFile ) );
334 System.setOut( ps );
335 System.setErr( ps );
336 }
337 catch ( FileNotFoundException e )
338 {
339
340
341
342 }
343 }
344
345 slf4jConfiguration.activate();
346
347 plexusLoggerManager = new Slf4jLoggerManager();
348 slf4jLogger = slf4jLoggerFactory.getLogger( this.getClass().getName() );
349 }
350
351 private void version( CliRequest cliRequest )
352 {
353 if ( cliRequest.debug || cliRequest.commandLine.hasOption( CLIManager.SHOW_VERSION ) )
354 {
355 System.out.println( CLIReportingUtils.showVersion() );
356 }
357 }
358
359 private void commands( CliRequest cliRequest )
360 {
361 if ( cliRequest.showErrors )
362 {
363 slf4jLogger.info( "Error stacktraces are turned on." );
364 }
365
366 if ( MavenExecutionRequest.CHECKSUM_POLICY_WARN.equals( cliRequest.request.getGlobalChecksumPolicy() ) )
367 {
368 slf4jLogger.info( "Disabling strict checksum verification on all artifact downloads." );
369 }
370 else if ( MavenExecutionRequest.CHECKSUM_POLICY_FAIL.equals( cliRequest.request.getGlobalChecksumPolicy() ) )
371 {
372 slf4jLogger.info( "Enabling strict checksum verification on all artifact downloads." );
373 }
374 }
375
376 private void properties( CliRequest cliRequest )
377 {
378 populateProperties( cliRequest.commandLine, cliRequest.systemProperties, cliRequest.userProperties );
379 }
380
381 private PlexusContainer container( CliRequest cliRequest )
382 throws Exception
383 {
384 if ( cliRequest.classWorld == null )
385 {
386 cliRequest.classWorld = new ClassWorld( "plexus.core", Thread.currentThread().getContextClassLoader() );
387 }
388
389 DefaultPlexusContainer container;
390
391 ContainerConfiguration cc = new DefaultContainerConfiguration()
392 .setClassWorld( cliRequest.classWorld )
393 .setRealm( setupContainerRealm( cliRequest ) )
394 .setClassPathScanning( PlexusConstants.SCANNING_INDEX )
395 .setAutoWiring( true )
396 .setName( "maven" );
397
398 container = new DefaultPlexusContainer( cc, new AbstractModule()
399 {
400 protected void configure()
401 {
402 bind( ILoggerFactory.class ).toInstance( slf4jLoggerFactory );
403 }
404 } );
405
406
407 container.setLookupRealm( null );
408
409 container.setLoggerManager( plexusLoggerManager );
410
411 customizeContainer( container );
412
413 container.getLoggerManager().setThresholds( cliRequest.request.getLoggingLevel() );
414
415 Thread.currentThread().setContextClassLoader( container.getContainerRealm() );
416
417 eventSpyDispatcher = container.lookup( EventSpyDispatcher.class );
418
419 DefaultEventSpyContext eventSpyContext = new DefaultEventSpyContext();
420 Map<String, Object> data = eventSpyContext.getData();
421 data.put( "plexus", container );
422 data.put( "workingDirectory", cliRequest.workingDirectory );
423 data.put( "systemProperties", cliRequest.systemProperties );
424 data.put( "userProperties", cliRequest.userProperties );
425 data.put( "versionProperties", CLIReportingUtils.getBuildProperties() );
426 eventSpyDispatcher.init( eventSpyContext );
427
428
429 slf4jLogger = slf4jLoggerFactory.getLogger( this.getClass().getName() );
430
431 maven = container.lookup( Maven.class );
432
433 executionRequestPopulator = container.lookup( MavenExecutionRequestPopulator.class );
434
435 modelProcessor = createModelProcessor( container );
436
437 settingsBuilder = container.lookup( SettingsBuilder.class );
438
439 dispatcher = (DefaultSecDispatcher) container.lookup( SecDispatcher.class, "maven" );
440
441 return container;
442 }
443
444 private ClassRealm setupContainerRealm( CliRequest cliRequest )
445 throws Exception
446 {
447 ClassRealm containerRealm = null;
448
449 String extClassPath = cliRequest.userProperties.getProperty( EXT_CLASS_PATH );
450 if ( extClassPath == null )
451 {
452 extClassPath = cliRequest.systemProperties.getProperty( EXT_CLASS_PATH );
453 }
454
455 if ( StringUtils.isNotEmpty( extClassPath ) )
456 {
457 String[] jars = StringUtils.split( extClassPath, File.pathSeparator );
458
459 if ( jars.length > 0 )
460 {
461 ClassRealm coreRealm = cliRequest.classWorld.getClassRealm( "plexus.core" );
462 if ( coreRealm == null )
463 {
464 coreRealm = cliRequest.classWorld.getRealms().iterator().next();
465 }
466
467 ClassRealm extRealm = cliRequest.classWorld.newRealm( "maven.ext", null );
468
469 slf4jLogger.debug( "Populating class realm " + extRealm.getId() );
470
471 for ( String jar : jars )
472 {
473 File file = resolveFile( new File( jar ), cliRequest.workingDirectory );
474
475 slf4jLogger.debug( " Included " + file );
476
477 extRealm.addURL( file.toURI().toURL() );
478 }
479
480 extRealm.setParentRealm( coreRealm );
481
482 containerRealm = extRealm;
483 }
484 }
485
486 return containerRealm;
487 }
488
489
490
491
492 private void encryption( CliRequest cliRequest )
493 throws Exception
494 {
495 if ( cliRequest.commandLine.hasOption( CLIManager.ENCRYPT_MASTER_PASSWORD ) )
496 {
497 String passwd = cliRequest.commandLine.getOptionValue( CLIManager.ENCRYPT_MASTER_PASSWORD );
498
499 if ( passwd == null )
500 {
501 Console cons;
502 char[] password;
503 if ( ( cons = System.console() ) != null
504 && ( password = cons.readPassword( "Master password: " ) ) != null )
505 {
506
507 passwd = String.copyValueOf( password );
508
509
510 java.util.Arrays.fill( password, ' ' );
511 }
512 }
513
514 DefaultPlexusCipher cipher = new DefaultPlexusCipher();
515
516 System.out.println( cipher.encryptAndDecorate( passwd, DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION ) );
517
518 throw new ExitException( 0 );
519 }
520 else if ( cliRequest.commandLine.hasOption( CLIManager.ENCRYPT_PASSWORD ) )
521 {
522 String passwd = cliRequest.commandLine.getOptionValue( CLIManager.ENCRYPT_PASSWORD );
523
524 if ( passwd == null )
525 {
526 Console cons;
527 char[] password;
528 if ( ( cons = System.console() ) != null
529 && ( password = cons.readPassword( "Password: " ) ) != null )
530 {
531
532 passwd = String.copyValueOf( password );
533
534
535 java.util.Arrays.fill( password, ' ' );
536 }
537 }
538
539 String configurationFile = dispatcher.getConfigurationFile();
540
541 if ( configurationFile.startsWith( "~" ) )
542 {
543 configurationFile = System.getProperty( "user.home" ) + configurationFile.substring( 1 );
544 }
545
546 String file = System.getProperty( DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION, configurationFile );
547
548 String master = null;
549
550 SettingsSecurity sec = SecUtil.read( file, true );
551 if ( sec != null )
552 {
553 master = sec.getMaster();
554 }
555
556 if ( master == null )
557 {
558 throw new IllegalStateException( "Master password is not set in the setting security file: " + file );
559 }
560
561 DefaultPlexusCipher cipher = new DefaultPlexusCipher();
562 String masterPasswd = cipher.decryptDecorated( master, DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION );
563 System.out.println( cipher.encryptAndDecorate( passwd, masterPasswd ) );
564
565 throw new ExitException( 0 );
566 }
567 }
568
569 private void repository( CliRequest cliRequest )
570 throws Exception
571 {
572 if ( cliRequest.commandLine.hasOption( CLIManager.LEGACY_LOCAL_REPOSITORY ) || Boolean.getBoolean( "maven.legacyLocalRepo" ) )
573 {
574 cliRequest.request.setUseLegacyLocalRepository( true );
575 }
576 }
577
578 private int execute( CliRequest cliRequest )
579 {
580 eventSpyDispatcher.onEvent( cliRequest.request );
581
582 MavenExecutionResult result = maven.execute( cliRequest.request );
583
584 eventSpyDispatcher.onEvent( result );
585
586 eventSpyDispatcher.close();
587
588 if ( result.hasExceptions() )
589 {
590 ExceptionHandler handler = new DefaultExceptionHandler();
591
592 Map<String, String> references = new LinkedHashMap<String, String>();
593
594 MavenProject project = null;
595
596 for ( Throwable exception : result.getExceptions() )
597 {
598 ExceptionSummary summary = handler.handleException( exception );
599
600 logSummary( summary, references, "", cliRequest.showErrors );
601
602 if ( project == null && exception instanceof LifecycleExecutionException )
603 {
604 project = ( (LifecycleExecutionException) exception ).getProject();
605 }
606 }
607
608 slf4jLogger.error( "" );
609
610 if ( !cliRequest.showErrors )
611 {
612 slf4jLogger.error( "To see the full stack trace of the errors, re-run Maven with the -e switch." );
613 }
614 if ( !slf4jLogger.isDebugEnabled() )
615 {
616 slf4jLogger.error( "Re-run Maven using the -X switch to enable full debug logging." );
617 }
618
619 if ( !references.isEmpty() )
620 {
621 slf4jLogger.error( "" );
622 slf4jLogger.error( "For more information about the errors and possible solutions"
623 + ", please read the following articles:" );
624
625 for ( Map.Entry<String, String> entry : references.entrySet() )
626 {
627 slf4jLogger.error( entry.getValue() + " " + entry.getKey() );
628 }
629 }
630
631 if ( project != null && !project.equals( result.getTopologicallySortedProjects().get( 0 ) ) )
632 {
633 slf4jLogger.error( "" );
634 slf4jLogger.error( "After correcting the problems, you can resume the build with the command" );
635 slf4jLogger.error( " mvn <goals> -rf :" + project.getArtifactId() );
636 }
637
638 if ( MavenExecutionRequest.REACTOR_FAIL_NEVER.equals( cliRequest.request.getReactorFailureBehavior() ) )
639 {
640 slf4jLogger.info( "Build failures were ignored." );
641
642 return 0;
643 }
644 else
645 {
646 return 1;
647 }
648 }
649 else
650 {
651 return 0;
652 }
653 }
654
655 private void logSummary( ExceptionSummary summary, Map<String, String> references, String indent,
656 boolean showErrors )
657 {
658 String referenceKey = "";
659
660 if ( StringUtils.isNotEmpty( summary.getReference() ) )
661 {
662 referenceKey = references.get( summary.getReference() );
663 if ( referenceKey == null )
664 {
665 referenceKey = "[Help " + ( references.size() + 1 ) + "]";
666 references.put( summary.getReference(), referenceKey );
667 }
668 }
669
670 String msg = summary.getMessage();
671
672 if ( StringUtils.isNotEmpty( referenceKey ) )
673 {
674 if ( msg.indexOf( '\n' ) < 0 )
675 {
676 msg += " -> " + referenceKey;
677 }
678 else
679 {
680 msg += "\n-> " + referenceKey;
681 }
682 }
683
684 String[] lines = msg.split( "(\r\n)|(\r)|(\n)" );
685
686 for ( int i = 0; i < lines.length; i++ )
687 {
688 String line = indent + lines[i].trim();
689
690 if ( i == lines.length - 1 && ( showErrors || ( summary.getException() instanceof InternalErrorException ) ) )
691 {
692 slf4jLogger.error( line, summary.getException() );
693 }
694 else
695 {
696 slf4jLogger.error( line );
697 }
698 }
699
700 indent += " ";
701
702 for ( ExceptionSummary child : summary.getChildren() )
703 {
704 logSummary( child, references, indent, showErrors );
705 }
706 }
707
708 private void settings( CliRequest cliRequest )
709 throws Exception
710 {
711 File userSettingsFile;
712
713 if ( cliRequest.commandLine.hasOption( CLIManager.ALTERNATE_USER_SETTINGS ) )
714 {
715 userSettingsFile = new File( cliRequest.commandLine.getOptionValue( CLIManager.ALTERNATE_USER_SETTINGS ) );
716 userSettingsFile = resolveFile( userSettingsFile, cliRequest.workingDirectory );
717
718 if ( !userSettingsFile.isFile() )
719 {
720 throw new FileNotFoundException( "The specified user settings file does not exist: "
721 + userSettingsFile );
722 }
723 }
724 else
725 {
726 userSettingsFile = DEFAULT_USER_SETTINGS_FILE;
727 }
728
729 File globalSettingsFile;
730
731 if ( cliRequest.commandLine.hasOption( CLIManager.ALTERNATE_GLOBAL_SETTINGS ) )
732 {
733 globalSettingsFile =
734 new File( cliRequest.commandLine.getOptionValue( CLIManager.ALTERNATE_GLOBAL_SETTINGS ) );
735 globalSettingsFile = resolveFile( globalSettingsFile, cliRequest.workingDirectory );
736
737 if ( !globalSettingsFile.isFile() )
738 {
739 throw new FileNotFoundException( "The specified global settings file does not exist: "
740 + globalSettingsFile );
741 }
742 }
743 else
744 {
745 globalSettingsFile = DEFAULT_GLOBAL_SETTINGS_FILE;
746 }
747
748 cliRequest.request.setGlobalSettingsFile( globalSettingsFile );
749 cliRequest.request.setUserSettingsFile( userSettingsFile );
750
751 SettingsBuildingRequest settingsRequest = new DefaultSettingsBuildingRequest();
752 settingsRequest.setGlobalSettingsFile( globalSettingsFile );
753 settingsRequest.setUserSettingsFile( userSettingsFile );
754 settingsRequest.setSystemProperties( cliRequest.systemProperties );
755 settingsRequest.setUserProperties( cliRequest.userProperties );
756
757 eventSpyDispatcher.onEvent( settingsRequest );
758
759 slf4jLogger.debug( "Reading global settings from "
760 + getSettingsLocation( settingsRequest.getGlobalSettingsSource(), settingsRequest.getGlobalSettingsFile() ) );
761 slf4jLogger.debug( "Reading user settings from "
762 + getSettingsLocation( settingsRequest.getUserSettingsSource(), settingsRequest.getUserSettingsFile() ) );
763
764 SettingsBuildingResult settingsResult = settingsBuilder.build( settingsRequest );
765
766 eventSpyDispatcher.onEvent( settingsResult );
767
768 executionRequestPopulator.populateFromSettings( cliRequest.request, settingsResult.getEffectiveSettings() );
769
770 if ( !settingsResult.getProblems().isEmpty() && slf4jLogger.isWarnEnabled() )
771 {
772 slf4jLogger.warn( "" );
773 slf4jLogger.warn( "Some problems were encountered while building the effective settings" );
774
775 for ( SettingsProblem problem : settingsResult.getProblems() )
776 {
777 slf4jLogger.warn( problem.getMessage() + " @ " + problem.getLocation() );
778 }
779
780 slf4jLogger.warn( "" );
781 }
782 }
783
784 private Object getSettingsLocation( SettingsSource source, File file )
785 {
786 if ( source != null )
787 {
788 return source.getLocation();
789 }
790 return file;
791 }
792
793 private MavenExecutionRequest populateRequest( CliRequest cliRequest )
794 {
795 MavenExecutionRequest request = cliRequest.request;
796 CommandLine commandLine = cliRequest.commandLine;
797 String workingDirectory = cliRequest.workingDirectory;
798 boolean quiet = cliRequest.quiet;
799 boolean showErrors = cliRequest.showErrors;
800
801 String[] deprecatedOptions = { "up", "npu", "cpu", "npr" };
802 for ( String deprecatedOption : deprecatedOptions )
803 {
804 if ( commandLine.hasOption( deprecatedOption ) )
805 {
806 slf4jLogger.warn( "Command line option -" + deprecatedOption
807 + " is deprecated and will be removed in future Maven versions." );
808 }
809 }
810
811
812
813
814
815
816 if ( commandLine.hasOption( CLIManager.BATCH_MODE ) )
817 {
818 request.setInteractiveMode( false );
819 }
820
821 boolean noSnapshotUpdates = false;
822 if ( commandLine.hasOption( CLIManager.SUPRESS_SNAPSHOT_UPDATES ) )
823 {
824 noSnapshotUpdates = true;
825 }
826
827
828
829
830
831 @SuppressWarnings( "unchecked" )
832 List<String> goals = commandLine.getArgList();
833
834 boolean recursive = true;
835
836
837 String reactorFailureBehaviour = MavenExecutionRequest.REACTOR_FAIL_FAST;
838
839 if ( commandLine.hasOption( CLIManager.NON_RECURSIVE ) )
840 {
841 recursive = false;
842 }
843
844 if ( commandLine.hasOption( CLIManager.FAIL_FAST ) )
845 {
846 reactorFailureBehaviour = MavenExecutionRequest.REACTOR_FAIL_FAST;
847 }
848 else if ( commandLine.hasOption( CLIManager.FAIL_AT_END ) )
849 {
850 reactorFailureBehaviour = MavenExecutionRequest.REACTOR_FAIL_AT_END;
851 }
852 else if ( commandLine.hasOption( CLIManager.FAIL_NEVER ) )
853 {
854 reactorFailureBehaviour = MavenExecutionRequest.REACTOR_FAIL_NEVER;
855 }
856
857 if ( commandLine.hasOption( CLIManager.OFFLINE ) )
858 {
859 request.setOffline( true );
860 }
861
862 boolean updateSnapshots = false;
863
864 if ( commandLine.hasOption( CLIManager.UPDATE_SNAPSHOTS ) )
865 {
866 updateSnapshots = true;
867 }
868
869 String globalChecksumPolicy = null;
870
871 if ( commandLine.hasOption( CLIManager.CHECKSUM_FAILURE_POLICY ) )
872 {
873 globalChecksumPolicy = MavenExecutionRequest.CHECKSUM_POLICY_FAIL;
874 }
875 else if ( commandLine.hasOption( CLIManager.CHECKSUM_WARNING_POLICY ) )
876 {
877 globalChecksumPolicy = MavenExecutionRequest.CHECKSUM_POLICY_WARN;
878 }
879
880 File baseDirectory = new File( workingDirectory, "" ).getAbsoluteFile();
881
882
883
884
885
886 List<String> activeProfiles = new ArrayList<String>();
887
888 List<String> inactiveProfiles = new ArrayList<String>();
889
890 if ( commandLine.hasOption( CLIManager.ACTIVATE_PROFILES ) )
891 {
892 String[] profileOptionValues = commandLine.getOptionValues( CLIManager.ACTIVATE_PROFILES );
893 if ( profileOptionValues != null )
894 {
895 for ( String profileOptionValue : profileOptionValues )
896 {
897 StringTokenizer profileTokens = new StringTokenizer( profileOptionValue, "," );
898
899 while ( profileTokens.hasMoreTokens() )
900 {
901 String profileAction = profileTokens.nextToken().trim();
902
903 if ( profileAction.startsWith( "-" ) || profileAction.startsWith( "!" ) )
904 {
905 inactiveProfiles.add( profileAction.substring( 1 ) );
906 }
907 else if ( profileAction.startsWith( "+" ) )
908 {
909 activeProfiles.add( profileAction.substring( 1 ) );
910 }
911 else
912 {
913 activeProfiles.add( profileAction );
914 }
915 }
916 }
917 }
918 }
919
920 TransferListener transferListener;
921
922 if ( quiet )
923 {
924 transferListener = new QuietMavenTransferListener();
925 }
926 else if ( request.isInteractiveMode() && !cliRequest.commandLine.hasOption( CLIManager.LOG_FILE ) )
927 {
928
929
930
931
932 transferListener = getConsoleTransferListener();
933 }
934 else
935 {
936 transferListener = getBatchTransferListener();
937 }
938
939 ExecutionListener executionListener = new ExecutionEventLogger();
940 executionListener = eventSpyDispatcher.chainListener( executionListener );
941
942 String alternatePomFile = null;
943 if ( commandLine.hasOption( CLIManager.ALTERNATE_POM_FILE ) )
944 {
945 alternatePomFile = commandLine.getOptionValue( CLIManager.ALTERNATE_POM_FILE );
946 }
947
948 File userToolchainsFile;
949 if ( commandLine.hasOption( CLIManager.ALTERNATE_USER_TOOLCHAINS ) )
950 {
951 userToolchainsFile = new File( commandLine.getOptionValue( CLIManager.ALTERNATE_USER_TOOLCHAINS ) );
952 userToolchainsFile = resolveFile( userToolchainsFile, workingDirectory );
953 }
954 else
955 {
956 userToolchainsFile = MavenCli.DEFAULT_USER_TOOLCHAINS_FILE;
957 }
958
959 request.setBaseDirectory( baseDirectory ).setGoals( goals )
960 .setSystemProperties( cliRequest.systemProperties )
961 .setUserProperties( cliRequest.userProperties )
962 .setReactorFailureBehavior( reactorFailureBehaviour )
963 .setRecursive( recursive )
964 .setShowErrors( showErrors )
965 .addActiveProfiles( activeProfiles )
966 .addInactiveProfiles( inactiveProfiles )
967 .setExecutionListener( executionListener )
968 .setTransferListener( transferListener )
969 .setUpdateSnapshots( updateSnapshots )
970 .setNoSnapshotUpdates( noSnapshotUpdates )
971 .setGlobalChecksumPolicy( globalChecksumPolicy )
972 .setUserToolchainsFile( userToolchainsFile );
973
974 if ( alternatePomFile != null )
975 {
976 File pom = resolveFile( new File( alternatePomFile ), workingDirectory );
977 if ( pom.isDirectory() )
978 {
979 pom = new File( pom, "pom.xml" );
980 }
981
982 request.setPom( pom );
983 }
984 else
985 {
986 File pom = modelProcessor.locatePom( baseDirectory );
987
988 if ( pom.isFile() )
989 {
990 request.setPom( pom );
991 }
992 }
993
994 if ( ( request.getPom() != null ) && ( request.getPom().getParentFile() != null ) )
995 {
996 request.setBaseDirectory( request.getPom().getParentFile() );
997 }
998
999 if ( commandLine.hasOption( CLIManager.RESUME_FROM ) )
1000 {
1001 request.setResumeFrom( commandLine.getOptionValue( CLIManager.RESUME_FROM ) );
1002 }
1003
1004 if ( commandLine.hasOption( CLIManager.PROJECT_LIST ) )
1005 {
1006 String[] projectOptionValues = commandLine.getOptionValues( CLIManager.PROJECT_LIST );
1007
1008 List<String> inclProjects = new ArrayList<String>();
1009 List<String> exclProjects = new ArrayList<String>();
1010
1011 if ( projectOptionValues != null )
1012 {
1013 for ( String projectOptionValue : projectOptionValues )
1014 {
1015 StringTokenizer projectTokens = new StringTokenizer( projectOptionValue, "," );
1016
1017 while ( projectTokens.hasMoreTokens() )
1018 {
1019 String projectAction = projectTokens.nextToken().trim();
1020
1021 if ( projectAction.startsWith( "-" ) || projectAction.startsWith( "!" ) )
1022 {
1023 exclProjects.add( projectAction.substring( 1 ) );
1024 }
1025 else if ( projectAction.startsWith( "+" ) )
1026 {
1027 inclProjects.add( projectAction.substring( 1 ) );
1028 }
1029 else
1030 {
1031 inclProjects.add( projectAction );
1032 }
1033 }
1034 }
1035 }
1036
1037 request.setSelectedProjects( inclProjects );
1038 request.setExcludedProjects( exclProjects );
1039 }
1040
1041 if ( commandLine.hasOption( CLIManager.ALSO_MAKE )
1042 && !commandLine.hasOption( CLIManager.ALSO_MAKE_DEPENDENTS ) )
1043 {
1044 request.setMakeBehavior( MavenExecutionRequest.REACTOR_MAKE_UPSTREAM );
1045 }
1046 else if ( !commandLine.hasOption( CLIManager.ALSO_MAKE )
1047 && commandLine.hasOption( CLIManager.ALSO_MAKE_DEPENDENTS ) )
1048 {
1049 request.setMakeBehavior( MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM );
1050 }
1051 else if ( commandLine.hasOption( CLIManager.ALSO_MAKE )
1052 && commandLine.hasOption( CLIManager.ALSO_MAKE_DEPENDENTS ) )
1053 {
1054 request.setMakeBehavior( MavenExecutionRequest.REACTOR_MAKE_BOTH );
1055 }
1056
1057 String localRepoProperty = request.getUserProperties().getProperty( MavenCli.LOCAL_REPO_PROPERTY );
1058
1059 if ( localRepoProperty == null )
1060 {
1061 localRepoProperty = request.getSystemProperties().getProperty( MavenCli.LOCAL_REPO_PROPERTY );
1062 }
1063
1064 if ( localRepoProperty != null )
1065 {
1066 request.setLocalRepositoryPath( localRepoProperty );
1067 }
1068
1069
1070 request.setCacheNotFound( true );
1071 request.setCacheTransferError( false );
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081 final String threadConfiguration = commandLine.hasOption( CLIManager.THREADS )
1082 ? commandLine.getOptionValue( CLIManager.THREADS )
1083 : request.getSystemProperties().getProperty(
1084 MavenCli.THREADS_DEPRECATED );
1085
1086 if ( threadConfiguration != null )
1087 {
1088
1089
1090
1091 request.setBuilderId( "multithreaded" );
1092
1093 if ( threadConfiguration.contains( "C" ) )
1094 {
1095 request.setDegreeOfConcurrency( calculateDegreeOfConcurrencyWithCoreMultiplier( threadConfiguration ) );
1096 }
1097 else
1098 {
1099 request.setDegreeOfConcurrency( Integer.valueOf( threadConfiguration ) );
1100 }
1101 }
1102
1103
1104
1105
1106 if ( commandLine.hasOption( CLIManager.BUILDER ) )
1107 {
1108 request.setBuilderId( commandLine.getOptionValue( CLIManager.BUILDER ) );
1109 }
1110
1111 return request;
1112 }
1113
1114 int calculateDegreeOfConcurrencyWithCoreMultiplier( String threadConfiguration )
1115 {
1116 return (int) ( Float.valueOf( threadConfiguration.replace( "C", "" ) ) * Runtime.getRuntime().availableProcessors() );
1117 }
1118
1119 static File resolveFile( File file, String workingDirectory )
1120 {
1121 if ( file == null )
1122 {
1123 return null;
1124 }
1125 else if ( file.isAbsolute() )
1126 {
1127 return file;
1128 }
1129 else if ( file.getPath().startsWith( File.separator ) )
1130 {
1131
1132 return file.getAbsoluteFile();
1133 }
1134 else
1135 {
1136 return new File( workingDirectory, file.getPath() ).getAbsoluteFile();
1137 }
1138 }
1139
1140
1141
1142
1143
1144 static void populateProperties( CommandLine commandLine, Properties systemProperties, Properties userProperties )
1145 {
1146 EnvironmentUtils.addEnvVars( systemProperties );
1147
1148
1149
1150
1151
1152
1153
1154 if ( commandLine.hasOption( CLIManager.SET_SYSTEM_PROPERTY ) )
1155 {
1156 String[] defStrs = commandLine.getOptionValues( CLIManager.SET_SYSTEM_PROPERTY );
1157
1158 if ( defStrs != null )
1159 {
1160 for ( String defStr : defStrs )
1161 {
1162 setCliProperty( defStr, userProperties );
1163 }
1164 }
1165 }
1166
1167 SystemProperties.addSystemProperties( systemProperties );
1168
1169
1170
1171
1172
1173
1174 Properties buildProperties = CLIReportingUtils.getBuildProperties();
1175
1176 String mavenVersion = buildProperties.getProperty( CLIReportingUtils.BUILD_VERSION_PROPERTY );
1177 systemProperties.setProperty( "maven.version", mavenVersion );
1178
1179 String mavenBuildVersion = CLIReportingUtils.createMavenVersionString( buildProperties );
1180 systemProperties.setProperty( "maven.build.version", mavenBuildVersion );
1181 }
1182
1183 private static void setCliProperty( String property, Properties properties )
1184 {
1185 String name;
1186
1187 String value;
1188
1189 int i = property.indexOf( "=" );
1190
1191 if ( i <= 0 )
1192 {
1193 name = property.trim();
1194
1195 value = "true";
1196 }
1197 else
1198 {
1199 name = property.substring( 0, i ).trim();
1200
1201 value = property.substring( i + 1 );
1202 }
1203
1204 properties.setProperty( name, value );
1205
1206
1207
1208
1209
1210
1211 System.setProperty( name, value );
1212 }
1213
1214 static class CliRequest
1215 {
1216 String[] args;
1217 CommandLine commandLine;
1218 ClassWorld classWorld;
1219 String workingDirectory;
1220 boolean debug;
1221 boolean quiet;
1222 boolean showErrors = true;
1223 Properties userProperties = new Properties();
1224 Properties systemProperties = new Properties();
1225 MavenExecutionRequest request;
1226
1227 CliRequest( String[] args, ClassWorld classWorld )
1228 {
1229 this.args = args;
1230 this.classWorld = classWorld;
1231 this.request = new DefaultMavenExecutionRequest();
1232 }
1233 }
1234
1235 static class ExitException
1236 extends Exception
1237 {
1238
1239 public int exitCode;
1240
1241 public ExitException( int exitCode )
1242 {
1243 this.exitCode = exitCode;
1244 }
1245
1246 }
1247
1248
1249
1250
1251
1252 protected TransferListener getConsoleTransferListener()
1253 {
1254 return new ConsoleMavenTransferListener( System.out );
1255 }
1256
1257 protected TransferListener getBatchTransferListener()
1258 {
1259 return new Slf4jMavenTransferListener();
1260 }
1261
1262 protected void customizeContainer( PlexusContainer container )
1263 {
1264 }
1265
1266 protected ModelProcessor createModelProcessor( PlexusContainer container )
1267 throws ComponentLookupException
1268 {
1269 return container.lookup( ModelProcessor.class );
1270 }
1271 }