blob: 697ca7735212c7c85a2bf7fb42aec8a49bfae282 [file] [log] [blame]
package org.apache.maven;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.TimeZone;
import org.apache.maven.artifact.manager.DefaultWagonManager;
import org.apache.maven.artifact.manager.WagonManager;
import org.apache.maven.artifact.manager.WagonProviderMapping;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.artifact.resolver.DefaultArtifactResolver;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.execution.BuildFailure;
import org.apache.maven.execution.DefaultMavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ReactorManager;
import org.apache.maven.execution.RuntimeInformation;
import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.lifecycle.LifecycleExecutor;
import org.apache.maven.model.Profile;
import org.apache.maven.monitor.event.DefaultEventDispatcher;
import org.apache.maven.monitor.event.EventDispatcher;
import org.apache.maven.monitor.event.MavenEvents;
import org.apache.maven.profiles.ProfileManager;
import org.apache.maven.profiles.activation.ProfileActivationException;
import org.apache.maven.project.DuplicateProjectException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
import org.apache.maven.project.MissingProjectException;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.reactor.MavenExecutionException;
import org.apache.maven.settings.Mirror;
import org.apache.maven.settings.Proxy;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;
import org.apache.maven.usability.SystemWarnings;
import org.apache.maven.usability.diagnostics.ErrorDiagnostics;
import org.codehaus.plexus.PlexusConstants;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.context.Context;
import org.codehaus.plexus.context.ContextException;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.Os;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.dag.CycleDetectedException;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException;
/**
* @author <a href="mailto:jason@maven.org">Jason van Zyl </a>
* @version $Id$
*/
public class DefaultMaven
extends AbstractLogEnabled
implements Maven, Contextualizable
{
// ----------------------------------------------------------------------
// Components
// ----------------------------------------------------------------------
protected MavenProjectBuilder projectBuilder;
protected LifecycleExecutor lifecycleExecutor;
protected PlexusContainer container;
protected ErrorDiagnostics errorDiagnostics;
protected RuntimeInformation runtimeInformation;
private static final long MB = 1024 * 1024;
private static final int MS_PER_SEC = 1000;
private static final int SEC_PER_MIN = 60;
// ----------------------------------------------------------------------
// Project execution
// ----------------------------------------------------------------------
public void execute( MavenExecutionRequest request )
throws MavenExecutionException
{
// if ( request.getLocalRepository() == null )
// {
// request.setLocalRepository( mavenTools.createLocalRepository( request.getLocalRepositoryPath() ) );
// }
EventDispatcher dispatcher = request.getEventDispatcher();
String event = MavenEvents.REACTOR_EXECUTION;
dispatcher.dispatchStart( event, request.getBaseDirectory() );
ReactorManager rm;
try
{
rm = doExecute( request, dispatcher );
}
catch ( LifecycleExecutionException e )
{
dispatcher.dispatchError( event, request.getBaseDirectory(), e );
logError( e, request.isShowErrors() );
stats( request.getStartTime() );
line();
throw new MavenExecutionException( e.getMessage(), e );
}
catch ( BuildFailureException e )
{
dispatcher.dispatchError( event, request.getBaseDirectory(), e );
logFailure( e, request.isShowErrors() );
stats( request.getStartTime() );
line();
throw new MavenExecutionException( e.getMessage(), e );
}
catch ( Throwable t )
{
dispatcher.dispatchError( event, request.getBaseDirectory(), t );
logFatal( t );
stats( request.getStartTime() );
line();
throw new MavenExecutionException( "Error executing project within the reactor", t );
}
// Either the build was successful, or it was a fail_at_end/fail_never reactor build
// TODO: should all the logging be left to the CLI?
logReactorSummary( rm );
if ( rm.hasBuildFailures() )
{
logErrors( rm, request.isShowErrors() );
if ( !ReactorManager.FAIL_NEVER.equals( rm.getFailureBehavior() ) )
{
dispatcher.dispatchError( event, request.getBaseDirectory(), null );
getLogger().info( "BUILD ERRORS" );
line();
stats( request.getStartTime() );
line();
throw new MavenExecutionException( "Some builds failed" );
}
else
{
getLogger().info( " + Ignoring failures" );
}
}
logSuccess( rm );
stats( request.getStartTime() );
line();
dispatcher.dispatchEnd( event, request.getBaseDirectory() );
}
private void logErrors( ReactorManager rm, boolean showErrors )
{
for ( Iterator it = rm.getSortedProjects().iterator(); it.hasNext(); )
{
MavenProject project = (MavenProject) it.next();
if ( rm.hasBuildFailure( project ) )
{
BuildFailure buildFailure = rm.getBuildFailure( project );
getLogger().info(
"Error for project: " + project.getName() + " (during " + buildFailure.getTask() + ")" );
line();
logDiagnostics( buildFailure.getCause() );
logTrace( buildFailure.getCause(), showErrors );
}
}
if ( !showErrors )
{
getLogger().info( "For more information, run Maven with the -e switch" );
line();
}
}
private ReactorManager doExecute( MavenExecutionRequest request, EventDispatcher dispatcher )
throws MavenExecutionException, BuildFailureException, LifecycleExecutionException
{
try
{
resolveParameters( request.getSettings(), request.getExecutionProperties() );
}
catch ( ComponentLookupException e )
{
throw new MavenExecutionException( "Unable to configure Maven for execution", e );
}
catch ( ComponentLifecycleException e )
{
throw new MavenExecutionException( "Unable to configure Maven for execution", e );
}
catch ( SettingsConfigurationException e )
{
throw new MavenExecutionException( "Unable to configure Maven for execution", e );
}
ProfileManager globalProfileManager = request.getGlobalProfileManager();
globalProfileManager.loadSettingsProfiles( request.getSettings() );
getLogger().info( "Scanning for projects..." );
boolean foundProjects = true;
List projects = getProjects( request );
if ( projects.isEmpty() )
{
projects.add( getSuperProject( request ) );
foundProjects = false;
}
ReactorManager rm;
try
{
String resumeFrom = request.getResumeFrom();
List projectList = request.getSelectedProjects();
String makeBehavior = request.getMakeBehavior();
rm = new ReactorManager( projects, projectList, resumeFrom, makeBehavior );
rm.setFailureBehavior( request.getFailureBehavior() );
}
catch ( CycleDetectedException e )
{
throw new BuildFailureException(
"The projects in the reactor contain a cyclic reference: " + e.getMessage(), e );
}
catch ( DuplicateProjectException e )
{
throw new BuildFailureException( e.getMessage(), e );
}
catch ( MissingProjectException e )
{
throw new BuildFailureException( e.getMessage(), e );
}
// --------------------------------------------------------------------------------
// MNG-3641: print a warning if one of the profiles to be activated explicitly
// was not activated
validateActivatedProfiles( globalProfileManager, projects );
if ( rm.hasMultipleProjects() )
{
getLogger().info( "Reactor build order: " );
for ( Iterator i = rm.getSortedProjects().iterator(); i.hasNext(); )
{
MavenProject project = (MavenProject) i.next();
getLogger().info( " " + project.getName() );
}
}
MavenSession session = createSession( request, rm );
session.setUsingPOMsFromFilesystem( foundProjects );
lifecycleExecutor.execute( session, rm, dispatcher );
return rm;
}
private void validateActivatedProfiles( ProfileManager globalProfileManager, List projects )
{
if ( globalProfileManager != null )
{
// get all activated profile ids
Set activeProfileIds = new HashSet();
for ( Iterator i = projects.iterator(); i.hasNext(); )
{
MavenProject project = (MavenProject) i.next();
do
{
for ( Iterator j = project.getActiveProfiles().iterator(); j.hasNext(); )
{
activeProfileIds.add( ( (Profile) j.next() ).getId() );
}
project = project.getParent();
}
while ( project != null );
}
for ( Iterator i = globalProfileManager.getExplicitlyActivatedIds().iterator(); i.hasNext(); )
{
String explicitProfileId = (String) i.next();
if ( !activeProfileIds.contains( explicitProfileId ) )
{
getLogger().warn( "\n\tProfile with id: \'" + explicitProfileId + "\' has not been activated.\n" );
}
}
}
}
private MavenProject getSuperProject( MavenExecutionRequest request )
throws MavenExecutionException
{
MavenProject superProject;
try
{
superProject = projectBuilder.buildStandaloneSuperProject( request.getLocalRepository(), request.getGlobalProfileManager() );
}
catch ( ProjectBuildingException e )
{
throw new MavenExecutionException( e.getMessage(), e );
}
return superProject;
}
private List getProjects( MavenExecutionRequest request )
throws MavenExecutionException, BuildFailureException
{
List projects;
try
{
List files = getProjectFiles( request );
projects = collectProjects( files, request, !request.isReactorActive() );
}
catch ( IOException e )
{
throw new MavenExecutionException( "Error processing projects for the reactor: " + e.getMessage(), e );
}
catch ( ArtifactResolutionException e )
{
throw new MavenExecutionException( e.getMessage(), e );
}
catch ( ProjectBuildingException e )
{
throw new MavenExecutionException( e.getMessage(), e );
}
catch ( ProfileActivationException e )
{
throw new MavenExecutionException( e.getMessage(), e );
}
return projects;
}
private void logReactorSummaryLine( String name, String status )
{
logReactorSummaryLine( name, status, -1 );
}
private void logReactorSummaryLine( String name, String status, long time )
{
StringBuffer messageBuffer = new StringBuffer();
messageBuffer.append( name );
int dotCount = 54;
dotCount -= name.length();
messageBuffer.append( " " );
for ( int i = 0; i < dotCount; i++ )
{
messageBuffer.append( '.' );
}
messageBuffer.append( " " );
messageBuffer.append( status );
if ( time >= 0 )
{
messageBuffer.append( " [" );
messageBuffer.append( getFormattedTime( time ) );
messageBuffer.append( "]" );
}
getLogger().info( messageBuffer.toString() );
}
private static String getFormattedTime( long time )
{
String pattern = "s.SSS's'";
if ( time / 60000L > 0 )
{
pattern = "m:s" + pattern;
if ( time / 3600000L > 0 )
{
pattern = "H:m" + pattern;
}
}
DateFormat fmt = new SimpleDateFormat( pattern );
fmt.setTimeZone( TimeZone.getTimeZone( "UTC" ) );
return fmt.format( new Date( time ) );
}
private List collectProjects( List files, MavenExecutionRequest request, boolean isRoot )
throws ArtifactResolutionException, ProjectBuildingException, ProfileActivationException,
MavenExecutionException, BuildFailureException
{
// .getLocalRepository(), request.isRecursive(),
// request.getSettings(), request.getUserProperties(), requ, !request.isReactorActive()
List projects = new ArrayList( files.size() );
for ( Iterator iterator = files.iterator(); iterator.hasNext(); )
{
File file = (File) iterator.next();
boolean usingReleasePom = false;
if ( RELEASE_POMv4.equals( file.getName() ) )
{
getLogger().info( "NOTE: Using release-pom: " + file + " in reactor build." );
usingReleasePom = true;
}
MavenProject project = getProject( file, request );
if ( isRoot )
{
project.setExecutionRoot( true );
}
if ( ( project.getPrerequisites() != null ) && ( project.getPrerequisites().getMaven() != null ) )
{
DefaultArtifactVersion version = new DefaultArtifactVersion( project.getPrerequisites().getMaven() );
if ( runtimeInformation.getApplicationVersion().compareTo( version ) < 0 )
{
throw new BuildFailureException( "Unable to build project '" + project.getFile() +
"; it requires Maven version " + version.toString() );
}
}
if ( ( project.getModules() != null ) && !project.getModules().isEmpty() && request.isRecursive() )
{
// TODO: Really should fail if it was not? What if it is aggregating - eg "ear"?
project.setPackaging( "pom" );
File basedir = file.getParentFile();
// Initial ordering is as declared in the modules section
List moduleFiles = new ArrayList( project.getModules().size() );
for ( Iterator i = project.getModules().iterator(); i.hasNext(); )
{
String name = (String) i.next();
if ( StringUtils.isEmpty( StringUtils.trim( name ) ) )
{
getLogger().warn(
"Empty module detected. Please check you don't have any empty module definitions in your POM." );
continue;
}
File moduleFile = new File( basedir, name );
if ( moduleFile.exists() && moduleFile.isDirectory() )
{
if ( usingReleasePom )
{
moduleFile = new File( basedir, name + "/" + Maven.RELEASE_POMv4 );
}
else
{
moduleFile = new File( basedir, name + "/" + Maven.POMv4 );
}
}
if ( Os.isFamily( "windows" ) )
{
// we don't canonicalize on unix to avoid interfering with symlinks
try
{
moduleFile = moduleFile.getCanonicalFile();
}
catch ( IOException e )
{
throw new MavenExecutionException( "Unable to canonicalize file name " + moduleFile, e );
}
}
else
{
moduleFile = new File( moduleFile.toURI().normalize() );
}
moduleFiles.add( moduleFile );
}
List collectedProjects =
collectProjects( moduleFiles, request, false );
projects.addAll( collectedProjects );
project.setCollectedProjects( collectedProjects );
}
projects.add( project );
}
return projects;
}
/**
* @deprecated Use {@link DefaultMaven#getProject(File, MavenExecutionRequest)} instead.
*/
public MavenProject getProject( File pom, ArtifactRepository localRepository, Settings settings,
Properties userProperties, ProfileManager globalProfileManager )
throws ProjectBuildingException, ArtifactResolutionException, ProfileActivationException
{
MavenExecutionRequest request = new DefaultMavenExecutionRequest(
localRepository,
settings,
new DefaultEventDispatcher(),
Collections.EMPTY_LIST,
pom.getParentFile()
.getAbsolutePath(),
globalProfileManager,
globalProfileManager.getRequestProperties(),
new Properties(), false );
return getProject( pom, request );
}
public MavenProject getProject( File pom, MavenExecutionRequest request )
throws ProjectBuildingException, ArtifactResolutionException, ProfileActivationException
{
if ( pom.exists() )
{
if ( pom.length() == 0 )
{
throw new ProjectBuildingException( "unknown", "The file " + pom.getAbsolutePath() +
" you specified has zero length." );
}
}
return projectBuilder.build( pom, request.getProjectBuilderConfiguration() );
}
// ----------------------------------------------------------------------
// Methods used by all execution request handlers
// ----------------------------------------------------------------------
//!! We should probably have the execution request handler create the
// session as
// the session type would be specific to the request i.e. having a project
// or not.
protected MavenSession createSession( MavenExecutionRequest request,
ReactorManager rpm )
{
return new MavenSession( container, request.getSettings(), request.getLocalRepository(),
request.getEventDispatcher(), rpm, request.getGoals(), request.getBaseDirectory(),
request.getExecutionProperties(), request.getUserProperties(), request.getStartTime() );
}
/**
* @todo [BP] this might not be required if there is a better way to pass
* them in. It doesn't feel quite right.
* @todo [JC] we should at least provide a mapping of protocol-to-proxy for
* the wagons, shouldn't we?
*/
private void resolveParameters( Settings settings, Properties executionProperties )
throws ComponentLookupException, ComponentLifecycleException, SettingsConfigurationException
{
WagonManager wagonManager = (WagonManager) container.lookup( WagonManager.ROLE );
try
{
if ( settings.isOffline() )
{
getLogger().info( SystemWarnings.getOfflineWarning() );
wagonManager.setOnline( false );
}
try
{
DefaultWagonManager wm = (DefaultWagonManager) wagonManager;
String oldUserAgent = wm.getHttpUserAgent();
int firstSpace = oldUserAgent == null ? -1 : oldUserAgent.indexOf( " " );
StringBuffer buffer = new StringBuffer();
buffer.append( "Apache-Maven/" );
ArtifactVersion version = runtimeInformation.getApplicationVersion();
if ( version != null )
{
buffer.append( version.getMajorVersion() );
buffer.append( '.' );
buffer.append( version.getMinorVersion() );
}
else
{
buffer.append( "unknown" );
}
buffer.append( ' ' );
if ( firstSpace > -1 )
{
buffer.append( oldUserAgent.substring( firstSpace + 1 ) );
buffer.append( ' ' );
buffer.append( oldUserAgent.substring( 0, firstSpace ) );
}
else
{
buffer.append( oldUserAgent );
}
wm.setHttpUserAgent( buffer.toString() );
}
catch ( ClassCastException e )
{
// ignore
}
SecDispatcher sd = null;
try
{
Proxy proxy = settings.getActiveProxy();
try
{
sd = (SecDispatcher) container.lookup( SecDispatcher.ROLE, "maven" );
}
catch (Exception e)
{
getLogger().warn( "Security features are disabled. Cannot find plexus component "+SecDispatcher.ROLE + ":maven" );
line();
}
if ( proxy != null )
{
if ( proxy.getHost() == null )
{
throw new SettingsConfigurationException( "Proxy in settings.xml has no host" );
}
String pass = proxy.getPassword();
if ( sd != null )
{
try
{
pass = sd.decrypt( pass );
}
catch ( SecDispatcherException e )
{
reportSecurityConfigurationError( "password for proxy '" + proxy.getId() + "'", e );
}
}
wagonManager.addProxy( proxy.getProtocol(), proxy.getHost(), proxy.getPort(), proxy.getUsername(),
pass, proxy.getNonProxyHosts() );
}
for ( Iterator i = settings.getServers().iterator(); i.hasNext(); )
{
Server server = (Server) i.next();
String passWord = server.getPassword();
if ( sd != null )
{
try
{
passWord = sd.decrypt( passWord );
}
catch ( SecDispatcherException e )
{
reportSecurityConfigurationError( "password for server '" + server.getId() + "'", e );
}
}
String passPhrase = server.getPassphrase();
if ( sd != null )
{
try
{
passPhrase = sd.decrypt( passPhrase );
}
catch ( SecDispatcherException e )
{
reportSecurityConfigurationError( "passphrase for server '" + server.getId() + "'", e );
}
}
wagonManager.addAuthenticationInfo( server.getId(), server.getUsername(), passWord,
server.getPrivateKey(), passPhrase );
wagonManager.addPermissionInfo( server.getId(), server.getFilePermissions(),
server.getDirectoryPermissions() );
if ( server.getConfiguration() != null )
{
wagonManager.addConfiguration( server.getId(), (Xpp3Dom) server.getConfiguration() );
}
}
for ( Iterator i = settings.getMirrors().iterator(); i.hasNext(); )
{
Mirror mirror = (Mirror) i.next();
wagonManager.addMirror( mirror.getId(), mirror.getMirrorOf(), mirror.getUrl() );
}
}
finally
{
if ( sd != null )
{
container.release( sd );
}
}
}
finally
{
container.release( wagonManager );
}
WagonProviderMapping mapping = (WagonProviderMapping) container.lookup( WagonProviderMapping.ROLE );
try
{
// set defaults
mapping.setWagonProvider( "http", "lightweight" );
mapping.setWagonProvider( "https", "lightweight" );
for ( Object k: executionProperties.keySet() )
{
String key = (String) k;
if ( key.startsWith( "maven.wagon.provider." ) )
{
String provider = executionProperties.getProperty( key );
key = key.substring( "maven.wagon.provider.".length() );
mapping.setWagonProvider( key, provider );
}
}
}
finally
{
container.release( mapping );
}
// Would be better in settings.xml, but it is not extensible yet
String numThreads = System.getProperty( "maven.artifact.threads" );
if ( numThreads != null )
{
int threads = 0;
try
{
threads = Integer.valueOf( numThreads ).intValue();
if ( threads < 1 )
{
getLogger().warn( "Invalid number of threads '" + threads + "' will be ignored" );
}
}
catch ( NumberFormatException e )
{
getLogger().warn( "Invalid number of threads '" + numThreads + "' will be ignored: " + e.getMessage() );
}
if ( threads > 0 )
{
DefaultArtifactResolver artifactResolver = (DefaultArtifactResolver) container.lookup( ArtifactResolver.ROLE );
try
{
artifactResolver.configureNumberOfThreads( threads );
getLogger().debug( "Resolution thread pool size set to: " + threads );
}
finally
{
container.release( artifactResolver );
}
}
}
}
private void reportSecurityConfigurationError( String affectedConfiguration, SecDispatcherException e )
{
Throwable cause = e;
String msg = "Not decrypting " + affectedConfiguration + " due to exception in security handler.";
// Drop to the actual cause, it wraps multiple times
while ( cause.getCause() != null )
{
cause = cause.getCause();
}
// common cause is missing settings-security.xml
if ( cause instanceof FileNotFoundException )
{
msg += "\nEnsure that you have configured your master password file (and relocation if appropriate)\nSee the installation instructions for details.";
}
getLogger().warn( msg + "\nCause: " + cause.getMessage() );
getLogger().debug( "Full trace follows", e );
}
// ----------------------------------------------------------------------
// Lifecylce Management
// ----------------------------------------------------------------------
public void contextualize( Context context )
throws ContextException
{
container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
}
// ----------------------------------------------------------------------
// Reporting / Logging
// ----------------------------------------------------------------------
protected void logFatal( Throwable error )
{
line();
getLogger().error( "FATAL ERROR" );
line();
logDiagnostics( error );
logTrace( error, true );
}
protected void logError( Exception e, boolean showErrors )
{
line();
getLogger().error( "BUILD ERROR" );
line();
logDiagnostics( e );
logTrace( e, showErrors );
if ( !showErrors )
{
getLogger().info( "For more information, run Maven with the -e switch" );
line();
}
}
protected void logFailure( BuildFailureException e, boolean showErrors )
{
line();
getLogger().error( "BUILD FAILURE" );
line();
logDiagnostics( e );
logTrace( e, showErrors );
if ( !showErrors )
{
getLogger().info( "For more information, run Maven with the -e switch" );
line();
}
}
private void logTrace( Throwable t, boolean showErrors )
{
if ( getLogger().isDebugEnabled() )
{
getLogger().debug( "Trace", t );
line();
}
else if ( showErrors )
{
getLogger().info( "Trace", t );
line();
}
}
private void logDiagnostics( Throwable t )
{
String message = null;
if ( errorDiagnostics != null )
{
message = errorDiagnostics.diagnose( t );
}
if ( message == null )
{
message = t.getMessage();
}
getLogger().info( message );
line();
}
protected void logSuccess( ReactorManager rm )
{
line();
getLogger().info( "BUILD SUCCESSFUL" );
line();
}
private void logReactorSummary( ReactorManager rm )
{
if ( rm.hasMultipleProjects() && rm.executedMultipleProjects() )
{
getLogger().info( "" );
getLogger().info( "" );
// -------------------------
// Reactor Summary:
// -------------------------
// o project-name...........FAILED
// o project2-name..........SKIPPED (dependency build failed or was skipped)
// o project-3-name.........SUCCESS
line();
getLogger().info( "Reactor Summary:" );
line();
for ( Iterator it = rm.getSortedProjects().iterator(); it.hasNext(); )
{
MavenProject project = (MavenProject) it.next();
if ( rm.hasBuildFailure( project ) )
{
logReactorSummaryLine( project.getName(), "FAILED", rm.getBuildFailure( project ).getTime() );
}
else if ( rm.isBlackListed( project ) )
{
logReactorSummaryLine( project.getName(), "SKIPPED (dependency build failed or was skipped)" );
}
else if ( rm.hasBuildSuccess( project ) )
{
logReactorSummaryLine( project.getName(), "SUCCESS", rm.getBuildSuccess( project ).getTime() );
}
else
{
logReactorSummaryLine( project.getName(), "NOT BUILT" );
}
}
line();
}
}
protected void stats( Date start )
{
Date finish = new Date();
long time = finish.getTime() - start.getTime();
getLogger().info( "Total time: " + formatTime( time ) );
getLogger().info( "Finished at: " + finish );
//noinspection CallToSystemGC
System.gc();
Runtime r = Runtime.getRuntime();
getLogger().info(
"Final Memory: " + ( r.totalMemory() - r.freeMemory() ) / MB + "M/" + r.totalMemory() / MB + "M" );
}
protected void line()
{
getLogger().info( "------------------------------------------------------------------------" );
}
protected static String formatTime( long ms )
{
long secs = ms / MS_PER_SEC;
long min = secs / SEC_PER_MIN;
secs = secs % SEC_PER_MIN;
String msg = "";
if ( min > 1 )
{
msg = min + " minutes ";
}
else if ( min == 1 )
{
msg = "1 minute ";
}
if ( secs > 1 )
{
msg += secs + " seconds";
}
else if ( secs == 1 )
{
msg += "1 second";
}
else if ( min == 0 )
{
msg += "< 1 second";
}
return msg;
}
private List getProjectFiles( MavenExecutionRequest request )
throws IOException
{
List files = Collections.EMPTY_LIST;
File userDir = new File( System.getProperty( "user.dir" ) );
if ( request.isReactorActive() )
{
// TODO: should we now include the pom.xml in the current directory?
// String includes = System.getProperty( "maven.reactor.includes", "**/" + POMv4 );
// String excludes = System.getProperty( "maven.reactor.excludes", POMv4 );
String includes = System.getProperty( "maven.reactor.includes", "**/" + POMv4 + ",**/" + RELEASE_POMv4 );
String excludes = System.getProperty( "maven.reactor.excludes", POMv4 + "," + RELEASE_POMv4 );
files = FileUtils.getFiles( userDir, includes, excludes );
filterOneProjectFilePerDirectory( files );
// make sure there is consistent ordering on all platforms, rather than using the filesystem ordering
Collections.sort( files );
}
else if ( request.getPomFile() != null )
{
File projectFile = new File( request.getPomFile() ).getAbsoluteFile();
if ( projectFile.exists() )
{
files = Collections.singletonList( projectFile );
}
}
else
{
File projectFile = new File( userDir, RELEASE_POMv4 );
if ( !projectFile.exists() )
{
projectFile = new File( userDir, POMv4 );
}
if ( projectFile.exists() )
{
files = Collections.singletonList( projectFile );
}
}
return files;
}
private void filterOneProjectFilePerDirectory( List files )
{
List releaseDirs = new ArrayList();
for ( Iterator it = files.iterator(); it.hasNext(); )
{
File projectFile = (File) it.next();
if ( RELEASE_POMv4.equals( projectFile.getName() ) )
{
releaseDirs.add( projectFile.getParentFile() );
}
}
for ( Iterator it = files.iterator(); it.hasNext(); )
{
File projectFile = (File) it.next();
// remove pom.xml files where there is a sibling release-pom.xml file...
if ( !RELEASE_POMv4.equals( projectFile.getName() ) && releaseDirs.contains( projectFile.getParentFile() ) )
{
it.remove();
}
}
}
}