Author: bentmann Date: Tue Sep 27 14:55:56 2011 New Revision: 1176414 URL: http://svn.apache.org/viewvc?rev=1176414&view=rev Log: [MNG-5073] ProjectBuilder.build(File,ProjectBuildingRequest) returns null project if dependency version info is missing
Added: maven/maven-3/trunk/maven-core/src/test/resources/projects/bad-dependency.xml (with props) Modified: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectDependenciesResolver.java maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/AbstractMavenProjectTestCase.java maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/DefaultMavenProjectBuilderTest.java maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/repository/TestRepositoryConnector.java maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblemCollector.java maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingException.java Modified: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java?rev=1176414&r1=1176413&r2=1176414&view=diff ============================================================================== --- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java (original) +++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java Tue Sep 27 14:55:56 2011 @@ -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(); - } + resolutionResult = resolveDependencies( project, config.session ); + } - Set<Artifact> artifacts = new LinkedHashSet<Artifact>(); - if ( resolutionResult.getDependencyGraph() != null ) - { - RepositoryUtils.toArtifacts( artifacts, resolutionResult.getDependencyGraph().getChildren(), - Collections.singletonList( project.getArtifact().getId() ), null ); + ProjectBuildingResult result = new DefaultProjectBuildingResult( project, modelProblems, resolutionResult ); - // 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 ); + if ( error != null ) + { + ProjectBuildingException e = new ProjectBuildingException( Arrays.asList( result ) ); + e.initCause( error ); + throw e; } - return new DefaultProjectBuildingResult( project, modelProblems, resolutionResult ); + 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() ); Modified: maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectDependenciesResolver.java URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectDependenciesResolver.java?rev=1176414&r1=1176413&r2=1176414&view=diff ============================================================================== --- maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectDependenciesResolver.java (original) +++ maven/maven-3/trunk/maven-core/src/main/java/org/apache/maven/project/DefaultProjectDependenciesResolver.java Tue Sep 27 14:55:56 2011 @@ -33,6 +33,7 @@ import org.apache.maven.model.InputSourc 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 DefaultProjectDependenciesR { 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 ) ); } } Modified: maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/AbstractMavenProjectTestCase.java URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/AbstractMavenProjectTestCase.java?rev=1176414&r1=1176413&r2=1176414&view=diff ============================================================================== --- maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/AbstractMavenProjectTestCase.java (original) +++ maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/AbstractMavenProjectTestCase.java Tue Sep 27 14:55:56 2011 @@ -124,12 +124,10 @@ public abstract class AbstractMavenProje 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 AbstractMavenProje message += problem + "\n"; } System.out.println( message ); - fail( message ); } throw e; @@ -156,11 +153,18 @@ public abstract class AbstractMavenProje 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 ) Modified: maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/DefaultMavenProjectBuilderTest.java URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/DefaultMavenProjectBuilderTest.java?rev=1176414&r1=1176413&r2=1176414&view=diff ============================================================================== --- maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/DefaultMavenProjectBuilderTest.java (original) +++ maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/project/DefaultMavenProjectBuilderTest.java Tue Sep 27 14:55:56 2011 @@ -155,5 +155,32 @@ public class DefaultMavenProjectBuilderT 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() ); + } + } + } Modified: maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/repository/TestRepositoryConnector.java URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/repository/TestRepositoryConnector.java?rev=1176414&r1=1176413&r2=1176414&view=diff ============================================================================== --- maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/repository/TestRepositoryConnector.java (original) +++ maven/maven-3/trunk/maven-core/src/test/java/org/apache/maven/repository/TestRepositoryConnector.java Tue Sep 27 14:55:56 2011 @@ -33,6 +33,7 @@ import org.sonatype.aether.spi.connector 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 ) ); + } } } } Added: maven/maven-3/trunk/maven-core/src/test/resources/projects/bad-dependency.xml URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-core/src/test/resources/projects/bad-dependency.xml?rev=1176414&view=auto ============================================================================== --- maven/maven-3/trunk/maven-core/src/test/resources/projects/bad-dependency.xml (added) +++ maven/maven-3/trunk/maven-core/src/test/resources/projects/bad-dependency.xml Tue Sep 27 14:55:56 2011 @@ -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> Propchange: maven/maven-3/trunk/maven-core/src/test/resources/projects/bad-dependency.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/maven-3/trunk/maven-core/src/test/resources/projects/bad-dependency.xml ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Modified: maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java?rev=1176414&r1=1176413&r2=1176414&view=diff ============================================================================== --- maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java (original) +++ maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java Tue Sep 27 14:55:56 2011 @@ -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; } Modified: maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblemCollector.java URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblemCollector.java?rev=1176414&r1=1176413&r2=1176414&view=diff ============================================================================== --- maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblemCollector.java (original) +++ maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblemCollector.java Tue Sep 27 14:55:56 2011 @@ -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 ); + } + } Modified: maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingException.java URL: http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingException.java?rev=1176414&r1=1176413&r2=1176414&view=diff ============================================================================== --- maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingException.java (original) +++ maven/maven-3/trunk/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingException.java Tue Sep 27 14:55:56 2011 @@ -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,29 +45,68 @@ 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 ) + { + DefaultModelBuildingResult tmp = new DefaultModelBuildingResult(); + if ( modelId == null ) + { + modelId = ""; + } + tmp.addModelId( modelId ); + tmp.setRawModel( modelId, model ); + tmp.setProblems( problems ); + result = tmp; + } + else { - this.problems.addAll( problems ); + 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; + } + + /** * Gets the model that could not be built properly. * * @return The erroneous model or {@code null} if not available. */ 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 )