diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnJava.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnJava.java index 6c76bdb71f07..9b022ad871fa 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnJava.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnJava.java @@ -22,8 +22,8 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.flywaydb.core.internal.util.ClassUtils; import org.springframework.context.annotation.Conditional; -import org.springframework.core.JdkVersion; import org.springframework.util.Assert; /** @@ -32,6 +32,7 @@ * * @author Oliver Gierke * @author Phillip Webb + * @author Andy Wilkinson * @since 1.1.0 */ @Target({ ElementType.TYPE, ElementType.METHOD }) @@ -78,32 +79,35 @@ enum Range { enum JavaVersion { /** - * Java 1.6. + * Java 1.9. */ - SIX(JdkVersion.JAVA_16, "1.6"), + NINE(9, "1.9", "java.security.cert.URICertStoreParameters"), /** - * Java 1.7. + * Java 1.8. */ - SEVEN(JdkVersion.JAVA_17, "1.7"), + EIGHT(8, "1.8", "java.util.function.Function"), /** - * Java 1.8. + * Java 1.7. */ - EIGHT(JdkVersion.JAVA_18, "1.8"), + SEVEN(7, "1.7", "java.nio.file.Files"), /** - * Java 1.9. + * Java 1.6. */ - NINE(JdkVersion.JAVA_19, "1.9"); + SIX(6, "1.6", "java.util.ServiceLoader"); private final int value; private final String name; - JavaVersion(int value, String name) { + private final boolean available; + + JavaVersion(int value, String name, String className) { this.value = value; this.name = name; + this.available = ClassUtils.isPresent(className, getClass().getClassLoader()); } /** @@ -134,9 +138,8 @@ public String toString() { * @return the {@link JavaVersion} */ public static JavaVersion getJavaVersion() { - int version = JdkVersion.getMajorJavaVersion(); for (JavaVersion candidate : JavaVersion.values()) { - if (candidate.value == version) { + if (candidate.available) { return candidate; } } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnJavaTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnJavaTests.java index e5c26b5b2778..cac831d54270 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnJavaTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnJavaTests.java @@ -16,6 +16,15 @@ package org.springframework.boot.autoconfigure.condition; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.util.Arrays; +import java.util.List; +import java.util.ServiceLoader; +import java.util.function.Function; + import org.hamcrest.Matcher; import org.junit.Test; import org.springframework.boot.autoconfigure.condition.ConditionalOnJava.JavaVersion; @@ -23,6 +32,7 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.util.ReflectionUtils; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; @@ -85,6 +95,41 @@ public void olderThanMessage() throws Exception { + "older than 1.6 found 1.7")); } + @Test + public void java8IsDetected() throws Exception { + assertThat(getJavaVersion(), is("1.8")); + } + + @Test + public void java7IsDetected() throws Exception { + assertThat(getJavaVersion(Function.class), is("1.7")); + } + + @Test + public void java6IsDetected() throws Exception { + assertThat(getJavaVersion(Function.class, Files.class), is("1.6")); + } + + @Test + public void java6IsTheFallback() throws Exception { + assertThat(getJavaVersion(Function.class, Files.class, ServiceLoader.class), + is("1.6")); + } + + private String getJavaVersion(Class... hiddenClasses) throws Exception { + URL[] urls = ((URLClassLoader) getClass().getClassLoader()).getURLs(); + URLClassLoader classLoader = new ClassHidingClassLoader(urls, hiddenClasses); + + Class javaVersionClass = classLoader + .loadClass(ConditionalOnJava.JavaVersion.class.getName()); + + Method getJavaVersionMethod = ReflectionUtils.findMethod(javaVersionClass, + "getJavaVersion"); + Object javaVersion = ReflectionUtils.invokeMethod(getJavaVersionMethod, null); + classLoader.close(); + return javaVersion.toString(); + } + private void testBounds(Range range, JavaVersion runningVersion, JavaVersion version, boolean expected) { ConditionOutcome outcome = this.condition.getMatchOutcome(range, runningVersion, @@ -103,6 +148,34 @@ private void assertPresent(boolean expected) { assertThat(this.context.getBeansOfType(String.class).values(), is(matcher)); } + private final class ClassHidingClassLoader extends URLClassLoader { + + private final List> hiddenClasses; + + private ClassHidingClassLoader(URL[] urls, Class... hiddenClasses) { + super(urls, null); + this.hiddenClasses = Arrays.asList(hiddenClasses); + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + if (isHidden(name)) { + throw new ClassNotFoundException(); + } + return super.loadClass(name); + } + + private boolean isHidden(String name) { + for (Class hiddenClass : this.hiddenClasses) { + if (hiddenClass.getName().equals(name)) { + return true; + } + } + return false; + } + + } + @Configuration @ConditionalOnJava(JavaVersion.NINE) static class Java9Required {