-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support arbitrary Java feature versions with JRE conditions #3931
base: main
Are you sure you want to change the base?
Support arbitrary Java feature versions with JRE conditions #3931
Conversation
This commit serves as a proof of concept for supporting arbitrary Java feature numbers in @EnabledOnJre, @EnabledForJreRange, and the JRE enum. See junit-team#3930
The current generated source for public enum JRE {
/**
* Java 8.
*/
JAVA_8(8),
/**
* Java 9.
*/
JAVA_9(9),
/**
* Java 10.
*/
JAVA_10(10),
/**
* Java 11.
*/
JAVA_11(11),
/**
* Java 12.
*
* @since 5.4
*/
@API(status = STABLE, since = "5.4")
JAVA_12(12),
/**
* Java 13.
*
* @since 5.4
*/
@API(status = STABLE, since = "5.4")
JAVA_13(13),
/**
* Java 14.
*
* @since 5.5
*/
@API(status = STABLE, since = "5.5")
JAVA_14(14),
/**
* Java 15.
*
* @since 5.6
*/
@API(status = STABLE, since = "5.6")
JAVA_15(15),
/**
* Java 16.
*
* @since 5.7
*/
@API(status = STABLE, since = "5.7")
JAVA_16(16),
/**
* Java 17.
*
* @since 5.7.1
*/
@API(status = STABLE, since = "5.7.1")
JAVA_17(17),
/**
* Java 18.
*
* @since 5.8.1
*/
@API(status = STABLE, since = "5.8.1")
JAVA_18(18),
/**
* Java 19.
*
* @since 5.9
*/
@API(status = STABLE, since = "5.9")
JAVA_19(19),
/**
* Java 20.
*
* @since 5.9
*/
@API(status = STABLE, since = "5.9")
JAVA_20(20),
/**
* Java 21.
*
* @since 5.9.2
*/
@API(status = STABLE, since = "5.9.2")
JAVA_21(21),
/**
* Java 22.
*
* @since 5.10
*/
@API(status = STABLE, since = "5.10")
JAVA_22(22),
/**
* Java 23.
*
* @since 5.11
*/
@API(status = STABLE, since = "5.11")
JAVA_23(23),
/**
* Java 24.
*
* @since 5.11
*/
@API(status = STABLE, since = "5.11")
JAVA_24(24),
/**
* A JRE version other than {@link #JAVA_8}, {@link #JAVA_9},
* {@link #JAVA_10}, {@link #JAVA_11}, {@link #JAVA_12},
* {@link #JAVA_13}, {@link #JAVA_14}, {@link #JAVA_15},
* {@link #JAVA_16}, {@link #JAVA_17}, {@link #JAVA_18},
* {@link #JAVA_19}, {@link #JAVA_20}, {@link #JAVA_21},
* {@link #JAVA_22}, {@link #JAVA_23}, or {@link #JAVA_24}.
*/
OTHER(Integer.MAX_VALUE);
private static final Logger logger = LoggerFactory.getLogger(JRE.class);
private static final int UNKNOWN_FEATURE_VERSION = -1;
private static final int CURRENT_FEATURE_VERSION = determineCurrentFeatureVersion();
private static final JRE CURRENT_VERSION = determineCurrentVersion(CURRENT_FEATURE_VERSION);
private static int determineCurrentFeatureVersion() {
String javaVersion = System.getProperty("java.version");
boolean javaVersionIsBlank = StringUtils.isBlank(javaVersion);
if (javaVersionIsBlank) {
logger.debug(
() -> "JVM system property 'java.version' is undefined. It is therefore not possible to detect Java 8.");
}
if (!javaVersionIsBlank && javaVersion.startsWith("1.8")) {
return 8;
}
try {
// java.lang.Runtime.version() is a static method available on Java 9+
// that returns an instance of java.lang.Runtime.Version which has the
// following method: public int major()
Method versionMethod = Runtime.class.getMethod("version");
Object version = ReflectionSupport.invokeMethod(versionMethod, null);
Method majorMethod = version.getClass().getMethod("major");
return (int) ReflectionSupport.invokeMethod(majorMethod, version);
}
catch (Exception ex) {
logger.debug(ex, () -> "Failed to determine the current JRE version via java.lang.Runtime.Version.");
}
return UNKNOWN_FEATURE_VERSION;
}
private static JRE determineCurrentVersion(int currentFeatureVersion) {
switch (currentFeatureVersion) {
case UNKNOWN_FEATURE_VERSION:
// null signals that the current JRE version is "unknown"
return null;
case 8:
return JAVA_8;
case 9:
return JAVA_9;
case 10:
return JAVA_10;
case 11:
return JAVA_11;
case 12:
return JAVA_12;
case 13:
return JAVA_13;
case 14:
return JAVA_14;
case 15:
return JAVA_15;
case 16:
return JAVA_16;
case 17:
return JAVA_17;
case 18:
return JAVA_18;
case 19:
return JAVA_19;
case 20:
return JAVA_20;
case 21:
return JAVA_21;
case 22:
return JAVA_22;
case 23:
return JAVA_23;
case 24:
return JAVA_24;
default:
return OTHER;
}
}
private final int featureVersion;
private JRE(int featureVersion) {
this.featureVersion = featureVersion;
}
/**
* @return {@code true} if <em>this</em> {@code JRE} is known to be the
* Java Runtime Environment version for the currently executing JVM or if
* the version is {@link #OTHER}
*/
public boolean isCurrentVersion() {
return this == CURRENT_VERSION;
}
/**
* Get the feature version of <em>this</em> {@code JRE}.
*
* @return the feature version of this {@code JRE}, or
* {@link Integer#MAX_VALUE} if this {@code JRE} is {@link #OTHER}
*
* @since 5.12
*/
@API(status = EXPERIMENTAL, since = "5.12")
public int featureVersion() {
return this.featureVersion;
}
/**
* @return the {@link JRE} for the currently executing JVM, potentially
* {@link #OTHER}
*
* @since 5.7
*/
@API(status = STABLE, since = "5.7")
public static JRE currentVersion() {
return CURRENT_VERSION;
}
/**
* @return the feature version for the currently executing JVM, or
* {@code -1} to signal that the feature version is unknown
*
* @since 5.12
*/
@API(status = EXPERIMENTAL, since = "5.12")
public static int currentFeatureVersion() {
return CURRENT_FEATURE_VERSION;
}
/**
* @return {@code true} if the supplied feature version is known to be
* the Java Runtime Environment version for the currently executing JVM
* or if the supplied feature version is {@code -1} and the feature
* version of the current JVM is unknown
*
* @since 5.12
*/
@API(status = EXPERIMENTAL, since = "5.12")
public static boolean isCurrentFeatureVersion(int featureVersion) {
return featureVersion == CURRENT_FEATURE_VERSION;
}
static boolean isCurrentVersionWithinRange(JRE min, JRE max) {
return EnumSet.range(min, max).contains(CURRENT_VERSION);
}
static boolean isCurrentVersionWithinRange(int min, int max) {
return CURRENT_FEATURE_VERSION >= min && CURRENT_FEATURE_VERSION <= max;
}
} |
As can be inferred from the demo tests in the
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The extensibility of this looks good to me, @sbrannen. Thanks for looking at it.
* <p>Defaults to {@code -1} to signal that {@link #min()} should be used instead. | ||
* | ||
* @since 5.12 | ||
* @see #min() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be useful to @see JRE#featureVersion()
here to connect the two in the reader's mind.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed. I'll improve the Javadoc once we've determined if we want to implement this feature.
*/ | ||
JRE max() default JRE.OTHER; | ||
|
||
/** | ||
* Java Runtime Environment feature version which should be used as the lower |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Linking "feature version" to java.lang.Runtime.Version.feature()
would help to connect some dots. Perhaps you can't given your Java baseline?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was planning on documenting that more thoroughly, though I'm glad you made the connection.
We're currently invoking the deprecated major()
method defensively via reflection for support on Java 9+, and I picked the "feature" terminology because of the new feature()
method in Java 10+.
So I plan to explain that to some extent.
As for linking to the newer API, I think that actually might not be an issue, because I believe we are generating Javadoc with a JDK version later than JDK 8 (perhaps JDK 11 or later -- I'll have to check).
Glad you like it, and thanks for reviewing it, @wilkinsona! 👍 |
Overview
This PR currently serves as a proof of concept for supporting arbitrary Java feature versions in
@EnabledOnJre
,@EnabledForJreRange
, and theJRE
enum.Related Issues
JAVA_23
andJAVA_24
JRE
constants to5.10.x
#3918JRE
conditions #3930Definition of Done
@API
annotations