Check if Windows XP or later in Java? - java

What would be the easiest way to check that the operating system running my Java application is Windows XP or later?
EDIT: I know about System.getProperty("os.name") but I don't know the best way and/or most efficient way to check what version of Windows is running. Ideally, I would also like to make it future proof so that if another version of Windows is released I don't need to change the code.

mkyong has given a tutorial: http://www.mkyong.com/java/how-to-detect-os-in-java-systemgetpropertyosname/
It relies on System.getProperty("os.name")

Since Windows reliably reports its version information as a float, "XP or higher" can be calculated by knowing what each Windows version is and comparing.
The shorthand:
// Is this XP or higher?
// Well, XP Reports as 5.1 (32-bit) or 5.2 (64-bit). All higher OSs use a higher version
final boolean XP_OR_HIGHER = (Float.parseFloat(System.getProperty("os.version")) >= 5.1f);
But due to exceptions that can be raised with parsing a System value, combined with the fact that XP is EOL and it's more likely that someone is looking for a newer OS comparison... here's a more comprehensive way to do it.
Note: With Windows 10, all versions are reported as 10.0 regardless of how much Microsoft changed between releases. For finer detail, you will have to look into the registry (See also HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ReleaseId).
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class WinVer {
enum WindowsType {
/*
* Keep descending for best match, or rewrite using comparitor
*/
WINDOWS_10(10.0f),
WINDOWS_8_1(6.3f),
WINDOWS_8(6.2f),
WINDOWS_7(6.1f),
WINDOWS_VISTA(6.0f),
WINDOWS_XP_64(5.2f),
WINDOWS_XP(5.1f),
WINDOWS_ME(4.9f),
WINDOWS_2000(5.0f),
WINDOWS_NT(4.0f), // or Win95
UNKNOWN(0.0f);
private float version;
WindowsType(float version) {
this.version = version;
}
public static float parseFloat(String versionString) {
float version = 0.0f;
/*
* Sanitize the String.
*
* Windows version is generally formatted x.x (e.g. 3.1, 6.1, 10.0)
* This format can later be treated as a float for comparison.
* Since we have no guarantee the String will be formatted properly, we'll sanitize it.
* For more complex comparisons, try a SemVer library, such as zafarkhaja/jsemver. <3
*/
List<String> parts = Arrays.asList(versionString.replaceAll("[^\\d.]", "").split("\\."));
// Fix .add(...), .remove(...), see https://stackoverflow.com/a/5755510/3196753
parts = new ArrayList<>(parts);
// Fix length
while (parts.size() != 2) {
if (parts.size() > 2) {
// pop off last element
parts.remove(parts.size() - 1);
}
if (parts.size() < 2) {
// push zero
parts.add("0");
}
}
String sanitized = String.join(".", parts.toArray(new String[0]));
try {
version = Float.parseFloat(sanitized);
} catch (NumberFormatException e) {
System.err.println("ERROR: Something went wrong parsing " + sanitized + " as a float");
}
return version;
}
public static WindowsType match(float version) {
WindowsType detectedType = UNKNOWN;
// Warning: Iterates in order they were declared. If you don't like this, write a proper comparator instead. <3
for (WindowsType type : WindowsType.values()) {
if (type.version >= version) {
detectedType = type;
} else {
break;
}
}
return detectedType;
}
}
public static void main(String... args) {
String osName = System.getProperty("os.name");
String osVer = System.getProperty("os.version");
if (osName.toLowerCase().startsWith("windows")) {
System.out.println("Yes, you appear to be running windows");
float windowsVersion = WindowsType.parseFloat(osVer);
System.out.println(" - Windows version reported is: " + windowsVersion);
WindowsType windowsType = WindowsType.match(windowsVersion);
System.out.println(" - Windows type is detected as: " + windowsType);
if(windowsVersion >= WindowsType.WINDOWS_XP.version) {
System.out.println("Yes, this OS is Windows XP or higher.");
} else {
System.out.println("No, this OS is NOT Windows XP or higher.");
}
}
}
}

Related

Using navigator.plugins to determine Java version

The following javascript code will inform all your browser's enabled plugins (yeah, I know it doesn't work on IE, but for IE there's always deployJava):
if ((navigator.plugins) && (navigator.plugins.length)) {
for (var bb = 0, l = navigator.plugins.length; bb < l; bb++) {
var vv = navigator.plugins[bb].name + "<br>";
document.write(vv);
}
}
I have Java 6.22 installed so the relevant line written to the page is this:
Java(TM) Platform SE 6 U22
My question is: how can I complement the above code so that it returns the major version (6) and update (22) found in my (or anyone's) browser?
I think the best way is to work with regular expression, but I am not good with it.
I think the easiest (read: hackiest) solution would be something like this:
var plugin_name = navigator.plugins[bb].name
if (plugin_name.toLowerCase().indexOf("java") != -1) {
var parts = plugin_name.split(" ").reverse();
// if the plugin has an update
if(plugin_name.match(/U[0-9]+/)) {
// grab the end of the plugin name and remove non numeric chars
var update = parts[0].replace(/[^0-9]/, "");
// grab the major version and remove non numeric chars
var major = parts[1].replace(/[^0-9]/, "");
// print the major number and update number
console.log(major);
console.log(update);
} else {
var update = "0";
// grab the major version and remove non numeric chars
var major = parts[0].replace(/[^0-9]/, "");
// print the major number and update number
console.log(major);
console.log(update);
}
}
You can then throw this code in your loop through the plugins and replace the console.log with whatever logic is appropriate given a major and update number.

com.python.util.PythonInterpreter: cannot set a python variable to a String

I have an odd problem. So I am writing a program that uses Python for a simple user scripting interface. But to keep my question simple...I am trying to use PythonInterpreter.set to set a variable in the Python interpreter to a String value. But when I set it I get this exception:
LookupError: no codec search functions registered: can't find encoding
The following is my code:
package demo;
import org.python.util.PythonInterpreter;
public class Application {
public static void main(String[] args) {
PythonInterpreter pi = new PythonInterpreter();
String greeting = "Jesus Christ";
Integer times = 6;
pi.exec("actor = 'Lucy'");
pi.set("greeting", greeting);
pi.set("times", times);
pi.exec("print '%s %s' % (greeting, actor)");
pi.exec("print \"%s %s \\n\" % (greeting, actor) * times");
System.out.println("RESULT: " + pi.eval("actor == 'Lucy'"));
System.out.println("ACTOR: " + pi.get("actor"));
}
}
If you need to see the pom file for my project, I can include it, but really I just have the Jython 2.5.0 library installed. I am wondering if I needed to install something else on my system other than having maven install this library for me. I do have Python installed on this computer, and PYTHON_HOME setup in the environment variables. What am I doing wrong?
EDIT: The line:
pi.set("times", times);
...works just fine.
But...
pi.set("greeting", greeting);
does not. I imagine it has something to with times being a primitive data type and greeting being a String.

In Java how to parse a string to a float and compare the value?

I have a small code snippet as shown below, which as you can see has a hard-coded value for checking server version.
Now my intention is, if the server version is 11.3.0 or higher, then the if should be entered, but i am not able to figure out a way, Integer.parseInt won't work i guess as i parses int not float.
String serverVersion = DatamodelVersion.getInstance().getVersion();
if(serverVersion.equalsIgnoreCase("11.3.0"))
{
outstr = new FileOutputStream(confFile);
prop.setProperty("NTFSDriver", "11.3.0/x86/tntfs.ko");
prop.setProperty("NTFSDriver_x64", "11.3.0/x86_64/tntfs.ko");
prop.store(outstr, "");
update = true;
System.out.println("Updated the tuxera conf file successfully");
logger.logDebugAlways("Updated the tuxera conf file successfully");
}
Try this
String serverVersion = DatamodelVersion.getInstance().getVersion();
String[] version = serverVersion.split("\\.");
if (Integer.parseInt(version[0]) > 11 || (Integer.parseInt(version[0]) == 11 && Integer.parseInt(version[1]) >= 3))
{
outstr = new FileOutputStream(confFile);
prop.setProperty("NTFSDriver", "11.3.0/x86/tntfs.ko");
prop.setProperty("NTFSDriver_x64", "11.3.0/x86_64/tntfs.ko");
prop.store(outstr, "");
update = true;
System.out.println("Updated the tuxera conf file successfully");
logger.logDebugAlways("Updated the tuxera conf file successfully");
}
there is not a built-in function in Java to transform 11.3.0 to float, because 11.3.0 is not a valid float number.
for strings containing a valid float number, you could use Float.valueOf in Java.
Split the version number by "."
Then compare one by one with your reference data.
String serverVersion = DatamodelVersion.getInstance().getVersion();
serverVersion.split('.')[0] // and so on..
A version number is neither an integer, nor a float. Your best bet is using a specialized class:
public class Version implements Comparable<Version> {
public Version(int major, int minor, int revision) {
// set fields
}
public int compareTo(Version other) {
// compare major minor and revision
}
public boolean equals(Object other) {
// code here
}
// parse a version in X.Y.Z form
static Version parse(String version) {
return new Version(//...);
}
}
Using this you may decide to later add support for versions like 1.3.4-ALPHA or -RC1 and the like.
You could try splitting the number into 3 parts, like so:
String[] bits = serverVersion.split(".");
Then, use a for loop and Integer.parseInt to parse each section of the number, and compare each.
You need to define your own method for checking version numbers, based on the rules these numbers must follow in your domain.
Based on the information you've provided, I would do a String split on . and compare each value in turn (as an integer) against 11, 3 and 0 respectively.
You have a Version class here : http://nvn.svn.sourceforge.net
It should be used like this
Version v = Version.parse(DatamodelVersion.getInstance().getVersion());
and store numbers in the standard format MAJOR.MINOR.BUILD.REVISION
11.3.0 is not a float number. What about to use following code instead:
int Compare(String ver1, String ver2)
{
String[] ver1s = ver1.Split("\.");
String[] ver2s = ver2.Split("\.");
if(ver1s.length > ver2.length) return 1;
if(ver2s.length > ver1.length) return -1;
for(int i = 0;i < ver1s.length;i++)
{
if(Integer.valueOf(ver1s[i]) > Integer.valueOf(ver2s[i])) return 1;
if(Integer.valueOf(ver2s[i]) > Integer.valueOf(ver1s[i])) return -1;
}
return 0;
}

Find Bugs - Not finding bugs

I have recently set up find bugs in eclipse to see what reports it generates. Ive set all the settings to be as sensitive as possible. If i create a small application that writes to a file and do not close the stream it picks it up which is all good.
However, using a project that has been written where we no there are a couple of bugs, especially in the output, we get no errors at all (in terms of find bugs)
I was wondering if anyone could run this through their version and report whether I may have find bugs set up incorrectly or whether in fact it could find no bugs?
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class SpellUtil {
private final static String teenSpelling[] = {"Zero", "One", "Two", "Three",
"Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven",
"Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen",
"Seventeen", "Eighteen", "Nineteen"};
private final static String centSpelling[] = {"Twenty", "Thirty", "Forty",
"Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
private final static String suffixSpelling[] = {
"", // Dummy! no level 0 (added for nicer indexing in code)
"", // Nothing for level 1
" Thousand, ", " Million, ", " Billion, ", " Trillion, ", " Quadrillion, ",
" Quintillion, "};
public static String spell(int number) {
int rem, placeIndicator = 1;
boolean isNegative = false;
List<String> spelling = new ArrayList<String>();
if (number < 0) {
isNegative = true;
number = Math.abs(number);
}
while (number > 0) {
rem = number % 1000;
number = number / 1000;
spelling.add(suffixSpelling[placeIndicator]);
try {
spelling.add(spellBelow1000(rem));
} catch (SpellingException e) {
System.out.println(e.getMessage());
}
placeIndicator++;
}
StringBuilder sb = new StringBuilder();
if (isNegative) sb.append("Minus ");
for (int i = spelling.size() - 1; i >= 0; i--) {
sb.append(spelling.get(i));
}
return sb.toString();
}
private static String spellBelow1000(int number) throws SpellingException {
if (number < 0 || number >= 1000)
throw new SpellingException("Expecting a number between 0 and 999: " + number);
if (number < 20) {
// if number is a teen,
// find it in teen table and return its equivalent text (word).
return teenSpelling[number];
} else if (number < 100) {
// otherwise, if it is a cent,
// find the most (div) and least (rem) significant digits (MSD/LSD)
int div = (int) number / 10;
int rem = (int) number % 10;
if (rem == 0) {
// if LSD is zero, return the cent key word directly (like
// fifty).
return centSpelling[div-2];
} else {
// otherwise, return the text as cent-teen (like fifty-one)
return centSpelling[div-2] + "-" + teenSpelling[rem];
}
} else {
// otherwise, it is a mil;
// find it's MSD and remaining cent.
int div = number / 100;
int rem = (int) number % 100; // TODO will findbugs detect unnecessary (int)?
// Prepare the mil prefix:
String milText = teenSpelling[div] + " Hundred";
// decide whether to append the cent tail or not.
if (rem == 0) {
// if it does have a non-zero cent, that's it.
// return the mil prefix, for example three hundred:
return milText;
} else {
// otherwise, spell the cent and append it to mil prefix.
// (now, rem is a cent).
// For example, three Hundred and Sixty-Four:
return milText + " and " + spellBelow1000(rem);
}
}
}
}
Your expectation to find a bug in this line:
int rem = (int) number % 100; // TODO will findbugs detect unnecessary (int)?
is WRONG because the result of a % operation is not an integer in general.
In C and C++, the remainder operator accepts only integral operands, but in Java, it also accepts floating-point operands. This means statements such as double x = 8.2 % 4; are quite valid in Java and the result could be a non-integer value. (0.1999999999999993 in this case)
Please see the Java language specification here.
You seem to have a problem with findbugs configuration. I suggest using Findbugs via Sonar. It is much more easy to configure and you get checkstyle, pmd and a system for managing and resolving violations.
Sonar findbugs page
I think that the problem is that you misunderstanding what FindBugs does and what its capabilities are.
Basically, FindBugs parses each class to produce a parse-tree - an in-memory representation of the structure of the program. Then attempts to find places in the tree that match known patterns which represent incorrect or questionable programming. For example:
if (someString == "42") {
....
}
FindBugs will most likely tell you comparing strings using the '==' operator here is wrong. What it has done is look through the class for any expression node where the operator is '==' and one or both of the operands is a String. It will repeat this procedure for a large number of patterns that it has been programmed to detect and report. Some will be more complicated than this one, but basically, FindBug is only doing a form of structural pattern matching.
What FindBugs does not and cannot do is to understand what your program is actually supposed to do. So for example:
public boolean isOdd(int arg) {
return (arg % 2) == 0;
}
This is obviously incorrect to anyone who understands simple mathematics ... but FindBugs won't notice it. That is because FindBugs has no idea what the method is actually supposed to do. Furthermore, it is not capable of doing the elementary semantic analysis that is required to figure out that the code doesn't implement the math.
The reason I am doing this is because I need to do a presentation of find bugs and I need an application to generate some bugs to show how it works.
Maybe you need to cheat a bit:
Read the Findbugs documentation to understand the things that it is capable of finding.
Write some "toy" applications with bugs that you know Findbugs can find for you.
It is also worthwhile including examples that you know it won't find ... so that you can explain the limitations of Findbugs.
What findbugs does is to look for some common mistakes that could (and most probably would) lead to unexpected/unwanted behavior. Most of those errors are technical or wrong use of java and its API. A list of all findbugs checks can be found here In other words if you did something you don't wanted in a right way, findbugs would not detect it. In your code I can't see anything that would be detected by findbugs. The unnecessary cast you mentioned in your comments is not a findbugs rule because it doesn't change the behavior of your code. It is more of a style or efficiency error and would be detected by tools like checkstyle or PMD.

Getting Java version at runtime

I need to work around a Java bug in JDK 1.5 which was fixed in 1.6. I'm using the following condition:
if (System.getProperty("java.version").startsWith("1.5.")) {
...
} else {
...
}
Will this work for other JVMs? Is there a better way to check this?
java.version is a system property that exists in every JVM. There are two possible formats for it:
Java 8 or lower: 1.6.0_23, 1.7.0, 1.7.0_80, 1.8.0_211
Java 9 or higher: 9.0.1, 11.0.4, 12, 12.0.1
Here is a trick to extract the major version: If it is a 1.x.y_z version string, extract the character at index 2 of the string. If it is a x.y.z version string, cut the string to its first dot character, if one exists.
private static int getVersion() {
String version = System.getProperty("java.version");
if(version.startsWith("1.")) {
version = version.substring(2, 3);
} else {
int dot = version.indexOf(".");
if(dot != -1) { version = version.substring(0, dot); }
} return Integer.parseInt(version);
}
Now you can check the version much more comfortably:
if(getVersion() < 6) {
// ...
}
What about getting the version from the package meta infos:
String version = Runtime.class.getPackage().getImplementationVersion();
Prints out something like:
1.7.0_13
Runtime.version()
Since Java 9, you can use Runtime.version(), which returns a Runtime.Version:
Runtime.Version version = Runtime.version();
These articles seem to suggest that checking for 1.5 or 1.6 prefix should work, as it follows proper version naming convention.
Sun Technical Articles
J2SE SDK/JRE Version String Naming Convention
Version 1.5.0 or 5.0?
"J2SE also keeps the version number 1.5.0 (or 1.5) in some places that are visible only to developers, or where the version number is parsed by programs"
"java.version system property"
Version 1.6.0 Used by Developers
"Java SE keeps the version number 1.6.0 (or 1.6) in some places that are visible only to developers, or where the version number is parsed by programs."
"java.version system property"
The simplest way (java.specification.version):
double version = Double.parseDouble(System.getProperty("java.specification.version"));
if (version == 1.5) {
// 1.5 specific code
} else {
// ...
}
or something like (java.version):
String[] javaVersionElements = System.getProperty("java.version").split("\\.");
int major = Integer.parseInt(javaVersionElements[1]);
if (major == 5) {
// 1.5 specific code
} else {
// ...
}
or if you want to break it all up (java.runtime.version):
String discard, major, minor, update, build;
String[] javaVersionElements = System.getProperty("java.runtime.version").split("\\.|_|-b");
discard = javaVersionElements[0];
major = javaVersionElements[1];
minor = javaVersionElements[2];
update = javaVersionElements[3];
build = javaVersionElements[4];
Example for Apache Commons Lang:
import org.apache.commons.lang.SystemUtils;
Float version = SystemUtils.JAVA_VERSION_FLOAT;
if (version < 1.4f) {
// legacy
} else if (SystemUtils.IS_JAVA_1_5) {
// 1.5 specific code
} else if (SystemUtils.isJavaVersionAtLeast(1.6f)) {
// 1.6 compatible code
} else {
// dodgy clause to catch 1.4 :)
}
Just a note that in Java 9 and above, the naming convention is different. System.getProperty("java.version") returns "9" rather than "1.9".
Does not work, need --pos to evaluate double:
String version = System.getProperty("java.version");
System.out.println("version:" + version);
int pos = 0, count = 0;
for (; pos < version.length() && count < 2; pos++) {
if (version.charAt(pos) == '.') {
count++;
}
}
--pos; //EVALUATE double
double dversion = Double.parseDouble(version.substring(0, pos));
System.out.println("dversion:" + dversion);
return dversion;
}
Here's the implementation in JOSM:
/**
* Returns the Java version as an int value.
* #return the Java version as an int value (8, 9, etc.)
* #since 12130
*/
public static int getJavaVersion() {
String version = System.getProperty("java.version");
if (version.startsWith("1.")) {
version = version.substring(2);
}
// Allow these formats:
// 1.8.0_72-ea
// 9-ea
// 9
// 9.0.1
int dotPos = version.indexOf('.');
int dashPos = version.indexOf('-');
return Integer.parseInt(version.substring(0,
dotPos > -1 ? dotPos : dashPos > -1 ? dashPos : 1));
}
If you can have dependency to apache utils you can use org.apache.commons.lang3.SystemUtils.
System.out.println("Is Java version at least 1.8: " + SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8));
Don't know another way of checking this, but this: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/System.html#getProperties()" implies "java.version" is a standard system property so I'd expect it to work with other JVMs.
Here is the answer from #mvanle, converted to Scala:
scala> val Array(javaVerPrefix, javaVerMajor, javaVerMinor, _, _) = System.getProperty("java.runtime.version").split("\\.|_|-b")
javaVerPrefix: String = 1
javaVerMajor: String = 8
javaVerMinor: String = 0
https://docs.oracle.com/javase/9/docs/api/java/lang/Runtime.Version.html#version--
Runtime.version().version()
For 17.0.1 it returns [17, 0, 1]
One can use Runtime.version().version().get(0) to get the major java version.
In kotlin:
/**
* Returns the major JVM version, e.g. 6 for Java 1.6, 8 for Java 8, 11 for Java 11 etc.
*/
public val jvmVersion: Int get() = System.getProperty("java.version").parseJvmVersion()
/**
* Returns the major JVM version, 1 for 1.1, 2 for 1.2, 3 for 1.3, 4 for 1.4, 5
* for 1.5 etc.
*/
fun String.parseJvmVersion(): Int {
val version: String = removePrefix("1.").takeWhile { it.isDigit() }
return version.toInt()
}

Categories

Resources