View Javadoc

1   package org.apache.maven;
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  
23  import java.io.File;
24  import java.io.FileNotFoundException;
25  import java.io.IOException;
26  import java.text.DateFormat;
27  import java.text.SimpleDateFormat;
28  import java.util.ArrayList;
29  import java.util.Collections;
30  import java.util.Date;
31  import java.util.HashSet;
32  import java.util.Iterator;
33  import java.util.List;
34  import java.util.Properties;
35  import java.util.Set;
36  import java.util.TimeZone;
37  
38  import org.apache.maven.artifact.manager.DefaultWagonManager;
39  import org.apache.maven.artifact.manager.WagonManager;
40  import org.apache.maven.artifact.repository.ArtifactRepository;
41  import org.apache.maven.artifact.resolver.ArtifactResolutionException;
42  import org.apache.maven.artifact.resolver.ArtifactResolver;
43  import org.apache.maven.artifact.resolver.DefaultArtifactResolver;
44  import org.apache.maven.artifact.versioning.ArtifactVersion;
45  import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
46  import org.apache.maven.execution.BuildFailure;
47  import org.apache.maven.execution.DefaultMavenExecutionRequest;
48  import org.apache.maven.execution.MavenExecutionRequest;
49  import org.apache.maven.execution.MavenSession;
50  import org.apache.maven.execution.ReactorManager;
51  import org.apache.maven.execution.RuntimeInformation;
52  import org.apache.maven.lifecycle.LifecycleExecutionException;
53  import org.apache.maven.lifecycle.LifecycleExecutor;
54  import org.apache.maven.model.Profile;
55  import org.apache.maven.monitor.event.DefaultEventDispatcher;
56  import org.apache.maven.monitor.event.EventDispatcher;
57  import org.apache.maven.monitor.event.MavenEvents;
58  import org.apache.maven.profiles.ProfileManager;
59  import org.apache.maven.profiles.activation.ProfileActivationException;
60  import org.apache.maven.project.DuplicateProjectException;
61  import org.apache.maven.project.MavenProject;
62  import org.apache.maven.project.MavenProjectBuilder;
63  import org.apache.maven.project.MissingProjectException;
64  import org.apache.maven.project.ProjectBuildingException;
65  import org.apache.maven.reactor.MavenExecutionException;
66  import org.apache.maven.settings.Mirror;
67  import org.apache.maven.settings.Proxy;
68  import org.apache.maven.settings.Server;
69  import org.apache.maven.settings.Settings;
70  import org.apache.maven.usability.SystemWarnings;
71  import org.apache.maven.usability.diagnostics.ErrorDiagnostics;
72  import org.codehaus.plexus.PlexusConstants;
73  import org.codehaus.plexus.PlexusContainer;
74  import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
75  import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
76  import org.codehaus.plexus.context.Context;
77  import org.codehaus.plexus.context.ContextException;
78  import org.codehaus.plexus.logging.AbstractLogEnabled;
79  import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
80  import org.codehaus.plexus.util.FileUtils;
81  import org.codehaus.plexus.util.Os;
82  import org.codehaus.plexus.util.StringUtils;
83  import org.codehaus.plexus.util.dag.CycleDetectedException;
84  import org.codehaus.plexus.util.xml.Xpp3Dom;
85  import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
86  import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException;
87  
88  /**
89   * @author <a href="mailto:jason@maven.org">Jason van Zyl </a>
90   * @version $Id: DefaultMaven.java 753089 2009-03-13 02:25:40Z brett $
91   */
92  public class DefaultMaven
93      extends AbstractLogEnabled
94      implements Maven, Contextualizable
95  {
96      // ----------------------------------------------------------------------
97      // Components
98      // ----------------------------------------------------------------------
99  
100     protected MavenProjectBuilder projectBuilder;
101 
102     protected LifecycleExecutor lifecycleExecutor;
103 
104     protected PlexusContainer container;
105 
106     protected ErrorDiagnostics errorDiagnostics;
107 
108     protected RuntimeInformation runtimeInformation;
109 
110     private static final long MB = 1024 * 1024;
111 
112     private static final int MS_PER_SEC = 1000;
113 
114     private static final int SEC_PER_MIN = 60;
115 
116     // ----------------------------------------------------------------------
117     // Project execution
118     // ----------------------------------------------------------------------
119 
120     public void execute( MavenExecutionRequest request )
121         throws MavenExecutionException
122     {
123 //        if ( request.getLocalRepository() == null )
124 //        {
125 //            request.setLocalRepository( mavenTools.createLocalRepository( request.getLocalRepositoryPath() ) );
126 //        }
127 
128         EventDispatcher dispatcher = request.getEventDispatcher();
129 
130         String event = MavenEvents.REACTOR_EXECUTION;
131 
132         dispatcher.dispatchStart( event, request.getBaseDirectory() );
133 
134         ReactorManager rm;
135         try
136         {
137             rm = doExecute( request, dispatcher );
138         }
139         catch ( LifecycleExecutionException e )
140         {
141             dispatcher.dispatchError( event, request.getBaseDirectory(), e );
142 
143             logError( e, request.isShowErrors() );
144 
145             stats( request.getStartTime() );
146 
147             line();
148 
149             throw new MavenExecutionException( e.getMessage(), e );
150         }
151         catch ( BuildFailureException e )
152         {
153             dispatcher.dispatchError( event, request.getBaseDirectory(), e );
154 
155             logFailure( e, request.isShowErrors() );
156 
157             stats( request.getStartTime() );
158 
159             line();
160 
161             throw new MavenExecutionException( e.getMessage(), e );
162         }
163         catch ( Throwable t )
164         {
165             dispatcher.dispatchError( event, request.getBaseDirectory(), t );
166 
167             logFatal( t );
168 
169             stats( request.getStartTime() );
170 
171             line();
172 
173             throw new MavenExecutionException( "Error executing project within the reactor", t );
174         }
175 
176         // Either the build was successful, or it was a fail_at_end/fail_never reactor build
177 
178         // TODO: should all the logging be left to the CLI?
179         logReactorSummary( rm );
180 
181         if ( rm.hasBuildFailures() )
182         {
183             logErrors( rm, request.isShowErrors() );
184 
185             if ( !ReactorManager.FAIL_NEVER.equals( rm.getFailureBehavior() ) )
186             {
187                 dispatcher.dispatchError( event, request.getBaseDirectory(), null );
188 
189                 getLogger().info( "BUILD ERRORS" );
190 
191                 line();
192 
193                 stats( request.getStartTime() );
194 
195                 line();
196 
197                 throw new MavenExecutionException( "Some builds failed" );
198             }
199             else
200             {
201                 getLogger().info( " + Ignoring failures" );
202             }
203         }
204 
205         logSuccess( rm );
206 
207         stats( request.getStartTime() );
208 
209         line();
210 
211         dispatcher.dispatchEnd( event, request.getBaseDirectory() );
212     }
213 
214     private void logErrors( ReactorManager rm, boolean showErrors )
215     {
216         for ( Iterator it = rm.getSortedProjects().iterator(); it.hasNext(); )
217         {
218             MavenProject project = (MavenProject) it.next();
219 
220             if ( rm.hasBuildFailure( project ) )
221             {
222                 BuildFailure buildFailure = rm.getBuildFailure( project );
223 
224                 getLogger().info(
225                     "Error for project: " + project.getName() + " (during " + buildFailure.getTask() + ")" );
226 
227                 line();
228 
229                 logDiagnostics( buildFailure.getCause() );
230 
231                 logTrace( buildFailure.getCause(), showErrors );
232             }
233         }
234 
235         if ( !showErrors )
236         {
237             getLogger().info( "For more information, run Maven with the -e switch" );
238 
239             line();
240         }
241 
242     }
243 
244     private ReactorManager doExecute( MavenExecutionRequest request, EventDispatcher dispatcher )
245         throws MavenExecutionException, BuildFailureException, LifecycleExecutionException
246     {
247         if ( request.getSettings().isOffline() )
248         {
249             getLogger().info( SystemWarnings.getOfflineWarning() );
250 
251             WagonManager wagonManager = null;
252 
253             try
254             {
255                 wagonManager = (WagonManager) container.lookup( WagonManager.ROLE );
256 
257                 wagonManager.setOnline( false );
258             }
259             catch ( ComponentLookupException e )
260             {
261                 throw new MavenExecutionException( "Cannot retrieve WagonManager in order to set offline mode.", e );
262             }
263             finally
264             {
265                 try
266                 {
267                     container.release( wagonManager );
268                 }
269                 catch ( ComponentLifecycleException e )
270                 {
271                     getLogger().warn( "Cannot release WagonManager.", e );
272                 }
273             }
274         }
275 
276         try
277         {
278             resolveParameters( request.getSettings(), request.getExecutionProperties() );
279         }
280         catch ( ComponentLookupException e )
281         {
282             throw new MavenExecutionException( "Unable to configure Maven for execution", e );
283         }
284         catch ( ComponentLifecycleException e )
285         {
286             throw new MavenExecutionException( "Unable to configure Maven for execution", e );
287         }
288         catch ( SettingsConfigurationException e )
289         {
290             throw new MavenExecutionException( "Unable to configure Maven for execution", e );
291         }
292 
293         ProfileManager globalProfileManager = request.getGlobalProfileManager();
294 
295         globalProfileManager.loadSettingsProfiles( request.getSettings() );
296 
297         getLogger().info( "Scanning for projects..." );
298 
299         boolean foundProjects = true;
300         List projects = getProjects( request );
301         if ( projects.isEmpty() )
302         {
303             projects.add( getSuperProject( request ) );
304             foundProjects = false;
305         }
306 
307         ReactorManager rm;
308         try
309         {
310             String resumeFrom = request.getResumeFrom();
311             
312             List projectList = request.getSelectedProjects();
313             
314             String makeBehavior = request.getMakeBehavior();
315             
316             rm = new ReactorManager( projects, projectList, resumeFrom, makeBehavior );
317 
318             rm.setFailureBehavior( request.getFailureBehavior() );
319             
320         }
321         catch ( CycleDetectedException e )
322         {
323             throw new BuildFailureException(
324                 "The projects in the reactor contain a cyclic reference: " + e.getMessage(), e );
325         }
326         catch ( DuplicateProjectException e )
327         {
328             throw new BuildFailureException( e.getMessage(), e );
329         }
330         catch ( MissingProjectException e )
331         {
332             throw new BuildFailureException( e.getMessage(), e );
333         }
334 
335         // --------------------------------------------------------------------------------
336         // MNG-3641: print a warning if one of the profiles to be activated explicitly
337         // was not activated
338 
339         validateActivatedProfiles( globalProfileManager, projects );
340 
341         if ( rm.hasMultipleProjects() )
342         {
343             getLogger().info( "Reactor build order: " );
344 
345             for ( Iterator i = rm.getSortedProjects().iterator(); i.hasNext(); )
346             {
347                 MavenProject project = (MavenProject) i.next();
348                 getLogger().info( "  " + project.getName() );
349             }
350         }
351 
352         MavenSession session = createSession( request, rm );
353 
354         session.setUsingPOMsFromFilesystem( foundProjects );
355 
356         lifecycleExecutor.execute( session, rm, dispatcher );
357 
358         return rm;
359     }
360 
361     private void validateActivatedProfiles( ProfileManager globalProfileManager, List projects )
362     {
363         if ( globalProfileManager != null )
364         {
365             // get all activated profile ids
366             Set activeProfileIds = new HashSet();
367 
368             for ( Iterator i = projects.iterator(); i.hasNext(); )
369             {
370                 MavenProject project = (MavenProject) i.next();
371 
372                 do
373                 {
374                     for ( Iterator j = project.getActiveProfiles().iterator(); j.hasNext(); )
375                     {
376                         activeProfileIds.add( ( (Profile) j.next() ).getId() );
377                     }
378                     project = project.getParent();
379                 }
380                 while ( project != null );
381             }
382 
383             for ( Iterator i = globalProfileManager.getExplicitlyActivatedIds().iterator(); i.hasNext(); )
384             {
385                 String explicitProfileId = (String) i.next();
386 
387                 if ( !activeProfileIds.contains( explicitProfileId ) )
388                 {
389                     getLogger().warn( "\n\tProfile with id: \'" + explicitProfileId + "\' has not been activated.\n" );
390                 }
391             }
392         }
393     }
394 
395     private MavenProject getSuperProject( MavenExecutionRequest request )
396         throws MavenExecutionException
397     {
398         MavenProject superProject;
399         try
400         {
401             superProject = projectBuilder.buildStandaloneSuperProject( request.getLocalRepository(), request.getGlobalProfileManager() );
402 
403         }
404         catch ( ProjectBuildingException e )
405         {
406             throw new MavenExecutionException( e.getMessage(), e );
407         }
408         return superProject;
409     }
410 
411     private List getProjects( MavenExecutionRequest request )
412         throws MavenExecutionException, BuildFailureException
413     {
414         List projects;
415         try
416         {
417             List files = getProjectFiles( request );
418 
419             projects = collectProjects( files, request, !request.isReactorActive() );
420 
421         }
422         catch ( IOException e )
423         {
424             throw new MavenExecutionException( "Error processing projects for the reactor: " + e.getMessage(), e );
425         }
426         catch ( ArtifactResolutionException e )
427         {
428             throw new MavenExecutionException( e.getMessage(), e );
429         }
430         catch ( ProjectBuildingException e )
431         {
432             throw new MavenExecutionException( e.getMessage(), e );
433         }
434         catch ( ProfileActivationException e )
435         {
436             throw new MavenExecutionException( e.getMessage(), e );
437         }
438         return projects;
439     }
440 
441     private void logReactorSummaryLine( String name, String status )
442     {
443         logReactorSummaryLine( name, status, -1 );
444     }
445 
446     private void logReactorSummaryLine( String name, String status, long time )
447     {
448         StringBuffer messageBuffer = new StringBuffer();
449 
450         messageBuffer.append( name );
451 
452         int dotCount = 54;
453 
454         dotCount -= name.length();
455 
456         messageBuffer.append( " " );
457 
458         for ( int i = 0; i < dotCount; i++ )
459         {
460             messageBuffer.append( '.' );
461         }
462 
463         messageBuffer.append( " " );
464 
465         messageBuffer.append( status );
466 
467         if ( time >= 0 )
468         {
469             messageBuffer.append( " [" );
470 
471             messageBuffer.append( getFormattedTime( time ) );
472 
473             messageBuffer.append( "]" );
474         }
475 
476         getLogger().info( messageBuffer.toString() );
477     }
478 
479     private static String getFormattedTime( long time )
480     {
481         String pattern = "s.SSS's'";
482         if ( time / 60000L > 0 )
483         {
484             pattern = "m:s" + pattern;
485             if ( time / 3600000L > 0 )
486             {
487                 pattern = "H:m" + pattern;
488             }
489         }
490         DateFormat fmt = new SimpleDateFormat( pattern );
491         fmt.setTimeZone( TimeZone.getTimeZone( "UTC" ) );
492         return fmt.format( new Date( time ) );
493     }
494 
495     private List collectProjects( List files, MavenExecutionRequest request, boolean isRoot )
496         throws ArtifactResolutionException, ProjectBuildingException, ProfileActivationException,
497         MavenExecutionException, BuildFailureException
498     {
499 //        .getLocalRepository(), request.isRecursive(),
500 //        request.getSettings(), request.getUserProperties(), requ, !request.isReactorActive()
501         List projects = new ArrayList( files.size() );
502 
503         for ( Iterator iterator = files.iterator(); iterator.hasNext(); )
504         {
505             File file = (File) iterator.next();
506 
507             boolean usingReleasePom = false;
508 
509             if ( RELEASE_POMv4.equals( file.getName() ) )
510             {
511                 getLogger().info( "NOTE: Using release-pom: " + file + " in reactor build." );
512                 usingReleasePom = true;
513             }
514 
515             MavenProject project = getProject( file, request );
516 
517             if ( isRoot )
518             {
519                 project.setExecutionRoot( true );
520             }
521 
522             if ( ( project.getPrerequisites() != null ) && ( project.getPrerequisites().getMaven() != null ) )
523             {
524                 DefaultArtifactVersion version = new DefaultArtifactVersion( project.getPrerequisites().getMaven() );
525                 if ( runtimeInformation.getApplicationVersion().compareTo( version ) < 0 )
526                 {
527                     throw new BuildFailureException( "Unable to build project '" + project.getFile() +
528                         "; it requires Maven version " + version.toString() );
529                 }
530             }
531 
532             if ( ( project.getModules() != null ) && !project.getModules().isEmpty() && request.isRecursive() )
533             {
534                 // TODO: Really should fail if it was not? What if it is aggregating - eg "ear"?
535                 project.setPackaging( "pom" );
536 
537                 File basedir = file.getParentFile();
538 
539                 // Initial ordering is as declared in the modules section
540                 List moduleFiles = new ArrayList( project.getModules().size() );
541                 for ( Iterator i = project.getModules().iterator(); i.hasNext(); )
542                 {
543                     String name = (String) i.next();
544 
545                     if ( StringUtils.isEmpty( StringUtils.trim( name ) ) )
546                     {
547                         getLogger().warn(
548                             "Empty module detected. Please check you don't have any empty module definitions in your POM." );
549 
550                         continue;
551                     }
552 
553                     File moduleFile = new File( basedir, name );
554 
555                     if ( moduleFile.exists() && moduleFile.isDirectory() )
556                     {
557                         if ( usingReleasePom )
558                         {
559                             moduleFile = new File( basedir, name + "/" + Maven.RELEASE_POMv4 );
560                         }
561                         else
562                         {
563                             moduleFile = new File( basedir, name + "/" + Maven.POMv4 );
564                         }
565                     }
566 
567                     if ( Os.isFamily( "windows" ) )
568                     {
569                         // we don't canonicalize on unix to avoid interfering with symlinks
570 
571                         try
572                         {
573                             moduleFile = moduleFile.getCanonicalFile();
574                         }
575                         catch ( IOException e )
576                         {
577                             throw new MavenExecutionException( "Unable to canonicalize file name " + moduleFile, e );
578                         }
579                     }
580                     else
581                     {
582                         moduleFile = new File( moduleFile.toURI().normalize() );
583                     }
584 
585                     moduleFiles.add( moduleFile );
586                 }
587 
588                 List collectedProjects =
589                     collectProjects( moduleFiles, request, false );
590                 projects.addAll( collectedProjects );
591                 project.setCollectedProjects( collectedProjects );
592             }
593             projects.add( project );
594         }
595 
596         return projects;
597     }
598 
599     /**
600      * @deprecated Use {@link DefaultMaven#getProject(File, MavenExecutionRequest)} instead.
601      */
602     public MavenProject getProject( File pom, ArtifactRepository localRepository, Settings settings,
603                                     Properties userProperties, ProfileManager globalProfileManager )
604         throws ProjectBuildingException, ArtifactResolutionException, ProfileActivationException
605     {
606         MavenExecutionRequest request = new DefaultMavenExecutionRequest(
607                                                                       localRepository,
608                                                                       settings,
609                                                                       new DefaultEventDispatcher(),
610                                                                       Collections.EMPTY_LIST,
611                                                                       pom.getParentFile()
612                                                                          .getAbsolutePath(),
613                                                                       globalProfileManager,
614                                                                       globalProfileManager.getRequestProperties(),
615                                                                       new Properties(), false );
616 
617         return getProject( pom, request );
618     }
619 
620     public MavenProject getProject( File pom, MavenExecutionRequest request )
621         throws ProjectBuildingException, ArtifactResolutionException, ProfileActivationException
622     {
623         if ( pom.exists() )
624         {
625             if ( pom.length() == 0 )
626             {
627                 throw new ProjectBuildingException( "unknown", "The file " + pom.getAbsolutePath() +
628                     " you specified has zero length." );
629             }
630         }
631 
632         return projectBuilder.build( pom, request.getProjectBuilderConfiguration() );
633     }
634 
635     // ----------------------------------------------------------------------
636     // Methods used by all execution request handlers
637     // ----------------------------------------------------------------------
638 
639     //!! We should probably have the execution request handler create the
640     // session as
641     // the session type would be specific to the request i.e. having a project
642     // or not.
643 
644     protected MavenSession createSession( MavenExecutionRequest request,
645                                           ReactorManager rpm )
646     {
647         return new MavenSession( container, request.getSettings(), request.getLocalRepository(),
648                                  request.getEventDispatcher(), rpm, request.getGoals(), request.getBaseDirectory(),
649                                  request.getExecutionProperties(), request.getUserProperties(), request.getStartTime() );
650     }
651 
652     /**
653      * @todo [BP] this might not be required if there is a better way to pass
654      * them in. It doesn't feel quite right.
655      * @todo [JC] we should at least provide a mapping of protocol-to-proxy for
656      * the wagons, shouldn't we?
657      */
658     private void resolveParameters( Settings settings, Properties executionProperties )
659         throws ComponentLookupException, ComponentLifecycleException, SettingsConfigurationException
660     {
661         // TODO: remove when components.xml can be used to configure this instead
662         try
663         {
664             DefaultWagonManager wagonManager = (DefaultWagonManager) container.lookup( WagonManager.ROLE );
665             
666             String oldUserAgent = wagonManager.getHttpUserAgent();
667             int firstSpace = oldUserAgent == null ? -1 : oldUserAgent.indexOf( " " );
668             
669             StringBuffer buffer = new StringBuffer();
670             
671             buffer.append( "Apache-Maven/" );
672             
673             ArtifactVersion version = runtimeInformation.getApplicationVersion();
674             if ( version != null )
675             {
676                 buffer.append( version.getMajorVersion() );
677                 buffer.append( '.' );
678                 buffer.append( version.getMinorVersion() );
679             }
680             else
681             {
682                 buffer.append( "unknown" );
683             }
684             
685             buffer.append( ' ' );
686             if ( firstSpace > -1 )
687             {
688                 buffer.append( oldUserAgent.substring( firstSpace + 1 ) );
689                 buffer.append( ' ' );
690                 buffer.append( oldUserAgent.substring( 0, firstSpace ) );
691             }
692             else
693             {
694                 buffer.append( oldUserAgent );
695             }
696             
697             wagonManager.setHttpUserAgent(  buffer.toString() );
698         }
699         catch ( ClassCastException e )
700         {
701             // ignore
702         }
703 
704         WagonManager wagonManager = (WagonManager) container.lookup( WagonManager.ROLE );
705 
706         try
707         {
708             Proxy proxy = settings.getActiveProxy();
709             
710             SecDispatcher sd = null;
711             
712             try
713             {
714                 sd = (SecDispatcher) container.lookup( SecDispatcher.ROLE, "maven" );
715             }
716             catch (Exception e)
717             {
718                 getLogger().warn( "security features are disabled. Cannot find plexus component "+SecDispatcher.ROLE +":maven");
719                 
720                 line();
721             }
722 
723             if ( proxy != null )
724             {
725                 if ( proxy.getHost() == null )
726                 {
727                     throw new SettingsConfigurationException( "Proxy in settings.xml has no host" );
728                 }
729                 
730                 String pass = proxy.getPassword();
731                 
732                 if ( sd != null )
733                 {
734                     try
735                     {
736                         pass = sd.decrypt( pass );
737                     }
738                     catch ( SecDispatcherException e )
739                     {
740                         reportSecurityConfigurationError( "password for proxy '" + proxy.getId() + "'", e );
741                     }
742                 }
743 
744                 wagonManager.addProxy( proxy.getProtocol(), proxy.getHost(), proxy.getPort(), proxy.getUsername(),
745                                        pass, proxy.getNonProxyHosts() );
746             }
747             
748             for ( Iterator i = settings.getServers().iterator(); i.hasNext(); )
749             {
750                 Server server = (Server) i.next();
751                 
752                 String passWord = server.getPassword();
753 
754                 if ( sd != null )
755                 {
756                     try
757                     {
758                         passWord = sd.decrypt( passWord );
759                     }
760                     catch ( SecDispatcherException e )
761                     {
762                         reportSecurityConfigurationError( "password for server '" + server.getId() + "'", e );
763                     }
764                 }
765                 
766                 String passPhrase = server.getPassphrase();
767 
768                 if ( sd != null )
769                 {
770                     try
771                     {
772                         passPhrase = sd.decrypt( passPhrase );
773                     }
774                     catch ( SecDispatcherException e )
775                     {
776                         reportSecurityConfigurationError( "passphrase for server '" + server.getId() + "'", e );
777                     }
778                 }
779 
780                 wagonManager.addAuthenticationInfo( server.getId(), server.getUsername(), passWord,
781                                                     server.getPrivateKey(), passPhrase );
782 
783                 wagonManager.addPermissionInfo( server.getId(), server.getFilePermissions(),
784                                                 server.getDirectoryPermissions() );
785 
786                 if ( server.getConfiguration() != null )
787                 {
788                     wagonManager.addConfiguration( server.getId(), (Xpp3Dom) server.getConfiguration() );
789                 }
790             }
791 
792             for ( Iterator i = settings.getMirrors().iterator(); i.hasNext(); )
793             {
794                 Mirror mirror = (Mirror) i.next();
795 
796                 wagonManager.addMirror( mirror.getId(), mirror.getMirrorOf(), mirror.getUrl() );
797             }
798         }
799         finally
800         {
801             container.release( wagonManager );
802         }
803         
804         // Would be better in settings.xml, but it is not extensible yet
805         String numThreads = System.getProperty( "maven.artifact.threads" );
806         if ( numThreads != null )
807         {
808             int threads = 0;
809             try
810             {
811                 threads = Integer.valueOf( numThreads ).intValue();
812 
813                 if ( threads < 1 )
814                 {
815                     getLogger().warn( "Invalid number of threads '" + threads + "' will be ignored" );
816                 }
817             }
818             catch ( NumberFormatException e )
819             {
820                 getLogger().warn( "Invalid number of threads '" + numThreads + "' will be ignored: " + e.getMessage() );
821             }
822             
823             if ( threads > 0 )
824             {
825                 DefaultArtifactResolver artifactResolver = (DefaultArtifactResolver) container.lookup( ArtifactResolver.ROLE );
826                 try
827                 {
828                     artifactResolver.configureNumberOfThreads( threads );
829                     getLogger().debug( "Resolution thread pool size set to: " + threads );
830                 }
831                 finally
832                 {
833                     container.release( artifactResolver );
834                 }
835             }
836         }
837     }
838 
839     private void reportSecurityConfigurationError( String affectedConfiguration, SecDispatcherException e )
840     {
841         Throwable cause = e;
842 
843         String msg = "Not decrypting " + affectedConfiguration + " due to exception in security handler.";
844 
845         // Drop to the actual cause, it wraps multiple times
846         while ( cause.getCause() != null )
847         {
848             cause = cause.getCause();
849         }
850 
851         // common cause is missing settings-security.xml
852         if ( cause instanceof FileNotFoundException )
853         {
854             msg += "\nEnsure that you have configured your master password file (and relocation if appropriate)\nSee the installation instructions for details.";
855         }
856 
857         getLogger().warn( msg + "\nCause: " + cause.getMessage() );
858         getLogger().debug( "Full trace follows", e );
859     }
860 
861     // ----------------------------------------------------------------------
862     // Lifecylce Management
863     // ----------------------------------------------------------------------
864 
865     public void contextualize( Context context )
866         throws ContextException
867     {
868         container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
869     }
870 
871     // ----------------------------------------------------------------------
872     // Reporting / Logging
873     // ----------------------------------------------------------------------
874 
875     protected void logFatal( Throwable error )
876     {
877         line();
878 
879         getLogger().error( "FATAL ERROR" );
880 
881         line();
882 
883         logDiagnostics( error );
884 
885         logTrace( error, true );
886     }
887 
888     protected void logError( Exception e, boolean showErrors )
889     {
890         line();
891 
892         getLogger().error( "BUILD ERROR" );
893 
894         line();
895 
896         logDiagnostics( e );
897 
898         logTrace( e, showErrors );
899 
900         if ( !showErrors )
901         {
902             getLogger().info( "For more information, run Maven with the -e switch" );
903 
904             line();
905         }
906     }
907 
908     protected void logFailure( BuildFailureException e, boolean showErrors )
909     {
910         line();
911 
912         getLogger().error( "BUILD FAILURE" );
913 
914         line();
915 
916         logDiagnostics( e );
917 
918         logTrace( e, showErrors );
919 
920         if ( !showErrors )
921         {
922             getLogger().info( "For more information, run Maven with the -e switch" );
923 
924             line();
925         }
926     }
927 
928     private void logTrace( Throwable t, boolean showErrors )
929     {
930         if ( getLogger().isDebugEnabled() )
931         {
932             getLogger().debug( "Trace", t );
933 
934             line();
935         }
936         else if ( showErrors )
937         {
938             getLogger().info( "Trace", t );
939 
940             line();
941         }
942     }
943 
944     private void logDiagnostics( Throwable t )
945     {
946         String message = null;
947         if ( errorDiagnostics != null )
948         {
949             message = errorDiagnostics.diagnose( t );
950         }
951 
952         if ( message == null )
953         {
954             message = t.getMessage();
955         }
956 
957         getLogger().info( message );
958 
959         line();
960     }
961 
962     protected void logSuccess( ReactorManager rm )
963     {
964         line();
965 
966         getLogger().info( "BUILD SUCCESSFUL" );
967 
968         line();
969     }
970 
971     private void logReactorSummary( ReactorManager rm )
972     {
973         if ( rm.hasMultipleProjects() && rm.executedMultipleProjects() )
974         {
975             getLogger().info( "" );
976             getLogger().info( "" );
977 
978             // -------------------------
979             // Reactor Summary:
980             // -------------------------
981             // o project-name...........FAILED
982             // o project2-name..........SKIPPED (dependency build failed or was skipped)
983             // o project-3-name.........SUCCESS
984 
985             line();
986             getLogger().info( "Reactor Summary:" );
987             line();
988 
989             for ( Iterator it = rm.getSortedProjects().iterator(); it.hasNext(); )
990             {
991                 MavenProject project = (MavenProject) it.next();
992 
993                 if ( rm.hasBuildFailure( project ) )
994                 {
995                     logReactorSummaryLine( project.getName(), "FAILED", rm.getBuildFailure( project ).getTime() );
996                 }
997                 else if ( rm.isBlackListed( project ) )
998                 {
999                     logReactorSummaryLine( project.getName(), "SKIPPED (dependency build failed or was skipped)" );
1000                 }
1001                 else if ( rm.hasBuildSuccess( project ) )
1002                 {
1003                     logReactorSummaryLine( project.getName(), "SUCCESS", rm.getBuildSuccess( project ).getTime() );
1004                 }
1005                 else
1006                 {
1007                     logReactorSummaryLine( project.getName(), "NOT BUILT" );
1008                 }
1009             }
1010             line();
1011         }
1012     }
1013 
1014     protected void stats( Date start )
1015     {
1016         Date finish = new Date();
1017 
1018         long time = finish.getTime() - start.getTime();
1019 
1020         getLogger().info( "Total time: " + formatTime( time ) );
1021 
1022         getLogger().info( "Finished at: " + finish );
1023 
1024         //noinspection CallToSystemGC
1025         System.gc();
1026 
1027         Runtime r = Runtime.getRuntime();
1028 
1029         getLogger().info(
1030             "Final Memory: " + ( r.totalMemory() - r.freeMemory() ) / MB + "M/" + r.totalMemory() / MB + "M" );
1031     }
1032 
1033     protected void line()
1034     {
1035         getLogger().info( "------------------------------------------------------------------------" );
1036     }
1037 
1038     protected static String formatTime( long ms )
1039     {
1040         long secs = ms / MS_PER_SEC;
1041 
1042         long min = secs / SEC_PER_MIN;
1043 
1044         secs = secs % SEC_PER_MIN;
1045 
1046         String msg = "";
1047 
1048         if ( min > 1 )
1049         {
1050             msg = min + " minutes ";
1051         }
1052         else if ( min == 1 )
1053         {
1054             msg = "1 minute ";
1055         }
1056 
1057         if ( secs > 1 )
1058         {
1059             msg += secs + " seconds";
1060         }
1061         else if ( secs == 1 )
1062         {
1063             msg += "1 second";
1064         }
1065         else if ( min == 0 )
1066         {
1067             msg += "< 1 second";
1068         }
1069         return msg;
1070     }
1071 
1072     private List getProjectFiles( MavenExecutionRequest request )
1073         throws IOException
1074     {
1075         List files = Collections.EMPTY_LIST;
1076 
1077         File userDir = new File( System.getProperty( "user.dir" ) );
1078         if ( request.isReactorActive() )
1079         {
1080             // TODO: should we now include the pom.xml in the current directory?
1081 //            String includes = System.getProperty( "maven.reactor.includes", "**/" + POMv4 );
1082 //            String excludes = System.getProperty( "maven.reactor.excludes", POMv4 );
1083 
1084             String includes = System.getProperty( "maven.reactor.includes", "**/" + POMv4 + ",**/" + RELEASE_POMv4 );
1085             String excludes = System.getProperty( "maven.reactor.excludes", POMv4 + "," + RELEASE_POMv4 );
1086 
1087             files = FileUtils.getFiles( userDir, includes, excludes );
1088 
1089             filterOneProjectFilePerDirectory( files );
1090 
1091             // make sure there is consistent ordering on all platforms, rather than using the filesystem ordering
1092             Collections.sort( files );
1093         }
1094         else if ( request.getPomFile() != null )
1095         {
1096             File projectFile = new File( request.getPomFile() ).getAbsoluteFile();
1097 
1098             if ( projectFile.exists() )
1099             {
1100                 files = Collections.singletonList( projectFile );
1101             }
1102         }
1103         else
1104         {
1105             File projectFile = new File( userDir, RELEASE_POMv4 );
1106 
1107             if ( !projectFile.exists() )
1108             {
1109                 projectFile = new File( userDir, POMv4 );
1110             }
1111 
1112             if ( projectFile.exists() )
1113             {
1114                 files = Collections.singletonList( projectFile );
1115             }
1116         }
1117 
1118         return files;
1119     }
1120 
1121     private void filterOneProjectFilePerDirectory( List files )
1122     {
1123         List releaseDirs = new ArrayList();
1124 
1125         for ( Iterator it = files.iterator(); it.hasNext(); )
1126         {
1127             File projectFile = (File) it.next();
1128 
1129             if ( RELEASE_POMv4.equals( projectFile.getName() ) )
1130             {
1131                 releaseDirs.add( projectFile.getParentFile() );
1132             }
1133         }
1134 
1135         for ( Iterator it = files.iterator(); it.hasNext(); )
1136         {
1137             File projectFile = (File) it.next();
1138 
1139             // remove pom.xml files where there is a sibling release-pom.xml file...
1140             if ( !RELEASE_POMv4.equals( projectFile.getName() ) && releaseDirs.contains( projectFile.getParentFile() ) )
1141             {
1142                 it.remove();
1143             }
1144         }
1145     }
1146 }