source: trunk/gli/src/org/greenstone/gatherer/util/WinRegistry.java@ 6540

Last change on this file since 6540 was 5581, checked in by mdewsnip, 21 years ago

Many formatting, structural and code improvements.

  • Property svn:keywords set to Author Date Id Revision
File size: 10.4 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * <BR><BR>
9 *
10 * Author: John Thompson, Greenstone Digital Library, University of Waikato
11 *
12 * <BR><BR>
13 *
14 * Copyright (C) 1999 New Zealand Digital Library Project
15 *
16 * <BR><BR>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * <BR><BR>
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * <BR><BR>
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *########################################################################
36 */
37package org.greenstone.gatherer.util;
38
39/**
40 * Title: The Gatherer
41 * Description: The Gatherer: a tool for gathering and enriching digital collections.
42 * Copyright: Copyright (c) 2001
43 * Company: The University of Waikato
44 * Written: 18/11/01
45 * Revised: 24/07/02
46 * @author John Thompson, Greenstone Digital Libraries
47 * @version 2.1
48 */
49import java.lang.reflect.Method;
50/** This class provides access to the Windows registry via the preferences modules of JDK1.4. But wouldn't you know it, it doesn't always read the windows key files correctly as they appear to have changed how they store keys between win98, win2000 and winNT. To combat this, this class will eventually be swallowed by the LauchProgramManager, and used only to attempt to determine the default launching commands. */
51public class WinRegistry {
52 /** Windows security mask */
53 private final static int KEY_QUERY_VALUE = 1;
54 /** A constant used to interpret the return of a native function as successful. */
55 private final static int NATIVE_HANDLE = 0;
56 /** A constant used to interpret the return of a native function as an error. */
57 private final static int ERROR_CODE = 1;
58 /** Windows error codes. */
59 private final static int ERROR_SUCCESS = 0;
60 /** HKEY_LOCAL_MACHINE address. */
61 private final static int HKEY_LOCAL_MACHINE = 0x80000002;
62 /** Called to build a command string that will launch the given file in its associated program according to the windows registry.
63 * @param filename The name of a file, including the required extension, as a <strong>String</strong>.
64 * @return Another <strong>String</strong> containing a command line which, when run in a command shell, will launch an external application to view this file.
65 */
66 public static String openCommand(String filename) {
67 if(filename.indexOf(".") != -1) {
68 String extension = filename.substring(filename.indexOf("."));
69 try {
70 // First find the name of the file type that is associated with this extension.
71 String file_type = getValue("Software\\CLASSES\\" + extension);
72 // Then if we got a type, get the open command from its shell reference.
73 ///ystem.err.println("Searching for file-type = " + file_type);
74 if(file_type != null) {
75 String raw = getValue("Software\\CLASSES\\" + file_type + "\\shell\\open\\command");
76 //Replace "%1" with "filename"
77 if(raw.indexOf("%1") != -1) {
78 String prefix = raw.substring(0, raw.indexOf("%1"));
79 if(!prefix.endsWith("\"")) {
80 prefix = prefix + "\"";
81 }
82 String suffix = raw.substring(raw.indexOf("%1") + 2);
83 if(!suffix.endsWith("\"")) {
84 suffix = suffix + "\"";
85 }
86 return prefix + filename + suffix;
87 }
88 // Arg. There is a windows flag called /dde, which if it exists in a command tells it to use the filename (hence the meaningful name dde eh?)
89 else if(raw.indexOf("/dde") != -1) {
90 String prefix = raw.substring(0, raw.indexOf("/dde"));
91 if(!prefix.endsWith("\"")) {
92 prefix = prefix + "\"";
93 }
94 String suffix = raw.substring(raw.indexOf("/dde") + 4);
95 if(!suffix.endsWith("\"")) {
96 suffix = suffix + "\"";
97 }
98 return prefix + filename + suffix;
99 }
100 // No file parameter. Append the file to the command and hope for the best.
101 return raw + " \"" + filename + "\"";
102 }
103 }
104 catch (Exception error) {
105 ///ystem.err.println("No such value.");
106 //error.printStackTrace();
107 }
108 }
109 return null;
110 }
111 /** Attempts to retrieve the value at the location given from the registry using Reflection.
112 * @param path The path to the desired key as a <strong>String</strong>.
113 * @return The value found at the indicated key as a <strong>String</strong>.
114 */
115 private static String getValue(String path)
116 throws ClassNotFoundException, Exception, NoSuchMethodException {
117 ///ystem.err.println("Get value " + path);
118 byte[] WINDOWS_ROOT_PATH = stringToByteArray(path);
119 Class theClass = Class.forName("java.util.prefs.WindowsPreferences");
120 int[] result = openKey(HKEY_LOCAL_MACHINE, WINDOWS_ROOT_PATH, KEY_QUERY_VALUE);
121 if (result[ERROR_CODE] != ERROR_SUCCESS) {
122 throw new Exception("Path not found!");
123 }
124 int native_handle = result[NATIVE_HANDLE];
125 Method m = theClass.getDeclaredMethod("WindowsRegQueryValueEx", new Class[]{int.class, byte[].class});
126 m.setAccessible(true);
127 byte[] windows_name = toWindowsName("");
128 Object value = m.invoke(null, new Object[]{new Integer(native_handle), windows_name});
129 WindowsRegCloseKey(native_handle);
130 if (value == null) {
131 throw new Exception("Path found. Key not found.");
132 }
133 byte[] origBuffer = (byte[]) value;
134 byte[] destBuffer = new byte[origBuffer.length - 1];
135 System.arraycopy(origBuffer, 0, destBuffer, 0, origBuffer.length - 1);
136 return new String(destBuffer);
137 }
138 /** Closes the reference (and hence the instantiated objects) to a certain entry within the registry. Do this or suffer massive memory leaks.
139 * @param nativeHandle A reference to the piece of memory containing an inspected windows key-value pair.
140 * @return The status code returned from closing the key, as an <i>int</i>.
141 */
142 public static int WindowsRegCloseKey(int nativeHandle)
143 throws Exception {
144 Class theClass = Class.forName("java.util.prefs.WindowsPreferences");
145 Method m = theClass.getDeclaredMethod("WindowsRegCloseKey", new Class[]{int.class});
146 m.setAccessible(true);
147 Object ret = m.invoke(null, new Object[]{new Integer(nativeHandle)});
148 return ((Integer) ret).intValue();
149 }
150 /** Attempts to open a certain key-value pair from the windows registry, from within a certain region (or HKEY).
151 * @param hkey An <i>int</i> which is the offset for a certain group within the registry.
152 * @param windowsAbsolutePath A <i>byte[]</i> containing the path to the desired key, relative to the given HKEY.
153 * @param securityMask A mask needed to read values from the registry, as an <i>int</i>.
154 * @return An <i>int[]</i> pair, the first of which is the reference to the indicated key if no error occured, and the second of which reports the end error state of the registry open attempt.
155 */
156 public static int[] openKey(int hkey, byte[] windowsAbsolutePath, int securityMask)
157 throws Exception {
158 Class theClass = Class.forName("java.util.prefs.WindowsPreferences");
159 Method m = theClass.getDeclaredMethod("WindowsRegOpenKey", new Class[]{int.class, byte[].class, int.class});
160 m.setAccessible(true);
161 Object ret = m.invoke(null, new Object[]{new Integer(hkey), windowsAbsolutePath, new Integer(securityMask)});
162 return (int[]) ret;
163 }
164 /** Converts a string to a byte array. Duh!
165 * @param str The <strong>String</strong> to be converted.
166 * @return A <i>byte[]</i> containing orderer characters from the String.
167 */
168 private static byte[] stringToByteArray(String str) {
169 byte[] result = new byte[str.length() + 1];
170 for (int i = 0; i < str.length(); i++) {
171 result[i] = (byte) str.charAt(i);
172 }
173 result[str.length()] = 0;
174 return result;
175 }
176
177 private static String toJavaValueString(byte[] windowsNameArray) {
178 // Use modified native2ascii algorithm
179 String windowsName = byteArrayToString(windowsNameArray);
180 StringBuffer javaName = new StringBuffer();
181 char ch;
182 for (int i = 0; i < windowsName.length(); i++) {
183 if ((ch = windowsName.charAt(i)) == '/') {
184 char next = ' ';
185
186 if (windowsName.length() > i + 1 &&
187 (next = windowsName.charAt(i + 1)) == 'u') {
188 if (windowsName.length() < i + 6) {
189 break;
190 } else {
191 ch = (char) Integer.parseInt
192 (windowsName.substring(i + 2, i + 6), 16);
193 i += 5;
194 }
195 } else
196 if ((windowsName.length() > i + 1) &&
197 ((windowsName.charAt(i + 1)) >= 'A') && (next <= 'Z')) {
198 ch = next;
199 i++;
200 } else if ((windowsName.length() > i + 1) &&
201 (next == '/')) {
202 ch = '\\';
203 i++;
204 }
205 } else if (ch == '\\') {
206 ch = '/';
207 }
208 javaName.append(ch);
209 }
210 return javaName.toString();
211 }
212 /** */
213 private static String byteArrayToString(byte[] array) {
214 StringBuffer result = new StringBuffer();
215 for (int i = 0; i < array.length - 1; i++) {
216 result.append((char) array[i]);
217 }
218 return result.toString();
219 }
220 /** Magics the name of a certain path component from a Java String to the unique string windows requires.
221 * @param javaName The name of a path component as a <strong>String</strong>.
222 * @return A <i>byte[]</i> containing the translated string.
223 */
224 private static byte[] toWindowsName(String javaName) {
225 StringBuffer windowsName = new StringBuffer();
226 for (int i = 0; i < javaName.length(); i++) {
227 char ch = javaName.charAt(i);
228 if ((ch < 0x0020) || (ch > 0x007f)) {
229 throw new RuntimeException("Unable to convert to Windows name");
230 }
231 if (ch == '\\') {
232 windowsName.append("//");
233 } else if (ch == '/') {
234 windowsName.append('\\');
235 } else if ((ch >= 'A') && (ch <= 'Z')) {
236 windowsName.append("/" + ch);
237 } else {
238 windowsName.append(ch);
239 }
240 }
241 return stringToByteArray(windowsName.toString());
242 }
243}
Note: See TracBrowser for help on using the repository browser.