Skip to content

Commit

Permalink
[MSHADE-413] Fix endless loop caused by manipulating shared objects
Browse files Browse the repository at this point in the history
Maven objects (like `Dependency` or `Model`) returned by Maven must not
be modified. Doing so will result in endless loops or incorrect builds.
  • Loading branch information
snazy committed Mar 21, 2022
1 parent aa019ca commit bacf88a
Showing 1 changed file with 47 additions and 13 deletions.
60 changes: 47 additions & 13 deletions src/main/java/org/apache/maven/plugins/shade/mojo/ShadeMojo.java
Expand Up @@ -1083,14 +1083,20 @@ private void createDependencyReducedPom( Set<String> artifactsToRemove )
// we'll figure out the exclusions in a bit.
transitiveDeps.add( dep );
}
List<Dependency> origDeps = project.getDependencies();

if ( promoteTransitiveDependencies )
Model model = project.getOriginalModel();

// MSHADE-413: Must not use objects (for example `Model` or `Dependency`) that are "owned
// by Maven" and being used by other projects/plugins. Modifying those will break the
// correctness of the build - or cause an endless loop.
List<Dependency> origDeps = new ArrayList<>();
List<Dependency> source = promoteTransitiveDependencies ? transitiveDeps : project.getDependencies();
for ( Dependency d : source )
{
origDeps = transitiveDeps;
origDeps.add( d.clone() );
}
model = model.clone();

Model model = project.getOriginalModel();
// MSHADE-185: We will remove all system scoped dependencies which usually
// have some kind of property usage. At this time the properties within
// such things are already evaluated.
Expand Down Expand Up @@ -1299,8 +1305,13 @@ public boolean updateExcludesInDeps( MavenProject project, List<Dependency> depe
boolean modified = false;
for ( DependencyNode n2 : node.getChildren() )
{
String artifactId2 = getId( n2.getArtifact() );

for ( DependencyNode n3 : n2.getChildren() )
{
Artifact artifact3 = n3.getArtifact();
String artifactId3 = getId( artifact3 );

// check if it really isn't in the list of original dependencies. Maven
// prior to 2.0.8 may grab versions from transients instead of
// from the direct deps in which case they would be marked included
Expand All @@ -1310,7 +1321,7 @@ public boolean updateExcludesInDeps( MavenProject project, List<Dependency> depe
boolean found = false;
for ( Dependency dep : transitiveDeps )
{
if ( getId( dep ).equals( getId( n3.getArtifact() ) ) )
if ( getId( dep ).equals( artifactId3 ) )
{
found = true;
break;
Expand All @@ -1321,18 +1332,41 @@ public boolean updateExcludesInDeps( MavenProject project, List<Dependency> depe
// note: MSHADE-31 introduced the exclusion logic for promoteTransitiveDependencies=true,
// but as of 3.2.1 promoteTransitiveDependencies has no effect for provided deps,
// which makes this fix even possible (see also MSHADE-181)
if ( !found && !"provided".equals( n3.getArtifact().getScope() ) )
if ( !found && !"provided".equals( artifact3.getScope() ) )
{
getLog().debug( String.format( "dependency %s (scope %s) not found in transitive dependencies",
artifactId3, artifact3.getScope() ) );
for ( Dependency dep : dependencies )
{
if ( getId( dep ).equals( getId( n2.getArtifact() ) ) )
if ( getId( dep ).equals( artifactId2 ) )
{
Exclusion exclusion = new Exclusion();
exclusion.setArtifactId( n3.getArtifact().getArtifactId() );
exclusion.setGroupId( n3.getArtifact().getGroupId() );
dep.addExclusion( exclusion );
modified = true;
break;
// First check whether the exclusion has already been added,
// because it's meaningless to add it more than once. Certain cases
// can end up adding the exclusion "forever" and cause an endless
// loop rewriting the whole dependency-reduced-pom.xml file.
boolean containsExclusion = false;
for ( Exclusion existingExclusion : dep.getExclusions() )
{
if ( existingExclusion.getGroupId().equals( artifact3.getGroupId() )
&& existingExclusion.getArtifactId().equals( artifact3.getArtifactId() ) )
{
containsExclusion = true;
break;
}
}
if ( !containsExclusion )
{
getLog().debug( String.format( "Adding exclusion for dependency %s (scope %s) "
+ "to %s (scope %s)",
artifactId3, artifact3.getScope(),
getId( dep ), dep.getScope() ) );
Exclusion exclusion = new Exclusion();
exclusion.setArtifactId( artifact3.getArtifactId() );
exclusion.setGroupId( artifact3.getGroupId() );
dep.addExclusion( exclusion );
modified = true;
break;
}
}
}
}
Expand Down

0 comments on commit bacf88a

Please sign in to comment.