jdk/src/share/classes/com/sun/servicetag/Util.java
changeset 16802 ea3325542aa8
parent 16801 e2de240b437f
parent 16575 d7ad0dfaa411
child 16803 3bdc22a32b0e
equal deleted inserted replaced
16801:e2de240b437f 16802:ea3325542aa8
     1 /*
       
     2  * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package com.sun.servicetag;
       
    27 
       
    28 import java.io.*;
       
    29 import java.util.Date;
       
    30 import java.text.SimpleDateFormat;
       
    31 import java.text.ParseException;
       
    32 import java.util.TimeZone;
       
    33 import java.util.UUID;
       
    34 import java.lang.reflect.Field;
       
    35 import java.lang.reflect.Method;
       
    36 
       
    37 // Utility class for com.sun.servicetag package
       
    38 class Util {
       
    39     private static boolean verbose = (System.getProperty("servicetag.verbose") != null);
       
    40     private static String jrepath = null;
       
    41     private static final String REGKEY_TAIL =
       
    42         "microsoft\\windows\\currentversion\\app paths\\stclient.exe";
       
    43     private static final String STCLIENT_TAIL =  "sun\\servicetag\\stclient.exe";
       
    44     private static final String WIN32_STCLIENT =
       
    45         "c:\\Program Files (x86)\\" + STCLIENT_TAIL;
       
    46 
       
    47     // for debugging and tracing
       
    48     static boolean isVerbose() {
       
    49         return verbose;
       
    50     }
       
    51 
       
    52     /**
       
    53      * Gets the pathname of JRE in the running platform
       
    54      * This can be a JDK or JRE.
       
    55      */
       
    56     static synchronized String getJrePath() {
       
    57         if (jrepath == null) {
       
    58             // Determine the JRE path by checking the existence of
       
    59             // <HOME>/jre/lib and <HOME>/lib.
       
    60             String javaHome = System.getProperty("java.home");
       
    61             jrepath = javaHome + File.separator + "jre";
       
    62             File f = new File(jrepath, "lib");
       
    63             if (!f.exists()) {
       
    64                 // java.home usually points to the JRE path
       
    65                 jrepath = javaHome;
       
    66             }
       
    67         }
       
    68         return jrepath;
       
    69     }
       
    70 
       
    71     /**
       
    72      * Tests if the running platform is a JDK.
       
    73      */
       
    74     static boolean isJdk() {
       
    75         // <HOME>/jre exists which implies it's a JDK
       
    76         return getJrePath().endsWith(File.separator + "jre");
       
    77     }
       
    78 
       
    79     /**
       
    80      * Generates the URN string of "urn:st" namespace
       
    81      */
       
    82     static String generateURN() {
       
    83         return "urn:st:" + UUID.randomUUID().toString();
       
    84     }
       
    85 
       
    86     static int getIntValue(String value) {
       
    87         try {
       
    88             return Integer.parseInt(value);
       
    89         } catch (NumberFormatException e) {
       
    90             throw new IllegalArgumentException("\"" + value + "\"" +
       
    91                 " expected to be an integer");
       
    92         }
       
    93     }
       
    94 
       
    95     /**
       
    96      * Formats the Date into a timestamp string in YYYY-MM-dd HH:mm:ss GMT.
       
    97      * @param timestamp Date
       
    98      * @return a string representation of the timestamp
       
    99      *         in the YYYY-MM-dd HH:mm:ss GMT format.
       
   100      */
       
   101     static String formatTimestamp(Date timestamp) {
       
   102         if (timestamp == null) {
       
   103             return "[No timestamp]";
       
   104         }
       
   105         SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
       
   106         df.setTimeZone(TimeZone.getTimeZone("GMT"));
       
   107         return df.format(timestamp);
       
   108     }
       
   109 
       
   110     /**
       
   111      * Parses a timestamp string in YYYY-MM-dd HH:mm:ss GMT format.
       
   112      * @param timestamp Timestamp in the YYYY-MM-dd HH:mm:ss GMT format.
       
   113      * @return Date
       
   114      */
       
   115     static Date parseTimestamp(String timestamp) {
       
   116         SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
       
   117         df.setTimeZone(TimeZone.getTimeZone("GMT"));
       
   118         try {
       
   119             return df.parse(timestamp);
       
   120         } catch (ParseException e) {
       
   121             // should not reach here
       
   122             e.printStackTrace();
       
   123             return new Date();
       
   124         }
       
   125     }
       
   126 
       
   127     static String commandOutput(Process p) throws IOException {
       
   128         Reader r = null;
       
   129         Reader err = null;
       
   130         try {
       
   131             r = new InputStreamReader(p.getInputStream());
       
   132             err = new InputStreamReader(p.getErrorStream());
       
   133             String output = commandOutput(r);
       
   134             String errorMsg = commandOutput(err);
       
   135             p.waitFor();
       
   136             return output + errorMsg.trim();
       
   137         } catch (InterruptedException e) {
       
   138             if (isVerbose()) {
       
   139                 e.printStackTrace();
       
   140             }
       
   141             return e.getMessage();
       
   142         } finally {
       
   143             try {
       
   144                 if (r != null) {
       
   145                     r.close();
       
   146                 }
       
   147             } finally {
       
   148                 if (err != null) {
       
   149                     err.close();
       
   150                 }
       
   151             }
       
   152         }
       
   153     }
       
   154 
       
   155     static String commandOutput(Reader r) throws IOException {
       
   156         StringBuilder sb = new StringBuilder();
       
   157         int c;
       
   158         while ((c = r.read()) > 0) {
       
   159             if (c != '\r') {
       
   160                 sb.append((char) c);
       
   161             }
       
   162         }
       
   163         return sb.toString();
       
   164     }
       
   165 
       
   166     static int getJdkVersion() {
       
   167         parseVersion();
       
   168         return jdkVersion;
       
   169     }
       
   170 
       
   171     static int getUpdateVersion() {
       
   172         parseVersion();
       
   173         return jdkUpdate;
       
   174     }
       
   175 
       
   176     private static int jdkVersion = 0;
       
   177     private static int jdkUpdate = 0;
       
   178     private static synchronized void parseVersion() {
       
   179         if (jdkVersion > 0) {
       
   180             return;
       
   181         }
       
   182 
       
   183         // parse java.runtime.version
       
   184         // valid format of the version string is:
       
   185         // n.n.n[_uu[c]][-<identifer>]-bxx
       
   186         String cs = System.getProperty("java.runtime.version");
       
   187         if (cs.length() >= 5 &&
       
   188             Character.isDigit(cs.charAt(0)) && cs.charAt(1) == '.' &&
       
   189             Character.isDigit(cs.charAt(2)) && cs.charAt(3) == '.' &&
       
   190             Character.isDigit(cs.charAt(4))) {
       
   191             jdkVersion = Character.digit(cs.charAt(2), 10);
       
   192             cs = cs.substring(5, cs.length());
       
   193             if (cs.charAt(0) == '_' && cs.length() >= 3 &&
       
   194                 Character.isDigit(cs.charAt(1)) &&
       
   195                 Character.isDigit(cs.charAt(2))) {
       
   196                 int nextChar = 3;
       
   197                 try {
       
   198                     String uu = cs.substring(1, 3);
       
   199                     jdkUpdate = Integer.valueOf(uu).intValue();
       
   200                 } catch (NumberFormatException e) {
       
   201                     // not conforming to the naming convention
       
   202                     return;
       
   203                 }
       
   204             }
       
   205         } else {
       
   206             throw new InternalError("Invalid java.runtime.version" + cs);
       
   207         }
       
   208     }
       
   209 
       
   210     /**
       
   211      * Returns this java string as a null-terminated byte array
       
   212      */
       
   213     private static byte[] stringToByteArray(String str) {
       
   214         return (str + "\u0000").getBytes();
       
   215     }
       
   216 
       
   217     /**
       
   218      * Converts a null-terminated byte array to java string
       
   219      */
       
   220     private static String byteArrayToString(byte[] array) {
       
   221         return new String(array, 0, array.length -1);
       
   222     }
       
   223 
       
   224     /**
       
   225      * Gets the stclient path using a well known location from
       
   226      * the Windows platform Registry, ensuring the path returned
       
   227      * by the registry is really the one we are looking for,
       
   228      * otherwise it will return null.
       
   229      */
       
   230     private static File getWindowsStClientFile(boolean wow64) {
       
   231         File out = null;
       
   232         String regKey = (wow64 == true)
       
   233             ? "software\\Wow6432Node\\" + REGKEY_TAIL
       
   234             : "software\\" + REGKEY_TAIL;
       
   235         String keyName = "" ; // use the default  key
       
   236         String path = getRegistryKey(regKey, keyName);
       
   237         if (path != null
       
   238                 && (new File(path)).exists()
       
   239                 && path.toLowerCase().endsWith(STCLIENT_TAIL.toLowerCase())) {
       
   240             out = new File(path);
       
   241         }
       
   242         if (isVerbose()) {
       
   243             System.out.println("stclient=" + out);
       
   244         }
       
   245         return out;
       
   246     }
       
   247 
       
   248     /**
       
   249      * Finds a stclient in 32 and 64 bit environments, first by querying
       
   250      * the windows registry, if not then get the well known paths for
       
   251      * 64bit see http://support.microsoft.com/kb/896459
       
   252      */
       
   253 
       
   254     static File getWindowsStClientFile() {
       
   255         File stclient = null;
       
   256         if (System.getProperty("os.arch").equals("x86")) {
       
   257             // try to get the default entry
       
   258             stclient = getWindowsStClientFile(false);
       
   259             if (stclient != null) {
       
   260                 return stclient;
       
   261             }
       
   262         } else { // we are on 64-bit system
       
   263             // try the wow64 area
       
   264             stclient = getWindowsStClientFile(true);
       
   265             if (stclient != null) {
       
   266                 return stclient;
       
   267             }
       
   268             // try the default hard coded path, maybe wow64 registry is missing
       
   269             stclient = new File(WIN32_STCLIENT);
       
   270             if (stclient.canExecute()) {
       
   271                 if (isVerbose()) {
       
   272                     System.out.println("stclient(default)=" + stclient);
       
   273                 }
       
   274                 return stclient;
       
   275             }
       
   276         }
       
   277         if (isVerbose()) {
       
   278             System.out.println("stclient not found");
       
   279         }
       
   280         return null;
       
   281     }
       
   282 
       
   283     /**
       
   284      * This uses reflection to access a private java windows registry
       
   285      * interface, any changes to that Class must be appropriately adjusted.
       
   286      * Returns a null if unsuccessful.
       
   287      */
       
   288     private static String getRegistryKey(String regKey, String keyName) {
       
   289         String out = null;
       
   290         try {
       
   291             Class<?> clazz = Class.forName("java.util.prefs.WindowsPreferences");
       
   292 
       
   293             // Get the registry methods
       
   294             Method winRegOpenKeyM = clazz.getDeclaredMethod("WindowsRegOpenKey",
       
   295                     int.class, byte[].class, int.class);
       
   296             winRegOpenKeyM.setAccessible(true);
       
   297 
       
   298             Method winRegCloseKeyM = clazz.getDeclaredMethod("WindowsRegCloseKey",
       
   299                     int.class);
       
   300             winRegCloseKeyM.setAccessible(true);
       
   301 
       
   302             Method winRegQueryValueM = clazz.getDeclaredMethod("WindowsRegQueryValueEx",
       
   303                     int.class, byte[].class);
       
   304             winRegQueryValueM.setAccessible(true);
       
   305 
       
   306             // Get all the constants we need
       
   307             int HKLM = getValueFromStaticField("HKEY_LOCAL_MACHINE", clazz);
       
   308             int KEY_READ = getValueFromStaticField("KEY_READ", clazz);
       
   309             int ERROR_CODE = getValueFromStaticField("ERROR_CODE", clazz);
       
   310             int NATIVE_HANDLE = getValueFromStaticField("NATIVE_HANDLE", clazz);
       
   311             int ERROR_SUCCESS = getValueFromStaticField("ERROR_SUCCESS", clazz);
       
   312 
       
   313             // Convert keys
       
   314             byte[] reg = stringToByteArray(regKey);
       
   315             byte[] key = stringToByteArray(keyName);
       
   316 
       
   317             // Open the registry
       
   318             int[] result = (int[]) winRegOpenKeyM.invoke(null, HKLM, reg, KEY_READ);
       
   319 
       
   320             if (result[ERROR_CODE] == ERROR_SUCCESS) {
       
   321                 byte[] stvalue = (byte[]) winRegQueryValueM.invoke(null,
       
   322                     result[NATIVE_HANDLE], key);
       
   323                 out = byteArrayToString(stvalue);
       
   324                 winRegCloseKeyM.invoke(null, result[NATIVE_HANDLE]);
       
   325             }
       
   326         } catch (Exception ex) {
       
   327             if (isVerbose()) {
       
   328                 ex.printStackTrace();
       
   329             }
       
   330         }
       
   331         return out;
       
   332     }
       
   333 
       
   334     private static int getValueFromStaticField(String fldName, Class<?> klass) throws Exception {
       
   335         Field f = klass.getDeclaredField(fldName);
       
   336         f.setAccessible(true);
       
   337         return f.getInt(null);
       
   338     }
       
   339 }