Fixing the case where there were exceptions in the build, but for whatever reason they didn't trigger a reactor-manager build failure flag...in cases where there isn't really a project against which to log the error, for instance.

git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@616968 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
John Dennis Casey 2008-01-31 00:36:26 +00:00
parent f2d7a5aa5f
commit b7ce1b8c93
9 changed files with 257 additions and 5 deletions

View File

@ -75,6 +75,7 @@ public privileged aspect LifecycleErrorReporterAspect
execution( private * DefaultLifecycleExecutor.getMojoDescriptorForDirectInvocation( String, MavenSession, MavenProject ) ) execution( private * DefaultLifecycleExecutor.getMojoDescriptorForDirectInvocation( String, MavenSession, MavenProject ) )
&& args( task, session, project ) && args( task, session, project )
{ {
System.out.println( "BINGO" );
getReporter().reportInvalidPluginForDirectInvocation( task, session, project, cause ); getReporter().reportInvalidPluginForDirectInvocation( task, session, project, cause );
} }

View File

@ -1685,6 +1685,7 @@ public void reportInvalidPluginForDirectInvocation( String task,
writer.write( NEWLINE ); writer.write( NEWLINE );
writer.write( NEWLINE ); writer.write( NEWLINE );
writer.write( "Error message:" ); writer.write( "Error message:" );
writer.write( NEWLINE );
writer.write( err.getMessage() ); writer.write( err.getMessage() );
addTips( CoreErrorTips.getInvalidPluginForDirectInvocationTips( task, session, project, err ), writer ); addTips( CoreErrorTips.getInvalidPluginForDirectInvocationTips( task, session, project, err ), writer );

View File

@ -8,14 +8,17 @@
import org.apache.maven.lifecycle.model.LifecycleBinding; import org.apache.maven.lifecycle.model.LifecycleBinding;
import org.apache.maven.lifecycle.model.LifecycleBindings; import org.apache.maven.lifecycle.model.LifecycleBindings;
import org.apache.maven.lifecycle.model.MojoBinding; import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.lifecycle.model.Phase;
import org.apache.maven.lifecycle.statemgmt.StateManagementUtils; import org.apache.maven.lifecycle.statemgmt.StateManagementUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.Stack; import java.util.Stack;
public class BuildPlan public class BuildPlan
@ -32,6 +35,10 @@ public class BuildPlan
private final Map directInvocationBindings; private final Map directInvocationBindings;
private Set fullyResolvedBindings = new HashSet();
private boolean includingReports = false;
public BuildPlan( final LifecycleBindings packaging, final LifecycleBindings projectBindings, public BuildPlan( final LifecycleBindings packaging, final LifecycleBindings projectBindings,
final LifecycleBindings defaults, final List tasks ) final LifecycleBindings defaults, final List tasks )
throws LifecycleSpecificationException, LifecycleLoaderException throws LifecycleSpecificationException, LifecycleLoaderException
@ -50,15 +57,66 @@ public BuildPlan( final LifecycleBindings bindings, final List tasks )
} }
private BuildPlan( final LifecycleBindings bindings, final Map forkedDirectInvocations, final Map forkedPhases, private BuildPlan( final LifecycleBindings bindings, final Map forkedDirectInvocations, final Map forkedPhases,
final Map directInvocationBindings, final List tasks ) final Map directInvocationBindings, final Set fullyResolvedMojoBindings, final List tasks,
boolean includingReports )
{ {
this.bindings = LifecycleUtils.cloneBindings( bindings ); this.bindings = LifecycleUtils.cloneBindings( bindings );
this.forkedDirectInvocations = new HashMap( forkedDirectInvocations ); this.forkedDirectInvocations = new HashMap( forkedDirectInvocations );
this.forkedPhases = new HashMap( forkedPhases ); this.forkedPhases = new HashMap( forkedPhases );
fullyResolvedBindings = new HashSet( fullyResolvedMojoBindings );
this.tasks = tasks; this.tasks = tasks;
this.includingReports = includingReports;
this.directInvocationBindings = new HashMap( directInvocationBindings ); this.directInvocationBindings = new HashMap( directInvocationBindings );
} }
public void markAsIncludingReports()
{
includingReports = true;
}
public boolean isIncludingReports()
{
return includingReports;
}
public boolean isFullyResolved( final MojoBinding mojoBinding )
{
String key = MojoBindingUtils.createMojoBindingKey( mojoBinding, false );
return fullyResolvedBindings.contains( key );
}
public void markFullyResolved()
{
for ( Iterator bindingIterator = bindings.getBindingList().iterator(); bindingIterator.hasNext(); )
{
LifecycleBinding binding = (LifecycleBinding) bindingIterator.next();
for ( Iterator phaseIterator = binding.getPhasesInOrder().iterator(); phaseIterator.hasNext(); )
{
Phase phase = (Phase) phaseIterator.next();
for ( Iterator mojoBindingIterator = phase.getBindings().iterator(); mojoBindingIterator.hasNext(); )
{
MojoBinding mojoBinding = (MojoBinding) mojoBindingIterator.next();
String key = MojoBindingUtils.createMojoBindingKey( mojoBinding, false );
fullyResolvedBindings.add( key );
}
}
}
for ( Iterator it = directInvocationBindings.values().iterator(); it.hasNext(); )
{
MojoBinding mojoBinding = (MojoBinding) it.next();
String key = MojoBindingUtils.createMojoBindingKey( mojoBinding, false );
fullyResolvedBindings.add( key );
}
}
public void addLifecycleOverlay( final LifecycleBindings overlay ) public void addLifecycleOverlay( final LifecycleBindings overlay )
{ {
bindings = LifecycleUtils.mergeBindings( overlay, bindings, null, true, true ); bindings = LifecycleUtils.mergeBindings( overlay, bindings, null, true, true );
@ -135,7 +193,7 @@ public BuildPlan copy( String task )
public BuildPlan copy( final List newTasks ) public BuildPlan copy( final List newTasks )
{ {
return new BuildPlan( bindings, forkedDirectInvocations, forkedPhases, directInvocationBindings, newTasks ); return new BuildPlan( bindings, forkedDirectInvocations, forkedPhases, directInvocationBindings, fullyResolvedBindings, newTasks, includingReports );
} }
public void resetExecutionProgress() public void resetExecutionProgress()

View File

@ -102,6 +102,8 @@ public BuildPlan constructBuildPlan( final List tasks,
addForkedLifecycleModifiers( plan, project, session, new LinkedList() ); addForkedLifecycleModifiers( plan, project, session, new LinkedList() );
addReportingLifecycleModifiers( plan, project, session, new LinkedList() ); addReportingLifecycleModifiers( plan, project, session, new LinkedList() );
plan.markFullyResolved();
// TODO: Inject relative-ordered project/plugin executions as plan modifiers. // TODO: Inject relative-ordered project/plugin executions as plan modifiers.
return plan; return plan;
@ -152,7 +154,10 @@ private void addForkedLifecycleModifiers( final BuildPlan plan,
{ {
MojoBinding mojoBinding = (MojoBinding) it.next(); MojoBinding mojoBinding = (MojoBinding) it.next();
findForkModifiers( mojoBinding, plan, project, session, callStack ); if ( !plan.isFullyResolved( mojoBinding ) )
{
findForkModifiers( mojoBinding, plan, project, session, callStack );
}
} }
} }
@ -197,6 +202,11 @@ private void addReportingLifecycleModifiers( final BuildPlan plan,
LinkedList callStack ) LinkedList callStack )
throws LifecyclePlannerException, LifecycleSpecificationException, LifecycleLoaderException throws LifecyclePlannerException, LifecycleSpecificationException, LifecycleLoaderException
{ {
if ( plan.isIncludingReports() )
{
return;
}
List planBindings = plan.renderExecutionPlan( new Stack() ); List planBindings = plan.renderExecutionPlan( new Stack() );
plan.resetExecutionProgress(); plan.resetExecutionProgress();
@ -204,6 +214,11 @@ private void addReportingLifecycleModifiers( final BuildPlan plan,
{ {
MojoBinding mojoBinding = (MojoBinding) it.next(); MojoBinding mojoBinding = (MojoBinding) it.next();
if ( plan.isFullyResolved( mojoBinding ) )
{
continue;
}
PluginDescriptor pluginDescriptor = loadPluginDescriptor( mojoBinding, PluginDescriptor pluginDescriptor = loadPluginDescriptor( mojoBinding,
plan, plan,
project, project,
@ -234,6 +249,11 @@ private void addReportingLifecycleModifiers( final BuildPlan plan,
{ {
MojoBinding reportBinding = (MojoBinding) reportBindingIt.next(); MojoBinding reportBinding = (MojoBinding) reportBindingIt.next();
if ( plan.isFullyResolved( reportBinding ) )
{
continue;
}
PluginDescriptor pd = loadPluginDescriptor( reportBinding, PluginDescriptor pd = loadPluginDescriptor( reportBinding,
plan, plan,
project, project,
@ -252,6 +272,8 @@ private void addReportingLifecycleModifiers( final BuildPlan plan,
} }
} }
plan.markAsIncludingReports();
// NOTE: the first sighting of a mojo requiring reports should satisfy this condition. // NOTE: the first sighting of a mojo requiring reports should satisfy this condition.
// therefore, we can break out as soon as we find one. // therefore, we can break out as soon as we find one.
break; break;

View File

@ -0,0 +1,35 @@
package org.apache.maven.errors;
import org.apache.maven.InvalidTaskException;
import org.apache.maven.lifecycle.TaskValidationResult;
import org.apache.maven.plugin.InvalidPluginException;
import junit.framework.TestCase;
public class DefaultCoreErrorReporterTest
extends TestCase
{
public void testReportInvalidPluginForDirectInvocation()
{
CoreErrorReporter reporter = new DefaultCoreErrorReporter();
InvalidPluginException err = new InvalidPluginException( "Test message" );
reporter.reportInvalidPluginForDirectInvocation( "test", null, null, err );
TaskValidationResult tvr = new TaskValidationResult( "test", "This is a test invalid task.", err );
InvalidTaskException exception = tvr.generateInvalidTaskException();
Throwable realCause = reporter.findReportedException( exception );
assertSame( err, realCause );
String message = reporter.getFormattedMessage( realCause );
System.out.println( message );
assertNotNull( message );
assertTrue( message.length() > 0 );
}
}

View File

@ -95,7 +95,7 @@ public static void logResult( MavenExecutionRequest request,
logReactorSummary( reactorManager, logger ); logReactorSummary( reactorManager, logger );
boolean printSuccess = true; boolean printSuccess = true;
if ( ( reactorManager == null ) || reactorManager.hasBuildFailures() ) if ( result.hasExceptions() )
{ {
for ( Iterator i = result.getExceptions().iterator(); i.hasNext(); ) for ( Iterator i = result.getExceptions().iterator(); i.hasNext(); )
{ {

View File

@ -0,0 +1,49 @@
<?xml version='1.0' encoding='UTF-8'?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.maven.errortest</groupId>
<artifactId>missing-direct-invoke-mojo-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<version>1</version>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.3.1</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.3</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.1</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
</plugin>
<plugin>
<artifactId>maven-plugin-plugin</artifactId>
<version>2.3</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@ -0,0 +1,36 @@
package org.plugin;
import org.apache.maven.plugin.Mojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
/**
* @goal test-unused
* @aggregator
*
* @author jdcasey
*/
public class TestPlugin
implements Mojo
{
private Log log;
public void execute()
throws MojoExecutionException, MojoFailureException
{
throw new MojoFailureException( this, "This mojo will always fail.", "This mojo is programmed to fail at all times, to express certain error-reporting functions." );
}
public Log getLog()
{
return log;
}
public void setLog( Log log )
{
this.log = log;
}
}

View File

@ -203,6 +203,15 @@ private void buildTestAccessory( File basedir )
private void reportExceptions( MavenExecutionResult result, private void reportExceptions( MavenExecutionResult result,
File basedir ) File basedir )
{ {
reportExceptions( result, basedir, false );
}
private void reportExceptions( MavenExecutionResult result,
File basedir,
boolean expectExceptions )
{
assertTrue( !expectExceptions || result.hasExceptions() );
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
PrintWriter pWriter = new PrintWriter( writer ); PrintWriter pWriter = new PrintWriter( writer );
@ -217,7 +226,14 @@ private void reportExceptions( MavenExecutionResult result,
error.printStackTrace( pWriter ); error.printStackTrace( pWriter );
} }
fail( writer.toString() ); if ( expectExceptions )
{
fail( writer.toString() );
}
else
{
System.out.println( writer.toString() );
}
} }
public void testReportErrorResolvingExtensionDirectDependencies() public void testReportErrorResolvingExtensionDirectDependencies()
@ -1455,4 +1471,38 @@ public void testReportMissingModulePom()
reporterCtl.verify(); reporterCtl.verify();
} }
public void testReportInvalidPluginForDirectInvocation()
throws IOException
{
File projectDir = prepareProjectDir( "missing-direct-invoke-mojo" );
File plugin = new File( projectDir, "plugin" );
buildTestAccessory( plugin );
Settings settings = new Settings();
settings.addPluginGroup( "org.apache.maven.errortest" );
reporter.reportInvalidPluginForDirectInvocation( null, null, null, null );
reporterCtl.setMatcher( MockControl.ALWAYS_MATCHER );
reporterCtl.setVoidCallable();
reporterCtl.replay();
MavenExecutionRequest request = new DefaultMavenExecutionRequest().setBaseDirectory( projectDir )
.setSettings( settings )
.setShowErrors( true )
.setErrorReporter( reporter )
.setGoals( Arrays.asList( new String[] {
"missing-direct-invoke-mojo:test"
} ) );
MavenExecutionResult result = maven.execute( request );
assertTrue( result.hasExceptions() );
reportExceptions( result, projectDir );
reporterCtl.verify();
}
} }