| /* |
| * Copyright (c) 2008, 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 com.sun.servicetag; |
| |
| import java.io.*; |
| import java.util.Date; |
| import java.text.SimpleDateFormat; |
| import java.text.ParseException; |
| import java.util.TimeZone; |
| import java.util.UUID; |
| import java.lang.reflect.Field; |
| import java.lang.reflect.Method; |
| |
| // Utility class for com.sun.servicetag package |
| class Util { |
| private static boolean verbose = (System.getProperty("servicetag.verbose") != null); |
| private static String jrepath = null; |
| private static final String REGKEY_TAIL = |
| "microsoft\\windows\\currentversion\\app paths\\stclient.exe"; |
| private static final String STCLIENT_TAIL = "sun\\servicetag\\stclient.exe"; |
| private static final String WIN32_STCLIENT = |
| "c:\\Program Files (x86)\\" + STCLIENT_TAIL; |
| |
| // for debugging and tracing |
| static boolean isVerbose() { |
| return verbose; |
| } |
| |
| /** |
| * Gets the pathname of JRE in the running platform |
| * This can be a JDK or JRE. |
| */ |
| static synchronized String getJrePath() { |
| if (jrepath == null) { |
| // Determine the JRE path by checking the existence of |
| // <HOME>/jre/lib and <HOME>/lib. |
| String javaHome = System.getProperty("java.home"); |
| jrepath = javaHome + File.separator + "jre"; |
| File f = new File(jrepath, "lib"); |
| if (!f.exists()) { |
| // java.home usually points to the JRE path |
| jrepath = javaHome; |
| } |
| } |
| return jrepath; |
| } |
| |
| /** |
| * Tests if the running platform is a JDK. |
| */ |
| static boolean isJdk() { |
| // <HOME>/jre exists which implies it's a JDK |
| return getJrePath().endsWith(File.separator + "jre"); |
| } |
| |
| /** |
| * Generates the URN string of "urn:st" namespace |
| */ |
| static String generateURN() { |
| return "urn:st:" + UUID.randomUUID().toString(); |
| } |
| |
| static int getIntValue(String value) { |
| try { |
| return Integer.parseInt(value); |
| } catch (NumberFormatException e) { |
| throw new IllegalArgumentException("\"" + value + "\"" + |
| " expected to be an integer"); |
| } |
| } |
| |
| /** |
| * Formats the Date into a timestamp string in YYYY-MM-dd HH:mm:ss GMT. |
| * @param timestamp Date |
| * @return a string representation of the timestamp |
| * in the YYYY-MM-dd HH:mm:ss GMT format. |
| */ |
| static String formatTimestamp(Date timestamp) { |
| if (timestamp == null) { |
| return "[No timestamp]"; |
| } |
| SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); |
| df.setTimeZone(TimeZone.getTimeZone("GMT")); |
| return df.format(timestamp); |
| } |
| |
| /** |
| * Parses a timestamp string in YYYY-MM-dd HH:mm:ss GMT format. |
| * @param timestamp Timestamp in the YYYY-MM-dd HH:mm:ss GMT format. |
| * @return Date |
| */ |
| static Date parseTimestamp(String timestamp) { |
| SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); |
| df.setTimeZone(TimeZone.getTimeZone("GMT")); |
| try { |
| return df.parse(timestamp); |
| } catch (ParseException e) { |
| // should not reach here |
| e.printStackTrace(); |
| return new Date(); |
| } |
| } |
| |
| static String commandOutput(Process p) throws IOException { |
| Reader r = null; |
| Reader err = null; |
| try { |
| r = new InputStreamReader(p.getInputStream()); |
| err = new InputStreamReader(p.getErrorStream()); |
| String output = commandOutput(r); |
| String errorMsg = commandOutput(err); |
| p.waitFor(); |
| return output + errorMsg.trim(); |
| } catch (InterruptedException e) { |
| if (isVerbose()) { |
| e.printStackTrace(); |
| } |
| return e.getMessage(); |
| } finally { |
| try { |
| if (r != null) { |
| r.close(); |
| } |
| } finally { |
| if (err != null) { |
| err.close(); |
| } |
| } |
| } |
| } |
| |
| static String commandOutput(Reader r) throws IOException { |
| StringBuilder sb = new StringBuilder(); |
| int c; |
| while ((c = r.read()) > 0) { |
| if (c != '\r') { |
| sb.append((char) c); |
| } |
| } |
| return sb.toString(); |
| } |
| |
| static int getJdkVersion() { |
| parseVersion(); |
| return jdkVersion; |
| } |
| |
| static int getUpdateVersion() { |
| parseVersion(); |
| return jdkUpdate; |
| } |
| |
| private static int jdkVersion = 0; |
| private static int jdkUpdate = 0; |
| private static synchronized void parseVersion() { |
| if (jdkVersion > 0) { |
| return; |
| } |
| |
| // parse java.runtime.version |
| // valid format of the version string is: |
| // n.n.n[_uu[c]][-<identifer>]-bxx |
| String cs = System.getProperty("java.runtime.version"); |
| if (cs.length() >= 5 && |
| Character.isDigit(cs.charAt(0)) && cs.charAt(1) == '.' && |
| Character.isDigit(cs.charAt(2)) && cs.charAt(3) == '.' && |
| Character.isDigit(cs.charAt(4))) { |
| jdkVersion = Character.digit(cs.charAt(2), 10); |
| cs = cs.substring(5, cs.length()); |
| if (cs.charAt(0) == '_' && cs.length() >= 3 && |
| Character.isDigit(cs.charAt(1)) && |
| Character.isDigit(cs.charAt(2))) { |
| int nextChar = 3; |
| try { |
| String uu = cs.substring(1, 3); |
| jdkUpdate = Integer.valueOf(uu).intValue(); |
| } catch (NumberFormatException e) { |
| // not conforming to the naming convention |
| return; |
| } |
| } |
| } else { |
| throw new InternalError("Invalid java.runtime.version" + cs); |
| } |
| } |
| |
| /** |
| * Returns this java string as a null-terminated byte array |
| */ |
| private static byte[] stringToByteArray(String str) { |
| return (str + "\u0000").getBytes(); |
| } |
| |
| /** |
| * Converts a null-terminated byte array to java string |
| */ |
| private static String byteArrayToString(byte[] array) { |
| return new String(array, 0, array.length -1); |
| } |
| |
| /** |
| * Gets the stclient path using a well known location from |
| * the Windows platform Registry, ensuring the path returned |
| * by the registry is really the one we are looking for, |
| * otherwise it will return null. |
| */ |
| private static File getWindowsStClientFile(boolean wow64) { |
| File out = null; |
| String regKey = (wow64 == true) |
| ? "software\\Wow6432Node\\" + REGKEY_TAIL |
| : "software\\" + REGKEY_TAIL; |
| String keyName = "" ; // use the default key |
| String path = getRegistryKey(regKey, keyName); |
| if (path != null |
| && (new File(path)).exists() |
| && path.toLowerCase().endsWith(STCLIENT_TAIL.toLowerCase())) { |
| out = new File(path); |
| } |
| if (isVerbose()) { |
| System.out.println("stclient=" + out); |
| } |
| return out; |
| } |
| |
| /** |
| * Finds a stclient in 32 and 64 bit environments, first by querying |
| * the windows registry, if not then get the well known paths for |
| * 64bit see http://support.microsoft.com/kb/896459 |
| */ |
| |
| static File getWindowsStClientFile() { |
| File stclient = null; |
| if (System.getProperty("os.arch").equals("x86")) { |
| // try to get the default entry |
| stclient = getWindowsStClientFile(false); |
| if (stclient != null) { |
| return stclient; |
| } |
| } else { // we are on 64-bit system |
| // try the wow64 area |
| stclient = getWindowsStClientFile(true); |
| if (stclient != null) { |
| return stclient; |
| } |
| // try the default hard coded path, maybe wow64 registry is missing |
| stclient = new File(WIN32_STCLIENT); |
| if (stclient.canExecute()) { |
| if (isVerbose()) { |
| System.out.println("stclient(default)=" + stclient); |
| } |
| return stclient; |
| } |
| } |
| if (isVerbose()) { |
| System.out.println("stclient not found"); |
| } |
| return null; |
| } |
| |
| /** |
| * This uses reflection to access a private java windows registry |
| * interface, any changes to that Class must be appropriately adjusted. |
| * Returns a null if unsuccessful. |
| */ |
| private static String getRegistryKey(String regKey, String keyName) { |
| String out = null; |
| try { |
| Class<?> clazz = Class.forName("java.util.prefs.WindowsPreferences"); |
| |
| // Get the registry methods |
| Method winRegOpenKeyM = clazz.getDeclaredMethod("WindowsRegOpenKey", |
| int.class, byte[].class, int.class); |
| winRegOpenKeyM.setAccessible(true); |
| |
| Method winRegCloseKeyM = clazz.getDeclaredMethod("WindowsRegCloseKey", |
| int.class); |
| winRegCloseKeyM.setAccessible(true); |
| |
| Method winRegQueryValueM = clazz.getDeclaredMethod("WindowsRegQueryValueEx", |
| int.class, byte[].class); |
| winRegQueryValueM.setAccessible(true); |
| |
| // Get all the constants we need |
| int HKLM = getValueFromStaticField("HKEY_LOCAL_MACHINE", clazz); |
| int KEY_READ = getValueFromStaticField("KEY_READ", clazz); |
| int ERROR_CODE = getValueFromStaticField("ERROR_CODE", clazz); |
| int NATIVE_HANDLE = getValueFromStaticField("NATIVE_HANDLE", clazz); |
| int ERROR_SUCCESS = getValueFromStaticField("ERROR_SUCCESS", clazz); |
| |
| // Convert keys |
| byte[] reg = stringToByteArray(regKey); |
| byte[] key = stringToByteArray(keyName); |
| |
| // Open the registry |
| int[] result = (int[]) winRegOpenKeyM.invoke(null, HKLM, reg, KEY_READ); |
| |
| if (result[ERROR_CODE] == ERROR_SUCCESS) { |
| byte[] stvalue = (byte[]) winRegQueryValueM.invoke(null, |
| result[NATIVE_HANDLE], key); |
| out = byteArrayToString(stvalue); |
| winRegCloseKeyM.invoke(null, result[NATIVE_HANDLE]); |
| } |
| } catch (Exception ex) { |
| if (isVerbose()) { |
| ex.printStackTrace(); |
| } |
| } |
| return out; |
| } |
| |
| private static int getValueFromStaticField(String fldName, Class<?> klass) throws Exception { |
| Field f = klass.getDeclaredField(fldName); |
| f.setAccessible(true); |
| return f.getInt(null); |
| } |
| } |