/*
JWildfire - an image and animation processor written in Java
Copyright (C) 1995-2012 Andreas Maschke
This 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 2.1 of the
License, or (at your option) any later version.
This software 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 software;
if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jwildfire.launcher;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.prefs.Preferences;
public class JDKScanner {
private final List<String> jdks = new ArrayList<String>();
private int currentVersionIdx = -1;
public void scan() {
jdks.clear();
currentVersionIdx = -1;
String osname = System.getProperty("os.name");
if (osname.startsWith("Windows")) {
try {
{
List<String> keys = readStringSubKeys(HKEY_LOCAL_MACHINE, "SOFTWARE\\Javasoft\\Java Runtime Environment");
String dfltVersion = readRegistryString("SOFTWARE\\Javasoft\\Java Runtime Environment", "CurrentVersion");
for (String key : keys) {
if (key != null && key.length() > 0) {
String jdk = readRegistryString("SOFTWARE\\Javasoft\\Java Runtime Environment\\" + key, "JavaHome");
addSafeJDK(jdk);
if (currentVersionIdx < 0 && dfltVersion != null && key.equals(dfltVersion)) {
currentVersionIdx = getSafeJDKIndex(jdk);
}
}
}
}
}
catch (Throwable ex) {
}
if (jdks.size() == 0) {
try {
List<String> keys = readStringSubKeys(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wow6432Node\\Javasoft\\Java Runtime Environment");
String dfltVersion = readRegistryString("SOFTWARE\\Wow6432Node\\Javasoft\\Java Runtime Environment", "CurrentVersion");
for (String key : keys) {
if (key != null && key.length() > 0) {
String jdk = readRegistryString("SOFTWARE\\Wow6432Node\\Javasoft\\Java Runtime Environment\\" + key, "JavaHome");
addSafeJDK(jdk);
if (currentVersionIdx < 0 && dfltVersion != null && key.equals(dfltVersion)) {
currentVersionIdx = getSafeJDKIndex(jdk);
}
}
}
}
catch (Throwable ex) {
}
}
}
if (jdks.size() == 0) {
addSafeJDK(System.getProperty("java.home"));
}
}
public int getSafeJDKIndex(String pJDK) {
if (pJDK != null) {
pJDK = pJDK.trim();
return jdks.indexOf(pJDK);
}
return -1;
}
public void addSafeJDK(String pJDK) {
if (pJDK != null) {
pJDK = pJDK.trim();
if (pJDK.length() > 0 && jdks.indexOf(pJDK) < 0) {
jdks.add(pJDK);
}
}
}
// Access the windows registry, inspired by http://www.rgagnon.com/javadetails/java-0630.html
private static final int HKEY_LOCAL_MACHINE = 0x80000002;
private static final int KEY_READ = 0x20019;
private static Preferences systemRoot = Preferences.systemRoot();
private static Class<? extends Preferences> userClass = systemRoot.getClass();
private static Method regOpenKey = null;
private static Method regCloseKey = null;
private static Method regQueryValueEx = null;
private static Method regQueryInfoKey = null;
private static Method regEnumKeyEx = null;
private String readRegistryString(String key, String value) throws Exception {
int[] handles = (int[]) regOpenKey.invoke(systemRoot, new Object[] {
new Integer(HKEY_LOCAL_MACHINE), toCstr(key), new Integer(KEY_READ) });
if (handles[1] != 0) {
return null;
}
byte[] res = (byte[]) regQueryValueEx.invoke(systemRoot, new Object[] {
Integer.valueOf(handles[0]), toCstr(value) });
regCloseKey.invoke(systemRoot, new Object[] { Integer.valueOf(handles[0]) });
return res != null ? new String(res).trim() : null;
}
private List<String> readStringSubKeys(int hkey, String key) throws Exception {
List<String> results = new ArrayList<String>();
int[] handles = (int[]) regOpenKey.invoke(systemRoot, new Object[] {
Integer.valueOf(hkey), toCstr(key), new Integer(KEY_READ)
});
if (handles[1] != 0) {
return null;
}
int[] info = (int[]) regQueryInfoKey.invoke(systemRoot, new Object[] { Integer.valueOf(handles[0]) });
int count = info[0]; // count
int maxlen = info[3]; // value length max
for (int index = 0; index < count; index++) {
byte[] name = (byte[]) regEnumKeyEx.invoke(systemRoot, new Object[] {
Integer.valueOf(handles[0]), Integer.valueOf(index), Integer.valueOf(maxlen + 1)
});
results.add(new String(name).trim());
}
regCloseKey.invoke(systemRoot, new Object[] { Integer.valueOf(handles[0]) });
return results;
}
static {
String osname = System.getProperty("os.name");
if (osname.startsWith("Windows")) {
try {
regOpenKey = userClass.getDeclaredMethod("WindowsRegOpenKey", new Class[] { int.class, byte[].class, int.class });
regOpenKey.setAccessible(true);
regCloseKey = userClass.getDeclaredMethod("WindowsRegCloseKey", new Class[] { int.class });
regCloseKey.setAccessible(true);
regQueryValueEx = userClass.getDeclaredMethod("WindowsRegQueryValueEx", new Class[] { int.class, byte[].class });
regQueryValueEx.setAccessible(true);
regQueryInfoKey = userClass.getDeclaredMethod("WindowsRegQueryInfoKey1", new Class[] { int.class });
regQueryInfoKey.setAccessible(true);
regEnumKeyEx = userClass.getDeclaredMethod("WindowsRegEnumKeyEx", new Class[] { int.class, int.class, int.class });
regEnumKeyEx.setAccessible(true);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
private byte[] toCstr(String str) {
byte[] result = new byte[str.length() + 1];
for (int i = 0; i < str.length(); i++) {
result[i] = (byte) str.charAt(i);
}
result[str.length()] = 0;
return result;
}
public String getDefaultJDK() {
if (currentVersionIdx >= 0 && currentVersionIdx < jdks.size()) {
return jdks.get(currentVersionIdx);
}
return jdks.size() > 0 ? jdks.get(0) : null;
}
public List<String> getJDKs() {
return jdks;
}
}