001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package com.sun.servicetag;
043:
044: import java.io.*;
045: import java.util.Date;
046: import java.text.SimpleDateFormat;
047: import java.text.ParseException;
048: import java.util.TimeZone;
049: import java.util.UUID;
050: import java.lang.reflect.Field;
051: import java.lang.reflect.Method;
052:
053: // Utility class for com.sun.servicetag package
054: class Util {
055: private static boolean verbose = (System
056: .getProperty("servicetag.verbose") != null);
057: private static String jrepath = null;
058:
059: // for debugging and tracing
060: static boolean isVerbose() {
061: return verbose;
062: }
063:
064: /**
065: * Gets the pathname of JRE in the running platform
066: * This can be a JDK or JRE.
067: */
068: static synchronized String getJrePath() {
069: if (jrepath == null) {
070: // Determine the JRE path by checking the existence of
071: // <HOME>/jre/lib and <HOME>/lib.
072: String javaHome = System.getProperty("java.home");
073: jrepath = javaHome + File.separator + "jre";
074: File f = new File(jrepath, "lib");
075: if (!f.exists()) {
076: // java.home usually points to the JRE path
077: jrepath = javaHome;
078: }
079: }
080: return jrepath;
081: }
082:
083: /**
084: * Tests if the running platform is a JDK.
085: */
086: static boolean isJdk() {
087: // <HOME>/jre exists which implies it's a JDK
088: return getJrePath().endsWith(File.separator + "jre");
089: }
090:
091: /**
092: * Generates the URN string of "urn:st" namespace
093: */
094: static String generateURN() {
095: return "urn:st:" + UUID.randomUUID().toString();
096: }
097:
098: static int getIntValue(String value) {
099: try {
100: return Integer.parseInt(value);
101: } catch (NumberFormatException e) {
102: throw new IllegalArgumentException("\"" + value + "\""
103: + " expected to be an integer");
104: }
105: }
106:
107: /**
108: * Formats the Date into a timestamp string in YYYY-MM-dd HH:mm:ss GMT.
109: * @param timestamp Date
110: * @return a string representation of the timestamp
111: * in the YYYY-MM-dd HH:mm:ss GMT format.
112: */
113: static String formatTimestamp(Date timestamp) {
114: if (timestamp == null) {
115: return "[No timestamp]";
116: }
117: SimpleDateFormat df = new SimpleDateFormat(
118: "yyyy-MM-dd HH:mm:ss z");
119: df.setTimeZone(TimeZone.getTimeZone("GMT"));
120: return df.format(timestamp);
121: }
122:
123: /**
124: * Parses a timestamp string in YYYY-MM-dd HH:mm:ss GMT format.
125: * @param timestamp Timestamp in the YYYY-MM-dd HH:mm:ss GMT format.
126: * @return Date
127: */
128: static Date parseTimestamp(String timestamp) {
129: SimpleDateFormat df = new SimpleDateFormat(
130: "yyyy-MM-dd HH:mm:ss z");
131: df.setTimeZone(TimeZone.getTimeZone("GMT"));
132: try {
133: return df.parse(timestamp);
134: } catch (ParseException e) {
135: // should not reach here
136: e.printStackTrace();
137: return new Date();
138: }
139: }
140:
141: static String commandOutput(Process p) throws IOException {
142: Reader r = null;
143: Reader err = null;
144: try {
145: r = new InputStreamReader(p.getInputStream());
146: err = new InputStreamReader(p.getErrorStream());
147: String output = commandOutput(r);
148: String errorMsg = commandOutput(err);
149: p.waitFor();
150: return output + errorMsg.trim();
151: } catch (InterruptedException e) {
152: if (isVerbose()) {
153: e.printStackTrace();
154: }
155: return e.getMessage();
156: } finally {
157: if (r != null) {
158: r.close();
159: }
160: if (err != null) {
161: err.close();
162: }
163: }
164: }
165:
166: static String commandOutput(Reader r) throws IOException {
167: StringBuilder sb = new StringBuilder();
168: int c;
169: while ((c = r.read()) > 0) {
170: if (c != '\r') {
171: sb.append((char) c);
172: }
173: }
174: return sb.toString();
175: }
176:
177: static int getJdkVersion() {
178: parseVersion();
179: return jdkVersion;
180: }
181:
182: static int getUpdateVersion() {
183: parseVersion();
184: return jdkUpdate;
185: }
186:
187: private static int jdkVersion = 0;
188: private static int jdkUpdate = 0;
189:
190: private static synchronized void parseVersion() {
191: if (jdkVersion > 0) {
192: return;
193: }
194:
195: // parse java.runtime.version
196: // valid format of the version string is:
197: // n.n.n[_uu[c]][-<identifer>]-bxx
198: String cs = System.getProperty("java.runtime.version");
199: if (cs.length() >= 5 && Character.isDigit(cs.charAt(0))
200: && cs.charAt(1) == '.'
201: && Character.isDigit(cs.charAt(2))
202: && cs.charAt(3) == '.'
203: && Character.isDigit(cs.charAt(4))) {
204: jdkVersion = Character.digit(cs.charAt(2), 10);
205: cs = cs.substring(5, cs.length());
206: if (cs.charAt(0) == '_' && cs.length() >= 3
207: && Character.isDigit(cs.charAt(1))
208: && Character.isDigit(cs.charAt(2))) {
209: int nextChar = 3;
210: try {
211: String uu = cs.substring(1, 3);
212: jdkUpdate = Integer.valueOf(uu).intValue();
213: } catch (NumberFormatException e) {
214: // not conforming to the naming convention
215: return;
216: }
217: }
218: } else {
219: throw new InternalError("Invalid java.runtime.version" + cs);
220: }
221: }
222:
223: /**
224: * Returns this java string as a null-terminated byte array
225: */
226: private static byte[] stringToByteArray(String str) {
227: return (str + "\u0000").getBytes();
228: }
229:
230: /**
231: * Converts a null-terminated byte array to java string
232: */
233: private static String byteArrayToString(byte[] array) {
234: return new String(array, 0, array.length - 1);
235: }
236:
237: /**
238: * Gets the stclient path using a well known location from
239: * the Windows platform Registry, otherwise it will return null.
240: */
241: static File getWindowsStClientFile() {
242: File out = null;
243: String regKey = "software\\microsoft\\windows\\currentversion\\app paths\\stclient.exe";
244: String keyName = ""; // use the default key
245: String path = getRegistryKey(regKey, keyName);
246:
247: if (path != null && (new File(path)).exists()) {
248: out = new File(path);
249: }
250: if (isVerbose()) {
251: System.out.println("stclient=" + out);
252: }
253: return out;
254: }
255:
256: /**
257: * This uses reflection to access a private java windows registry
258: * interface, any changes to that Class must be appropriately adjusted.
259: * Returns a null if unsuccessful.
260: */
261: private static String getRegistryKey(String regKey, String keyName) {
262: String out = null;
263: try {
264: Class<?> clazz = Class
265: .forName("java.util.prefs.WindowsPreferences");
266:
267: // Get the registry methods
268: Method winRegOpenKeyM = clazz.getDeclaredMethod(
269: "WindowsRegOpenKey", int.class, byte[].class,
270: int.class);
271: winRegOpenKeyM.setAccessible(true);
272:
273: Method winRegCloseKeyM = clazz.getDeclaredMethod(
274: "WindowsRegCloseKey", int.class);
275: winRegCloseKeyM.setAccessible(true);
276:
277: Method winRegQueryValueM = clazz.getDeclaredMethod(
278: "WindowsRegQueryValueEx", int.class, byte[].class);
279: winRegQueryValueM.setAccessible(true);
280:
281: // Get all the constants we need
282: int HKLM = getValueFromStaticField("HKEY_LOCAL_MACHINE",
283: clazz);
284: int KEY_READ = getValueFromStaticField("KEY_READ", clazz);
285: int ERROR_CODE = getValueFromStaticField("ERROR_CODE",
286: clazz);
287: int NATIVE_HANDLE = getValueFromStaticField(
288: "NATIVE_HANDLE", clazz);
289: int ERROR_SUCCESS = getValueFromStaticField(
290: "ERROR_SUCCESS", clazz);
291:
292: // Convert keys
293: byte[] reg = stringToByteArray(regKey);
294: byte[] key = stringToByteArray(keyName);
295:
296: // Open the registry
297: int[] result = (int[]) winRegOpenKeyM.invoke(null, HKLM,
298: reg, KEY_READ);
299:
300: if (result[ERROR_CODE] == ERROR_SUCCESS) {
301: byte[] stvalue = (byte[]) winRegQueryValueM.invoke(
302: null, result[NATIVE_HANDLE], key);
303: out = byteArrayToString(stvalue);
304: winRegCloseKeyM.invoke(null, result[NATIVE_HANDLE]);
305: }
306: } catch (Exception ex) {
307: if (isVerbose()) {
308: ex.printStackTrace();
309: }
310: }
311: return out;
312: }
313:
314: private static int getValueFromStaticField(String fldName,
315: Class<?> klass) throws Exception {
316: Field f = klass.getDeclaredField(fldName);
317: f.setAccessible(true);
318: return f.getInt(null);
319: }
320: }
|