View Javadoc

1   package org.apache.maven.cli;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.text.SimpleDateFormat;
26  import java.util.Arrays;
27  import java.util.Date;
28  import java.util.Iterator;
29  import java.util.Locale;
30  import java.util.Properties;
31  import java.util.StringTokenizer;
32  import java.util.Map.Entry;
33  
34  import org.apache.commons.cli.CommandLine;
35  import org.apache.commons.cli.ParseException;
36  import org.apache.maven.Maven;
37  import org.apache.maven.SettingsConfigurationException;
38  import org.apache.maven.artifact.manager.WagonManager;
39  import org.apache.maven.artifact.repository.ArtifactRepository;
40  import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
41  import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
42  import org.apache.maven.artifact.repository.DefaultArtifactRepository;
43  import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
44  import org.apache.maven.execution.DefaultMavenExecutionRequest;
45  import org.apache.maven.execution.MavenExecutionRequest;
46  import org.apache.maven.execution.ReactorManager;
47  import org.apache.maven.monitor.event.DefaultEventDispatcher;
48  import org.apache.maven.monitor.event.DefaultEventMonitor;
49  import org.apache.maven.monitor.event.EventDispatcher;
50  import org.apache.maven.plugin.Mojo;
51  import org.apache.maven.profiles.DefaultProfileManager;
52  import org.apache.maven.profiles.ProfileManager;
53  import org.apache.maven.reactor.MavenExecutionException;
54  import org.apache.maven.settings.MavenSettingsBuilder;
55  import org.apache.maven.settings.RuntimeInfo;
56  import org.apache.maven.settings.Settings;
57  import org.codehaus.classworlds.ClassWorld;
58  import org.codehaus.plexus.PlexusContainerException;
59  import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
60  import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
61  import org.codehaus.plexus.embed.Embedder;
62  import org.codehaus.plexus.logging.Logger;
63  import org.codehaus.plexus.logging.LoggerManager;
64  import org.codehaus.plexus.util.IOUtil;
65  import org.codehaus.plexus.util.Os;
66  import org.codehaus.plexus.util.StringUtils;
67  import org.codehaus.plexus.util.cli.CommandLineUtils;
68  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
69  import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
70  import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
71  import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
72  import org.sonatype.plexus.components.sec.dispatcher.SecUtil;
73  import org.sonatype.plexus.components.sec.dispatcher.model.SettingsSecurity;
74  
75  /**
76   * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
77   * @version $Id: MavenCli.java 788791 2009-06-26 17:55:26Z jdcasey $
78   * @noinspection UseOfSystemOutOrSystemErr,ACCESS_STATIC_VIA_INSTANCE
79   */
80  public class MavenCli
81  {
82      /** @deprecated use {@link Os#OS_NAME} */
83      public static final String OS_NAME = Os.OS_NAME;
84  
85      /** @deprecated use {@link Os#OS_ARCH} */
86      public static final String OS_ARCH = Os.OS_ARCH;
87  
88      /** @deprecated use {@link Os#OS_VERSION} */
89      public static final String OS_VERSION = Os.OS_VERSION;
90  
91      private static Embedder embedder;
92  
93      /**
94       * @deprecated Use {@link Main#main(String[])} instead.
95       */
96      public static void main( String[] args )
97      {
98          ClassWorld classWorld = new ClassWorld( "plexus.core", Thread.currentThread().getContextClassLoader() );
99  
100         int result = main( args, classWorld );
101 
102         System.exit( result );
103     }
104 
105     /**
106      * @noinspection ConfusingMainMethod
107      */
108     public static int main( String[] args, ClassWorld classWorld )
109     {
110         // ----------------------------------------------------------------------
111         // Setup the command line parser
112         // ----------------------------------------------------------------------
113         
114         CLIManager cliManager = new CLIManager();
115 
116         CommandLine commandLine;
117         try
118         {
119             commandLine = cliManager.parse( args );
120         }
121         catch ( ParseException e )
122         {
123             System.err.println( "Unable to parse command line options: " + e.getMessage() );
124             cliManager.displayHelp();
125             return 1;
126         }
127 
128         boolean debug = commandLine.hasOption( CLIManager.DEBUG );
129 
130         boolean showErrors = debug || commandLine.hasOption( CLIManager.ERRORS );
131 
132         if ( showErrors )
133         {
134             System.out.println( "+ Error stacktraces are turned on." );
135         }
136 
137         // ----------------------------------------------------------------------
138         // Process particular command line options
139         // ----------------------------------------------------------------------
140 
141         if ( commandLine.hasOption( CLIManager.HELP ) )
142         {
143             cliManager.displayHelp();
144             return 0;
145         }
146         
147         if ( commandLine.hasOption( CLIManager.VERSION ) )
148         {
149             showVersion();
150 
151             return 0;
152         }
153         else if ( debug || commandLine.hasOption( CLIManager.SHOW_VERSION ) )
154         {
155             showVersion();
156         }
157 
158         EventDispatcher eventDispatcher = new DefaultEventDispatcher();
159 
160         // Make sure the Maven home directory is an absolute path to save us from confusion with say drive-relative
161         // Windows paths.
162         String mavenHome = System.getProperty( "maven.home" );
163         if ( mavenHome != null )
164         {
165             System.setProperty( "maven.home", new File( mavenHome ).getAbsolutePath() );
166         }
167 
168         // ----------------------------------------------------------------------
169         // Now that we have everything that we need we will fire up plexus and
170         // bring the maven component to life for use.
171         // ----------------------------------------------------------------------
172 
173         embedder = new Embedder();
174 
175         try
176         {
177             embedder.start( classWorld );
178         }
179         catch ( PlexusContainerException e )
180         {
181             showFatalError( "Unable to start the embedded plexus container", e, showErrors );
182 
183             return 1;
184         }
185 
186         // wraps the following code to ensure the embedder is stopped no matter what else happens.
187         try
188         {
189             // ----------------------------------------------------------------------
190             // The execution properties need to be created before the settings
191             // are constructed.
192             // ----------------------------------------------------------------------
193 
194             Properties executionProperties = new Properties();
195             Properties userProperties = new Properties();
196             populateProperties( commandLine, executionProperties, userProperties );
197 
198             Settings settings;
199 
200             try
201             {
202                 settings = buildSettings( commandLine );
203             }
204             catch ( SettingsConfigurationException e )
205             {
206                 showError( "Error reading settings.xml: " + e.getMessage(), e, showErrors );
207 
208                 return 1;
209             }
210             catch ( ComponentLookupException e )
211             {
212                 showFatalError( "Unable to read settings.xml", e, showErrors );
213 
214                 return 1;
215             }
216 
217             DefaultSecDispatcher dispatcher;
218             try
219             {
220                 if ( commandLine.hasOption( CLIManager.ENCRYPT_MASTER_PASSWORD ) )
221                 {
222                     String passwd = commandLine.getOptionValue( CLIManager.ENCRYPT_MASTER_PASSWORD );
223 
224                     DefaultPlexusCipher cipher = new DefaultPlexusCipher();
225 
226                     System.out.println( cipher.encryptAndDecorate( passwd,
227                                                                    DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION ) );
228                     
229                     return 0;
230                 }
231                 else if ( commandLine.hasOption( CLIManager.ENCRYPT_PASSWORD ) )
232                 {
233                     String passwd = commandLine.getOptionValue( CLIManager.ENCRYPT_PASSWORD );
234                     
235                     dispatcher = (DefaultSecDispatcher) embedder.lookup( SecDispatcher.ROLE );
236                     String configurationFile = dispatcher.getConfigurationFile();
237                     if ( configurationFile.startsWith( "~" ) )
238                     {
239                         configurationFile = System.getProperty( "user.home" ) + configurationFile.substring( 1 );
240                     }
241                     String file = System.getProperty( DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION, configurationFile );
242                     embedder.release( dispatcher );
243                     
244                     String master = null;
245                     
246                     SettingsSecurity sec = SecUtil.read( file, true );
247                     if ( sec != null )
248                     {
249                         master = sec.getMaster();
250                     }
251 
252                     if ( master == null )
253                     {
254                         System.err.println( "Master password is not set in the setting security file" );
255                         
256                         return 1;
257                     }
258                     
259                     DefaultPlexusCipher cipher = new DefaultPlexusCipher();
260                     String masterPasswd =
261                         cipher.decryptDecorated( master, DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION );
262                     System.out.println( cipher.encryptAndDecorate( passwd, masterPasswd ) );
263                     
264                     return 0;
265                 }
266             }
267             catch ( Exception e )
268             {
269                 showFatalError( "Error encrypting password: " + e.getMessage(), e, showErrors );
270                 
271                 return 1;
272             }
273                 
274             Maven maven = null;
275 
276             MavenExecutionRequest request = null;
277 
278             LoggerManager loggerManager = null;
279 
280             try
281             {
282                 // logger must be created first
283                 loggerManager = (LoggerManager) embedder.lookup( LoggerManager.ROLE );
284 
285                 if ( debug )
286                 {
287                     loggerManager.setThreshold( Logger.LEVEL_DEBUG );
288                 }
289                 else if ( commandLine.hasOption( CLIManager.QUIET ) )
290                 {
291                     // TODO: we need to do some more work here. Some plugins use sys out or log errors at info level.
292                     // Ideally, we could use Warn across the board
293                     loggerManager.setThreshold( Logger.LEVEL_ERROR );
294                     // TODO:Additionally, we can't change the mojo level because the component key includes the version and it isn't known ahead of time. This seems worth changing.
295                 }
296 
297                 ProfileManager profileManager = new DefaultProfileManager( embedder.getContainer(), executionProperties );
298 
299                 if ( commandLine.hasOption( CLIManager.ACTIVATE_PROFILES ) )
300                 {
301                     String [] profileOptionValues = commandLine.getOptionValues( CLIManager.ACTIVATE_PROFILES );
302 
303                     if ( profileOptionValues != null )
304                     {
305                         for ( int i=0; i < profileOptionValues.length; ++i )
306                         {
307                             StringTokenizer profileTokens = new StringTokenizer( profileOptionValues[i], "," );
308 
309                             while ( profileTokens.hasMoreTokens() )
310                             {
311                                 String profileAction = profileTokens.nextToken().trim();
312 
313                                 if ( profileAction.startsWith( "-" ) || profileAction.startsWith( "!" ) )
314                                 {
315                                     profileManager.explicitlyDeactivate( profileAction.substring( 1 ) );
316                                 }
317                                 else if ( profileAction.startsWith( "+" ) )
318                                 {
319                                     profileManager.explicitlyActivate( profileAction.substring( 1 ) );
320                                 }
321                                 else
322                                 {
323                                     profileManager.explicitlyActivate( profileAction );
324                                 }
325                             }
326                         }
327                     }
328                 }
329 
330                 request = createRequest( commandLine, settings, eventDispatcher, loggerManager, profileManager,
331                                          executionProperties, userProperties, showErrors );
332 
333                 setProjectFileOptions( commandLine, request );
334 
335                 maven =
336                     createMavenInstance( settings.isInteractiveMode(),
337                                          loggerManager.getLoggerForComponent( WagonManager.ROLE ) );
338             }
339             catch ( ComponentLookupException e )
340             {
341                 showFatalError( "Unable to configure the Maven application", e, showErrors );
342 
343                 return 1;
344             }
345             finally
346             {
347                 if ( loggerManager != null )
348                 {
349                     try
350                     {
351                         embedder.release( loggerManager );
352                     }
353                     catch ( ComponentLifecycleException e )
354                     {
355                         showFatalError( "Error releasing logging manager", e, showErrors );
356                     }
357                 }
358             }
359 
360             try
361             {
362                 maven.execute( request );
363             }
364             catch ( MavenExecutionException e )
365             {
366                 return 1;
367             }
368         }
369         finally
370         {
371             try
372             {
373                 embedder.stop();
374             }
375             catch ( Exception e )
376             {
377                 // do nothing; we took our best shot.
378             }
379         }
380 
381         return 0;
382     }
383 
384     private static Settings buildSettings( CommandLine commandLine )
385         throws ComponentLookupException, SettingsConfigurationException
386     {
387         String userSettingsPath = null;
388 
389         if ( commandLine.hasOption( CLIManager.ALTERNATE_USER_SETTINGS ) )
390         {
391             userSettingsPath = commandLine.getOptionValue( CLIManager.ALTERNATE_USER_SETTINGS );
392         }
393 
394         if ( commandLine.hasOption( CLIManager.ALTERNATE_GLOBAL_SETTINGS ) )
395         {
396             String globalSettingsPath = commandLine.getOptionValue( CLIManager.ALTERNATE_GLOBAL_SETTINGS );
397             System.setProperty( MavenSettingsBuilder.ALT_GLOBAL_SETTINGS_XML_LOCATION, globalSettingsPath );
398         }
399 
400         Settings settings = null;
401 
402         MavenSettingsBuilder settingsBuilder = (MavenSettingsBuilder) embedder.lookup( MavenSettingsBuilder.ROLE );
403 
404         try
405         {
406             if ( userSettingsPath != null )
407             {
408                 File userSettingsFile = new File( userSettingsPath );
409 
410                 if ( userSettingsFile.exists() && !userSettingsFile.isDirectory() )
411                 {
412                     settings = settingsBuilder.buildSettings( userSettingsFile );
413                 }
414                 else
415                 {
416                     System.out.println( "WARNING: Alternate user settings file: " + userSettingsPath +
417                         " is invalid. Using default path." );
418                 }
419             }
420 
421             if ( settings == null )
422             {
423                 settings = settingsBuilder.buildSettings();
424             }
425         }
426         catch ( IOException e )
427         {
428             throw new SettingsConfigurationException( "Error reading settings file", e );
429         }
430         catch ( XmlPullParserException e )
431         {
432             throw new SettingsConfigurationException( e.getMessage(), e, e.getLineNumber(),
433                                                       e.getColumnNumber() );
434         }
435 
436         // why aren't these part of the runtime info? jvz.
437 
438         if ( commandLine.hasOption( CLIManager.BATCH_MODE ) )
439         {
440             settings.setInteractiveMode( false );
441         }
442 
443         if ( commandLine.hasOption( CLIManager.SUPPRESS_PLUGIN_REGISTRY ) )
444         {
445             settings.setUsePluginRegistry( false );
446         }
447 
448         // Create settings runtime info
449 
450         settings.setRuntimeInfo( createRuntimeInfo( commandLine, settings ) );
451 
452         return settings;
453     }
454 
455     private static RuntimeInfo createRuntimeInfo( CommandLine commandLine, Settings settings )
456     {
457         RuntimeInfo runtimeInfo = new RuntimeInfo( settings );
458 
459         if ( commandLine.hasOption( CLIManager.FORCE_PLUGIN_UPDATES ) ||
460             commandLine.hasOption( CLIManager.FORCE_PLUGIN_UPDATES2 ) )
461         {
462             runtimeInfo.setPluginUpdateOverride( Boolean.TRUE );
463         }
464         else if ( commandLine.hasOption( CLIManager.SUPPRESS_PLUGIN_UPDATES ) )
465         {
466             runtimeInfo.setPluginUpdateOverride( Boolean.FALSE );
467         }
468 
469         return runtimeInfo;
470     }
471 
472 
473     private static void showFatalError( String message, Exception e, boolean show )
474     {
475         System.err.println( "FATAL ERROR: " + message );
476         if ( show )
477         {
478             System.err.println( "Error stacktrace:" );
479 
480             e.printStackTrace();
481         }
482         else
483         {
484             System.err.println( "For more information, run with the -e flag" );
485         }
486     }
487 
488     private static void showError( String message, Exception e, boolean show )
489     {
490         System.err.println( message );
491         if ( show )
492         {
493             System.err.println( "Error stacktrace:" );
494 
495             e.printStackTrace();
496         }
497     }
498 
499     private static MavenExecutionRequest createRequest( CommandLine commandLine, Settings settings,
500                                                         EventDispatcher eventDispatcher, LoggerManager loggerManager,
501                                                         ProfileManager profileManager, Properties executionProperties,
502                                                         Properties userProperties, boolean showErrors )
503         throws ComponentLookupException
504     {
505         MavenExecutionRequest request;
506 
507         ArtifactRepository localRepository = createLocalRepository( embedder, settings, commandLine );
508 
509         File userDir = new File( System.getProperty( "user.dir" ) );
510 
511         request = new DefaultMavenExecutionRequest( localRepository, settings, eventDispatcher,
512                                                     commandLine.getArgList(), userDir.getPath(), profileManager,
513                                                     executionProperties, userProperties, showErrors );
514 
515         // TODO [BP]: do we set one per mojo? where to do it?
516         Logger logger = loggerManager.getLoggerForComponent( Mojo.ROLE );
517 
518         if ( logger != null )
519         {
520             request.addEventMonitor( new DefaultEventMonitor( logger ) );
521         }
522 
523         if ( commandLine.hasOption( CLIManager.NON_RECURSIVE ) )
524         {
525             request.setRecursive( false );
526         }
527 
528         if ( commandLine.hasOption( CLIManager.FAIL_FAST ) )
529         {
530             request.setFailureBehavior( ReactorManager.FAIL_FAST );
531         }
532         else if ( commandLine.hasOption( CLIManager.FAIL_AT_END ) )
533         {
534             request.setFailureBehavior( ReactorManager.FAIL_AT_END );
535         }
536         else if ( commandLine.hasOption( CLIManager.FAIL_NEVER ) )
537         {
538             request.setFailureBehavior( ReactorManager.FAIL_NEVER );
539         }
540 
541         return request;
542     }
543 
544     private static void setProjectFileOptions( CommandLine commandLine, MavenExecutionRequest request )
545     {
546         if ( commandLine.hasOption( CLIManager.REACTOR ) )
547         {
548             request.setReactorActive( true );
549         }
550         else if ( commandLine.hasOption( CLIManager.ALTERNATE_POM_FILE ) )
551         {
552             request.setPomFile( commandLine.getOptionValue( CLIManager.ALTERNATE_POM_FILE ) );
553         }
554         
555         if ( commandLine.hasOption( CLIManager.RESUME_FROM ) )
556         {
557             request.setResumeFrom( commandLine.getOptionValue( CLIManager.RESUME_FROM ) );
558         }
559         
560         if ( commandLine.hasOption( CLIManager.PROJECT_LIST ) )
561         {
562             String projectList = commandLine.getOptionValue( CLIManager.PROJECT_LIST );
563             String[] projects = StringUtils.split( projectList, "," );
564             request.setSelectedProjects( Arrays.asList( projects ) );
565         }
566         
567         if ( commandLine.hasOption( CLIManager.ALSO_MAKE ) && !commandLine.hasOption( CLIManager.ALSO_MAKE_DEPENDENTS ) )
568         {
569             request.setMakeBehavior( ReactorManager.MAKE_MODE );
570         }
571         else if ( !commandLine.hasOption( CLIManager.ALSO_MAKE )
572             && commandLine.hasOption( CLIManager.ALSO_MAKE_DEPENDENTS ) )
573         {
574             request.setMakeBehavior( ReactorManager.MAKE_DEPENDENTS_MODE );
575         }
576         if ( commandLine.hasOption( CLIManager.ALSO_MAKE ) && commandLine.hasOption( CLIManager.ALSO_MAKE_DEPENDENTS ) )
577         {
578             request.setMakeBehavior( ReactorManager.MAKE_BOTH_MODE );
579         }
580     }
581 
582     private static Maven createMavenInstance( boolean interactive, Logger logger )
583         throws ComponentLookupException
584     {
585         // TODO [BP]: doing this here as it is CLI specific, though it doesn't feel like the right place (likewise logger).
586         WagonManager wagonManager = (WagonManager) embedder.lookup( WagonManager.ROLE );
587         if ( interactive )
588         {
589             wagonManager.setDownloadMonitor( new ConsoleDownloadMonitor( logger ) );
590         }
591         else
592         {
593             wagonManager.setDownloadMonitor( new BatchModeDownloadMonitor( logger ) );
594         }
595 
596         wagonManager.setInteractive( interactive );
597 
598         return (Maven) embedder.lookup( Maven.ROLE );
599     }
600 
601     private static ArtifactRepository createLocalRepository( Embedder embedder, Settings settings,
602                                                              CommandLine commandLine )
603         throws ComponentLookupException
604     {
605         // TODO: release
606         // TODO: something in plexus to show all active hooks?
607         ArtifactRepositoryLayout repositoryLayout =
608             (ArtifactRepositoryLayout) embedder.lookup( ArtifactRepositoryLayout.ROLE, "default" );
609 
610         ArtifactRepositoryFactory artifactRepositoryFactory =
611             (ArtifactRepositoryFactory) embedder.lookup( ArtifactRepositoryFactory.ROLE );
612 
613         String url = settings.getLocalRepository();
614 
615         if ( !url.startsWith( "file:" ) )
616         {
617             url = "file://" + url;
618         }
619 
620         ArtifactRepository localRepository = new DefaultArtifactRepository( "local", url, repositoryLayout );
621 
622         boolean snapshotPolicySet = false;
623 
624         if ( commandLine.hasOption( CLIManager.OFFLINE ) )
625         {
626             settings.setOffline( true );
627 
628             snapshotPolicySet = true;
629         }
630 
631         if ( !snapshotPolicySet && commandLine.hasOption( CLIManager.UPDATE_SNAPSHOTS ) )
632         {
633             artifactRepositoryFactory.setGlobalUpdatePolicy( ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS );
634         }
635 
636         if ( commandLine.hasOption( CLIManager.CHECKSUM_FAILURE_POLICY ) )
637         {
638             System.out.println( "+ Enabling strict checksum verification on all artifact downloads." );
639 
640             artifactRepositoryFactory.setGlobalChecksumPolicy( ArtifactRepositoryPolicy.CHECKSUM_POLICY_FAIL );
641         }
642         else if ( commandLine.hasOption( CLIManager.CHECKSUM_WARNING_POLICY ) )
643         {
644             System.out.println( "+ Disabling strict checksum verification on all artifact downloads." );
645 
646             artifactRepositoryFactory.setGlobalChecksumPolicy( ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN );
647         }
648 
649         return localRepository;
650     }
651 
652     static Properties getBuildProperties()
653     {
654         Properties properties = new Properties();
655         InputStream resourceAsStream = null;
656         try
657         {
658             resourceAsStream = MavenCli.class.getClassLoader().getResourceAsStream( "org/apache/maven/messages/build.properties" );
659 
660             if ( resourceAsStream != null )
661             {
662                 properties.load( resourceAsStream );
663             }
664         }
665         catch ( IOException e )
666         {
667             System.err.println( "Unable determine version from JAR file: " + e.getMessage() );
668         }
669         finally
670         {
671             IOUtil.close( resourceAsStream );
672         }
673 
674         return properties;
675     }
676 
677     private static void showVersion()
678     {
679         Properties properties = getBuildProperties();
680 
681         String timestamp = reduce( properties.getProperty( "timestamp" ) );
682         String version = reduce( properties.getProperty( "version" ) );
683         String rev = reduce( properties.getProperty( "buildNumber" ) );
684 
685         String msg = "Apache Maven ";
686         msg += ( version != null ? version : "<version unknown>" );
687         if ( rev != null || timestamp != null )
688         {
689             msg += " (";
690             msg += ( rev != null ? "r" + rev : "" );
691             if ( timestamp != null )
692             {
693                 SimpleDateFormat fmt = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ssZ" );
694                 String ts = fmt.format( new Date( Long.valueOf( timestamp ).longValue() ) );
695                 msg += ( rev != null ? "; " : "" ) + ts;
696             }
697             msg += ")";
698         }
699 
700         System.out.println( msg );
701 
702         System.out.println( "Java version: " + System.getProperty( "java.version", "<unknown java version>" ) );
703 
704         System.out.println( "Java home: " + System.getProperty( "java.home", "<unknown java home>" ) );
705 
706         System.out.println( "Default locale: " + Locale.getDefault() + ", platform encoding: "
707                             + System.getProperty( "file.encoding", "<unknown encoding>" ) );
708 
709         System.out.println( "OS name: \"" + Os.OS_NAME + "\" version: \"" + Os.OS_VERSION +
710                             "\" arch: \"" + Os.OS_ARCH + "\" Family: \"" + Os.OS_FAMILY + "\"" );
711     }
712 
713     private static String reduce( String s )
714     {
715         return ( s != null ? ( s.startsWith( "${" ) && s.endsWith( "}" ) ? null : s ) : null );
716     }
717 
718     // ----------------------------------------------------------------------
719     // System properties handling
720     // ----------------------------------------------------------------------
721 
722     static void populateProperties( CommandLine commandLine, Properties executionProperties, Properties userProperties )
723     {
724         // add the env vars to the property set, with the "env." prefix
725         // XXX support for env vars should probably be removed from the ModelInterpolator
726         try
727         {
728             Properties envVars = CommandLineUtils.getSystemEnvVars();
729             Iterator i = envVars.entrySet().iterator();
730             while ( i.hasNext() )
731             {
732                 Entry e = (Entry) i.next();
733                 executionProperties.setProperty( "env." + e.getKey().toString(), e.getValue().toString() );
734             }
735         }
736         catch ( IOException e )
737         {
738             System.err.println( "Error getting environment vars for profile activation: " + e );
739         }
740 
741         // ----------------------------------------------------------------------
742         // Options that are set on the command line become system properties
743         // and therefore are set in the session properties. System properties
744         // are most dominant.
745         // ----------------------------------------------------------------------
746 
747         if ( commandLine.hasOption( CLIManager.SET_SYSTEM_PROPERTY ) )
748         {
749             String[] defStrs = commandLine.getOptionValues( CLIManager.SET_SYSTEM_PROPERTY );
750 
751             if ( defStrs != null )
752             {
753                 for ( int i = 0; i < defStrs.length; ++i )
754                 {
755                     setCliProperty( defStrs[i], userProperties );
756                 }
757             }
758 
759             executionProperties.putAll( userProperties );
760         }
761 
762         executionProperties.putAll( System.getProperties() );
763     }
764 
765     private static void setCliProperty( String property, Properties requestProperties )
766     {
767         String name;
768 
769         String value;
770 
771         int i = property.indexOf( "=" );
772 
773         if ( i <= 0 )
774         {
775             name = property.trim();
776 
777             value = "true";
778         }
779         else
780         {
781             name = property.substring( 0, i ).trim();
782 
783             value = property.substring( i + 1 ).trim();
784         }
785 
786         requestProperties.setProperty( name, value );
787 
788         // ----------------------------------------------------------------------
789         // I'm leaving the setting of system properties here as not to break
790         // the SystemPropertyProfileActivator. This won't harm embedding. jvz.
791         // ----------------------------------------------------------------------
792 
793         System.setProperty( name, value );
794     }
795 }