diff --git a/org.eclipse.m2e.pde.target.tests/src/org/eclipse/m2e/pde/target/tests/DependencyExclusionTest.java b/org.eclipse.m2e.pde.target.tests/src/org/eclipse/m2e/pde/target/tests/DependencyExclusionTest.java
index 28613dddb..4810bfafc 100644
--- a/org.eclipse.m2e.pde.target.tests/src/org/eclipse/m2e/pde/target/tests/DependencyExclusionTest.java
+++ b/org.eclipse.m2e.pde.target.tests/src/org/eclipse/m2e/pde/target/tests/DependencyExclusionTest.java
@@ -153,6 +153,74 @@ public void testExclusionOfDifferentVersions() throws Exception {
assertTargetBundles(target, includeSource ? withSourceBundles(expectedBundles) : expectedBundles);
}
+ @Test
+ public void testMavenExclusionSyntaxOnDependency() throws Exception {
+ ITargetLocation target = resolveMavenTarget(String.format(
+ """
+
+
+
+ org.junit.platform
+ junit-platform-commons
+ 1.9.3
+ jar
+
+
+ org.apiguardian
+ apiguardian-api
+
+
+
+
+
+ """,
+ includeSource));
+ assertStatusOk(target.getStatus());
+ assertArrayEquals(EMPTY, target.getFeatures());
+ List expectedBundles = List.of(junitPlatformCommons("1.9.3"));
+ assertTargetBundles(target, includeSource ? withSourceBundles(expectedBundles) : expectedBundles);
+ }
+
+ @Test
+ public void testMavenExclusionSyntaxIsPerDependency() throws Exception {
+ ITargetLocation target = resolveMavenTarget(String.format(
+ """
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.9.3
+ jar
+
+
+ org.apiguardian
+ apiguardian-api
+
+
+
+
+ org.junit.platform
+ junit-platform-commons
+ 1.9.3
+ jar
+
+
+
+ """,
+ includeSource));
+ assertStatusOk(target.getStatus());
+ assertArrayEquals(EMPTY, target.getFeatures());
+ // apiguardian excluded from junit-jupiter-api's transitive graph,
+ // but junit-platform-commons (without exclusion) still pulls it in
+ List expectedBundles = List.of(//
+ junitJupiterAPI(), //
+ junitPlatformCommons("1.9.3"), //
+ apiGuardian("1.1.2"), //
+ opentest4j());
+ assertTargetBundles(target, includeSource ? withSourceBundles(expectedBundles) : expectedBundles);
+ }
+
private static ExpectedBundle junitPlatformCommons(String version) {
return originalOSGiBundle("junit-platform-commons", version, "org.junit.platform:junit-platform-commons");
}
diff --git a/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/MavenTargetDependency.java b/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/MavenTargetDependency.java
index c55252d07..c4cae6881 100644
--- a/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/MavenTargetDependency.java
+++ b/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/MavenTargetDependency.java
@@ -12,10 +12,12 @@
*******************************************************************************/
package org.eclipse.m2e.pde.target;
+import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.apache.maven.model.Dependency;
+import org.apache.maven.model.Exclusion;
import org.eclipse.aether.graph.DependencyNode;
public final class MavenTargetDependency extends Dependency {
@@ -66,7 +68,13 @@ public void bind(MavenTargetLocation mavenTargetLocation) {
}
public MavenTargetDependency copy() {
- return new MavenTargetDependency(getGroupId(), getArtifactId(), getVersion(), getType(), getClassifier());
+ MavenTargetDependency copy = new MavenTargetDependency(getGroupId(), getArtifactId(), getVersion(), getType(),
+ getClassifier());
+ List exclusions = getExclusions();
+ if (!exclusions.isEmpty()) {
+ copy.setExclusions(new ArrayList<>(exclusions));
+ }
+ return copy;
}
public boolean matches(Dependency other) {
diff --git a/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/MavenTargetLocation.java b/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/MavenTargetLocation.java
index 37b0ec788..ee2f84677 100644
--- a/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/MavenTargetLocation.java
+++ b/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/MavenTargetLocation.java
@@ -48,6 +48,7 @@
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.graph.DependencyNode;
+import org.eclipse.aether.graph.Exclusion;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.VersionRangeRequest;
import org.eclipse.aether.resolution.VersionRangeResolutionException;
@@ -97,6 +98,8 @@ public class MavenTargetLocation extends AbstractBundleContainer {
public static final String ELEMENT_GROUP_ID = "groupId";
public static final String ELEMENT_INSTRUCTIONS = "instructions";
public static final String ELEMENT_EXCLUDED = "exclude";
+ public static final String ELEMENT_EXCLUSIONS = "exclusions";
+ public static final String ELEMENT_EXCLUSION = "exclusion";
public static final String ELEMENT_DEPENDENCY = "dependency";
public static final String ELEMENT_DEPENDENCIES = "dependencies";
public static final String ELEMENT_REPOSITORY = "repository";
@@ -251,8 +254,10 @@ private Artifact resolveDependency(MavenTargetDependency root, IMaven maven, Lis
root.getVersion(), root.getType(), root.getClassifier(), repositories, subMonitor.split(80)));
}
if (artifact != null) {
+ List exclusions = root.getExclusions().stream()
+ .map(ex -> new Exclusion(ex.getGroupId(), ex.getArtifactId(), null, null)).toList();
MavenRootDependency dependency = new MavenRootDependency(artifact.getGroupId(), artifact.getArtifactId(),
- artifact.getVersion(), artifact.getClassifier(), artifact.getExtension());
+ artifact.getVersion(), artifact.getClassifier(), artifact.getExtension(), exclusions);
DependencyDepth depth = MavenDependencyCollector.getEffectiveDepth(dependency,
dependencyDepth);
SubMonitor split = subMonitor.split(20);
@@ -600,6 +605,17 @@ public String serialize() {
element(xml, ELEMENT_VERSION, dependency.getVersion());
element(xml, ELEMENT_TYPE, dependency.getType());
element(xml, ELEMENT_CLASSIFIER, dependency.getClassifier());
+ List depExclusions = dependency.getExclusions();
+ if (!depExclusions.isEmpty()) {
+ xml.append("<" + ELEMENT_EXCLUSIONS + ">");
+ depExclusions.forEach(ex -> {
+ xml.append("<" + ELEMENT_EXCLUSION + ">");
+ element(xml, ELEMENT_GROUP_ID, ex.getGroupId());
+ element(xml, ELEMENT_ARTIFACT_ID, ex.getArtifactId());
+ xml.append("" + ELEMENT_EXCLUSION + ">");
+ });
+ xml.append("" + ELEMENT_EXCLUSIONS + ">");
+ }
xml.append("" + ELEMENT_DEPENDENCY + ">");
});
xml.append("" + ELEMENT_DEPENDENCIES + ">");
diff --git a/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/MavenTargetLocationFactory.java b/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/MavenTargetLocationFactory.java
index e31e02a5a..f7e128a25 100644
--- a/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/MavenTargetLocationFactory.java
+++ b/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/MavenTargetLocationFactory.java
@@ -15,6 +15,7 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
@@ -130,7 +131,19 @@ private static MavenTargetDependency parseDependency(Element element) {
String version = getText(MavenTargetLocation.ELEMENT_VERSION, element);
String artifactType = getText(MavenTargetLocation.ELEMENT_TYPE, element);
String classifier = getText(MavenTargetLocation.ELEMENT_CLASSIFIER, element);
- return new MavenTargetDependency(groupId, artifactId, version, artifactType, classifier);
+ MavenTargetDependency dependency = new MavenTargetDependency(groupId, artifactId, version, artifactType,
+ classifier);
+ List exclusions = descendants(element,
+ MavenTargetLocation.ELEMENT_EXCLUSION).map(exclusionElement -> {
+ org.apache.maven.model.Exclusion exclusion = new org.apache.maven.model.Exclusion();
+ exclusion.setGroupId(getText(MavenTargetLocation.ELEMENT_GROUP_ID, exclusionElement));
+ exclusion.setArtifactId(getText(MavenTargetLocation.ELEMENT_ARTIFACT_ID, exclusionElement));
+ return exclusion;
+ }).toList();
+ if (!exclusions.isEmpty()) {
+ dependency.setExclusions(new ArrayList<>(exclusions));
+ }
+ return dependency;
}
private static String getText(String tagName, Element location) {
diff --git a/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/shared/MavenDependencyCollector.java b/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/shared/MavenDependencyCollector.java
index ccf5846a2..af69512b0 100644
--- a/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/shared/MavenDependencyCollector.java
+++ b/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/shared/MavenDependencyCollector.java
@@ -30,6 +30,7 @@
import org.eclipse.aether.graph.DefaultDependencyNode;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.graph.DependencyNode;
+import org.eclipse.aether.graph.Exclusion;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.repository.RepositoryPolicy;
import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
@@ -91,6 +92,7 @@ public DependencyResult collect(MavenRootDependency root) throws RepositoryExcep
"Invalid root dependency: " + root + " allowed types are " + VALID_EXTENSIONS);
}
DependencyDepth depth = getEffectiveDepth(root, dependencyDepth);
+ List exclusions = root.exclusions();
List artifacts = new ArrayList<>();
List nodes = new ArrayList<>();
ArtifactDescriptor rootDescriptor = readArtifactDescriptor(new Dependency(
@@ -101,7 +103,9 @@ public DependencyResult collect(MavenRootDependency root) throws RepositoryExcep
}
if (depth == DependencyDepth.DIRECT) {
for (Dependency dependency : rootDescriptor.dependencies()) {
- readArtifactDescriptor(dependency, rootDescriptor.node(), artifacts, nodes);
+ if (!isExcluded(dependency, exclusions)) {
+ readArtifactDescriptor(dependency, rootDescriptor.node(), artifacts, nodes);
+ }
}
return new DependencyResult(depth, artifacts, rootDescriptor.node(), nodes);
}
@@ -113,7 +117,7 @@ public DependencyResult collect(MavenRootDependency root) throws RepositoryExcep
while (!queue.isEmpty()) {
ArtifactDescriptor current = queue.poll();
for (Dependency dependency : current.dependencies()) {
- if (isValidDependency(dependency) && isValidScope(dependency)) {
+ if (isValidDependency(dependency) && isValidScope(dependency) && !isExcluded(dependency, exclusions)) {
if (isVersionRanged(dependency)) {
ArtifactDescriptor dependencyDescriptor = resolveHighestVersion(dependency, current.node(),
artifacts, nodes);
@@ -134,6 +138,25 @@ public DependencyResult collect(MavenRootDependency root) throws RepositoryExcep
return new DependencyResult(depth, artifacts, rootDescriptor.node(), nodes);
}
+ private static boolean isExcluded(Dependency dependency, List exclusions) {
+ if (exclusions.isEmpty()) {
+ return false;
+ }
+ String groupId = dependency.getArtifact().getGroupId();
+ String artifactId = dependency.getArtifact().getArtifactId();
+ for (Exclusion exclusion : exclusions) {
+ if (matchesPattern(exclusion.getGroupId(), groupId)
+ && matchesPattern(exclusion.getArtifactId(), artifactId)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean matchesPattern(String pattern, String value) {
+ return "*".equals(pattern) || pattern.equals(value);
+ }
+
private ArtifactDescriptor resolveHighestVersion(Dependency dependency, DependencyNode parent,
Collection artifacts, List nodes)
throws VersionRangeResolutionException {
diff --git a/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/shared/MavenRootDependency.java b/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/shared/MavenRootDependency.java
index 1575b31c2..ff63c4125 100644
--- a/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/shared/MavenRootDependency.java
+++ b/org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/shared/MavenRootDependency.java
@@ -12,13 +12,22 @@
*******************************************************************************/
package org.eclipse.m2e.pde.target.shared;
-public record MavenRootDependency(String groupId, String artifactId, String version, String classifier, String type) {
+import java.util.List;
- public String getType() {
- if (type == null || type.isBlank()) {
- return "jar";
- }
- return type;
- }
+import org.eclipse.aether.graph.Exclusion;
+
+public record MavenRootDependency(String groupId, String artifactId, String version, String classifier, String type,
+ List exclusions) {
+
+ public MavenRootDependency(String groupId, String artifactId, String version, String classifier, String type) {
+ this(groupId, artifactId, version, classifier, type, List.of());
+ }
+
+ public String getType() {
+ if (type == null || type.isBlank()) {
+ return "jar";
+ }
+ return type;
+ }
}