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 org.apache.commons.cli.CommandLine;
23 import org.apache.commons.cli.ParseException;
24 import org.apache.maven.Maven;
25 import org.apache.maven.SettingsConfigurationException;
26 import org.apache.maven.artifact.manager.WagonManager;
27 import org.apache.maven.artifact.repository.ArtifactRepository;
28 import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
29 import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
30 import org.apache.maven.artifact.repository.DefaultArtifactRepository;
31 import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
32 import org.apache.maven.execution.DefaultMavenExecutionRequest;
33 import org.apache.maven.execution.MavenExecutionRequest;
34 import org.apache.maven.execution.ReactorManager;
35 import org.apache.maven.monitor.event.DefaultEventDispatcher;
36 import org.apache.maven.monitor.event.DefaultEventMonitor;
37 import org.apache.maven.monitor.event.EventDispatcher;
38 import org.apache.maven.plugin.Mojo;
39 import org.apache.maven.profiles.DefaultProfileManager;
40 import org.apache.maven.profiles.ProfileManager;
41 import org.apache.maven.reactor.MavenExecutionException;
42 import org.apache.maven.settings.MavenSettingsBuilder;
43 import org.apache.maven.settings.RuntimeInfo;
44 import org.apache.maven.settings.Settings;
45 import org.codehaus.classworlds.ClassWorld;
46 import org.codehaus.plexus.PlexusContainerException;
47 import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
48 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
49 import org.codehaus.plexus.embed.Embedder;
50 import org.codehaus.plexus.logging.Logger;
51 import org.codehaus.plexus.logging.LoggerManager;
52 import org.codehaus.plexus.util.IOUtil;
53 import org.codehaus.plexus.util.Os;
54 import org.codehaus.plexus.util.cli.CommandLineUtils;
55 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
56
57 import java.io.File;
58 import java.io.IOException;
59 import java.io.InputStream;
60 import java.text.SimpleDateFormat;
61 import java.util.Date;
62 import java.util.Iterator;
63 import java.util.Locale;
64 import java.util.Properties;
65 import java.util.StringTokenizer;
66 import java.util.Map.Entry;
67
68
69
70
71
72
73 public class MavenCli
74 {
75
76 public static final String OS_NAME = Os.OS_NAME;
77
78
79 public static final String OS_ARCH = Os.OS_ARCH;
80
81
82 public static final String OS_VERSION = Os.OS_VERSION;
83
84 private static Embedder embedder;
85
86 public static void main( String[] args )
87 {
88 ClassWorld classWorld = new ClassWorld( "plexus.core", Thread.currentThread().getContextClassLoader() );
89
90 int result = main( args, classWorld );
91
92 System.exit( result );
93 }
94
95
96
97
98 public static int main( String[] args, ClassWorld classWorld )
99 {
100
101
102
103
104 CLIManager cliManager = new CLIManager();
105
106 CommandLine commandLine;
107 try
108 {
109 commandLine = cliManager.parse( args );
110 }
111 catch ( ParseException e )
112 {
113 System.err.println( "Unable to parse command line options: " + e.getMessage() );
114 cliManager.displayHelp();
115 return 1;
116 }
117
118 boolean debug = commandLine.hasOption( CLIManager.DEBUG );
119
120 boolean showErrors = debug || commandLine.hasOption( CLIManager.ERRORS );
121
122 if ( showErrors )
123 {
124 System.out.println( "+ Error stacktraces are turned on." );
125 }
126
127
128
129
130
131 if ( commandLine.hasOption( CLIManager.HELP ) )
132 {
133 cliManager.displayHelp();
134 return 0;
135 }
136
137 if ( commandLine.hasOption( CLIManager.VERSION ) )
138 {
139 showVersion();
140
141 return 0;
142 }
143 else if ( debug )
144 {
145 showVersion();
146 }
147
148 EventDispatcher eventDispatcher = new DefaultEventDispatcher();
149
150
151
152 String mavenHome = System.getProperty( "maven.home" );
153 if ( mavenHome != null )
154 {
155 System.setProperty( "maven.home", new File( mavenHome ).getAbsolutePath() );
156 }
157
158
159
160
161
162
163 embedder = new Embedder();
164
165 try
166 {
167 embedder.start( classWorld );
168 }
169 catch ( PlexusContainerException e )
170 {
171 showFatalError( "Unable to start the embedded plexus container", e, showErrors );
172
173 return 1;
174 }
175
176
177
178
179
180
181 Properties executionProperties = new Properties();
182 Properties userProperties = new Properties();
183 populateProperties( commandLine, executionProperties, userProperties );
184
185 Settings settings;
186
187 try
188 {
189 settings = buildSettings( commandLine );
190 }
191 catch ( SettingsConfigurationException e )
192 {
193 showError( "Error reading settings.xml: " + e.getMessage(), e, showErrors );
194
195 return 1;
196 }
197 catch ( ComponentLookupException e )
198 {
199 showFatalError( "Unable to read settings.xml", e, showErrors );
200
201 return 1;
202 }
203
204 Maven maven = null;
205
206 MavenExecutionRequest request = null;
207
208 LoggerManager loggerManager = null;
209
210 try
211 {
212
213 loggerManager = (LoggerManager) embedder.lookup( LoggerManager.ROLE );
214
215 if ( debug )
216 {
217 loggerManager.setThreshold( Logger.LEVEL_DEBUG );
218 }
219 else if ( commandLine.hasOption( CLIManager.QUIET ) )
220 {
221
222
223 loggerManager.setThreshold( Logger.LEVEL_ERROR );
224
225 }
226
227 ProfileManager profileManager = new DefaultProfileManager( embedder.getContainer(), executionProperties );
228
229 if ( commandLine.hasOption( CLIManager.ACTIVATE_PROFILES ) )
230 {
231 String [] profileOptionValues = commandLine.getOptionValues( CLIManager.ACTIVATE_PROFILES );
232
233 if ( profileOptionValues != null )
234 {
235 for ( int i=0; i < profileOptionValues.length; ++i )
236 {
237 StringTokenizer profileTokens = new StringTokenizer( profileOptionValues[i], "," );
238
239 while ( profileTokens.hasMoreTokens() )
240 {
241 String profileAction = profileTokens.nextToken().trim();
242
243 if ( profileAction.startsWith( "-" ) || profileAction.startsWith( "!" ) )
244 {
245 profileManager.explicitlyDeactivate( profileAction.substring( 1 ) );
246 }
247 else if ( profileAction.startsWith( "+" ) )
248 {
249 profileManager.explicitlyActivate( profileAction.substring( 1 ) );
250 }
251 else
252 {
253 profileManager.explicitlyActivate( profileAction );
254 }
255 }
256 }
257 }
258 }
259
260 request = createRequest( commandLine, settings, eventDispatcher, loggerManager, profileManager,
261 executionProperties, userProperties, showErrors );
262
263 setProjectFileOptions( commandLine, request );
264
265 maven = createMavenInstance( settings.isInteractiveMode() );
266 }
267 catch ( ComponentLookupException e )
268 {
269 showFatalError( "Unable to configure the Maven application", e, showErrors );
270
271 return 1;
272 }
273 finally
274 {
275 if ( loggerManager != null )
276 {
277 try
278 {
279 embedder.release( loggerManager );
280 }
281 catch ( ComponentLifecycleException e )
282 {
283 showFatalError( "Error releasing logging manager", e, showErrors );
284 }
285 }
286 }
287
288 try
289 {
290 maven.execute( request );
291 }
292 catch ( MavenExecutionException e )
293 {
294 return 1;
295 }
296
297 return 0;
298 }
299
300 private static Settings buildSettings( CommandLine commandLine )
301 throws ComponentLookupException, SettingsConfigurationException
302 {
303 String userSettingsPath = null;
304
305 if ( commandLine.hasOption( CLIManager.ALTERNATE_USER_SETTINGS ) )
306 {
307 userSettingsPath = commandLine.getOptionValue( CLIManager.ALTERNATE_USER_SETTINGS );
308 }
309
310 Settings settings = null;
311
312 MavenSettingsBuilder settingsBuilder = (MavenSettingsBuilder) embedder.lookup( MavenSettingsBuilder.ROLE );
313
314 try
315 {
316 if ( userSettingsPath != null )
317 {
318 File userSettingsFile = new File( userSettingsPath );
319
320 if ( userSettingsFile.exists() && !userSettingsFile.isDirectory() )
321 {
322 settings = settingsBuilder.buildSettings( userSettingsFile );
323 }
324 else
325 {
326 System.out.println( "WARNING: Alternate user settings file: " + userSettingsPath +
327 " is invalid. Using default path." );
328 }
329 }
330
331 if ( settings == null )
332 {
333 settings = settingsBuilder.buildSettings();
334 }
335 }
336 catch ( IOException e )
337 {
338 throw new SettingsConfigurationException( "Error reading settings file", e );
339 }
340 catch ( XmlPullParserException e )
341 {
342 throw new SettingsConfigurationException( e.getMessage(), e.getDetail(), e.getLineNumber(),
343 e.getColumnNumber() );
344 }
345
346
347
348 if ( commandLine.hasOption( CLIManager.BATCH_MODE ) )
349 {
350 settings.setInteractiveMode( false );
351 }
352
353 if ( commandLine.hasOption( CLIManager.SUPPRESS_PLUGIN_REGISTRY ) )
354 {
355 settings.setUsePluginRegistry( false );
356 }
357
358
359
360 settings.setRuntimeInfo( createRuntimeInfo( commandLine, settings ) );
361
362 return settings;
363 }
364
365 private static RuntimeInfo createRuntimeInfo( CommandLine commandLine, Settings settings )
366 {
367 RuntimeInfo runtimeInfo = new RuntimeInfo( settings );
368
369 if ( commandLine.hasOption( CLIManager.FORCE_PLUGIN_UPDATES ) ||
370 commandLine.hasOption( CLIManager.FORCE_PLUGIN_UPDATES2 ) )
371 {
372 runtimeInfo.setPluginUpdateOverride( Boolean.TRUE );
373 }
374 else if ( commandLine.hasOption( CLIManager.SUPPRESS_PLUGIN_UPDATES ) )
375 {
376 runtimeInfo.setPluginUpdateOverride( Boolean.FALSE );
377 }
378
379 return runtimeInfo;
380 }
381
382
383 private static void showFatalError( String message, Exception e, boolean show )
384 {
385 System.err.println( "FATAL ERROR: " + message );
386 if ( show )
387 {
388 System.err.println( "Error stacktrace:" );
389
390 e.printStackTrace();
391 }
392 else
393 {
394 System.err.println( "For more information, run with the -e flag" );
395 }
396 }
397
398 private static void showError( String message, Exception e, boolean show )
399 {
400 System.err.println( message );
401 if ( show )
402 {
403 System.err.println( "Error stacktrace:" );
404
405 e.printStackTrace();
406 }
407 }
408
409 private static MavenExecutionRequest createRequest( CommandLine commandLine, Settings settings,
410 EventDispatcher eventDispatcher, LoggerManager loggerManager,
411 ProfileManager profileManager, Properties executionProperties,
412 Properties userProperties, boolean showErrors )
413 throws ComponentLookupException
414 {
415 MavenExecutionRequest request;
416
417 ArtifactRepository localRepository = createLocalRepository( embedder, settings, commandLine );
418
419 File userDir = new File( System.getProperty( "user.dir" ) );
420
421 request = new DefaultMavenExecutionRequest( localRepository, settings, eventDispatcher,
422 commandLine.getArgList(), userDir.getPath(), profileManager,
423 executionProperties, userProperties, showErrors );
424
425
426 Logger logger = loggerManager.getLoggerForComponent( Mojo.ROLE );
427
428 if ( logger != null )
429 {
430 request.addEventMonitor( new DefaultEventMonitor( logger ) );
431 }
432
433 if ( commandLine.hasOption( CLIManager.NON_RECURSIVE ) )
434 {
435 request.setRecursive( false );
436 }
437
438 if ( commandLine.hasOption( CLIManager.FAIL_FAST ) )
439 {
440 request.setFailureBehavior( ReactorManager.FAIL_FAST );
441 }
442 else if ( commandLine.hasOption( CLIManager.FAIL_AT_END ) )
443 {
444 request.setFailureBehavior( ReactorManager.FAIL_AT_END );
445 }
446 else if ( commandLine.hasOption( CLIManager.FAIL_NEVER ) )
447 {
448 request.setFailureBehavior( ReactorManager.FAIL_NEVER );
449 }
450
451 return request;
452 }
453
454 private static void setProjectFileOptions( CommandLine commandLine, MavenExecutionRequest request )
455 {
456 if ( commandLine.hasOption( CLIManager.REACTOR ) )
457 {
458 request.setReactorActive( true );
459 }
460 else if ( commandLine.hasOption( CLIManager.ALTERNATE_POM_FILE ) )
461 {
462 request.setPomFile( commandLine.getOptionValue( CLIManager.ALTERNATE_POM_FILE ) );
463 }
464 }
465
466 private static Maven createMavenInstance( boolean interactive )
467 throws ComponentLookupException
468 {
469
470 WagonManager wagonManager = (WagonManager) embedder.lookup( WagonManager.ROLE );
471 if ( interactive )
472 {
473 wagonManager.setDownloadMonitor( new ConsoleDownloadMonitor() );
474 }
475 else
476 {
477 wagonManager.setDownloadMonitor( new BatchModeDownloadMonitor() );
478 }
479
480 wagonManager.setInteractive( interactive );
481
482 return (Maven) embedder.lookup( Maven.ROLE );
483 }
484
485 private static ArtifactRepository createLocalRepository( Embedder embedder, Settings settings,
486 CommandLine commandLine )
487 throws ComponentLookupException
488 {
489
490
491 ArtifactRepositoryLayout repositoryLayout =
492 (ArtifactRepositoryLayout) embedder.lookup( ArtifactRepositoryLayout.ROLE, "default" );
493
494 ArtifactRepositoryFactory artifactRepositoryFactory =
495 (ArtifactRepositoryFactory) embedder.lookup( ArtifactRepositoryFactory.ROLE );
496
497 String url = settings.getLocalRepository();
498
499 if ( !url.startsWith( "file:" ) )
500 {
501 url = "file://" + url;
502 }
503
504 ArtifactRepository localRepository = new DefaultArtifactRepository( "local", url, repositoryLayout );
505
506 boolean snapshotPolicySet = false;
507
508 if ( commandLine.hasOption( CLIManager.OFFLINE ) )
509 {
510 settings.setOffline( true );
511
512 snapshotPolicySet = true;
513 }
514
515 if ( !snapshotPolicySet && commandLine.hasOption( CLIManager.UPDATE_SNAPSHOTS ) )
516 {
517 artifactRepositoryFactory.setGlobalUpdatePolicy( ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS );
518 }
519
520 if ( commandLine.hasOption( CLIManager.CHECKSUM_FAILURE_POLICY ) )
521 {
522 System.out.println( "+ Enabling strict checksum verification on all artifact downloads." );
523
524 artifactRepositoryFactory.setGlobalChecksumPolicy( ArtifactRepositoryPolicy.CHECKSUM_POLICY_FAIL );
525 }
526 else if ( commandLine.hasOption( CLIManager.CHECKSUM_WARNING_POLICY ) )
527 {
528 System.out.println( "+ Disabling strict checksum verification on all artifact downloads." );
529
530 artifactRepositoryFactory.setGlobalChecksumPolicy( ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN );
531 }
532
533 return localRepository;
534 }
535
536 static Properties getBuildProperties()
537 {
538 Properties properties = new Properties();
539 InputStream resourceAsStream = null;
540 try
541 {
542 resourceAsStream = MavenCli.class.getClassLoader().getResourceAsStream( "org/apache/maven/messages/build.properties" );
543
544 if ( resourceAsStream != null )
545 {
546 properties.load( resourceAsStream );
547 }
548 }
549 catch ( IOException e )
550 {
551 System.err.println( "Unable determine version from JAR file: " + e.getMessage() );
552 }
553 finally
554 {
555 IOUtil.close( resourceAsStream );
556 }
557
558 return properties;
559 }
560
561 private static void showVersion()
562 {
563 Properties properties = getBuildProperties();
564
565 String timestamp = reduce( properties.getProperty( "timestamp" ) );
566 String version = reduce( properties.getProperty( "version" ) );
567 String rev = reduce( properties.getProperty( "buildNumber" ) );
568
569 String msg = "Apache Maven ";
570 msg += ( version != null ? version : "<version unknown>" );
571 if ( rev != null || timestamp != null )
572 {
573 msg += " (";
574 msg += ( rev != null ? "r" + rev : "" );
575 if ( timestamp != null )
576 {
577 SimpleDateFormat fmt = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ssZ" );
578 String ts = fmt.format( new Date( Long.valueOf( timestamp ).longValue() ) );
579 msg += ( rev != null ? "; " : "" ) + ts;
580 }
581 msg += ")";
582 }
583
584 System.out.println( msg );
585
586 System.out.println( "Java version: " + System.getProperty( "java.version", "<unknown java version>" ) );
587
588 System.out.println( "Java home: " + System.getProperty( "java.home", "<unknown java home>" ) );
589
590 System.out.println( "Default locale: " + Locale.getDefault() + ", platform encoding: "
591 + System.getProperty( "file.encoding", "<unknown encoding>" ) );
592
593 System.out.println( "OS name: \"" + Os.OS_NAME + "\" version: \"" + Os.OS_VERSION +
594 "\" arch: \"" + Os.OS_ARCH + "\" Family: \"" + Os.OS_FAMILY + "\"" );
595 }
596
597 private static String reduce( String s )
598 {
599 return ( s != null ? ( s.startsWith( "${" ) && s.endsWith( "}" ) ? null : s ) : null );
600 }
601
602
603
604
605
606 static void populateProperties( CommandLine commandLine, Properties executionProperties, Properties userProperties )
607 {
608
609
610 try
611 {
612 Properties envVars = CommandLineUtils.getSystemEnvVars();
613 Iterator i = envVars.entrySet().iterator();
614 while ( i.hasNext() )
615 {
616 Entry e = (Entry) i.next();
617 executionProperties.setProperty( "env." + e.getKey().toString(), e.getValue().toString() );
618 }
619 }
620 catch ( IOException e )
621 {
622 System.err.println( "Error getting environment vars for profile activation: " + e );
623 }
624
625
626
627
628
629
630
631 if ( commandLine.hasOption( CLIManager.SET_SYSTEM_PROPERTY ) )
632 {
633 String[] defStrs = commandLine.getOptionValues( CLIManager.SET_SYSTEM_PROPERTY );
634
635 if ( defStrs != null )
636 {
637 for ( int i = 0; i < defStrs.length; ++i )
638 {
639 setCliProperty( defStrs[i], userProperties );
640 }
641 }
642
643 executionProperties.putAll( userProperties );
644 }
645
646 executionProperties.putAll( System.getProperties() );
647 }
648
649 private static void setCliProperty( String property, Properties requestProperties )
650 {
651 String name;
652
653 String value;
654
655 int i = property.indexOf( "=" );
656
657 if ( i <= 0 )
658 {
659 name = property.trim();
660
661 value = "true";
662 }
663 else
664 {
665 name = property.substring( 0, i ).trim();
666
667 value = property.substring( i + 1 ).trim();
668 }
669
670 requestProperties.setProperty( name, value );
671
672
673
674
675
676
677 System.setProperty( name, value );
678 }
679 }