From eae7b0364b4b907a684b83326f8bedadeb7b002c Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 2 Oct 2015 18:10:21 +0100 Subject: [PATCH] Replace use of deprecated JdkVersion API by looking for presence of classes This commit updates ConditionalOnJava to remove a dependency on the deprecated JdkVersion API from Spring Framework. In its place it now looks for the presence of certain classes to determine the version of Java on which its running. Closes gh-4005 --- .../condition/ConditionalOnJava.java | 31 ++++---- .../condition/ConditionalOnJavaTests.java | 73 +++++++++++++++++++ 2 files changed, 90 insertions(+), 14 deletions(-) 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 6c76bdb71f..9b022ad871 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.Retention; 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 @@ import org.springframework.util.Assert; * * @author Oliver Gierke * @author Phillip Webb + * @author Andy Wilkinson * @since 1.1.0 */ @Target({ ElementType.TYPE, ElementType.METHOD }) @@ -78,32 +79,35 @@ public @interface ConditionalOnJava { enum JavaVersion { /** - * Java 1.6. + * Java 1.9. */ - SIX(JdkVersion.JAVA_16, "1.6"), - - /** - * Java 1.7. - */ - SEVEN(JdkVersion.JAVA_17, "1.7"), + NINE(9, "1.9", "java.security.cert.URICertStoreParameters"), /** * Java 1.8. */ - EIGHT(JdkVersion.JAVA_18, "1.8"), + EIGHT(8, "1.8", "java.util.function.Function"), /** - * Java 1.9. + * Java 1.7. */ - NINE(JdkVersion.JAVA_19, "1.9"); + SEVEN(7, "1.7", "java.nio.file.Files"), + + /** + * Java 1.6. + */ + 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 @interface ConditionalOnJava { * @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 e5c26b5b27..cac831d542 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.boot.autoconfigure.condition.ConditionalOnJava.Range; 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 class ConditionalOnJavaTests { + "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 @@ public class ConditionalOnJavaTests { 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 {