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);
}
}