[MNG-5073] ProjectBuilder.build(File,ProjectBuildingRequest) returns null project if dependency version info is missing

git-svn-id: https://svn.apache.org/repos/asf/maven/maven-3/trunk@1176414 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Benjamin Bentmann 2011-09-27 14:55:56 +00:00
parent 870a3b3e80
commit c3bf134f57
9 changed files with 238 additions and 77 deletions

View File

@ -18,6 +18,7 @@ package org.apache.maven.project;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
@ -119,6 +120,7 @@ public class DefaultProjectBuilder
MavenProject project = configuration.getProject();
List<ModelProblem> modelProblems = null;
Throwable error = null;
if ( project == null )
{
@ -141,7 +143,13 @@ public class DefaultProjectBuilder
}
catch ( ModelBuildingException e )
{
throw new ProjectBuildingException( e.getModelId(), e.getMessage(), pomFile, e );
result = e.getResult();
if ( result == null || result.getEffectiveModel() == null )
{
throw new ProjectBuildingException( e.getModelId(), e.getMessage(), pomFile, e );
}
// validation error, continue project building and delay failing to help IDEs
error = e;
}
modelProblems = result.getProblems();
@ -158,39 +166,19 @@ public class DefaultProjectBuilder
if ( configuration.isResolveDependencies() )
{
try
{
DefaultDependencyResolutionRequest resolution =
new DefaultDependencyResolutionRequest( project, config.session );
resolutionResult = dependencyResolver.resolve( resolution );
}
catch ( DependencyResolutionException e )
{
resolutionResult = e.getResult();
}
Set<Artifact> artifacts = new LinkedHashSet<Artifact>();
if ( resolutionResult.getDependencyGraph() != null )
{
RepositoryUtils.toArtifacts( artifacts, resolutionResult.getDependencyGraph().getChildren(),
Collections.singletonList( project.getArtifact().getId() ), null );
// Maven 2.x quirk: an artifact always points at the local repo, regardless whether resolved or not
LocalRepositoryManager lrm = config.session.getLocalRepositoryManager();
for ( Artifact artifact : artifacts )
{
if ( !artifact.isResolved() )
{
String path = lrm.getPathForLocalArtifact( RepositoryUtils.toArtifact( artifact ) );
artifact.setFile( new File( lrm.getRepository().getBasedir(), path ) );
}
}
}
project.setResolvedArtifacts( artifacts );
project.setArtifacts( artifacts );
resolutionResult = resolveDependencies( project, config.session );
}
return new DefaultProjectBuildingResult( project, modelProblems, resolutionResult );
ProjectBuildingResult result = new DefaultProjectBuildingResult( project, modelProblems, resolutionResult );
if ( error != null )
{
ProjectBuildingException e = new ProjectBuildingException( Arrays.asList( result ) );
e.initCause( error );
throw e;
}
return result;
}
finally
{
@ -198,6 +186,43 @@ public class DefaultProjectBuilder
}
}
private DependencyResolutionResult resolveDependencies( MavenProject project, RepositorySystemSession session )
{
DependencyResolutionResult resolutionResult = null;
try
{
DefaultDependencyResolutionRequest resolution = new DefaultDependencyResolutionRequest( project, session );
resolutionResult = dependencyResolver.resolve( resolution );
}
catch ( DependencyResolutionException e )
{
resolutionResult = e.getResult();
}
Set<Artifact> artifacts = new LinkedHashSet<Artifact>();
if ( resolutionResult.getDependencyGraph() != null )
{
RepositoryUtils.toArtifacts( artifacts, resolutionResult.getDependencyGraph().getChildren(),
Collections.singletonList( project.getArtifact().getId() ), null );
// Maven 2.x quirk: an artifact always points at the local repo, regardless whether resolved or not
LocalRepositoryManager lrm = session.getLocalRepositoryManager();
for ( Artifact artifact : artifacts )
{
if ( !artifact.isResolved() )
{
String path = lrm.getPathForLocalArtifact( RepositoryUtils.toArtifact( artifact ) );
artifact.setFile( new File( lrm.getRepository().getBasedir(), path ) );
}
}
}
project.setResolvedArtifacts( artifacts );
project.setArtifacts( artifacts );
return resolutionResult;
}
private List<String> getProfileIds( List<Profile> profiles )
{
List<String> ids = new ArrayList<String>( profiles.size() );

View File

@ -33,6 +33,7 @@ import org.apache.maven.model.InputSource;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.util.StringUtils;
import org.sonatype.aether.RepositorySystem;
import org.sonatype.aether.RepositorySystemSession;
import org.sonatype.aether.RequestTrace;
@ -85,6 +86,12 @@ public class DefaultProjectDependenciesResolver
{
for ( Dependency dependency : project.getDependencies() )
{
if ( StringUtils.isEmpty( dependency.getGroupId() ) || StringUtils.isEmpty( dependency.getArtifactId() )
|| StringUtils.isEmpty( dependency.getVersion() ) )
{
// guard against case where best-effort resolution for invalid models is requested
continue;
}
collect.addDependency( RepositoryUtils.toDependency( dependency, stereotypes ) );
}
}

View File

@ -124,12 +124,10 @@ public abstract class AbstractMavenProjectTestCase
protected MavenProject getProjectWithDependencies( File pom )
throws Exception
{
ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
configuration.setLocalRepository( getLocalRepository() );
ProjectBuildingRequest configuration = newBuildingRequest();
configuration.setRemoteRepositories( Arrays.asList( new ArtifactRepository[] {} ) );
configuration.setProcessPlugins( false );
configuration.setResolveDependencies( true );
initRepoSession( configuration );
try
{
@ -146,7 +144,6 @@ public abstract class AbstractMavenProjectTestCase
message += problem + "\n";
}
System.out.println( message );
fail( message );
}
throw e;
@ -155,12 +152,19 @@ public abstract class AbstractMavenProjectTestCase
protected MavenProject getProject( File pom )
throws Exception
{
ProjectBuildingRequest configuration = newBuildingRequest();
return projectBuilder.build( pom, configuration ).getProject();
}
protected ProjectBuildingRequest newBuildingRequest()
throws Exception
{
ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
configuration.setLocalRepository( getLocalRepository() );
initRepoSession( configuration );
return projectBuilder.build( pom, configuration ).getProject();
return configuration;
}
protected void initRepoSession( ProjectBuildingRequest request )

View File

@ -155,5 +155,32 @@ public class DefaultMavenProjectBuilderTest
getProject( f1 );
}
}
public void testPartialResultUponBadDependencyDeclaration()
throws Exception
{
File pomFile = getTestFile( "src/test/resources/projects/bad-dependency.xml" );
try
{
ProjectBuildingRequest request = newBuildingRequest();
request.setProcessPlugins( false );
request.setResolveDependencies( true );
projectBuilder.build( pomFile, request );
fail( "Project building did not fail despite invalid POM" );
}
catch ( ProjectBuildingException e )
{
List<ProjectBuildingResult> results = e.getResults();
assertNotNull( results );
assertEquals( 1, results.size() );
ProjectBuildingResult result = results.get( 0 );
assertNotNull( result );
assertNotNull( result.getProject() );
assertEquals( 1, result.getProblems().size() );
assertEquals( 1, result.getProject().getArtifacts().size() );
assertNotNull( result.getDependencyResolutionResult() );
}
}
}

View File

@ -33,6 +33,7 @@ import org.sonatype.aether.spi.connector.ArtifactUpload;
import org.sonatype.aether.spi.connector.MetadataDownload;
import org.sonatype.aether.spi.connector.MetadataUpload;
import org.sonatype.aether.spi.connector.RepositoryConnector;
import org.sonatype.aether.transfer.ArtifactNotFoundException;
import org.sonatype.aether.transfer.ArtifactTransferException;
/**
@ -77,7 +78,14 @@ public class TestRepositoryConnector
}
catch ( IOException e )
{
download.setException( new ArtifactTransferException( download.getArtifact(), repository, e ) );
if ( !remoteFile.exists() )
{
download.setException( new ArtifactNotFoundException( download.getArtifact(), repository ) );
}
else
{
download.setException( new ArtifactTransferException( download.getArtifact(), repository, e ) );
}
}
}
}

View File

@ -0,0 +1,27 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>invalid</artifactId>
<version>0.0.1-SNAPSHOT</version>
<repositories>
<repository>
<id>central</id>
<url>file:src/test/remote-repo</url>
</repository>
</repositories>
<dependencies>
<dependency>
<!-- groupId deliberately missing -->
<artifactId>b</artifactId>
<version>0.1</version>
</dependency>
<dependency>
<groupId>org.apache.maven.its</groupId>
<artifactId>a</artifactId>
<version>0.1</version>
</dependency>
</dependencies>
</project>

View File

@ -237,7 +237,7 @@ public class DefaultModelBuilder
{
DefaultModelBuildingResult result = new DefaultModelBuildingResult();
DefaultModelProblemCollector problems = new DefaultModelProblemCollector( null );
DefaultModelProblemCollector problems = new DefaultModelProblemCollector( result );
DefaultProfileActivationContext profileActivationContext = getProfileActivationContext( request );
@ -245,6 +245,8 @@ public class DefaultModelBuilder
List<Profile> activeExternalProfiles =
profileSelector.getActiveProfiles( request.getProfiles(), profileActivationContext, problems );
result.setActiveExternalProfiles( activeExternalProfiles );
if ( !activeExternalProfiles.isEmpty() )
{
Properties profileProps = new Properties();
@ -321,8 +323,7 @@ public class DefaultModelBuilder
message += currentData.getId();
problems.add( ModelProblem.Severity.FATAL, message, null, null );
throw new ModelBuildingException( problems.getRootModel(), problems.getRootModelId(),
problems.getProblems() );
throw problems.newModelBuildingException();
}
}
@ -345,12 +346,8 @@ public class DefaultModelBuilder
resultData.setArtifactId( resultModel.getArtifactId() );
resultData.setVersion( resultModel.getVersion() );
result.setProblems( problems.getProblems() );
result.setEffectiveModel( resultModel );
result.setActiveExternalProfiles( activeExternalProfiles );
for ( ModelData currentData : lineage )
{
String modelId = ( currentData != superData ) ? currentData.getId() : "";
@ -380,7 +377,7 @@ public class DefaultModelBuilder
{
Model resultModel = result.getEffectiveModel();
DefaultModelProblemCollector problems = new DefaultModelProblemCollector( result.getProblems() );
DefaultModelProblemCollector problems = new DefaultModelProblemCollector( result );
problems.setSource( resultModel );
problems.setRootModel( resultModel );
@ -419,7 +416,7 @@ public class DefaultModelBuilder
if ( problems.hasErrors() )
{
throw new ModelBuildingException( resultModel, problems.getRootModelId(), problems.getProblems() );
throw problems.newModelBuildingException();
}
return result;
@ -499,8 +496,7 @@ public class DefaultModelBuilder
{
problems.add( Severity.FATAL, "Non-parseable POM " + modelSource.getLocation() + ": " + e.getMessage(),
null, e );
throw new ModelBuildingException( problems.getRootModel(), problems.getRootModelId(),
problems.getProblems() );
throw problems.newModelBuildingException();
}
catch ( IOException e )
{
@ -518,8 +514,7 @@ public class DefaultModelBuilder
}
}
problems.add( Severity.FATAL, "Non-readable POM " + modelSource.getLocation() + ": " + msg, null, e );
throw new ModelBuildingException( problems.getRootModel(), problems.getRootModelId(),
problems.getProblems() );
throw problems.newModelBuildingException();
}
model.setPomFile( pomFile );
@ -529,8 +524,7 @@ public class DefaultModelBuilder
if ( problems.hasFatalErrors() )
{
throw new ModelBuildingException( problems.getRootModel(), problems.getRootModelId(),
problems.getProblems() );
throw problems.newModelBuildingException();
}
return model;
@ -844,8 +838,7 @@ public class DefaultModelBuilder
}
problems.add( Severity.FATAL, buffer.toString(), parent.getLocation( "" ), e );
throw new ModelBuildingException( problems.getRootModel(), problems.getRootModelId(),
problems.getProblems() );
throw problems.newModelBuildingException();
}
ModelBuildingRequest lenientRequest = request;
@ -863,8 +856,7 @@ public class DefaultModelBuilder
Model parentModel = readModel( modelSource, null, lenientRequest, problems );
ModelData parentData =
new ModelData( parentModel, parent.getGroupId(), parent.getArtifactId(), parent.getVersion() );
ModelData parentData = new ModelData( parentModel, groupId, artifactId, version );
return parentData;
}

View File

@ -19,7 +19,6 @@ package org.apache.maven.model.building;
* under the License.
*/
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
@ -42,6 +41,8 @@ class DefaultModelProblemCollector
implements ModelProblemCollector
{
private final ModelBuildingResult result;
private List<ModelProblem> problems;
private String source;
@ -52,9 +53,10 @@ class DefaultModelProblemCollector
private Set<ModelProblem.Severity> severities = EnumSet.noneOf( ModelProblem.Severity.class );
public DefaultModelProblemCollector( List<ModelProblem> problems )
public DefaultModelProblemCollector( ModelBuildingResult result )
{
this.problems = ( problems != null ) ? problems : new ArrayList<ModelProblem>();
this.result = result;
this.problems = result.getProblems();
for ( ModelProblem problem : this.problems )
{
@ -176,4 +178,21 @@ class DefaultModelProblemCollector
add( problem );
}
public ModelBuildingException newModelBuildingException()
{
ModelBuildingResult result = this.result;
if ( result.getModelIds().isEmpty() )
{
DefaultModelBuildingResult tmp = new DefaultModelBuildingResult();
tmp.setEffectiveModel( result.getEffectiveModel() );
tmp.setProblems( getProblems() );
tmp.setActiveExternalProfiles( result.getActiveExternalProfiles() );
String id = getRootModelId();
tmp.addModelId( id );
tmp.setRawModel( id, getRootModel() );
result = tmp;
}
return new ModelBuildingException( result );
}
}

View File

@ -21,7 +21,7 @@ package org.apache.maven.model.building;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.maven.model.Model;
@ -37,11 +37,7 @@ public class ModelBuildingException
extends Exception
{
private final Model model;
private final String modelId;
private final List<ModelProblem> problems;
private final ModelBuildingResult result;
/**
* Creates a new exception with the specified problems.
@ -49,19 +45,50 @@ public class ModelBuildingException
* @param model The model that could not be built, may be {@code null}.
* @param modelId The identifier of the model that could not be built, may be {@code null}.
* @param problems The problems that causes this exception, may be {@code null}.
* @deprecated Use {@link #ModelBuildingException(ModelBuildingResult)} instead.
*/
@Deprecated
public ModelBuildingException( Model model, String modelId, List<ModelProblem> problems )
{
super( toMessage( modelId, problems ) );
this.model = model;
this.modelId = ( modelId != null ) ? modelId : "";
this.problems = new ArrayList<ModelProblem>();
if ( problems != null )
if ( model != null )
{
this.problems.addAll( problems );
DefaultModelBuildingResult tmp = new DefaultModelBuildingResult();
if ( modelId == null )
{
modelId = "";
}
tmp.addModelId( modelId );
tmp.setRawModel( modelId, model );
tmp.setProblems( problems );
result = tmp;
}
else
{
result = null;
}
}
/**
* Creates a new exception from the specified interim result and its associated problems.
*
* @param result The interim result, may be {@code null}.
*/
public ModelBuildingException( ModelBuildingResult result )
{
super( toMessage( result ) );
this.result = result;
}
/**
* Gets the interim result of the model building up to the point where it failed.
*
* @return The interim model building result or {@code null} if not available.
*/
public ModelBuildingResult getResult()
{
return result;
}
/**
@ -71,7 +98,15 @@ public class ModelBuildingException
*/
public Model getModel()
{
return model;
if ( result == null )
{
return null;
}
if ( result.getEffectiveModel() != null )
{
return result.getEffectiveModel();
}
return result.getRawModel();
}
/**
@ -83,7 +118,11 @@ public class ModelBuildingException
*/
public String getModelId()
{
return modelId;
if ( result == null || result.getModelIds().isEmpty() )
{
return "";
}
return result.getModelIds().get( 0 );
}
/**
@ -93,7 +132,20 @@ public class ModelBuildingException
*/
public List<ModelProblem> getProblems()
{
return problems;
if ( result == null )
{
return Collections.emptyList();
}
return result.getProblems();
}
private static String toMessage( ModelBuildingResult result )
{
if ( result != null && !result.getModelIds().isEmpty() )
{
return toMessage( result.getModelIds().get( 0 ), result.getProblems() );
}
return null;
}
private static String toMessage( String modelId, List<ModelProblem> problems )