/* * sulky-modules - several general-purpose modules. * Copyright (C) 2007-2015 Joern Huxhorn * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* * Copyright 2007-2015 Joern Huxhorn * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.huxhorn.sulky.version; import java.util.Comparator; /** * This class handles parsing and comparison of * <a href="http://www.oracle.com/technetwork/java/javase/versioning-naming-139433.html">Java version numbers</a>. * * The static JVM attribute contains the version retrieved from the "java.version" system property. * If parsing that property fails (because security prevents access or the content is invalid) then * "java.specification.version" is used as a fallback. If parsing that property also fails (for similar reasons) * then the JVM attribute is initialized with MIN_VALUE, i.e. new JavaVersion(0,0,0,0,"!"). * * This class does already handle the proposed version string suggested in http://openjdk.java.net/jeps/223 * * The heuristic currently used is the following: * If the version string starts with "1." it is parsed as an YeOldeJavaVersion, otherwise Jep223JavaVersion is used. * * The COMPARATOR */ @SuppressWarnings({"TryWithIdenticalCatches", "Convert2Lambda"}) // this is compiled with source and target 1.5 public abstract class JavaVersion { /* e.g. 1.8.0_25 */ private static final String JAVA_VERSION_PROPERTY_NAME = "java.version"; /* e.g. 1.8 */ private static final String JAVA_SPECIFICATION_VERSION_PROPERTY_NAME = "java.specification.version"; /** * The best possible approximation to the JVM JavaVersion. * * @return the JVM JavaVersion. */ public static JavaVersion getSystemJavaVersion() { JavaVersion version=null; try { String versionString = System.getProperty(JAVA_VERSION_PROPERTY_NAME); if(versionString != null) { version = parse(versionString); } } catch(SecurityException ex) { // ignore } catch(IllegalArgumentException ex) { // didn't parse. Probably some strangeness like 1.8.0_25.1 } if(version == null) { // either SecurityException or missing/broken standard property // fall back to specification version try { String versionString = System.getProperty(JAVA_SPECIFICATION_VERSION_PROPERTY_NAME); if(versionString != null) { version = parse(versionString); } } catch(SecurityException ex) { // ignore } catch(IllegalArgumentException ex) { // didn't parse. } } if(version != null) { return version; } return YeOldeJavaVersion.MIN_VALUE; } /** * Parses a Java version and returns the corresponding JavaVersion instance. * * @param versionString the String to be parsed * @return the JavaVersion corresponding to the given versionString * @throws java.lang.NullPointerException if versionString is null. * @throws java.lang.IllegalArgumentException if versionString is invalid. */ public static JavaVersion parse(String versionString) { if(versionString == null) { throw new NullPointerException("versionString must not be null!"); } if(versionString.startsWith("1.")) { return YeOldeJavaVersion.parse(versionString); } return Jep223JavaVersion.parse(versionString); } /** * Returns true, if the JVM version is bigger or equals to the given versionString. * * This is a convenience method that is simply a shortcut for * (getSystemJavaVersion().compareTo(parse(versionString)) >= 0). * * @param versionString the version to compare with the JVM version. * @return true, if the JVM version is bigger or equals to the given versionString. * @throws java.lang.NullPointerException if versionString is null. * @throws java.lang.IllegalArgumentException if versionString is invalid. */ public static boolean isAtLeast(String versionString) { return isAtLeast(versionString, false); } /** * Returns true, if the JVM version is bigger or equals to the given versionString. * * This is a convenience method that is simply a shortcut for * (getSystemJavaVersion().compareTo(parse(versionString)) >= 0). * * @param versionString the version to compare with the JVM version. * @param ignoringPreReleaseIdentifier whether or not a potential pre-release identifier should be ignored. * @return true, if the JVM version is bigger or equals to the given versionString. * @throws java.lang.NullPointerException if versionString is null. * @throws java.lang.IllegalArgumentException if versionString is invalid. */ public static boolean isAtLeast(String versionString, boolean ignoringPreReleaseIdentifier) { return isAtLeast(parse(versionString), ignoringPreReleaseIdentifier); } /** * Returns true, if the JVM version is bigger or equals to the given versionString. * * This is a convenience method that is simply a shortcut for * (getSystemJavaVersion().compareTo(version) >= 0). * * @param version the version to compare with the JVM version. * @return true, if the JVM version is bigger or equals to the given versionString. * @throws java.lang.NullPointerException if version is null. */ public static boolean isAtLeast(JavaVersion version) { return isAtLeast(version, false); } /** * Returns true, if the JVM version is bigger or equals to the given versionString. * * This is a convenience method that is simply a shortcut for * (getSystemJavaVersion().compareTo(version) >= 0). * * @param version the version to compare with the JVM version. * @param ignoringPreReleaseIdentifier whether or not a potential pre-release identifier should be ignored. * @return true, if the JVM version is bigger or equals to the given versionString. * @throws java.lang.NullPointerException if version is null. */ public static boolean isAtLeast(JavaVersion version, boolean ignoringPreReleaseIdentifier) { if(version == null) { throw new NullPointerException("version must not be null!"); } JavaVersion systemJavaVersion = getSystemJavaVersion(); if(ignoringPreReleaseIdentifier) { systemJavaVersion = systemJavaVersion.withoutPreReleaseIdentifier(); version = version.withoutPreReleaseIdentifier(); } return COMPARATOR.compare(systemJavaVersion, version) >= 0; } /** * Returns the "major" part of this version. * * @return the "major" part of this version. */ public abstract int getMajor(); /** * Returns the "minor" part of this version. * * @return the "minor" part of this version. */ public abstract int getMinor(); /** * Returns the "patch" (or update) part of this version. * * @return the "patch" (or update) part of this version. */ public abstract int getPatch(); /** * Returns the "identifier" part of this version. * * @return the "identifier" part of this version. */ public abstract String getPreReleaseIdentifier(); /** * Returns the full version string of this version. * * @return the full version string of this version. */ public abstract String toVersionString(); /** * Returns the short version string of this version. * * @return the short version string of this version. */ public abstract String toShortVersionString(); /** * Returns this JavaVersion without pre-release identifier. * * @return this JavaVersion without pre-release identifier. */ public abstract JavaVersion withoutPreReleaseIdentifier(); public static final Comparator<JavaVersion> COMPARATOR = new Comparator<JavaVersion>() { @Override public int compare(JavaVersion o1, JavaVersion o2) { if(o1 == null && o2 == null) { return 0; } if(o1 == null) { return -1; } if(o2 == null) { return 1; } if(o1 instanceof YeOldeJavaVersion) { if(o2 instanceof YeOldeJavaVersion) { return ((YeOldeJavaVersion)o1).compareTo((YeOldeJavaVersion) o2); } if(o2 instanceof Jep223JavaVersion) { return -1; } throw new ClassCastException("Unexpected JavaVersion of class "+o2.getClass().getName()+"!"); } if(o1 instanceof Jep223JavaVersion) { if(o2 instanceof Jep223JavaVersion) { return ((Jep223JavaVersion)o1).compareTo((Jep223JavaVersion) o2); } if(o2 instanceof YeOldeJavaVersion) { return 1; } throw new ClassCastException("Unexpected JavaVersion of class "+o2.getClass().getName()+"!"); } throw new ClassCastException("Unexpected JavaVersion of class "+o1.getClass().getName()+"!"); } }; }