package net.bytebuddy.test.utility; import net.bytebuddy.ClassFileVersion; import org.junit.rules.MethodRule; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.Statement; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.Locale; import java.util.logging.Logger; public class JavaVersionRule implements MethodRule { private final ClassFileVersion currentVersion; private final boolean hotSpot; public JavaVersionRule() { currentVersion = ClassFileVersion.ofThisVm(); hotSpot = System.getProperty("java.vm.name", "").toLowerCase(Locale.US).contains("hotspot"); } @Override public Statement apply(Statement base, FrameworkMethod method, Object target) { Enforce enforce = method.getAnnotation(Enforce.class); if (enforce != null) { if (!enforce.sort().check(currentVersion, ClassFileVersion.ofJavaVersion(enforce.value()))) { return new NoOpStatement(enforce.value()); } else if (!hotSpot) { for (int javaVersion : enforce.hotSpot()) { if (currentVersion.getJavaVersion() == javaVersion) { return new NoOpHotSpotStatement(javaVersion); } } } } return base; } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Enforce { int value(); Sort sort() default Sort.AT_LEAST; int[] hotSpot() default {}; } private static class NoOpStatement extends Statement { private final int requiredVersion; public NoOpStatement(int requiredVersion) { this.requiredVersion = requiredVersion; } @Override public void evaluate() throws Throwable { Logger.getLogger("net.bytebuddy").warning("Ignoring test case: Requires a Java version of at least " + requiredVersion); } } private static class NoOpHotSpotStatement extends Statement { private final int restrictedVersion; public NoOpHotSpotStatement(int restrictedVersion) { this.restrictedVersion = restrictedVersion; } @Override public void evaluate() throws Throwable { Logger.getLogger("net.bytebuddy").warning("Ignoring test case: Only works on HotSpot for Java version " + restrictedVersion); } } public enum Sort { AT_LEAST { @Override protected boolean check(ClassFileVersion current, ClassFileVersion enforced) { return current.isAtLeast(enforced); } }, AT_MOST { @Override protected boolean check(ClassFileVersion current, ClassFileVersion enforced) { return current.isLessThan(enforced) || current.equals(enforced); } }; protected abstract boolean check(ClassFileVersion current, ClassFileVersion enforced); } }