mirror of https://github.com/apache/maven.git
[MNG-7843] Allow glob patterns in dependency exclusions (#1200)
This commit is contained in:
parent
b0170a612b
commit
22ae75a304
|
@ -1366,6 +1366,9 @@
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
The {@code <exclusion>} element contains informations required to exclude
|
The {@code <exclusion>} element contains informations required to exclude
|
||||||
an artifact to the project.
|
an artifact to the project.
|
||||||
|
<p>
|
||||||
|
The {@code groupId} and {@code artifactId} fields are interpreted as glob patterns,
|
||||||
|
see {@link java.nio.file.FileSystem#getPathMatcher}.
|
||||||
]]>
|
]]>
|
||||||
</description>
|
</description>
|
||||||
<fields>
|
<fields>
|
||||||
|
|
|
@ -18,8 +18,13 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.maven.artifact.resolver.filter;
|
package org.apache.maven.artifact.resolver.filter;
|
||||||
|
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.nio.file.FileSystems;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.PathMatcher;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.maven.artifact.Artifact;
|
import org.apache.maven.artifact.Artifact;
|
||||||
import org.apache.maven.model.Exclusion;
|
import org.apache.maven.model.Exclusion;
|
||||||
|
@ -28,37 +33,42 @@ import org.apache.maven.model.Exclusion;
|
||||||
* Filter to exclude from a list of artifact patterns.
|
* Filter to exclude from a list of artifact patterns.
|
||||||
*/
|
*/
|
||||||
public class ExclusionArtifactFilter implements ArtifactFilter {
|
public class ExclusionArtifactFilter implements ArtifactFilter {
|
||||||
private static final String WILDCARD = "*";
|
|
||||||
|
|
||||||
private final List<Exclusion> exclusions;
|
private final List<Exclusion> exclusions;
|
||||||
|
private final List<Predicate<Artifact>> predicates;
|
||||||
|
|
||||||
public ExclusionArtifactFilter(List<Exclusion> exclusions) {
|
public ExclusionArtifactFilter(List<Exclusion> exclusions) {
|
||||||
this.exclusions = exclusions;
|
this.exclusions = exclusions;
|
||||||
}
|
this.predicates =
|
||||||
|
exclusions.stream().map(ExclusionArtifactFilter::toPredicate).collect(Collectors.toList());
|
||||||
private Predicate<Exclusion> sameArtifactId(Artifact artifact) {
|
|
||||||
return exclusion -> exclusion.getArtifactId().equals(artifact.getArtifactId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Predicate<Exclusion> sameGroupId(Artifact artifact) {
|
|
||||||
return exclusion -> exclusion.getGroupId().equals(artifact.getGroupId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Predicate<Exclusion> groupIdIsWildcard = exclusion -> WILDCARD.equals(exclusion.getGroupId());
|
|
||||||
|
|
||||||
private Predicate<Exclusion> artifactIdIsWildcard = exclusion -> WILDCARD.equals(exclusion.getArtifactId());
|
|
||||||
|
|
||||||
private Predicate<Exclusion> groupIdAndArtifactIdIsWildcard = groupIdIsWildcard.and(artifactIdIsWildcard);
|
|
||||||
|
|
||||||
private Predicate<Exclusion> exclude(Artifact artifact) {
|
|
||||||
return groupIdAndArtifactIdIsWildcard
|
|
||||||
.or(groupIdIsWildcard.and(sameArtifactId(artifact)))
|
|
||||||
.or(artifactIdIsWildcard.and(sameGroupId(artifact)))
|
|
||||||
.or(sameGroupId(artifact).and(sameArtifactId(artifact)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean include(Artifact artifact) {
|
public boolean include(Artifact artifact) {
|
||||||
return !exclusions.stream().anyMatch(exclude(artifact));
|
return predicates.stream().noneMatch(p -> p.test(artifact));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Predicate<Artifact> toPredicate(Exclusion exclusion) {
|
||||||
|
PathMatcher groupId = FileSystems.getDefault().getPathMatcher("glob:" + exclusion.getGroupId());
|
||||||
|
PathMatcher artifactId = FileSystems.getDefault().getPathMatcher("glob:" + exclusion.getArtifactId());
|
||||||
|
Predicate<Artifact> predGroupId = a -> groupId.matches(createPathProxy(a.getGroupId()));
|
||||||
|
Predicate<Artifact> predArtifactId = a -> artifactId.matches(createPathProxy(a.getArtifactId()));
|
||||||
|
return predGroupId.and(predArtifactId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In order to reuse the glob matcher from the filesystem, we need
|
||||||
|
* to create Path instances. Those are only used with the toString method.
|
||||||
|
* This hack works because the only system-dependent thing is the path
|
||||||
|
* separator which should not be part of the groupId or artifactId.
|
||||||
|
*/
|
||||||
|
private static Path createPathProxy(String value) {
|
||||||
|
return (Path) Proxy.newProxyInstance(
|
||||||
|
ExclusionArtifactFilter.class.getClassLoader(), new Class[] {Path.class}, (proxy1, method, args) -> {
|
||||||
|
if ("toString".equals(method.getName())) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,12 +33,17 @@ import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
class ExclusionArtifactFilterTest {
|
class ExclusionArtifactFilterTest {
|
||||||
private Artifact artifact;
|
private Artifact artifact;
|
||||||
|
private Artifact artifact2;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setup() {
|
void setup() {
|
||||||
artifact = mock(Artifact.class);
|
artifact = mock(Artifact.class);
|
||||||
when(artifact.getGroupId()).thenReturn("org.apache.maven");
|
when(artifact.getGroupId()).thenReturn("org.apache.maven");
|
||||||
when(artifact.getArtifactId()).thenReturn("maven-core");
|
when(artifact.getArtifactId()).thenReturn("maven-core");
|
||||||
|
|
||||||
|
artifact2 = mock(Artifact.class);
|
||||||
|
when(artifact2.getGroupId()).thenReturn("org.junit.jupiter");
|
||||||
|
when(artifact2.getArtifactId()).thenReturn("junit-jupiter-engine");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -140,4 +145,26 @@ class ExclusionArtifactFilterTest {
|
||||||
|
|
||||||
assertThat(filter.include(artifact), is(false));
|
assertThat(filter.include(artifact), is(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testExcludeWithGlob() {
|
||||||
|
Exclusion exclusion = new Exclusion();
|
||||||
|
exclusion.setGroupId("*");
|
||||||
|
exclusion.setArtifactId("maven-*");
|
||||||
|
ExclusionArtifactFilter filter = new ExclusionArtifactFilter(Collections.singletonList(exclusion));
|
||||||
|
|
||||||
|
assertThat(filter.include(artifact), is(false));
|
||||||
|
assertThat(filter.include(artifact2), is(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testExcludeWithGlobStar() {
|
||||||
|
Exclusion exclusion = new Exclusion();
|
||||||
|
exclusion.setGroupId("**");
|
||||||
|
exclusion.setArtifactId("maven-**");
|
||||||
|
ExclusionArtifactFilter filter = new ExclusionArtifactFilter(Collections.singletonList(exclusion));
|
||||||
|
|
||||||
|
assertThat(filter.include(artifact), is(false));
|
||||||
|
assertThat(filter.include(artifact2), is(true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue