Skip to content

Commit

Permalink
Allow third parties to provide a custom ClasspathScanner implementa…
Browse files Browse the repository at this point in the history
…tion (#4191)

Resolves #3628

---------

Co-authored-by: Marc Philipp <[email protected]>
  • Loading branch information
juliette-derancourt and marcphilipp authored Dec 19, 2024
1 parent 3aa0f48 commit 6fb2ea3
Show file tree
Hide file tree
Showing 25 changed files with 284 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ JUnit repository on GitHub.
* Output written to `System.out` and `System.err` from non-test threads is now attributed
to the most recent test or container that was started or has written output.
* Introduced contracts for Kotlin-specific assertion methods.
* New public interface `ClasspathScanner` allowing third parties to provide a custom
implementation for scanning the classpath for classes and resources.


[[release-notes-5.12.0-M1-junit-jupiter]]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Maintained functional interfaces and support classes.
* Functional interfaces and support classes.
*/

package org.junit.platform.commons.function;
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,33 @@
* https://www.eclipse.org/legal/epl-v20.html
*/

package org.junit.platform.commons.util;
package org.junit.platform.commons.support;

import static org.apiguardian.api.API.Status.INTERNAL;

import java.net.URI;
import java.util.Objects;

import org.junit.platform.commons.support.Resource;
import org.apiguardian.api.API;
import org.junit.platform.commons.util.Preconditions;
import org.junit.platform.commons.util.ToStringBuilder;

/**
* <h2>DISCLAIMER</h2>
*
* <p>These utilities are intended solely for usage within the JUnit framework
* itself. <strong>Any usage by external parties is not supported.</strong>
* Use at your own risk!
*
* @since 1.11
*/
class ClasspathResource implements Resource {
@API(status = INTERNAL, since = "1.12")
public class DefaultResource implements Resource {

private final String name;
private final URI uri;

ClasspathResource(String name, URI uri) {
public DefaultResource(String name, URI uri) {
this.name = Preconditions.notNull(name, "name must not be null");
this.uri = Preconditions.notNull(uri, "uri must not be null");
}
Expand All @@ -44,7 +55,7 @@ public boolean equals(Object o) {
return true;
if (o == null || getClass() != o.getClass())
return false;
ClasspathResource that = (ClasspathResource) o;
DefaultResource that = (DefaultResource) o;
return name.equals(that.name) && uri.equals(that.uri);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Maintained conversion APIs provided by the JUnit Platform.
* Conversion APIs provided by the JUnit Platform.
*/

package org.junit.platform.commons.support.conversion;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Maintained common support APIs provided by the JUnit Platform.
* Common support APIs provided by the JUnit Platform.
*
* <p>The purpose of this package is to provide {@code TestEngine} and
* {@code Extension} authors convenient access to a subset of internal utility
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,39 @@
* https://www.eclipse.org/legal/epl-v20.html
*/

package org.junit.platform.commons.util;
package org.junit.platform.commons.support.scanning;

import static org.apiguardian.api.API.Status.INTERNAL;
import static org.apiguardian.api.API.Status.EXPERIMENTAL;

import java.util.function.Predicate;

import org.apiguardian.api.API;
import org.junit.platform.commons.util.Preconditions;

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

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

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

/**
* Test name using the stored name predicate.
* Test the given name using the stored name predicate.
*
* @param name the name to test; never {@code null}
* @return {@code true} if the input name matches the predicate, otherwise
* {@code false}
*/
public boolean match(String name) {
return namePredicate.test(name);
}

/**
* Test class using the stored class predicate.
* Test the given class using the stored class predicate.
*
* @param type the type to test; never {@code null}
* @return {@code true} if the input type matches the predicate, otherwise
* {@code false}
*/
public boolean match(Class<?> type) {
return classPredicate.test(type);
}

/**
* @implNote This implementation combines all tests stored in the predicates
* of this instance. Any new predicate must be added to this test method as
* well.
*/
@Override
public boolean test(Class<?> type) {
return match(type.getName()) && match(type);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* https://www.eclipse.org/legal/epl-v20.html
*/

package org.junit.platform.commons.util;
package org.junit.platform.commons.support.scanning;

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* https://www.eclipse.org/legal/epl-v20.html
*/

package org.junit.platform.commons.util;
package org.junit.platform.commons.support.scanning;

import java.nio.file.Path;
import java.util.function.Predicate;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright 2015-2024 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/

package org.junit.platform.commons.support.scanning;

import static org.apiguardian.api.API.Status;

import java.net.URI;
import java.util.List;
import java.util.function.Predicate;

import org.apiguardian.api.API;
import org.junit.platform.commons.support.Resource;

/**
* {@code ClasspathScanner} allows to scan the classpath for classes and
* resources.
*
* <p>An implementation of this interface can be registered via the
* {@link java.util.ServiceLoader ServiceLoader} mechanism.
*
* @since 1.12
*/
@API(status = Status.EXPERIMENTAL, since = "1.12")
public interface ClasspathScanner {

/**
* Find all {@linkplain Class classes} in the supplied classpath {@code root}
* that match the specified {@code classFilter} filter.
*
* <p>The classpath scanning algorithm searches recursively in subpackages
* beginning with the root of the classpath.
*
* @param basePackageName the name of the base package in which to start
* scanning; must not be {@code null} and must be valid in terms of Java
* syntax
* @param classFilter the class type filter; never {@code null}
* @return a list of all such classes found; never {@code null}
* but potentially empty
*/
List<Class<?>> scanForClassesInPackage(String basePackageName, ClassFilter classFilter);

/**
* Find all {@linkplain Class classes} in the supplied classpath {@code root}
* that match the specified {@code classFilter} filter.
*
* <p>The classpath scanning algorithm searches recursively in subpackages
* beginning with the root of the classpath.
*
* @param root the URI for the classpath root in which to scan; never
* {@code null}
* @param classFilter the class type filter; never {@code null}
* @return a list of all such classes found; never {@code null}
* but potentially empty
*/
List<Class<?>> scanForClassesInClasspathRoot(URI root, ClassFilter classFilter);

/**
* Find all {@linkplain Resource resources} in the supplied classpath {@code root}
* that match the specified {@code resourceFilter} predicate.
*
* <p>The classpath scanning algorithm searches recursively in subpackages
* beginning with the root of the classpath.
*
* @param basePackageName the name of the base package in which to start
* scanning; must not be {@code null} and must be valid in terms of Java
* syntax
* @param resourceFilter the resource type filter; never {@code null}
* @return a list of all such resources found; never {@code null}
* but potentially empty
*/
List<Resource> scanForResourcesInPackage(String basePackageName, Predicate<Resource> resourceFilter);

/**
* Find all {@linkplain Resource resources} in the supplied classpath {@code root}
* that match the specified {@code resourceFilter} predicate.
*
* <p>The classpath scanning algorithm searches recursively in subpackages
* beginning with the root of the classpath.
*
* @param root the URI for the classpath root in which to scan; never
* {@code null}
* @param resourceFilter the resource type filter; never {@code null}
* @return a list of all such resources found; never {@code null}
* but potentially empty
*/
List<Resource> scanForResourcesInClasspathRoot(URI root, Predicate<Resource> resourceFilter);

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* https://www.eclipse.org/legal/epl-v20.html
*/

package org.junit.platform.commons.util;
package org.junit.platform.commons.support.scanning;

import static java.util.Collections.emptyMap;

Expand Down
Loading

0 comments on commit 6fb2ea3

Please sign in to comment.