Skip to content

Commit

Permalink
[MNG-2199] Support version ranges in parent elements
Browse files Browse the repository at this point in the history
o Updated to fix parent version range resolution broken since 3.2.3 and to
  remove parent version range resolution logic obsolete since Maven
  3.2.3 which changed the initialization of MavenProject instances.
o Updated local parent resolution to behave the same way remote parent
  resolution behaves. When referencing a parent using version ranges,
  inheriting the version or using version expressions should not be supported.
  It has been implemented that way for remote parent resolution as it got
  introduced in Maven 3.2.2. For local parent resolution the version in parent
  declarations had been ignored completely as of Maven 3.3.0 due to commit
  be3fb20 removing all local parent version
  validation. Work on fixing this is tracked by MNG-5840 released with Maven
  3.3.9. This commit adds the final missing bits to make local and remote parent
  resolution behave the same way as much as possible. As an exception, remote
  parent resolution still is a bit more strict than local parent resolution due
  to a different API in use. When resolving a parent from a repository using
  version ranges, the ModelBuilder verifies the range in use to declare an upper
  bound. When resolving a parent locally using version ranges, those ranges are
  not required to declare an upper bound because the API in use does not support
  querying that. Authoring a POM relying on this difference should be considered
  a bug.
o Added test cases to maven-core testing parent version range resolution for
  local and remote parent models.
  • Loading branch information
ChristianSchulte committed Feb 10, 2017
1 parent f4e07ac commit 0514c1b
Show file tree
Hide file tree
Showing 20 changed files with 484 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 43,6 @@
import org.apache.maven.model.DeploymentRepository;
import org.apache.maven.model.Extension;
import org.apache.maven.model.Model;
import org.apache.maven.model.Parent;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.Profile;
import org.apache.maven.model.ReportPlugin;
Expand Down Expand Up @@ -73,9 72,6 @@
import org.eclipse.aether.repository.WorkspaceRepository;
import org.eclipse.aether.resolution.ArtifactRequest;
import org.eclipse.aether.resolution.ArtifactResult;
import org.eclipse.aether.resolution.VersionRangeRequest;
import org.eclipse.aether.resolution.VersionRangeResolutionException;
import org.eclipse.aether.resolution.VersionRangeResult;

/**
*/
Expand Down Expand Up @@ -298,44 294,6 @@ public ProjectBuildingResult build( Artifact artifact, boolean allowStubModel, P

boolean localProject;

if ( request.isResolveVersionRanges() )
{
VersionRangeRequest versionRangeRequest = new VersionRangeRequest( pomArtifact, config.repositories, null );

try
{
VersionRangeResult versionRangeResult =
repoSystem.resolveVersionRange( config.session, versionRangeRequest );

if ( versionRangeResult.getHighestVersion() == null )
{
throw new ProjectBuildingException(
artifact.getId(), "Error resolving project artifact: No versions matched the requested range",
(Throwable) null );

}

if ( versionRangeResult.getVersionConstraint() != null
&& versionRangeResult.getVersionConstraint().getRange() != null
&& versionRangeResult.getVersionConstraint().getRange().getUpperBound() == null )
{
throw new ProjectBuildingException(
artifact.getId(),
"Error resolving project artifact: The requested version range does not specify an upper bound",
(Throwable) null );

}

pomArtifact = pomArtifact.setVersion( versionRangeResult.getHighestVersion().toString() );
}
catch ( VersionRangeResolutionException e )
{
throw new ProjectBuildingException(
artifact.getId(), "Error resolving project artifact: " e.getMessage(), e );

}
}

try
{
ArtifactRequest pomRequest = new ArtifactRequest();
Expand Down Expand Up @@ -656,11 614,20 @@ private void initProject( MavenProject project, Map<String, MavenProject> projec
project.setModel( model );
project.setOriginalModel( result.getRawModel() );
project.setFile( model.getPomFile() );
Parent p = model.getParent();
if ( p != null )

Model parentModel = result.getModelIds().size() > 1 && !result.getModelIds().get( 1 ).isEmpty()
? result.getRawModel( result.getModelIds().get( 1 ) )
: null;

if ( parentModel != null )
{
project.setParentArtifact( repositorySystem.createProjectArtifact( p.getGroupId(), p.getArtifactId(),
p.getVersion() ) );
final String parentGroupId = inheritedGroupId( result, 1 );
final String parentVersion = inheritedVersion( result, 1 );

project.setParentArtifact( repositorySystem.createProjectArtifact( parentGroupId,
parentModel.getArtifactId(),
parentVersion ) );

// org.apache.maven.its.mng4834:parent:0.1
String parentModelId = result.getModelIds().get( 1 );
File parentPomFile = result.getRawModel( parentModelId ).getPomFile();
Expand All @@ -683,7 650,16 @@ private void initProject( MavenProject project, Map<String, MavenProject> projec
catch ( ProjectBuildingException e )
{
// MNG-4488 where let invalid parents slide on by
logger.warn( "Failed to build parent project for " project.getId() );
if ( logger.isDebugEnabled() )
{
// Message below is checked for in the MNG-2199 core IT.
logger.warn( "Failed to build parent project for " project.getId(), e );
}
else
{
// Message below is checked for in the MNG-2199 core IT.
logger.warn( "Failed to build parent project for " project.getId() );
}
}
}
else
Expand All @@ -696,7 672,16 @@ private void initProject( MavenProject project, Map<String, MavenProject> projec
catch ( ProjectBuildingException e )
{
// MNG-4488 where let invalid parents slide on by
logger.warn( "Failed to build parent project for " project.getId() );
if ( logger.isDebugEnabled() )
{
// Message below is checked for in the MNG-2199 core IT.
logger.warn( "Failed to build parent project for " project.getId(), e );
}
else
{
// Message below is checked for in the MNG-2199 core IT.
logger.warn( "Failed to build parent project for " project.getId() );
}
}
}
}
Expand Down Expand Up @@ -878,6 863,40 @@ private void initProject( MavenProject project, Map<String, MavenProject> projec
}
}

private static String inheritedGroupId( final ModelBuildingResult result, final int modelIndex )
{
String groupId = null;
final String modelId = result.getModelIds().get( modelIndex );

if ( !modelId.isEmpty() )
{
final Model model = result.getRawModel( modelId );
groupId = model.getGroupId() != null
? model.getGroupId()
: inheritedGroupId( result, modelIndex 1 );

}

return groupId;
}

private static String inheritedVersion( final ModelBuildingResult result, final int modelIndex )
{
String version = null;
final String modelId = result.getModelIds().get( modelIndex );

if ( !modelId.isEmpty() )
{
final Model model = result.getRawModel( modelId );
version = model.getVersion() != null
? model.getVersion()
: inheritedVersion( result, modelIndex 1 );

}

return version;
}

private String findProfilesXml( ModelBuildingResult result, Map<File, Boolean> profilesXmls )
{
for ( String modelId : result.getModelIds() )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 63,7 @@ public class DefaultProjectBuildingRequest

private boolean resolveDependencies;

@Deprecated
private boolean resolveVersionRanges;

private RepositoryMerging repositoryMerging = RepositoryMerging.POM_DOMINANT;
Expand Down Expand Up @@ -218,14 219,24 @@ public boolean isResolveDependencies()
return resolveDependencies;
}

/** @since 3.2.2 */
/**
* @since 3.2.2
* @deprecated This got added when implementing MNG-2199 and is no longer used.
* Commit 6cf9320942c34bc68205425ab696b1712ace9ba4 updated the way 'MavenProject' objects are initialized.
*/
@Deprecated
public ProjectBuildingRequest setResolveVersionRanges( boolean value )
{
this.resolveVersionRanges = value;
return this;
}

/** @since 3.2.2 */
/**
* @since 3.2.2
* @deprecated This got added when implementing MNG-2199 and is no longer used.
* Commit 6cf9320942c34bc68205425ab696b1712ace9ba4 updated the way 'MavenProject' objects are initialized.
*/
@Deprecated
public boolean isResolveVersionRanges()
{
return this.resolveVersionRanges;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 168,20 @@ public interface ProjectBuildingRequest
*/
RepositoryMerging getRepositoryMerging();

/** @since 3.2.2 */
/**
* @since 3.2.2
* @deprecated This got added when implementing MNG-2199 and is no longer used.
* Commit 6cf9320942c34bc68205425ab696b1712ace9ba4 updated the way 'MavenProject' objects are initialized.
*/
@Deprecated
boolean isResolveVersionRanges();

/** @since 3.2.2 */
/**
* @since 3.2.2
* @deprecated This got added when implementing MNG-2199 and is no longer used.
* Commit 6cf9320942c34bc68205425ab696b1712ace9ba4 updated the way 'MavenProject' objects are initialized.
*/
@Deprecated
ProjectBuildingRequest setResolveVersionRanges( boolean value );

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 228,7 @@ public ModelSource resolveModel( Parent parent )
&& versionRangeResult.getVersionConstraint().getRange() != null
&& versionRangeResult.getVersionConstraint().getRange().getUpperBound() == null )
{
// Message below is checked for in the MNG-2199 core IT.
throw new UnresolvableModelException( "The requested version range '" parent.getVersion()
"' does not specify an upper bound", parent.getGroupId(),
parent.getArtifactId(), parent.getVersion() );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 169,17 @@ protected MavenProject getProject( File pom )
return projectBuilder.build( pom, configuration ).getProject();
}

protected MavenProject getProjectFromRemoteRepository( final File pom )
throws Exception
{
final ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
configuration.setLocalRepository( this.getLocalRepository() );
configuration.setRemoteRepositories( Arrays.asList( this.repositorySystem.createDefaultRemoteRepository() ) );
initRepoSession( configuration );

return projectBuilder.build( pom, configuration ).getProject();
}

protected ProjectBuildingRequest newBuildingRequest()
throws Exception
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,4 189,134 @@ public void testImportScopePomResolvesFromPropertyBasedRepository()
request.setResolveDependencies( true );
projectBuilder.build( pomFile, request );
}

/**
* Tests whether local version range parent references are build correctly.
*
* @throws Exception
*/
public void testBuildValidParentVersionRangeLocally() throws Exception
{
File f1 = getTestFile( "src/test/resources/projects/parent-version-range-local-valid/child/pom.xml" );

final MavenProject childProject = getProject( f1 );

assertNotNull( childProject.getParentArtifact() );
assertEquals( childProject.getParentArtifact().getVersion(), "1" );
assertNotNull( childProject.getParent() );
assertEquals( childProject.getParent().getVersion(), "1" );
assertNotNull( childProject.getModel().getParent() );
assertEquals( childProject.getModel().getParent().getVersion(), "[1,10]" );
}

/**
* Tests whether local version range parent references are build correctly.
*
* @throws Exception
*/
public void testBuildParentVersionRangeLocallyWithoutChildVersion() throws Exception
{
File f1 =
getTestFile( "src/test/resources/projects/parent-version-range-local-child-without-version/child/pom.xml" );

try
{
getProject( f1 );
fail( "Expected 'ProjectBuildingException' not thrown." );
}
catch ( final ProjectBuildingException e )
{
assertNotNull( e.getMessage() );
assertTrue( e.getMessage().contains( "Version must be a constant" ) );
}
}

/**
* Tests whether local version range parent references are build correctly.
*
* @throws Exception
*/
public void testBuildParentVersionRangeLocallyWithChildVersionExpression() throws Exception
{
File f1 =
getTestFile(
"src/test/resources/projects/parent-version-range-local-child-version-expression/child/pom.xml" );

try
{
getProject( f1 );
fail( "Expected 'ProjectBuildingException' not thrown." );
}
catch ( final ProjectBuildingException e )
{
assertNotNull( e.getMessage() );
assertTrue( e.getMessage().contains( "Version must be a constant" ) );
}
}

/**
* Tests whether external version range parent references are build correctly.
*
* @throws Exception
*/
public void testBuildParentVersionRangeExternally() throws Exception
{
File f1 = getTestFile( "src/test/resources/projects/parent-version-range-external-valid/pom.xml" );

final MavenProject childProject = this.getProjectFromRemoteRepository( f1 );

assertNotNull( childProject.getParentArtifact() );
assertEquals( childProject.getParentArtifact().getVersion(), "1" );
assertNotNull( childProject.getParent() );
assertEquals( childProject.getParent().getVersion(), "1" );
assertNotNull( childProject.getModel().getParent() );
assertEquals( childProject.getModel().getParent().getVersion(), "[1,1]" );
}

/**
* Tests whether external version range parent references are build correctly.
*
* @throws Exception
*/
public void testBuildParentVersionRangeExternallyWithoutChildVersion() throws Exception
{
File f1 =
getTestFile(
"src/test/resources/projects/parent-version-range-external-child-without-version/pom.xml" );

try
{
this.getProjectFromRemoteRepository( f1 );
fail( "Expected 'ProjectBuildingException' not thrown." );
}
catch ( final ProjectBuildingException e )
{
assertNotNull( e.getMessage() );
assertTrue( e.getMessage().contains( "Version must be a constant" ) );
}
}

/**
* Tests whether external version range parent references are build correctly.
*
* @throws Exception
*/
public void testBuildParentVersionRangeExternallyWithChildVersionExpression() throws Exception
{
File f1 =
getTestFile(
"src/test/resources/projects/parent-version-range-external-child-version-expression/pom.xml" );

try
{
this.getProjectFromRemoteRepository( f1 );
fail( "Expected 'ProjectBuildingException' not thrown." );
}
catch ( final ProjectBuildingException e )
{
assertNotNull( e.getMessage() );
assertTrue( e.getMessage().contains( "Version must be a constant" ) );
}
}

}
Loading

0 comments on commit 0514c1b

Please sign in to comment.