Skip to content

Commit 0ad7b82

Browse files
steve-aom-elliotttimtebeekgithub-actions[bot]
authored
Resolve GAVs, classifiers and types of transitive dependencies via the containing POM (#6464)
Co-authored-by: Tim te Beek <[email protected]> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 0a91b12 commit 0ad7b82

File tree

3 files changed

+116
-38
lines changed

3 files changed

+116
-38
lines changed

rewrite-maven/src/main/java/org/openrewrite/maven/internal/MavenPomDownloader.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ public class MavenPomDownloader {
9898
* @param activeProfiles The active profiles to use, if any. This argument overrides any active profiles
9999
* set on the execution context.
100100
*/
101-
public MavenPomDownloader(Map<Path, Pom> projectPoms, ExecutionContext ctx,
101+
public MavenPomDownloader(Map<Path, Pom> projectPoms,
102+
ExecutionContext ctx,
102103
@Nullable MavenSettings mavenSettings,
103104
@Nullable List<String> activeProfiles) {
104105
this(projectPoms, HttpSenderExecutionContextView.view(ctx).getHttpSender(), ctx);

rewrite-maven/src/main/java/org/openrewrite/maven/tree/ResolvedPom.java

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import java.util.function.UnaryOperator;
4343

4444
import static java.util.Collections.*;
45+
import static java.util.Objects.requireNonNull;
4546
import static java.util.stream.Collectors.toMap;
4647
import static org.openrewrite.internal.StringUtils.matchesGlob;
4748

@@ -1020,7 +1021,7 @@ public List<ResolvedDependency> resolveDependencies(Scope scope, Map<GroupArtifa
10201021
int depth = 0;
10211022
Collection<DependencyAndDependent> dependenciesAtDepth = rootDependencies.values();
10221023
while (!dependenciesAtDepth.isEmpty()) {
1023-
Map<GroupArtifact, DependencyAndDependent> dependenciesAtNextDepthMap = new LinkedHashMap<>();
1024+
Map<GroupArtifactClassifierType, DependencyAndDependent> dependenciesAtNextDepthMap = new LinkedHashMap<>();
10241025

10251026
for (DependencyAndDependent dd : dependenciesAtDepth) {
10261027
// First get the dependency (relative to the pom it was defined in)
@@ -1087,19 +1088,32 @@ public List<ResolvedDependency> resolveDependencies(Scope scope, Map<GroupArtifa
10871088
MavenPomCache cache = MavenExecutionContextView.view(ctx).getPomCache();
10881089
ResolvedPom resolvedPom = cache.getResolvedDependencyPom(dPom.getGav());
10891090
if (resolvedPom == null) {
1090-
resolvedPom = new ResolvedPom(dPom, getActiveProfiles(), emptyMap(),
1091-
emptyList(), true, initialRepositories, emptyList(), emptyList(),
1092-
emptyList(), emptyList(), emptyList(), emptyList());
1091+
resolvedPom = new ResolvedPom(
1092+
dPom,
1093+
getActiveProfiles(),
1094+
emptyMap(),
1095+
emptyList(),
1096+
true,
1097+
initialRepositories,
1098+
emptyList(),
1099+
emptyList(),
1100+
emptyList(),
1101+
emptyList(),
1102+
emptyList(),
1103+
emptyList());
10931104
resolvedPom.resolver(ctx, downloader).resolveParentsRecursively(dPom);
10941105
cache.putResolvedDependencyPom(dPom.getGav(), resolvedPom);
10951106
}
10961107

1097-
ResolvedDependency resolved = new ResolvedDependency(dPom.getRepository(),
1098-
resolvedPom.getGav(), dd.getDependency(), emptyList(),
1108+
ResolvedDependency resolved = new ResolvedDependency(
1109+
dPom.getRepository(),
1110+
resolvedPom.getGav(),
1111+
dd.getDependency(),
1112+
emptyList(),
10991113
resolvedPom.getRequested().getLicenses(),
1100-
resolvedPom.getValue(dd.getDependency().getType()),
1101-
resolvedPom.getValue(dd.getDependency().getClassifier()),
1102-
Boolean.valueOf(resolvedPom.getValue(dd.getDependency().getOptional())),
1114+
dd.getDependency().getType(),
1115+
dd.getDependency().getClassifier(),
1116+
Boolean.valueOf(dd.getDependency().getOptional()),
11031117
depth,
11041118
emptyList());
11051119

@@ -1129,6 +1143,16 @@ public List<ResolvedDependency> resolveDependencies(Scope scope, Map<GroupArtifa
11291143
d2 = d2.withGav(d2.getGav().withGroupId(resolvedPom.getGroupId()));
11301144
}
11311145

1146+
d2 = d2
1147+
.withGav(d2.getGav()
1148+
.withGroupId(resolvedPom.getValue(d2.getGroupId()))
1149+
.withArtifactId(requireNonNull(resolvedPom.getValue(d2.getArtifactId())))
1150+
.withVersion(resolvedPom.getValue(d2.getVersion()))
1151+
)
1152+
.withClassifier(resolvedPom.getValue(d2.getClassifier()))
1153+
.withScope(resolvedPom.getValue(d2.getScope()))
1154+
.withType(resolvedPom.getValue(d2.getType()));
1155+
11321156
if (d.getExclusions() != null) {
11331157
d2 = d2.withExclusions(ListUtils.concatAll(d2.getExclusions(), d.getExclusions()));
11341158
for (GroupArtifact exclusion : d.getExclusions()) {
@@ -1151,8 +1175,13 @@ public List<ResolvedDependency> resolveDependencies(Scope scope, Map<GroupArtifa
11511175
Scope d2Scope = getDependencyScope(d2, resolvedPom);
11521176
if (d2Scope.isInClasspathOf(dd.getScope())) {
11531177
// For transitive dependencies at same depth, first parent declaration wins
1154-
GroupArtifact d2Ga = new GroupArtifact(d2.getGroupId() == null ? "" : d2.getGroupId(), d2.getArtifactId());
1155-
dependenciesAtNextDepthMap.putIfAbsent(d2Ga, new DependencyAndDependent(d2, d2Scope, resolved, dd.getRootDependent(), resolvedPom));
1178+
GroupArtifactClassifierType d2Gact = new GroupArtifactClassifierType(
1179+
d2.getGroupId(), // will not be null based on check higher up
1180+
d2.getArtifactId(),
1181+
d2.getClassifier(),
1182+
d2.getType()
1183+
);
1184+
dependenciesAtNextDepthMap.putIfAbsent(d2Gact, new DependencyAndDependent(d2, d2Scope, resolved, dd.getRootDependent(), resolvedPom));
11561185
}
11571186
}
11581187
} catch (MavenDownloadingException e) {
@@ -1185,17 +1214,26 @@ private Scope getDependencyScope(Dependency d2, ResolvedPom containingPom) {
11851214
Scope scopeInContainingPom;
11861215
//noinspection ConstantConditions
11871216
if (d2.getScope() != null) {
1188-
scopeInContainingPom = Scope.fromName(getValue(d2.getScope()));
1217+
scopeInContainingPom = Scope.fromName(d2.getScope());
11891218
} else {
1190-
scopeInContainingPom = containingPom.getManagedScope(getValue(d2.getGroupId()), getValue(d2.getArtifactId()), getValue(d2.getType()),
1191-
getValue(d2.getClassifier()));
1219+
scopeInContainingPom = containingPom.getManagedScope(
1220+
requireNonNull(d2.getGroupId()),
1221+
d2.getArtifactId(),
1222+
d2.getType(),
1223+
d2.getClassifier()
1224+
);
11921225
if (scopeInContainingPom == null) {
11931226
scopeInContainingPom = Scope.Compile;
11941227
}
11951228
}
1229+
11961230
//noinspection ConstantConditions
1197-
Scope scopeInThisProject = getManagedScope(getValue(d2.getGroupId()), getValue(d2.getArtifactId()), getValue(d2.getType()),
1198-
getValue(d2.getClassifier()));
1231+
Scope scopeInThisProject = getManagedScope(
1232+
getValue(d2.getGroupId()),
1233+
getValue(d2.getArtifactId()),
1234+
getValue(d2.getType()),
1235+
getValue(d2.getClassifier())
1236+
);
11991237
// project POM's dependency management overrules the containingPom's dependencyManagement
12001238
// IFF the dependency is in the runtime classpath of the containingPom;
12011239
// if the dependency was not already in the classpath of the containingPom, then project POM cannot override scope / "promote" it into the classpath

rewrite-maven/src/test/java/org/openrewrite/maven/internal/MavenPomDownloaderTest.java

Lines changed: 60 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,28 +1352,67 @@ public MockResponse dispatch(RecordedRequest recordedRequest) {
13521352
@Test
13531353
void resolveDependencies() throws Exception {
13541354
Xml.Document doc = (Xml.Document) MavenParser.builder().build().parse("""
1355-
<project>
1356-
<parent>
1357-
<groupId>org.springframework.boot</groupId>
1358-
<artifactId>spring-boot-starter-parent</artifactId>
1359-
<version>3.2.0</version>
1360-
<relativePath/>
1361-
</parent>
1362-
<groupId>com.example</groupId>
1363-
<artifactId>demo</artifactId>
1364-
<version>0.0.1-SNAPSHOT</version>
1365-
<name>demo</name>
1366-
<dependencies>
1367-
<dependency>
1368-
<groupId>org.springframework.boot</groupId>
1369-
<artifactId>spring-boot-starter-web</artifactId>
1370-
</dependency>
1371-
</dependencies>
1372-
</project>
1373-
""").toList().getFirst();
1374-
MavenResolutionResult resolutionResult = doc.getMarkers().findFirst(MavenResolutionResult.class).orElseThrow();
1375-
resolutionResult = resolutionResult.resolveDependencies(new MavenPomDownloader(emptyMap(), new InMemoryExecutionContext(), null, null), new InMemoryExecutionContext());
1355+
<project>
1356+
<parent>
1357+
<groupId>org.springframework.boot</groupId>
1358+
<artifactId>spring-boot-starter-parent</artifactId>
1359+
<version>3.2.0</version>
1360+
<relativePath/>
1361+
</parent>
1362+
<groupId>com.example</groupId>
1363+
<artifactId>demo</artifactId>
1364+
<version>0.0.1-SNAPSHOT</version>
1365+
<name>demo</name>
1366+
<dependencies>
1367+
<dependency>
1368+
<groupId>org.springframework.boot</groupId>
1369+
<artifactId>spring-boot-starter-web</artifactId>
1370+
</dependency>
1371+
</dependencies>
1372+
</project>
1373+
""").toList().getFirst();
1374+
InMemoryExecutionContext ctx = new InMemoryExecutionContext();
1375+
MavenResolutionResult resolutionResult = doc.getMarkers().findFirst(MavenResolutionResult.class).orElseThrow()
1376+
.resolveDependencies(new MavenPomDownloader(emptyMap(), ctx, null, null), ctx);
13761377
List<ResolvedDependency> deps = resolutionResult.getDependencies().get(Scope.Compile);
13771378
assertThat(deps).hasSize(35);
13781379
}
1380+
1381+
@Issue("https://github.com/openrewrite/rewrite/pull/6464")
1382+
@Test
1383+
void emptyClassifierPropertyInIntermediatePom() throws Exception {
1384+
// `azure-spring-data-cosmos` brings in `azure-core-http-netty`, which uses property `<boring-ssl-classifier/>`
1385+
// https://repo1.maven.org/maven2/com/azure/azure-spring-data-cosmos/3.45.0/azure-spring-data-cosmos-3.45.0.pom
1386+
// https://repo1.maven.org/maven2/com/azure/azure-core-http-netty/1.16.2/azure-core-http-netty-1.16.2.pom
1387+
Xml.Document doc = (Xml.Document) MavenParser.builder().build().parse("""
1388+
<project>
1389+
<groupId>com.example</groupId>
1390+
<artifactId>demo</artifactId>
1391+
<version>1.0.0</version>
1392+
<properties>
1393+
<boring-ssl-classifier>something-else</boring-ssl-classifier>
1394+
</properties>
1395+
<dependencies>
1396+
<dependency>
1397+
<groupId>com.azure</groupId>
1398+
<artifactId>azure-spring-data-cosmos</artifactId>
1399+
<version>3.45.0</version>
1400+
</dependency>
1401+
</dependencies>
1402+
</project>
1403+
""").toList().getFirst();
1404+
InMemoryExecutionContext ctx = new InMemoryExecutionContext();
1405+
MavenResolutionResult resolutionResult = doc.getMarkers().findFirst(MavenResolutionResult.class).orElseThrow()
1406+
.resolveDependencies(new MavenPomDownloader(emptyMap(), ctx, null, null), ctx);
1407+
List<ResolvedDependency> deps = resolutionResult.getDependencies().get(Scope.Compile);
1408+
assertThat(deps)
1409+
.filteredOn(rd -> "io.netty".equals(rd.getGroupId()))
1410+
.filteredOn(rd -> "netty-tcnative-boringssl-static".equals(rd.getArtifactId()))
1411+
.isNotEmpty()
1412+
.extracting(ResolvedDependency::getClassifier)
1413+
.doesNotContain("${boring-ssl-classifier}")
1414+
.doesNotContain("something-else")
1415+
.contains("")
1416+
.anyMatch(c -> !"".equals(c));
1417+
}
13791418
}

0 commit comments

Comments
 (0)