Polish ConditionalOnJava

Apply formating and simplify the condition implementation. Delegate
to Spring's JdkVersion class to obtain the running version.
pull/1050/merge
Phillip Webb 11 years ago
parent 2df4ead4d6
commit 4a6e66fe8b

@ -22,6 +22,7 @@ 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;
/** /**
@ -29,6 +30,7 @@ import org.springframework.util.Assert;
* 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 {
* 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 {
*/ */
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;
} }
} }
} }

@ -28,38 +28,33 @@ 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) {
case OLDER_THAN:
return equalOrBetter ? noMatch : match;
case EQUAL_OR_NEWER:
default:
return equalOrBetter ? match : noMatch;
} }
private String getMessage(Range range, JavaVersion runningVersion, JavaVersion version) {
String expected = String.format(range == Range.EQUAL_OR_NEWER ? "%s or newer"
: "older than %s", version);
return "Required JVM version " + expected + " found " + runningVersion;
} }
} }

@ -24,6 +24,7 @@ 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;
@ -32,42 +33,79 @@ 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 {
} }
@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 {
@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));
}
} }

Loading…
Cancel
Save