Skip to content

Commit 6fb2ea3

Browse files
Allow third parties to provide a custom ClasspathScanner implementation (#4191)
Resolves #3628 --------- Co-authored-by: Marc Philipp <mail@marcphilipp.de>
1 parent 3aa0f48 commit 6fb2ea3

File tree

25 files changed

+284
-94
lines changed

25 files changed

+284
-94
lines changed

documentation/src/docs/asciidoc/release-notes/release-notes-5.12.0-M1.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ JUnit repository on GitHub.
5555
* Output written to `System.out` and `System.err` from non-test threads is now attributed
5656
to the most recent test or container that was started or has written output.
5757
* Introduced contracts for Kotlin-specific assertion methods.
58+
* New public interface `ClasspathScanner` allowing third parties to provide a custom
59+
implementation for scanning the classpath for classes and resources.
5860

5961

6062
[[release-notes-5.12.0-M1-junit-jupiter]]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Maintained functional interfaces and support classes.
2+
* Functional interfaces and support classes.
33
*/
44

55
package org.junit.platform.commons.function;

junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClasspathResource.java renamed to junit-platform-commons/src/main/java/org/junit/platform/commons/support/DefaultResource.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,33 @@
88
* https://www.eclipse.org/legal/epl-v20.html
99
*/
1010

11-
package org.junit.platform.commons.util;
11+
package org.junit.platform.commons.support;
12+
13+
import static org.apiguardian.api.API.Status.INTERNAL;
1214

1315
import java.net.URI;
1416
import java.util.Objects;
1517

16-
import org.junit.platform.commons.support.Resource;
18+
import org.apiguardian.api.API;
19+
import org.junit.platform.commons.util.Preconditions;
20+
import org.junit.platform.commons.util.ToStringBuilder;
1721

1822
/**
23+
* <h2>DISCLAIMER</h2>
24+
*
25+
* <p>These utilities are intended solely for usage within the JUnit framework
26+
* itself. <strong>Any usage by external parties is not supported.</strong>
27+
* Use at your own risk!
28+
*
1929
* @since 1.11
2030
*/
21-
class ClasspathResource implements Resource {
31+
@API(status = INTERNAL, since = "1.12")
32+
public class DefaultResource implements Resource {
2233

2334
private final String name;
2435
private final URI uri;
2536

26-
ClasspathResource(String name, URI uri) {
37+
public DefaultResource(String name, URI uri) {
2738
this.name = Preconditions.notNull(name, "name must not be null");
2839
this.uri = Preconditions.notNull(uri, "uri must not be null");
2940
}
@@ -44,7 +55,7 @@ public boolean equals(Object o) {
4455
return true;
4556
if (o == null || getClass() != o.getClass())
4657
return false;
47-
ClasspathResource that = (ClasspathResource) o;
58+
DefaultResource that = (DefaultResource) o;
4859
return name.equals(that.name) && uri.equals(that.uri);
4960
}
5061

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Maintained conversion APIs provided by the JUnit Platform.
2+
* Conversion APIs provided by the JUnit Platform.
33
*/
44

55
package org.junit.platform.commons.support.conversion;

junit-platform-commons/src/main/java/org/junit/platform/commons/support/package-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Maintained common support APIs provided by the JUnit Platform.
2+
* Common support APIs provided by the JUnit Platform.
33
*
44
* <p>The purpose of this package is to provide {@code TestEngine} and
55
* {@code Extension} authors convenient access to a subset of internal utility

junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClassFilter.java renamed to junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/ClassFilter.java

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,37 +8,39 @@
88
* https://www.eclipse.org/legal/epl-v20.html
99
*/
1010

11-
package org.junit.platform.commons.util;
11+
package org.junit.platform.commons.support.scanning;
1212

13-
import static org.apiguardian.api.API.Status.INTERNAL;
13+
import static org.apiguardian.api.API.Status.EXPERIMENTAL;
1414

1515
import java.util.function.Predicate;
1616

1717
import org.apiguardian.api.API;
18+
import org.junit.platform.commons.util.Preconditions;
1819

1920
/**
2021
* Class-related predicate used by reflection utilities.
2122
*
22-
* <h2>DISCLAIMER</h2>
23-
*
24-
* <p>These utilities are intended solely for usage within the JUnit framework
25-
* itself. <strong>Any usage by external parties is not supported.</strong>
26-
* Use at your own risk!
27-
*
2823
* @since 1.1
2924
*/
30-
@API(status = INTERNAL, since = "1.1")
31-
public class ClassFilter implements Predicate<Class<?>> {
25+
@API(status = EXPERIMENTAL, since = "1.12")
26+
public class ClassFilter {
3227

3328
/**
3429
* Create a {@link ClassFilter} instance that accepts all names but filters classes.
30+
*
31+
* @param classPredicate the class type predicate; never {@code null}
32+
* @return an instance of {@code ClassFilter}; never {@code null}
3533
*/
3634
public static ClassFilter of(Predicate<Class<?>> classPredicate) {
3735
return of(name -> true, classPredicate);
3836
}
3937

4038
/**
4139
* Create a {@link ClassFilter} instance that filters by names and classes.
40+
*
41+
* @param namePredicate the class name predicate; never {@code null}
42+
* @param classPredicate the class type predicate; never {@code null}
43+
* @return an instance of {@code ClassFilter}; never {@code null}
4244
*/
4345
public static ClassFilter of(Predicate<String> namePredicate, Predicate<Class<?>> classPredicate) {
4446
return new ClassFilter(namePredicate, classPredicate);
@@ -53,26 +55,25 @@ private ClassFilter(Predicate<String> namePredicate, Predicate<Class<?>> classPr
5355
}
5456

5557
/**
56-
* Test name using the stored name predicate.
58+
* Test the given name using the stored name predicate.
59+
*
60+
* @param name the name to test; never {@code null}
61+
* @return {@code true} if the input name matches the predicate, otherwise
62+
* {@code false}
5763
*/
5864
public boolean match(String name) {
5965
return namePredicate.test(name);
6066
}
6167

6268
/**
63-
* Test class using the stored class predicate.
69+
* Test the given class using the stored class predicate.
70+
*
71+
* @param type the type to test; never {@code null}
72+
* @return {@code true} if the input type matches the predicate, otherwise
73+
* {@code false}
6474
*/
6575
public boolean match(Class<?> type) {
6676
return classPredicate.test(type);
6777
}
6878

69-
/**
70-
* @implNote This implementation combines all tests stored in the predicates
71-
* of this instance. Any new predicate must be added to this test method as
72-
* well.
73-
*/
74-
@Override
75-
public boolean test(Class<?> type) {
76-
return match(type.getName()) && match(type);
77-
}
7879
}

junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClasspathFileVisitor.java renamed to junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/ClasspathFileVisitor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* https://www.eclipse.org/legal/epl-v20.html
99
*/
1010

11-
package org.junit.platform.commons.util;
11+
package org.junit.platform.commons.support.scanning;
1212

1313
import static java.nio.file.FileVisitResult.CONTINUE;
1414

junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClasspathFilters.java renamed to junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/ClasspathFilters.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* https://www.eclipse.org/legal/epl-v20.html
99
*/
1010

11-
package org.junit.platform.commons.util;
11+
package org.junit.platform.commons.support.scanning;
1212

1313
import java.nio.file.Path;
1414
import java.util.function.Predicate;
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright 2015-2024 the original author or authors.
3+
*
4+
* All rights reserved. This program and the accompanying materials are
5+
* made available under the terms of the Eclipse Public License v2.0 which
6+
* accompanies this distribution and is available at
7+
*
8+
* https://www.eclipse.org/legal/epl-v20.html
9+
*/
10+
11+
package org.junit.platform.commons.support.scanning;
12+
13+
import static org.apiguardian.api.API.Status;
14+
15+
import java.net.URI;
16+
import java.util.List;
17+
import java.util.function.Predicate;
18+
19+
import org.apiguardian.api.API;
20+
import org.junit.platform.commons.support.Resource;
21+
22+
/**
23+
* {@code ClasspathScanner} allows to scan the classpath for classes and
24+
* resources.
25+
*
26+
* <p>An implementation of this interface can be registered via the
27+
* {@link java.util.ServiceLoader ServiceLoader} mechanism.
28+
*
29+
* @since 1.12
30+
*/
31+
@API(status = Status.EXPERIMENTAL, since = "1.12")
32+
public interface ClasspathScanner {
33+
34+
/**
35+
* Find all {@linkplain Class classes} in the supplied classpath {@code root}
36+
* that match the specified {@code classFilter} filter.
37+
*
38+
* <p>The classpath scanning algorithm searches recursively in subpackages
39+
* beginning with the root of the classpath.
40+
*
41+
* @param basePackageName the name of the base package in which to start
42+
* scanning; must not be {@code null} and must be valid in terms of Java
43+
* syntax
44+
* @param classFilter the class type filter; never {@code null}
45+
* @return a list of all such classes found; never {@code null}
46+
* but potentially empty
47+
*/
48+
List<Class<?>> scanForClassesInPackage(String basePackageName, ClassFilter classFilter);
49+
50+
/**
51+
* Find all {@linkplain Class classes} in the supplied classpath {@code root}
52+
* that match the specified {@code classFilter} filter.
53+
*
54+
* <p>The classpath scanning algorithm searches recursively in subpackages
55+
* beginning with the root of the classpath.
56+
*
57+
* @param root the URI for the classpath root in which to scan; never
58+
* {@code null}
59+
* @param classFilter the class type filter; never {@code null}
60+
* @return a list of all such classes found; never {@code null}
61+
* but potentially empty
62+
*/
63+
List<Class<?>> scanForClassesInClasspathRoot(URI root, ClassFilter classFilter);
64+
65+
/**
66+
* Find all {@linkplain Resource resources} in the supplied classpath {@code root}
67+
* that match the specified {@code resourceFilter} predicate.
68+
*
69+
* <p>The classpath scanning algorithm searches recursively in subpackages
70+
* beginning with the root of the classpath.
71+
*
72+
* @param basePackageName the name of the base package in which to start
73+
* scanning; must not be {@code null} and must be valid in terms of Java
74+
* syntax
75+
* @param resourceFilter the resource type filter; never {@code null}
76+
* @return a list of all such resources found; never {@code null}
77+
* but potentially empty
78+
*/
79+
List<Resource> scanForResourcesInPackage(String basePackageName, Predicate<Resource> resourceFilter);
80+
81+
/**
82+
* Find all {@linkplain Resource resources} in the supplied classpath {@code root}
83+
* that match the specified {@code resourceFilter} predicate.
84+
*
85+
* <p>The classpath scanning algorithm searches recursively in subpackages
86+
* beginning with the root of the classpath.
87+
*
88+
* @param root the URI for the classpath root in which to scan; never
89+
* {@code null}
90+
* @param resourceFilter the resource type filter; never {@code null}
91+
* @return a list of all such resources found; never {@code null}
92+
* but potentially empty
93+
*/
94+
List<Resource> scanForResourcesInClasspathRoot(URI root, Predicate<Resource> resourceFilter);
95+
96+
}

junit-platform-commons/src/main/java/org/junit/platform/commons/util/CloseablePath.java renamed to junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/CloseablePath.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* https://www.eclipse.org/legal/epl-v20.html
99
*/
1010

11-
package org.junit.platform.commons.util;
11+
package org.junit.platform.commons.support.scanning;
1212

1313
import static java.util.Collections.emptyMap;
1414

0 commit comments

Comments
 (0)