From b6aa21b64199fb9a09bd4bb49724162982b33813 Mon Sep 17 00:00:00 2001 From: Valentin Delaye Date: Fri, 16 Oct 2026 11:50:56 +0200 Subject: [PATCH] chore(deps): drop classgraph test dependency ClassGraph 6 requires Java 25 (class file version 69) while the project targets Java 17. Replace its single use in ClassAnnotationsTest with a plain JDK scan of the compiled classes. Supersedes #931 Co-Authored-By: Claude Opus 5.5 Signed-off-by: Valentin Delaye --- pom.xml | 11 -- .../java/land/oras/ClassAnnotationsTest.java | 129 ++++++++++-------- 2 files changed, 69 insertions(+), 71 deletions(-) diff --git a/pom.xml b/pom.xml index af2c805d..63cf1842 100644 --- a/pom.xml +++ b/pom.xml @@ -75,7 +75,6 @@ 3.13.2 5.24.0 2.1.8 - 4.8.199 4.3.0 @@ -144,11 +143,6 @@ zstd-jni ${zstd-jni.version} - - io.github.classgraph - classgraph - ${classgraph.version} - org.apache.commons commons-compress @@ -265,11 +259,6 @@ logback-classic test - - io.github.classgraph - classgraph - test - org.awaitility awaitility diff --git a/src/test/java/land/oras/ClassAnnotationsTest.java b/src/test/java/land/oras/ClassAnnotationsTest.java index dfc607e2..32338ccd 100644 --- a/src/test/java/land/oras/ClassAnnotationsTest.java +++ b/src/test/java/land/oras/ClassAnnotationsTest.java @@ -23,10 +23,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import io.github.classgraph.ClassGraph; -import io.github.classgraph.ScanResult; -import java.util.HashSet; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; import land.oras.auth.HttpClient; import land.oras.exception.Error; import org.junit.jupiter.api.Test; @@ -37,73 +40,79 @@ class ClassAnnotationsTest { @Test - void shouldHaveAnnotationOnModel() { - try (ScanResult scanResult = new ClassGraph() - .enableClassInfo() - .enableAllInfo() - .enableAnnotationInfo() - .acceptPackages("land.oras") - .scan()) { - Set> modelClasses = new HashSet<>(scanResult - .getClassesWithAnnotation(OrasModel.class.getName()) - .loadClasses()); + void shouldHaveAnnotationOnModel() throws Exception { + Set> modelClasses = findAnnotatedClasses("land.oras"); - // Check number of classes - assertEquals(43, modelClasses.size()); + // Check number of classes + assertEquals(43, modelClasses.size()); - // Check classes - assertTrue(modelClasses.contains(Annotations.class)); - assertTrue(modelClasses.contains(ArtifactType.class)); - assertTrue(modelClasses.contains(Config.class)); - assertTrue(modelClasses.contains(CopyUtils.CopyOptions.class)); - assertTrue(modelClasses.contains(Descriptor.class)); - assertTrue(modelClasses.contains(Describable.class)); - assertTrue(modelClasses.contains(Error.class)); - assertTrue(modelClasses.contains(HttpClient.TokenResponse.class)); - assertTrue(modelClasses.contains(Index.class)); - assertTrue(modelClasses.contains(Layer.class)); - assertTrue(modelClasses.contains(Manifest.class)); - assertTrue(modelClasses.contains(ManifestDescriptor.class)); - assertTrue(modelClasses.contains(OCILayout.class)); - assertTrue(modelClasses.contains(OCI.PullOptions.class)); - assertTrue(modelClasses.contains(OCI.PushOptions.class)); - assertTrue(modelClasses.contains(Repositories.class)); - assertTrue(modelClasses.contains(Subject.class)); - assertTrue(modelClasses.contains(Tags.class)); - } + // Check classes + assertTrue(modelClasses.contains(Annotations.class)); + assertTrue(modelClasses.contains(ArtifactType.class)); + assertTrue(modelClasses.contains(Config.class)); + assertTrue(modelClasses.contains(CopyUtils.CopyOptions.class)); + assertTrue(modelClasses.contains(Descriptor.class)); + assertTrue(modelClasses.contains(Describable.class)); + assertTrue(modelClasses.contains(Error.class)); + assertTrue(modelClasses.contains(HttpClient.TokenResponse.class)); + assertTrue(modelClasses.contains(Index.class)); + assertTrue(modelClasses.contains(Layer.class)); + assertTrue(modelClasses.contains(Manifest.class)); + assertTrue(modelClasses.contains(ManifestDescriptor.class)); + assertTrue(modelClasses.contains(OCILayout.class)); + assertTrue(modelClasses.contains(OCI.PullOptions.class)); + assertTrue(modelClasses.contains(OCI.PushOptions.class)); + assertTrue(modelClasses.contains(Repositories.class)); + assertTrue(modelClasses.contains(Subject.class)); + assertTrue(modelClasses.contains(Tags.class)); } @Test - void shouldHaveAnnotationOnAuthPackage() { - try (ScanResult scanResult = new ClassGraph() - .enableClassInfo() - .enableAllInfo() - .enableAnnotationInfo() - .acceptPackages("land.oras.auth") - .scan()) { - Set> modelClasses = new HashSet<>(scanResult - .getClassesWithAnnotation(OrasModel.class.getName()) - .loadClasses()); + void shouldHaveAnnotationOnAuthPackage() throws Exception { + Set> modelClasses = findAnnotatedClasses("land.oras.auth"); - // Check number of classes - assertEquals(10, modelClasses.size()); - } + // Check number of classes + assertEquals(10, modelClasses.size()); } @Test - void shouldHaveAnnotationOnPolicyPackage() { - try (ScanResult scanResult = new ClassGraph() - .enableClassInfo() - .enableAllInfo() - .enableAnnotationInfo() - .acceptPackages("land.oras.policy") - .scan()) { - Set> modelClasses = new HashSet<>(scanResult - .getClassesWithAnnotation(OrasModel.class.getName()) - .loadClasses()); + void shouldHaveAnnotationOnPolicyPackage() throws Exception { + Set> modelClasses = findAnnotatedClasses("land.oras.policy"); + + // Check number of classes + assertEquals(11, modelClasses.size()); + } + + /** + * Find all classes annotated with {@link OrasModel} in the given package and its sub-packages + * @param packageName The package name + * @return The annotated classes + */ + private static Set> findAnnotatedClasses(String packageName) throws IOException, URISyntaxException { + Path root = Path.of(OrasModel.class + .getProtectionDomain() + .getCodeSource() + .getLocation() + .toURI()); + Path packageDir = root.resolve(packageName.replace('.', '/')); + ClassLoader classLoader = ClassAnnotationsTest.class.getClassLoader(); + try (Stream paths = Files.walk(packageDir)) { + return paths.filter(path -> path.toString().endsWith(".class")) + .map(path -> root.relativize(path).toString()) + .map(name -> name.substring(0, name.length() - ".class".length()) + .replace('/', '.') + .replace('\\', '.')) + .map(name -> loadClass(name, classLoader)) + .filter(clazz -> clazz.isAnnotationPresent(OrasModel.class)) + .collect(Collectors.toSet()); + } + } - // Check number of classes - assertEquals(11, modelClasses.size()); + private static Class loadClass(String name, ClassLoader classLoader) { + try { + return Class.forName(name, false, classLoader); + } catch (ClassNotFoundException e) { + throw new IllegalStateException(e); } } }