Skip to content

Commit

Permalink
Introduces ScanOption.ignoreExternalJars
Browse files Browse the repository at this point in the history
  • Loading branch information
jqno committed Feb 6, 2025
1 parent a137d34 commit 3776c43
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ public static ScanOption recursive() {
return ScanOptions.O.RECURSIVE;
}

/**
* Signals that packages from external jars, which can't be scanned, will be ignored rather than throw an exception.
*
* @return The 'ignore external jars' flag.
*/
public static ScanOption ignoreExternalJars() {
return ScanOptions.O.IGNORE_EXTERNAL_JARS;
}

/**
* Finds only classes that extend or implement the given type.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ final class ScanOptions {
private ScanOptions() {}

enum O implements ScanOption {
RECURSIVE;
RECURSIVE, IGNORE_EXTERNAL_JARS;
}

static class MustExtend implements ScanOption {
Expand Down Expand Up @@ -45,6 +45,9 @@ public static PackageScanOptions process(ScanOption... options) {
if (option.equals(O.RECURSIVE)) {
result.scanRecursively = true;
}
if (option.equals(O.IGNORE_EXTERNAL_JARS)) {
result.ignoreExternalJars = true;
}
if (option instanceof MustExtend) {
MustExtend me = (MustExtend) option;
result.mustExtend = me.type;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
public class PackageScanOptions {

public boolean scanRecursively = false;
public boolean ignoreExternalJars = false;
public Class<?> mustExtend = null;
public Set<Class<?>> exceptClasses = new HashSet<>();
public Predicate<Class<?>> exclusionPredicate = c -> false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@

import java.io.File;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import nl.jqno.equalsverifier.internal.exceptions.ReflectionException;
import nl.jqno.equalsverifier.internal.util.Validations;
Expand All @@ -30,7 +29,7 @@ private PackageScanner() {}
* @return the classes contained in the given package.
*/
public static List<Class<?>> getClassesIn(String packageName, PackageScanOptions options) {
List<Class<?>> result = getDirs(packageName)
List<Class<?>> result = getDirs(packageName, options)
.stream()
.flatMap(d -> getClassesInDir(packageName, d, options).stream())
.collect(Collectors.toList());
Expand All @@ -41,24 +40,27 @@ public static List<Class<?>> getClassesIn(String packageName, PackageScanOptions
return result;
}

private static List<File> getDirs(String packageName) {
private static List<File> getDirs(String packageName, PackageScanOptions options) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
String path = packageName.replace('.', '/');
return rethrow(
() -> Collections
.list(cl.getResources(path))
.stream()
.map(r -> new File(getResourcePath(r)))
.flatMap(r -> getResourcePath(r, options))
.collect(Collectors.toList()),
e -> "Could not scan package " + packageName);
}

private static String getResourcePath(URL r) {
private static Stream<File> getResourcePath(URL r, PackageScanOptions options) {
String result = rethrow(() -> r.toURI().getPath(), e -> "Could not resolve resource path: " + e.getMessage());
if (result == null) {
if (options.ignoreExternalJars) {
return Stream.empty();
}
throw new ReflectionException("Could not resolve third-party resource " + r);
}
return result;
return Stream.of(new File(result));
}

private static List<Class<?>> getClassesInDir(String packageName, File dir, PackageScanOptions options) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ void fail_whenVerifyingAThirdPartyPackage() {
.assertMessageContains("Could not resolve");
}

@Test
void failDifferently_whenVerifyingAThirdPartyPackage_givenScanOptionIgnoreExternalJars() {
ExpectedException
.when(() -> EqualsVerifier.forPackage("org.junit", ScanOption.ignoreExternalJars()).verify())
.assertThrows(IllegalStateException.class)
.assertMessageContains("org.junit", "doesn't contain any (non-Test) types");
}

@Test
void doesNotReportNonrecursive_whenPackageContainsRecursiveAndNonrecursiveClasses() {
ExpectedException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,13 @@ void dependencyPackage() {
.hasMessageContaining("Could not resolve third-party resource");
}

@Test
void dependencyPackageWithIgnore() {
opts.ignoreExternalJars = true;
List<Class<?>> classes = PackageScanner.getClassesIn("org.junit", opts);
assertThat(classes).isEmpty();
}

private void sort(List<Class<?>> classes) {
classes.sort(Comparator.comparing(Class::getName));
}
Expand Down

0 comments on commit 3776c43

Please sign in to comment.