Skip to content

Commit

Permalink
Support classpath resource scanning
Browse files Browse the repository at this point in the history
  • Loading branch information
mpkorstanje committed Feb 25, 2024
1 parent ad82d2a commit 8b2e447
Show file tree
Hide file tree
Showing 15 changed files with 892 additions and 8 deletions.
Expand Up @@ -67,7 +67,6 @@ private ReflectionSupport() {
*/
@API(status = DEPRECATED, since = "1.4")
@Deprecated
@SuppressWarnings("deprecation")
public static Optional<Class<?>> loadClass(String name) {
return ReflectionUtils.loadClass(name);
}
Expand Down Expand Up @@ -137,6 +136,30 @@ public static List<Class<?>> findAllClassesInClasspathRoot(URI root, Predicate<C
return ReflectionUtils.findAllClassesInClasspathRoot(root, classFilter, classNameFilter);
}

/**
* Find all {@linkplain Resource resources} in the supplied classpath {@code root}
* that match the specified {@code resourceFilter} and {@code resourceNameFilter}
* predicates.
*
* <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}
* @param resourceNameFilter the resource name filter; never {@code null}
* @return an immutable list of all such resources found; never {@code null}
* but potentially empty
* @see #findAllResourcesInPackage(String, Predicate, Predicate)
* @see #findAllResourcesInModule(String, Predicate, Predicate)
*/
@API(status = EXPERIMENTAL, since = "1.11")
public static List<Resource> findAllResourcesInClasspathRoot(URI root, Predicate<Resource> resourceFilter,
Predicate<String> resourceNameFilter) {

return ReflectionUtils.findAllResourcesInClasspathRoot(root, resourceFilter, resourceNameFilter);
}

/**
* Find all {@linkplain Class classes} in the supplied classpath {@code root}
* that match the specified {@code classFilter} and {@code classNameFilter}
Expand All @@ -162,6 +185,31 @@ public static Stream<Class<?>> streamAllClassesInClasspathRoot(URI root, Predica
return ReflectionUtils.streamAllClassesInClasspathRoot(root, classFilter, classNameFilter);
}

/**
* Find all {@linkplain Resource resources} in the supplied classpath {@code root}
* that match the specified {@code resourceFilter} and {@code resourceNameFilter}
* predicates.
*
* <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}
* @param resourceNameFilter the resources name filter; never {@code null}
* @return a stream of all such classes found; never {@code null}
* but potentially empty
* @since 1.10
* @see #streamAllResourcesInPackage(String, Predicate, Predicate)
* @see #streamAllResourcesInModule(String, Predicate, Predicate)
*/
@API(status = EXPERIMENTAL, since = "1.11")
public static Stream<Resource> streamAllResourcesInClasspathRoot(URI root, Predicate<Resource> resourceFilter,
Predicate<String> resourceNameFilter) {

return ReflectionUtils.streamAllResourcesInClasspathRoot(root, resourceFilter, resourceNameFilter);
}

/**
* Find all {@linkplain Class classes} in the supplied {@code basePackageName}
* that match the specified {@code classFilter} and {@code classNameFilter}
Expand All @@ -186,6 +234,31 @@ public static List<Class<?>> findAllClassesInPackage(String basePackageName, Pre
return ReflectionUtils.findAllClassesInPackage(basePackageName, classFilter, classNameFilter);
}

/**
* Find all {@linkplain Resource resources} in the supplied {@code basePackageName}
* that match the specified {@code resourceFilter} and {@code resourceNameFilter}
* predicates.
*
* <p>The classpath scanning algorithm searches recursively in subpackages
* beginning within the supplied base package.
*
* @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}
* @param resourceNameFilter the resource name filter; never {@code null}
* @return an immutable list of all such classes found; never {@code null}
* but potentially empty
* @see #findAllResourcesInClasspathRoot(URI, Predicate, Predicate)
* @see #findAllResourcesInModule(String, Predicate, Predicate)
*/
@API(status = EXPERIMENTAL, since = "1.11")
public static List<Resource> findAllResourcesInPackage(String basePackageName, Predicate<Resource> resourceFilter,
Predicate<String> resourceNameFilter) {

return ReflectionUtils.findAllResourcesInPackage(basePackageName, resourceFilter, resourceNameFilter);
}

/**
* Find all {@linkplain Class classes} in the supplied {@code basePackageName}
* that match the specified {@code classFilter} and {@code classNameFilter}
Expand All @@ -212,6 +285,32 @@ public static Stream<Class<?>> streamAllClassesInPackage(String basePackageName,
return ReflectionUtils.streamAllClassesInPackage(basePackageName, classFilter, classNameFilter);
}

/**
* Find all {@linkplain Resource resources} in the supplied {@code basePackageName}
* that match the specified {@code resourceFilter} and {@code resourceNameFilter}
* predicates.
*
* <p>The classpath scanning algorithm searches recursively in subpackages
* beginning within the supplied base package.
*
* @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}
* @param resourceNameFilter the resource name filter; never {@code null}
* @return a stream of all such resources found; never {@code null}
* but potentially empty
* @since 1.10
* @see #streamAllResourcesInClasspathRoot(URI, Predicate, Predicate)
* @see #streamAllResourcesInModule(String, Predicate, Predicate)
*/
@API(status = EXPERIMENTAL, since = "1.11")
public static Stream<Resource> streamAllResourcesInPackage(String basePackageName,
Predicate<Resource> resourceFilter, Predicate<String> resourceNameFilter) {

return ReflectionUtils.streamAllResourcesInPackage(basePackageName, resourceFilter, resourceNameFilter);
}

/**
* Find all {@linkplain Class classes} in the supplied {@code moduleName}
* that match the specified {@code classFilter} and {@code classNameFilter}
Expand All @@ -236,6 +335,31 @@ public static List<Class<?>> findAllClassesInModule(String moduleName, Predicate
return ReflectionUtils.findAllClassesInModule(moduleName, classFilter, classNameFilter);
}

/**
* Find all {@linkplain Resource resources} in the supplied {@code moduleName}
* that match the specified {@code resourceFilter} and {@code resourceNameFilter}
* predicates.
*
* <p>The module-path scanning algorithm searches recursively in all
* packages contained in the module.
*
* @param moduleName the name of the module to scan; never {@code null} or
* <em>empty</em>
* @param resourceFilter the resource type filter; never {@code null}
* @param resourceNameFilter the resource name filter; never {@code null}
* @return an immutable list of all such resources found; never {@code null}
* but potentially empty
* @since 1.1.1
* @see #findAllResourcesInClasspathRoot(URI, Predicate, Predicate)
* @see #findAllResourcesInPackage(String, Predicate, Predicate)
*/
@API(status = EXPERIMENTAL, since = "1.11")
public static List<Resource> findAllResourcesInModule(String moduleName, Predicate<Resource> resourceFilter,
Predicate<String> resourceNameFilter) {

return ReflectionUtils.findAllResourcesInModule(moduleName, resourceFilter, resourceNameFilter);
}

/**
* Find all {@linkplain Class classes} in the supplied {@code moduleName}
* that match the specified {@code classFilter} and {@code classNameFilter}
Expand All @@ -261,6 +385,31 @@ public static Stream<Class<?>> streamAllClassesInModule(String moduleName, Predi
return ReflectionUtils.streamAllClassesInModule(moduleName, classFilter, classNameFilter);
}

/**
* Find all {@linkplain Resource resources} in the supplied {@code moduleName}
* that match the specified {@code resourceFilter} and {@code resourceNameFilter}
* predicates.
*
* <p>The module-path scanning algorithm searches recursively in all
* packages contained in the module.
*
* @param moduleName the name of the module to scan; never {@code null} or
* <em>empty</em>
* @param resourceFilter the resource type filter; never {@code null}
* @param resourceNameFilter the resource name filter; never {@code null}
* @return a stream of all such resources found; never {@code null}
* but potentially empty
* @since 1.10
* @see #streamAllResourcesInClasspathRoot(URI, Predicate, Predicate)
* @see #streamAllResourcesInPackage(String, Predicate, Predicate)
*/
@API(status = EXPERIMENTAL, since = "1.11")
public static Stream<Resource> streamAllResourcesInModule(String moduleName, Predicate<Resource> resourceFilter,
Predicate<String> resourceNameFilter) {

return ReflectionUtils.streamAllResourcesInModule(moduleName, resourceFilter, resourceNameFilter);
}

/**
* Create a new instance of the specified {@link Class} by invoking
* the constructor whose argument list matches the types of the supplied
Expand Down
@@ -0,0 +1,61 @@
/*
* 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;

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

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.function.Predicate;

import org.apiguardian.api.API;

/**
* Represents a resource on the classpath.
*
* @see ReflectionSupport#findAllResourcesInClasspathRoot(URI, Predicate, Predicate)
* @see ReflectionSupport#findAllResourcesInPackage(String, Predicate, Predicate)
* @see ReflectionSupport#findAllResourcesInModule(String, Predicate, Predicate)
* @see ReflectionSupport#streamAllResourcesInClasspathRoot(URI, Predicate, Predicate)
* @see ReflectionSupport#streamAllResourcesInPackage(String, Predicate, Predicate)
* @see ReflectionSupport#streamAllResourcesInModule(String, Predicate, Predicate)
*/
@API(status = EXPERIMENTAL, since = "1.11")
public interface Resource {

/**
* Get the resource name.
* <p>
* The resource name is a {@code /}-separated path. The path is relative to
* the classpath root in which the resource is located.
*
* @return the resource name; never {@code null}
*/
String getName();

/**
* Get URI to a resource.
*
* @return the uri of the resource; never {@code null}
*/
URI getUri();

/**
* Returns an input stream for reading this resource.
*
* @return an input stream for this resource; never {@code null}
* @throws IOException if an I/O exception occurs
*/
default InputStream getInputStream() throws IOException {
return getUri().toURL().openStream();
}
}
@@ -0,0 +1,51 @@
/*
* 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.util;

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

import org.junit.platform.commons.support.Resource;

class ClasspathResource implements Resource {
private final String name;
private final URI uri;

ClasspathResource(String name, URI uri) {
this.name = Preconditions.notNull(name, "name must not be null");
this.uri = Preconditions.notNull(uri, "uri must not be null");
}

@Override
public String getName() {
return name;
}

@Override
public URI getUri() {
return uri;
}

@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
ClasspathResource that = (ClasspathResource) o;
return name.equals(that.name) && uri.equals(that.uri);
}

@Override
public int hashCode() {
return Objects.hash(name, uri);
}
}

0 comments on commit 8b2e447

Please sign in to comment.