[MNG-4463] Dependency management import should support version ranges. o Extended the 'ModelResolver' interface to support resolving 'Dependency's in addition to 'Parent's.
Closes #64 without merging. ITs are pending to be committed. Project: http://git-wip-us.apache.org/repos/asf/maven/repo Commit: http://git-wip-us.apache.org/repos/asf/maven/commit/086ebf06 Tree: http://git-wip-us.apache.org/repos/asf/maven/tree/086ebf06 Diff: http://git-wip-us.apache.org/repos/asf/maven/diff/086ebf06 Branch: refs/heads/DEPMGMT-INCLUDE-IT Commit: 086ebf0682399c66a268b3f185f71f45a2383815 Parents: 9353ad7 Author: Christian Schulte <schu...@apache.org> Authored: Sat Jan 30 19:17:34 2016 +0100 Committer: Christian Schulte <schu...@apache.org> Committed: Wed Feb 1 21:19:41 2017 +0100 ---------------------------------------------------------------------- .../maven/project/ProjectModelResolver.java | 82 +++++++++++++++---- .../model/building/DefaultModelBuilder.java | 20 ++++- .../maven/model/resolution/ModelResolver.java | 32 ++++++++ .../internal/DefaultModelResolver.java | 84 ++++++++++++++++---- 4 files changed, 184 insertions(+), 34 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/maven/blob/086ebf06/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java ---------------------------------------------------------------------- diff --git a/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java b/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java index 184be70..f11e77d 100644 --- a/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java +++ b/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java @@ -26,6 +26,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import org.apache.maven.model.Dependency; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; @@ -203,24 +204,26 @@ public class ProjectModelResolver return new FileModelSource( pomFile ); } - public ModelSource resolveModel( Parent parent ) + @Override + public ModelSource resolveModel( final Parent parent ) throws UnresolvableModelException { - Artifact artifact = new DefaultArtifact( parent.getGroupId(), parent.getArtifactId(), "", "pom", - parent.getVersion() ); - - VersionRangeRequest versionRangeRequest = new VersionRangeRequest( artifact, repositories, context ); - versionRangeRequest.setTrace( trace ); - try { - VersionRangeResult versionRangeResult = resolver.resolveVersionRange( session, versionRangeRequest ); + final Artifact artifact = new DefaultArtifact( parent.getGroupId(), parent.getArtifactId(), "", "pom", + parent.getVersion() ); + + final VersionRangeRequest versionRangeRequest = new VersionRangeRequest( artifact, repositories, context ); + versionRangeRequest.setTrace( trace ); + + final VersionRangeResult versionRangeResult = resolver.resolveVersionRange( session, versionRangeRequest ); if ( versionRangeResult.getHighestVersion() == null ) { - throw new UnresolvableModelException( "No versions matched the requested range '" + parent.getVersion() - + "'", parent.getGroupId(), parent.getArtifactId(), - parent.getVersion() ); + throw new UnresolvableModelException( + String.format( "No versions matched the requested parent version range '%s'", + parent.getVersion() ), + parent.getGroupId(), parent.getArtifactId(), parent.getVersion() ); } @@ -228,21 +231,68 @@ public class ProjectModelResolver && versionRangeResult.getVersionConstraint().getRange() != null && versionRangeResult.getVersionConstraint().getRange().getUpperBound() == null ) { - throw new UnresolvableModelException( "The requested version range '" + parent.getVersion() - + "' does not specify an upper bound", parent.getGroupId(), - parent.getArtifactId(), parent.getVersion() ); + throw new UnresolvableModelException( + String.format( "The requested parent version range '%s' does not specify an upper bound", + parent.getVersion() ), + parent.getGroupId(), parent.getArtifactId(), parent.getVersion() ); } parent.setVersion( versionRangeResult.getHighestVersion().toString() ); + + return resolveModel( parent.getGroupId(), parent.getArtifactId(), parent.getVersion() ); } - catch ( VersionRangeResolutionException e ) + catch ( final VersionRangeResolutionException e ) { throw new UnresolvableModelException( e.getMessage(), parent.getGroupId(), parent.getArtifactId(), parent.getVersion(), e ); } + } + + @Override + public ModelSource resolveModel( final Dependency dependency ) + throws UnresolvableModelException + { + try + { + final Artifact artifact = new DefaultArtifact( dependency.getGroupId(), dependency.getArtifactId(), "", + "pom", dependency.getVersion() ); + + final VersionRangeRequest versionRangeRequest = new VersionRangeRequest( artifact, repositories, context ); + versionRangeRequest.setTrace( trace ); + + final VersionRangeResult versionRangeResult = resolver.resolveVersionRange( session, versionRangeRequest ); + + if ( versionRangeResult.getHighestVersion() == null ) + { + throw new UnresolvableModelException( + String.format( "No versions matched the requested dependency version range '%s'", + dependency.getVersion() ), + dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() ); + + } + + if ( versionRangeResult.getVersionConstraint() != null + && versionRangeResult.getVersionConstraint().getRange() != null + && versionRangeResult.getVersionConstraint().getRange().getUpperBound() == null ) + { + throw new UnresolvableModelException( + String.format( "The requested dependency version range '%s' does not specify an upper bound", + dependency.getVersion() ), + dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() ); + + } + + dependency.setVersion( versionRangeResult.getHighestVersion().toString() ); + + return resolveModel( dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() ); + } + catch ( VersionRangeResolutionException e ) + { + throw new UnresolvableModelException( e.getMessage(), dependency.getGroupId(), dependency.getArtifactId(), + dependency.getVersion(), e ); - return resolveModel( parent.getGroupId(), parent.getArtifactId(), parent.getVersion() ); + } } } http://git-wip-us.apache.org/repos/asf/maven/blob/086ebf06/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java ---------------------------------------------------------------------- diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java index 49a1f3c..3532660 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java @@ -1208,7 +1208,25 @@ public class DefaultModelBuilder final ModelSource importSource; try { - importSource = modelResolver.resolveModel( groupId, artifactId, version ); + dependency = dependency.clone(); + importSource = modelResolver.resolveModel( dependency ); + final String resolvedId = + dependency.getGroupId() + ':' + dependency.getArtifactId() + ':' + dependency.getVersion(); + + if ( !imported.equals( resolvedId ) && importIds.contains( resolvedId ) ) + { + // A version range has been resolved to a cycle. + String message = "The dependencies of type=pom and with scope=import form a cycle: "; + for ( String modelId : importIds ) + { + message += modelId + " -> "; + } + message += resolvedId; + problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ). + setMessage( message ) ); + + continue; + } } catch ( UnresolvableModelException e ) { http://git-wip-us.apache.org/repos/asf/maven/blob/086ebf06/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java ---------------------------------------------------------------------- diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java index c81a536..cb2a3ed 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java @@ -19,6 +19,7 @@ package org.apache.maven.model.resolution; * under the License. */ +import org.apache.maven.model.Dependency; import org.apache.maven.model.Parent; import org.apache.maven.model.Repository; import org.apache.maven.model.building.ModelSource; @@ -47,16 +48,47 @@ public interface ModelResolver /** * Tries to resolve the POM for the specified parent coordinates possibly updating {@code parent}. + * <p> + * Unlike the {@link #resolveModel(java.lang.String, java.lang.String, java.lang.String)} method, this method + * supports version ranges and updates the given {@code parent} instance to match the returned {@code ModelSource}. + * If {@code parent} declares a version range, the version corresponding to the returned {@code ModelSource} will + * be set on the given {@code parent}. + * </p> * * @param parent The parent coordinates to resolve, must not be {@code null}. + * * @return The source of the requested POM, never {@code null}. + * * @throws UnresolvableModelException If the POM could not be resolved from any configured repository. * @since 3.2.2 + * + * @see Parent#clone() */ ModelSource resolveModel( Parent parent ) throws UnresolvableModelException; /** + * Tries to resolve the POM for the specified dependency coordinates possibly updating {@code dependency}. + * <p> + * Unlike the {@link #resolveModel(java.lang.String, java.lang.String, java.lang.String)} method, this method + * supports version ranges and updates the given {@code dependency} instance to match the returned + * {@code ModelSource}. If {@code dependency} declares a version range, the version corresponding to the returned + * {@code ModelSource} will be set on the given {@code dependency}. + * </p> + * + * @param dependency The dependency coordinates to resolve, must not be {@code null}. + * + * @return The source of the requested POM, never {@code null}. + * + * @throws UnresolvableModelException If the POM could not be resolved from any configured repository. + * @since 3.4 + * + * @see Dependency#clone() + */ + ModelSource resolveModel( Dependency dependency ) + throws UnresolvableModelException; + + /** * Adds a repository to use for subsequent resolution requests. The order in which repositories are added matters, * repositories that were added first should also be searched first. When multiple repositories with the same * identifier are added, only the first repository being added will be used. http://git-wip-us.apache.org/repos/asf/maven/blob/086ebf06/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java ---------------------------------------------------------------------- diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java index f344959..0832a3a 100644 --- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java +++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java @@ -26,6 +26,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import org.apache.maven.model.Dependency; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import org.apache.maven.model.Parent; @@ -182,25 +183,27 @@ class DefaultModelResolver return new FileModelSource( pomFile ); } - public ModelSource resolveModel( Parent parent ) + @Override + public ModelSource resolveModel( final Parent parent ) throws UnresolvableModelException { - Artifact artifact = new DefaultArtifact( parent.getGroupId(), parent.getArtifactId(), "", "pom", - parent.getVersion() ); - - VersionRangeRequest versionRangeRequest = new VersionRangeRequest( artifact, repositories, context ); - versionRangeRequest.setTrace( trace ); - try { - VersionRangeResult versionRangeResult = + final Artifact artifact = new DefaultArtifact( parent.getGroupId(), parent.getArtifactId(), "", "pom", + parent.getVersion() ); + + final VersionRangeRequest versionRangeRequest = new VersionRangeRequest( artifact, repositories, context ); + versionRangeRequest.setTrace( trace ); + + final VersionRangeResult versionRangeResult = versionRangeResolver.resolveVersionRange( session, versionRangeRequest ); if ( versionRangeResult.getHighestVersion() == null ) { - throw new UnresolvableModelException( "No versions matched the requested range '" + parent.getVersion() - + "'", parent.getGroupId(), parent.getArtifactId(), - parent.getVersion() ); + throw new UnresolvableModelException( + String.format( "No versions matched the requested parent version range '%s'", + parent.getVersion() ), + parent.getGroupId(), parent.getArtifactId(), parent.getVersion() ); } @@ -208,22 +211,69 @@ class DefaultModelResolver && versionRangeResult.getVersionConstraint().getRange() != null && versionRangeResult.getVersionConstraint().getRange().getUpperBound() == null ) { - throw new UnresolvableModelException( "The requested version range '" + parent.getVersion() - + "' does not specify an upper bound", parent.getGroupId(), - parent.getArtifactId(), parent.getVersion() ); + throw new UnresolvableModelException( + String.format( "The requested parent version range '%s' does not specify an upper bound", + parent.getVersion() ), + parent.getGroupId(), parent.getArtifactId(), parent.getVersion() ); } parent.setVersion( versionRangeResult.getHighestVersion().toString() ); + + return resolveModel( parent.getGroupId(), parent.getArtifactId(), parent.getVersion() ); } - catch ( VersionRangeResolutionException e ) + catch ( final VersionRangeResolutionException e ) { throw new UnresolvableModelException( e.getMessage(), parent.getGroupId(), parent.getArtifactId(), parent.getVersion(), e ); } - - return resolveModel( parent.getGroupId(), parent.getArtifactId(), parent.getVersion() ); } + @Override + public ModelSource resolveModel( final Dependency dependency ) + throws UnresolvableModelException + { + try + { + final Artifact artifact = new DefaultArtifact( dependency.getGroupId(), dependency.getArtifactId(), "", + "pom", dependency.getVersion() ); + + final VersionRangeRequest versionRangeRequest = new VersionRangeRequest( artifact, repositories, context ); + versionRangeRequest.setTrace( trace ); + + final VersionRangeResult versionRangeResult = + versionRangeResolver.resolveVersionRange( session, versionRangeRequest ); + + if ( versionRangeResult.getHighestVersion() == null ) + { + throw new UnresolvableModelException( + String.format( "No versions matched the requested dependency version range '%s'", + dependency.getVersion() ), + dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() ); + + } + + if ( versionRangeResult.getVersionConstraint() != null + && versionRangeResult.getVersionConstraint().getRange() != null + && versionRangeResult.getVersionConstraint().getRange().getUpperBound() == null ) + { + throw new UnresolvableModelException( + String.format( "The requested dependency version range '%s' does not specify an upper bound", + dependency.getVersion() ), + dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() ); + + } + + dependency.setVersion( versionRangeResult.getHighestVersion().toString() ); + + return resolveModel( dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() ); + } + catch ( VersionRangeResolutionException e ) + { + throw new UnresolvableModelException( e.getMessage(), dependency.getGroupId(), dependency.getArtifactId(), + dependency.getVersion(), e ); + + } + } }