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

Last change on this file since 4293 was 4293, checked in by jmt12, 21 years ago

Initial revision

  • 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 */
37
38
39
40
41
42
43package org.greenstone.gatherer.util;
44/**
45 * Title: The Gatherer
46 * Description: The Gatherer: a tool for gathering and enriching digital collections.
47 * Copyright: Copyright (c) 2001
48 * Company: The University of Waikato
49 * Written: 18/11/01
50 * Revised: 24/07/02
51 * @author John Thompson, Greenstone Digital Libraries
52 * @version 2.1
53 */
54import java.lang.reflect.Method;
55/** 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. */
56public class WinRegistry {
57 /** Windows security mask */
58 private final static int KEY_QUERY_VALUE = 1;
59 /** A constant used to interpret the return of a native function as successful. */
60 private final static int NATIVE_HANDLE = 0;
61 /** A constant used to interpret the return of a native function as an error. */
62 private final static int ERROR_CODE = 1;
63 /** Windows error codes. */
64 private final static int ERROR_SUCCESS = 0;
65 /** HKEY_LOCAL_MACHINE address. */
66 private final static int HKEY_LOCAL_MACHINE = 0x80000002;
67 /** Called to build a command string that will launch the given file in its associated program according to the windows registry.
68 * @param filename The name of a file, including the required extension, as a <strong>String</strong>.
69 * @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.
70 */
71 public static String openCommand(String filename) {
72 if(filename.indexOf(".") != -1) {
73 String extension = filename.substring(filename.indexOf("."));
74 try {
75 // First find the name of the file type that is associated with this extension.
76 String file_type = getValue("Software\\CLASSES\\" + extension);
77 // Then if we got a type, get the open command from its shell reference.
78 ///ystem.err.println("Searching for file-type = " + file_type);
79 if(file_type != null) {
80 String raw = getValue("Software\\CLASSES\\" + file_type + "\\shell\\open\\command");
81 //Replace "%1" with "filename"
82 if(raw.indexOf("%1") != -1) {
83 String prefix = raw.substring(0, raw.indexOf("%1"));
84 if(!prefix.endsWith("\"")) {
85 prefix = prefix + "\"";
86 }
87 String suffix = raw.substring(raw.indexOf("%1") + 2);
88 if(!suffix.endsWith("\"")) {
89 suffix = suffix + "\"";
90 }
91 return prefix + filename + suffix;
92 }
93 // 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?)
94 else if(raw.indexOf("/dde") != -1) {
95 String prefix = raw.substring(0, raw.indexOf("/dde"));
96 if(!prefix.endsWith("\"")) {
97 prefix = prefix + "\"";
98 }
99 String suffix = raw.substring(raw.indexOf("/dde") + 4);
100 if(!suffix.endsWith("\"")) {
101 suffix = suffix + "\"";
102 }
103 return prefix + filename + suffix;
104 }
105 // No file parameter. Append the file to the command and hope for the best.
106 return raw + " \"" + filename + "\"";
107 }
108 }
109 catch (Exception error) {
110 ///ystem.err.println("No such value.");
111 //error.printStackTrace();
112 }
113 }
114 return null;
115 }
116 /** Attempts to retrieve the value at the location given from the registry using Reflection.
117 * @param path The path to the desired key as a <strong>String</strong>.
118 * @return The value found at the indicated key as a <strong>String</strong>.
119 */
120 private static String getValue(String path)
121 throws ClassNotFoundException, Exception, NoSuchMethodException {
122 ///ystem.err.println("Get value " + path);
123 byte[] WINDOWS_ROOT_PATH = stringToByteArray(path);
124 Class theClass = Class.forName("java.util.prefs.WindowsPreferences");
125 int[] result = openKey(HKEY_LOCAL_MACHINE, WINDOWS_ROOT_PATH, KEY_QUERY_VALUE);
126 if (result[ERROR_CODE] != ERROR_SUCCESS) {
127 throw new Exception("Path not found!");
128 }
129 int native_handle = result[NATIVE_HANDLE];
130 Method m = theClass.getDeclaredMethod("WindowsRegQueryValueEx", new Class[]{int.class, byte[].class});
131 m.setAccessible(true);
132 byte[] windows_name = toWindowsName("");
133 Object value = m.invoke(null, new Object[]{new Integer(native_handle), windows_name});
134 WindowsRegCloseKey(native_handle);
135 if (value == null) {
136 throw new Exception("Path found. Key not found.");
137 }
138 byte[] origBuffer = (byte[]) value;
139 byte[] destBuffer = new byte[origBuffer.length - 1];
140 System.arraycopy(origBuffer, 0, destBuffer, 0, origBuffer.length - 1);
141 return new String(destBuffer);
142 }
143 /** Closes the reference (and hence the instantiated objects) to a certain entry within the registry. Do this or suffer massive memory leaks.
144 * @param nativeHandle A reference to the piece of memory containing an inspected windows key-value pair.
145 * @return The status code returned from closing the key, as an <i>int</i>.
146 */
147 public static int WindowsRegCloseKey(int nativeHandle)
148 throws Exception {
149 Class theClass = Class.forName("java.util.prefs.WindowsPreferences");
150 Method m = theClass.getDeclaredMethod("WindowsRegCloseKey", new Class[]{int.class});
151 m.setAccessible(true);
152 Object ret = m.invoke(null, new Object[]{new Integer(nativeHandle)});
153 return ((Integer) ret).intValue();
154 }
155 /** Attempts to open a certain key-value pair from the windows registry, from within a certain region (or HKEY).
156 * @param hkey An <i>int</i> which is the offset for a certain group within the registry.
157 * @param windowsAbsolutePath A <i>byte[]</i> containing the path to the desired key, relative to the given HKEY.
158 * @param securityMask A mask needed to read values from the registry, as an <i>int</i>.
159 * @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.
160 */
161 public static int[] openKey(int hkey, byte[] windowsAbsolutePath, int securityMask)
162 throws Exception {
163 Class theClass = Class.forName("java.util.prefs.WindowsPreferences");
164 Method m = theClass.getDeclaredMethod("WindowsRegOpenKey", new Class[]{int.class, byte[].class, int.class});
165 m.setAccessible(true);
166 Object ret = m.invoke(null, new Object[]{new Integer(hkey), windowsAbsolutePath, new Integer(securityMask)});
167 return (int[]) ret;
168 }
169 /** Converts a string to a byte array. Duh!
170 * @param str The <strong>String</strong> to be converted.
171 * @return A <i>byte[]</i> containing orderer characters from the String.
172 */
173 private static byte[] stringToByteArray(String str) {
174 byte[] result = new byte[str.length() + 1];
175 for (int i = 0; i < str.length(); i++) {
176 result[i] = (byte) str.charAt(i);
177 }
178 result[str.length()] = 0;
179 return result;
180 }
181
182 private static String toJavaValueString(byte[] windowsNameArray) {
183 // Use modified native2ascii algorithm
184 String windowsName = byteArrayToString(windowsNameArray);
185 StringBuffer javaName = new StringBuffer();
186 char ch;
187 for (int i = 0; i < windowsName.length(); i++) {
188 if ((ch = windowsName.charAt(i)) == '/') {
189 char next = ' ';
190
191 if (windowsName.length() > i + 1 &&
192 (next = windowsName.charAt(i + 1)) == 'u') {
193 if (windowsName.length() < i + 6) {
194 break;
195 } else {
196 ch = (char) Integer.parseInt
197 (windowsName.substring(i + 2, i + 6), 16);
198 i += 5;
199 }
200 } else
201 if ((windowsName.length() > i + 1) &&
202 ((windowsName.charAt(i + 1)) >= 'A') && (next <= 'Z')) {
203 ch = next;
204 i++;
205 } else if ((windowsName.length() > i + 1) &&
206 (next == '/')) {
207 ch = '\\';
208 i++;
209 }
210 } else if (ch == '\\') {
211 ch = '/';
212 }
213 javaName.append(ch);
214 }
215 return javaName.toString();
216 }
217 /** */
218 private static String byteArrayToString(byte[] array) {
219 StringBuffer result = new StringBuffer();
220 for (int i = 0; i < array.length - 1; i++) {
221 result.append((char) array[i]);
222 }
223 return result.toString();
224 }
225 /** Magics the name of a certain path component from a Java String to the unique string windows requires.
226 * @param javaName The name of a path component as a <strong>String</strong>.
227 * @return A <i>byte[]</i> containing the translated string.
228 */
229 private static byte[] toWindowsName(String javaName) {
230 StringBuffer windowsName = new StringBuffer();
231 for (int i = 0; i < javaName.length(); i++) {
232 char ch = javaName.charAt(i);
233 if ((ch < 0x0020) || (ch > 0x007f)) {
234 throw new RuntimeException("Unable to convert to Windows name");
235 }
236 if (ch == '\\') {
237 windowsName.append("//");
238 } else if (ch == '/') {
239 windowsName.append('\\');
240 } else if ((ch >= 'A') && (ch <= 'Z')) {
241 windowsName.append("/" + ch);
242 } else {
243 windowsName.append(ch);
244 }
245 }
246 return stringToByteArray(windowsName.toString());
247 }
248}
Note: See TracBrowser for help on using the repository browser.