001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.lang3;
018
019/**
020 * <p>An enum representing all the versions of the Java specification.
021 * This is intended to mirror available values from the
022 * <em>java.specification.version</em> System property. </p>
023 *
024 * @since 3.0
025 * @version $Id: JavaVersion.java 1654140 2015-01-23 08:41:18Z britter $
026 */
027public enum JavaVersion {
028    
029    /**
030     * The Java version reported by Android. This is not an official Java version number.
031     */
032    JAVA_0_9(1.5f, "0.9"),
033    
034    /**
035     * Java 1.1.
036     */
037    JAVA_1_1(1.1f, "1.1"),
038
039    /**
040     * Java 1.2.
041     */
042    JAVA_1_2(1.2f, "1.2"),
043
044    /**
045     * Java 1.3.
046     */
047    JAVA_1_3(1.3f, "1.3"),
048
049    /**
050     * Java 1.4.
051     */
052    JAVA_1_4(1.4f, "1.4"),
053
054    /**
055     * Java 1.5.
056     */
057    JAVA_1_5(1.5f, "1.5"),
058
059    /**
060     * Java 1.6.
061     */
062    JAVA_1_6(1.6f, "1.6"),
063
064    /**
065     * Java 1.7.
066     */
067    JAVA_1_7(1.7f, "1.7"),
068
069    /**
070     * Java 1.8.
071     */
072    JAVA_1_8(1.8f, "1.8"),
073
074    /**
075     * Java 1.9.
076     */
077    JAVA_1_9(1.9f, "1.9"),
078
079    /**
080     * Java 1.x, x &gt; 9. Mainly introduced to avoid to break when a new version of Java is used.
081     */
082    JAVA_RECENT(maxVersion(), Float.toString(maxVersion()));
083
084    /**
085     * The float value.
086     */
087    private final float value;
088    /**
089     * The standard name.
090     */
091    private final String name;
092
093    /**
094     * Constructor.
095     *
096     * @param value  the float value
097     * @param name  the standard name, not null
098     */
099    JavaVersion(final float value, final String name) {
100        this.value = value;
101        this.name = name;
102    }
103
104    //-----------------------------------------------------------------------
105    /**
106     * <p>Whether this version of Java is at least the version of Java passed in.</p>
107     *
108     * <p>For example:<br>
109     *  {@code myVersion.atLeast(JavaVersion.JAVA_1_4)}<p>
110     *
111     * @param requiredVersion  the version to check against, not null
112     * @return true if this version is equal to or greater than the specified version
113     */
114    public boolean atLeast(final JavaVersion requiredVersion) {
115        return this.value >= requiredVersion.value;
116    }
117
118    /**
119     * Transforms the given string with a Java version number to the
120     * corresponding constant of this enumeration class. This method is used
121     * internally.
122     *
123     * @param nom the Java version as string
124     * @return the corresponding enumeration constant or <b>null</b> if the
125     * version is unknown
126     */
127    // helper for static importing
128    static JavaVersion getJavaVersion(final String nom) {
129        return get(nom);
130    }
131
132    /**
133     * Transforms the given string with a Java version number to the
134     * corresponding constant of this enumeration class. This method is used
135     * internally.
136     *
137     * @param nom the Java version as string
138     * @return the corresponding enumeration constant or <b>null</b> if the
139     * version is unknown
140     */
141    static JavaVersion get(final String nom) {
142        if ("0.9".equals(nom)) {
143            return JAVA_0_9;
144        } else if ("1.1".equals(nom)) {
145            return JAVA_1_1;
146        } else if ("1.2".equals(nom)) {
147            return JAVA_1_2;
148        } else if ("1.3".equals(nom)) {
149            return JAVA_1_3;
150        } else if ("1.4".equals(nom)) {
151            return JAVA_1_4;
152        } else if ("1.5".equals(nom)) {
153            return JAVA_1_5;
154        } else if ("1.6".equals(nom)) {
155            return JAVA_1_6;
156        } else if ("1.7".equals(nom)) {
157            return JAVA_1_7;
158        } else if ("1.8".equals(nom)) {
159            return JAVA_1_8;
160        } else if ("1.9".equals(nom)) {
161            return JAVA_1_9;
162        }
163        if (nom == null) {
164            return null;
165        }
166        final float v = toFloatVersion(nom);
167        if ((v - 1.) < 1.) { // then we need to check decimals > .9
168            final int firstComma = Math.max(nom.indexOf('.'), nom.indexOf(','));
169            final int end = Math.max(nom.length(), nom.indexOf(',', firstComma));
170            if (Float.parseFloat(nom.substring(firstComma + 1, end)) > .9f) {
171                return JAVA_RECENT;
172            }
173        }
174        return null;
175    }
176
177    //-----------------------------------------------------------------------
178    /**
179     * <p>The string value is overridden to return the standard name.</p>
180     *
181     * <p>For example, <code>"1.5"</code>.</p>
182     *
183     * @return the name, not null
184     */
185    @Override
186    public String toString() {
187        return name;
188    }
189
190    /**
191     * Gets the Java Version from the system or 2.0 if the {@code java.version} system property is not set.
192     * 
193     * @return the value of {@code java.version} system property or 2.0 if it is not set.
194     */
195    private static float maxVersion() {
196        final float v = toFloatVersion(System.getProperty("java.version", "2.0"));
197        if (v > 0) {
198            return v;
199        }
200        return 2f;
201    }
202
203    /**
204     * Parses a float value from a String.
205     * 
206     * @param value the String to parse.
207     * @return the float value represented by teh string or -1 if the given String can not be parsed.
208     */
209    private static float toFloatVersion(final String value) {
210        final String[] toParse = value.split("\\.");
211        if (toParse.length >= 2) {
212            try {
213                return Float.parseFloat(toParse[0] + '.' + toParse[1]);
214            } catch (final NumberFormatException nfe) {
215                // no-op, let use default
216            }
217        }
218        return -1;
219    }
220}