package com.ankurm.customvalidation; import org.junit.jupiter.api.Test; import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Path; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; import static org.assertj.core.api.Assertions.assertThat; /** * Reads the real jar manifests off the classpath directly with {@link JarFile}, rather than * trusting a version number typed into a pom.xml or a blog post -- the same "unzip the jar" * standard used for the version-of-record facts elsewhere in this repo. {@code * Class.getResourceAsStream("/META-INF/MANIFEST.MF")} is NOT reliable for this on a flat * classpath (as opposed to the module path): it resolves to whichever jar's manifest the * classloader happens to find first, not necessarily the jar the anchor class was loaded from. * Opening the anchor class's own code-source location as a {@link JarFile} is unambiguous. */ class ClasspathVersionTest { private static Manifest manifestOf(Class anchor) throws IOException, URISyntaxException { Path jarPath = Path.of(anchor.getProtectionDomain().getCodeSource().getLocation().toURI()); try (JarFile jar = new JarFile(jarPath.toFile())) { return jar.getManifest(); } } @Test void jakartaValidationApiIs3_1() throws IOException, URISyntaxException { Class anchor = jakarta.validation.Validation.class; Path jarPath = Path.of(anchor.getProtectionDomain().getCodeSource().getLocation().toURI()); Manifest mf = manifestOf(anchor); Attributes attrs = mf.getMainAttributes(); StringBuilder sb = new StringBuilder(); sb.append("Class: ").append(anchor.getName()).append('\n'); sb.append("Jar file: ").append(jarPath.getFileName()).append('\n'); sb.append("Bundle-SymbolicName: ").append(attrs.getValue("Bundle-SymbolicName")).append('\n'); sb.append("Bundle-Version: ").append(attrs.getValue("Bundle-Version")).append('\n'); sb.append("Implementation-Version: ").append(attrs.getValue("Implementation-Version")).append('\n'); Transcript.write("00-jakarta-validation-api-manifest.txt", sb.toString()); // The jar file name and its own manifest both say 3.1.x -- Spring Boot 4.1.1 pins // Jakarta Validation 3.1 (renamed from "Bean Validation" in the 3.1 spec revision), // confirmed two independent ways rather than one. assertThat(jarPath.getFileName().toString()).startsWith("jakarta.validation-api-3.1"); } @Test void hibernateValidatorIs9_1() throws IOException, URISyntaxException { Class anchor = org.hibernate.validator.internal.engine.ValidatorFactoryImpl.class; Path jarPath = Path.of(anchor.getProtectionDomain().getCodeSource().getLocation().toURI()); Manifest mf = manifestOf(anchor); Attributes attrs = mf.getMainAttributes(); StringBuilder sb = new StringBuilder(); sb.append("Class: ").append(anchor.getName()).append('\n'); sb.append("Jar file: ").append(jarPath.getFileName()).append('\n'); sb.append("Implementation-Title: ").append(attrs.getValue("Implementation-Title")).append('\n'); sb.append("Implementation-Version: ").append(attrs.getValue("Implementation-Version")).append('\n'); Transcript.write("00b-hibernate-validator-manifest.txt", sb.toString()); assertThat(jarPath.getFileName().toString()).startsWith("hibernate-validator-9.1"); } }