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