blob: 0f4abd8996422011ff4c6ccc6542ed2851bc2874 [file]
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal.util;
/**
* A software Version with major, minor, and micro components.
* @param major major version
* @param minor minor version
* @param micro micro version
*/
public record OSVersion(int major, int minor, int micro) implements Comparable<OSVersion> {
// Parse and save the current OS version
private static final OSVersion CURRENT_OSVERSION = initVersion();
/**
* {@return a Version for major, minor versions}
*
* @param major major version
* @param minor minor version
*/
public OSVersion(int major, int minor) {
this(major, minor, 0);
}
/*
* Initialize the current Version from the os.version system property
*/
private static OSVersion initVersion() {
final String osVer = StaticProperty.osVersion();
try {
return parse(osVer);
} catch (IllegalArgumentException iae) {
throw new InternalError("os.version malformed: " + osVer, iae);
}
}
/**
* {@return the current operating system version}
*/
public static OSVersion current() {
return CURRENT_OSVERSION;
}
/**
* {@return Compare this version with another version}
*
* @param other the object to be compared
*/
@Override
public int compareTo(OSVersion other) {
int result = Integer.compare(major, other.major);
if (result == 0) {
result = Integer.compare(minor, other.minor);
if (result == 0) {
return Integer.compare(micro, other.micro);
}
}
return result;
}
@Override
public String toString() {
return (micro == 0)
? major + "." + minor
: major + "." + minor + "." + micro;
}
/**
* {@return A Version parsed from a version string split on "." characters}
* Only major, minor, and micro version numbers are parsed, finer detail is ignored.
* Missing values for minor and micro are replaced with zero.
* The string must start with a number, if there is a '.' it must be followed by a number.
* <p>
* Parsed by hand because it is called before RegEx can be initialized safely.
*
* @param str a version string
* @throws IllegalArgumentException if the string does not start with digits
* or digits do not follow '.'
*/
public static OSVersion parse(String str) throws IllegalArgumentException {
int len = str.length();
int majorStart = 0;
int majorEnd = skipDigits(str, majorStart);
int major = Integer.parseInt(str.substring(majorStart, majorEnd));
int minor = 0, micro = 0;
if (majorEnd < len && str.charAt(majorEnd) == '.') {
int minorStart = majorEnd + 1;
int minorEnd = skipDigits(str, minorStart);
minor = Integer.parseInt(str.substring(minorStart, minorEnd));
if (minorEnd < len && str.charAt(minorEnd) == '.') {
int microStart = minorEnd + 1;
int microEnd = skipDigits(str, microStart);
micro = Integer.parseInt(str.substring(microStart, microEnd));
}
}
return new OSVersion(major, minor, micro);
}
/**
* {@return The index of the first non-digit from start}
* @throws IllegalArgumentException if there are no digits
*/
private static int skipDigits(String s, int start) {
int index = start;
while (index < s.length() && Character.isDigit(s.charAt(index))) {
index++;
}
if (index == start)
throw new IllegalArgumentException("malformed version, missing digits: " + s);
return index;
}
}