Commit 4a6e66fe authored by Phillip Webb's avatar Phillip Webb

Polish ConditionalOnJava

Apply formating and simplify the condition implementation. Delegate
to Spring's JdkVersion class to obtain the running version.
parent 2df4ead4
...@@ -22,13 +22,15 @@ import java.lang.annotation.RetentionPolicy; ...@@ -22,13 +22,15 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Conditional;
import org.springframework.core.JdkVersion;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
* {@link Conditional} that matches based on the JVM version the application is running * {@link Conditional} that matches based on the JVM version the application is running
* on. * on.
* *
* @author Oliver Gierke * @author Oliver Gierke
* @author Phillip Webb
* @since 1.1.0 * @since 1.1.0
*/ */
@Target({ ElementType.TYPE, ElementType.METHOD }) @Target({ ElementType.TYPE, ElementType.METHOD })
...@@ -41,7 +43,6 @@ public @interface ConditionalOnJava { ...@@ -41,7 +43,6 @@ public @interface ConditionalOnJava {
* Configures whether the value configured in {@link #value()} shall be considered the * Configures whether the value configured in {@link #value()} shall be considered the
* upper exclusive or lower inclusive boundary. Defaults to * upper exclusive or lower inclusive boundary. Defaults to
* {@link Range#EQUAL_OR_NEWER}. * {@link Range#EQUAL_OR_NEWER}.
* @return the range of the version
*/ */
Range range() default Range.EQUAL_OR_NEWER; Range range() default Range.EQUAL_OR_NEWER;
...@@ -51,66 +52,91 @@ public @interface ConditionalOnJava { ...@@ -51,66 +52,91 @@ public @interface ConditionalOnJava {
*/ */
JavaVersion value(); JavaVersion value();
/**
* Range options.
*/
public enum Range { public enum Range {
OLDER_THAN("older than %s"), EQUAL_OR_NEWER("%s or newer"); /**
* Equal to, or newer than the specified {@link JavaVersion}.
private final String message; */
EQUAL_OR_NEWER,
private Range(String message) { /**
this.message = message; * Older than the specified {@link JavaVersion}.
} */
OLDER_THAN;
public String getMessage(JavaVersion version) {
return String.format(this.message, version);
}
} }
/** /**
* An enum to abstract major Java versions. * Java versions.
*/ */
public enum JavaVersion { public enum JavaVersion {
FIVE("1.5"), SIX("1.6"), SEVEN("1.7"), EIGHT("1.8"), NINE("1.9"); /**
* Java 1.6.
*/
SIX(JdkVersion.JAVA_16, "1.6"),
private String value; /**
* Java 1.7.
*/
SEVEN(JdkVersion.JAVA_17, "1.7"),
private JavaVersion(String value) { /**
this.value = value; * Java 1.8.
} */
EIGHT(JdkVersion.JAVA_18, "1.8"),
/** /**
* Returns the {@link JavaVersion} of the current runtime. * Java 1.9.
*/ */
public static JavaVersion fromRuntime() { NINE(JdkVersion.JAVA_19, "1.9");
String source = System.getProperty("java.version"); private final int value;
for (JavaVersion version : JavaVersion.values()) { private final String name;
if (source.startsWith(version.value)) {
return version;
}
}
throw new IllegalArgumentException(String.format( private JavaVersion(int value, String name) {
"Could not detect Java version for %s.", source)); this.value = value;
this.name = name;
} }
/** /**
* Returns whether the given {@link JavaVersion} is considered equal or better * Determines if this version is within the specified range of versions.
* than the given one. * @param range the range
* * @param version the bounds of the range
* @param version must not be {code null}. * @return if this version is within the specified range
*/ */
public boolean isEqualOrBetter(JavaVersion version) { public boolean isWithin(Range range, JavaVersion version) {
Assert.notNull(range, "Range must not be null");
Assert.notNull(version, "Java version must not be null!"); Assert.notNull(version, "Version must not be null");
return this.value.compareTo(version.value) >= 0; switch (range) {
case EQUAL_OR_NEWER:
return this.value >= version.value;
case OLDER_THAN:
return this.value < version.value;
}
throw new IllegalStateException("Unknown range " + range);
} }
@Override @Override
public String toString() { public String toString() {
return this.value; return this.name;
}
/**
* Returns the {@link JavaVersion} of the current runtime.
*/
public static JavaVersion getJavaVersion() {
int version = JdkVersion.getMajorJavaVersion();
for (JavaVersion candidate : JavaVersion.values()) {
if (candidate.value == version) {
return candidate;
}
}
return SIX;
} }
} }
} }
...@@ -26,40 +26,35 @@ import org.springframework.core.type.AnnotatedTypeMetadata; ...@@ -26,40 +26,35 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
/** /**
* {@link Condition} that checks for a required version of Java * {@link Condition} that checks for a required version of Java
* *
* @author Oliver Gierke * @author Oliver Gierke
* @author Phillip Webb
* @see ConditionalOnJava * @see ConditionalOnJava
* @since 1.1.0 * @since 1.1.0
*/ */
class OnJavaCondition extends SpringBootCondition { class OnJavaCondition extends SpringBootCondition {
private static final JavaVersion JVM_VERSION = JavaVersion.fromRuntime(); private static final JavaVersion JVM_VERSION = JavaVersion.getJavaVersion();
private static final String MATCH_MESSAGE = "Required JVM version %s and found %s.";
private static final String NO_MATCH_MESSAGE = "Required JVM version %s but found %s.";
@Override @Override
public ConditionOutcome getMatchOutcome(ConditionContext context, public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) { AnnotatedTypeMetadata metadata) {
Map<String, Object> attributes = metadata Map<String, Object> attributes = metadata
.getAnnotationAttributes(ConditionalOnJava.class.getName()); .getAnnotationAttributes(ConditionalOnJava.class.getName());
JavaVersion version = (JavaVersion) attributes.get("value");
Range range = (Range) attributes.get("range"); Range range = (Range) attributes.get("range");
JavaVersion version = (JavaVersion) attributes.get("value");
return getMatchOutcome(range, JVM_VERSION, version);
}
ConditionOutcome match = ConditionOutcome.match(// protected ConditionOutcome getMatchOutcome(Range range, JavaVersion runningVersion,
String.format(MATCH_MESSAGE, range.getMessage(version), JVM_VERSION)); JavaVersion version) {
ConditionOutcome noMatch = ConditionOutcome.noMatch(// boolean match = runningVersion.isWithin(range, version);
String.format(NO_MATCH_MESSAGE, range.getMessage(version), JVM_VERSION)); return new ConditionOutcome(match, getMessage(range, runningVersion, version));
}
boolean equalOrBetter = JVM_VERSION.isEqualOrBetter(version);
switch (range) { private String getMessage(Range range, JavaVersion runningVersion, JavaVersion version) {
case OLDER_THAN: String expected = String.format(range == Range.EQUAL_OR_NEWER ? "%s or newer"
return equalOrBetter ? noMatch : match; : "older than %s", version);
case EQUAL_OR_NEWER: return "Required JVM version " + expected + " found " + runningVersion;
default:
return equalOrBetter ? match : noMatch;
}
} }
} }
...@@ -24,50 +24,88 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext ...@@ -24,50 +24,88 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.iterableWithSize; import static org.hamcrest.Matchers.iterableWithSize;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
/** /**
* Tests for {@link ConditionalOnJava}. * Tests for {@link ConditionalOnJava}.
* *
* @author Oliver Gierke * @author Oliver Gierke
* @author Phillip Webb
*/ */
public class ConditionalOnJavaTests { public class ConditionalOnJavaTests {
private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
private final OnJavaCondition condition = new OnJavaCondition();
@Test @Test
public void doesNotMatchIfBetterVersionIsRequired() { public void doesNotMatchIfBetterVersionIsRequired() {
registerAndRefresh(Java9Required.class);
this.context.register(Java9Required.class);
this.context.refresh();
assertPresent(false); assertPresent(false);
} }
@Test @Test
public void doesNotMatchIfLowerIsRequired() { public void doesNotMatchIfLowerIsRequired() {
registerAndRefresh(Java5Required.class);
this.context.register(Java5Required.class);
this.context.refresh();
assertPresent(false); assertPresent(false);
} }
@Test @Test
public void matchesIfVersionIsInRange() { public void matchesIfVersionIsInRange() {
registerAndRefresh(Java6Required.class);
assertPresent(true);
}
@Test
public void boundsTests() throws Exception {
testBounds(Range.EQUAL_OR_NEWER, JavaVersion.SEVEN, JavaVersion.SIX, true);
testBounds(Range.EQUAL_OR_NEWER, JavaVersion.SEVEN, JavaVersion.SEVEN, true);
testBounds(Range.EQUAL_OR_NEWER, JavaVersion.SEVEN, JavaVersion.EIGHT, false);
testBounds(Range.OLDER_THAN, JavaVersion.SEVEN, JavaVersion.SIX, false);
testBounds(Range.OLDER_THAN, JavaVersion.SEVEN, JavaVersion.SEVEN, false);
testBounds(Range.OLDER_THAN, JavaVersion.SEVEN, JavaVersion.EIGHT, true);
}
@Test
public void equalOrNewerMessage() throws Exception {
ConditionOutcome outcome = this.condition.getMatchOutcome(Range.EQUAL_OR_NEWER,
JavaVersion.SEVEN, JavaVersion.SIX);
assertThat(outcome.getMessage(), equalTo("Required JVM version "
+ "1.6 or newer found 1.7"));
}
@Test
public void olderThanMessage() throws Exception {
ConditionOutcome outcome = this.condition.getMatchOutcome(Range.OLDER_THAN,
JavaVersion.SEVEN, JavaVersion.SIX);
assertThat(outcome.getMessage(), equalTo("Required JVM version "
+ "older than 1.6 found 1.7"));
}
this.context.register(Java6Required.class); private void testBounds(Range range, JavaVersion runningVersion, JavaVersion version,
boolean expected) {
ConditionOutcome outcome = this.condition.getMatchOutcome(range, runningVersion,
version);
assertThat(outcome.getMessage(), outcome.isMatch(), equalTo(expected));
}
private void registerAndRefresh(Class<?> annotatedClasses) {
this.context.register(annotatedClasses);
this.context.refresh(); this.context.refresh();
}
assertPresent(true); private void assertPresent(boolean expected) {
int expectedNumber = expected ? 1 : 0;
Matcher<Iterable<String>> matcher = iterableWithSize(expectedNumber);
assertThat(this.context.getBeansOfType(String.class).values(), is(matcher));
} }
@Configuration @Configuration
@ConditionalOnJava(JavaVersion.NINE) @ConditionalOnJava(JavaVersion.NINE)
static class Java9Required { static class Java9Required {
@Bean @Bean
String foo() { String foo() {
return "foo"; return "foo";
...@@ -75,9 +113,8 @@ public class ConditionalOnJavaTests { ...@@ -75,9 +113,8 @@ public class ConditionalOnJavaTests {
} }
@Configuration @Configuration
@ConditionalOnJava(value = JavaVersion.SIX, range = Range.OLDER_THAN) @ConditionalOnJava(range = Range.OLDER_THAN, value = JavaVersion.SIX)
static class Java5Required { static class Java5Required {
@Bean @Bean
String foo() { String foo() {
return "foo"; return "foo";
...@@ -87,18 +124,10 @@ public class ConditionalOnJavaTests { ...@@ -87,18 +124,10 @@ public class ConditionalOnJavaTests {
@Configuration @Configuration
@ConditionalOnJava(JavaVersion.SIX) @ConditionalOnJava(JavaVersion.SIX)
static class Java6Required { static class Java6Required {
@Bean @Bean
String foo() { String foo() {
return "foo"; return "foo";
} }
} }
private void assertPresent(boolean expected) {
int expectedNumber = expected ? 1 : 0;
Matcher<Iterable<String>> matcher = iterableWithSize(expectedNumber);
assertThat(this.context.getBeansOfType(String.class).values(), is(matcher));
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment