1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.lang3; 18 19 import org.apache.commons.lang3.math.NumberUtils; 20 21 /** 22 * An enum representing all the versions of the Java specification. 23 * This is intended to mirror available values from the 24 * <em>java.specification.version</em> System property. 25 * 26 * @since 3.0 27 */ 28 public enum JavaVersion { 29 30 /** 31 * The Java version reported by Android. This is not an official Java version number. 32 */ 33 JAVA_0_9(1.5f, "0.9"), 34 35 /** 36 * Java 1.1. 37 */ 38 JAVA_1_1(1.1f, "1.1"), 39 40 /** 41 * Java 1.2. 42 */ 43 JAVA_1_2(1.2f, "1.2"), 44 45 /** 46 * Java 1.3. 47 */ 48 JAVA_1_3(1.3f, "1.3"), 49 50 /** 51 * Java 1.4. 52 */ 53 JAVA_1_4(1.4f, "1.4"), 54 55 /** 56 * Java 1.5. 57 */ 58 JAVA_1_5(1.5f, "1.5"), 59 60 /** 61 * Java 1.6. 62 */ 63 JAVA_1_6(1.6f, "1.6"), 64 65 /** 66 * Java 1.7. 67 */ 68 JAVA_1_7(1.7f, "1.7"), 69 70 /** 71 * Java 1.8. 72 */ 73 JAVA_1_8(1.8f, "1.8"), 74 75 /** 76 * Java 1.9. 77 * 78 * @deprecated As of release 3.5, replaced by {@link #JAVA_9} 79 */ 80 @Deprecated 81 JAVA_1_9(9.0f, "9"), 82 83 /** 84 * Java 9. 85 * 86 * @since 3.5 87 */ 88 JAVA_9(9.0f, "9"), 89 90 /** 91 * Java 10. 92 * 93 * @since 3.7 94 */ 95 JAVA_10(10.0f, "10"), 96 97 /** 98 * Java 11. 99 * 100 * @since 3.8 101 */ 102 JAVA_11(11.0f, "11"), 103 104 /** 105 * Java 12. 106 * 107 * @since 3.9 108 */ 109 JAVA_12(12.0f, "12"), 110 111 /** 112 * Java 13. 113 * 114 * @since 3.9 115 */ 116 JAVA_13(13.0f, "13"), 117 118 /** 119 * Java 14. 120 * 121 * @since 3.11 122 */ 123 JAVA_14(14.0f, "14"), 124 125 /** 126 * Java 15. 127 * 128 * @since 3.11 129 */ 130 JAVA_15(15.0f, "15"), 131 132 /** 133 * Java 16. 134 * 135 * @since 3.11 136 */ 137 JAVA_16(16.0f, "16"), 138 139 /** 140 * Java 17. 141 * 142 * @since 3.12.0 143 */ 144 JAVA_17(17.0f, "17"), 145 146 /** 147 * Java 18. 148 * 149 * @since 3.13.0 150 */ 151 JAVA_18(18.0f, "18"), 152 153 /** 154 * The most recent java version. Mainly introduced to avoid to break when a new version of Java is used. 155 */ 156 JAVA_RECENT(maxVersion(), Float.toString(maxVersion())); 157 158 /** 159 * The float value. 160 */ 161 private final float value; 162 163 /** 164 * The standard name. 165 */ 166 private final String name; 167 168 /** 169 * Constructor. 170 * 171 * @param value the float value 172 * @param name the standard name, not null 173 */ JavaVersion(final float value, final String name)174 JavaVersion(final float value, final String name) { 175 this.value = value; 176 this.name = name; 177 } 178 179 /** 180 * Whether this version of Java is at least the version of Java passed in. 181 * 182 * <p>For example:<br> 183 * {@code myVersion.atLeast(JavaVersion.JAVA_1_4)}</p> 184 * 185 * @param requiredVersion the version to check against, not null 186 * @return true if this version is equal to or greater than the specified version 187 */ atLeast(final JavaVersion requiredVersion)188 public boolean atLeast(final JavaVersion requiredVersion) { 189 return this.value >= requiredVersion.value; 190 } 191 192 /** 193 * Whether this version of Java is at most the version of Java passed in. 194 * 195 * <p>For example:<br> 196 * {@code myVersion.atMost(JavaVersion.JAVA_1_4)}</p> 197 * 198 * @param requiredVersion the version to check against, not null 199 * @return true if this version is equal to or greater than the specified version 200 * @since 3.9 201 */ atMost(final JavaVersion requiredVersion)202 public boolean atMost(final JavaVersion requiredVersion) { 203 return this.value <= requiredVersion.value; 204 } 205 206 /** 207 * Transforms the given string with a Java version number to the 208 * corresponding constant of this enumeration class. This method is used 209 * internally. 210 * 211 * @param versionStr the Java version as string 212 * @return the corresponding enumeration constant or <b>null</b> if the 213 * version is unknown 214 */ 215 // helper for static importing getJavaVersion(final String versionStr)216 static JavaVersion getJavaVersion(final String versionStr) { 217 return get(versionStr); 218 } 219 220 /** 221 * Transforms the given string with a Java version number to the 222 * corresponding constant of this enumeration class. This method is used 223 * internally. 224 * 225 * @param versionStr the Java version as string 226 * @return the corresponding enumeration constant or <b>null</b> if the 227 * version is unknown 228 */ get(final String versionStr)229 static JavaVersion get(final String versionStr) { 230 if (versionStr == null) { 231 return null; 232 } 233 switch (versionStr) { 234 case "0.9": 235 return JAVA_0_9; 236 case "1.1": 237 return JAVA_1_1; 238 case "1.2": 239 return JAVA_1_2; 240 case "1.3": 241 return JAVA_1_3; 242 case "1.4": 243 return JAVA_1_4; 244 case "1.5": 245 return JAVA_1_5; 246 case "1.6": 247 return JAVA_1_6; 248 case "1.7": 249 return JAVA_1_7; 250 case "1.8": 251 return JAVA_1_8; 252 case "9": 253 return JAVA_9; 254 case "10": 255 return JAVA_10; 256 case "11": 257 return JAVA_11; 258 case "12": 259 return JAVA_12; 260 case "13": 261 return JAVA_13; 262 case "14": 263 return JAVA_14; 264 case "15": 265 return JAVA_15; 266 case "16": 267 return JAVA_16; 268 case "17": 269 return JAVA_17; 270 case "18": 271 return JAVA_18; 272 default: 273 final float v = toFloatVersion(versionStr); 274 if ((v - 1.) < 1.) { // then we need to check decimals > .9 275 final int firstComma = Math.max(versionStr.indexOf('.'), versionStr.indexOf(',')); 276 final int end = Math.max(versionStr.length(), versionStr.indexOf(',', firstComma)); 277 if (Float.parseFloat(versionStr.substring(firstComma + 1, end)) > .9f) { 278 return JAVA_RECENT; 279 } 280 } else if (v > 10) { 281 return JAVA_RECENT; 282 } 283 return null; 284 } 285 } 286 287 /** 288 * The string value is overridden to return the standard name. 289 * 290 * <p>For example, {@code "1.5"}.</p> 291 * 292 * @return the name, not null 293 */ 294 @Override toString()295 public String toString() { 296 return name; 297 } 298 299 /** 300 * Gets the Java Version from the system or 99.0 if the {@code java.specification.version} system property is not set. 301 * 302 * @return the value of {@code java.specification.version} system property or 99.0 if it is not set. 303 */ maxVersion()304 private static float maxVersion() { 305 final float v = toFloatVersion(System.getProperty("java.specification.version", "99.0")); 306 return v > 0 ? v : 99f; 307 } 308 309 /** 310 * Parses a float value from a String. 311 * 312 * @param value the String to parse. 313 * @return the float value represented by the string or -1 if the given String can not be parsed. 314 */ toFloatVersion(final String value)315 private static float toFloatVersion(final String value) { 316 final int defaultReturnValue = -1; 317 if (!value.contains(".")) { 318 return NumberUtils.toFloat(value, defaultReturnValue); 319 } 320 final String[] toParse = value.split("\\."); 321 if (toParse.length >= 2) { 322 return NumberUtils.toFloat(toParse[0] + '.' + toParse[1], defaultReturnValue); 323 } 324 return defaultReturnValue; 325 } 326 } 327