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