View Javadoc

1   /*
2    * $Id: Registry.java 125 2008-11-04 07:18:28Z arnep $
3    */
4   package net.sf.ovanttasks.ovnative.win32;
5   
6   import java.math.BigDecimal;
7   import java.math.BigInteger;
8   import java.util.ArrayList;
9   import java.util.Iterator;
10  import java.util.List;
11  
12  /**
13   * Registry accesses the Windows Registry.
14   * Read/write/test/create/delete are supported for both data and subtrees.
15   * 
16   * @author lars.gersmann@roxes.com
17   * @author arnep@users.sf.net
18   */
19  public class Registry implements Iterable<Registry> {
20  
21      public class SubKeyIterator implements Iterator<Registry> {
22  
23          final private String[] keys;
24          private int subKeyIndex = 0;
25  
26          public SubKeyIterator(String[] keys) {
27              this.keys = keys;
28          }
29  
30          public boolean hasNext() {
31              return subKeyIndex < keys.length;
32          }
33  
34          public Registry next() {
35              return openSubKey(keys[subKeyIndex++]);
36          }
37  
38          public void remove() {
39              throw new UnsupportedOperationException();
40          }
41      }    // Key access rights
42      public static final int KEY_QUERY_VALUE = 1;
43      public static final int KEY_SET_VALUE = 2;
44      public static final int KEY_CREATE_SUB_KEY = 4;
45      public static final int KEY_ENUMERATE_SUB_KEYS = 8;
46      public static final int KEY_NOTIFY = 16;
47      public static final int KEY_CREATE_LINK = 32;
48      public static final int KEY_WRITE = 0x20006;
49      public static final int KEY_EXECUTE = 0x20019;
50      public static final int KEY_READ = 0x20019;
51      public static final int KEY_ALL_ACCESS = 0xf003f;
52      public static final int HKEY_CLASSES_ROOT = 0x80000000;
53      public static final int HKEY_CURRENT_USER = 0x80000001;
54      public static final int HKEY_LOCAL_MACHINE = 0x80000002;
55      public static final int HKEY_USERS = 0x80000003;
56      public static final int HKEY_PERFORMANCE_DATA = 0x80000004;
57      public static final int HKEY_PERFORMANCE_TEXT = 0x80000050;
58      public static final int HKEY_PERFORMANCE_NLSTEXT = 0x80000060;
59      public static final int HKEY_CURRENT_CONFIG = 0x80000005;
60      public static final int HKEY_DYN_DATA = 0x80000006;
61      /**
62       * No value type
63       */
64      public static final int REG_NONE = 0;
65      /**
66       * Unicode null terminated string
67       * 
68       */
69      public static final int REG_SZ = 1;
70      /**
71       * Unicode nul terminated string (with environment variable references)
72       */
73      public static final int REG_EXPAND_SZ = 2;
74      /**
75       * Free form binary
76       */
77      public static final int REG_BINARY = 3;
78      /**
79       * 32-bit number
80       */
81      public static final int REG_DWORD = 4;
82      /**
83       * 32-bit number (same as REG_DWORD)
84       */
85      public static final int REG_DWORD_LITTLE_ENDIAN = 4;
86      /**
87       * 32-bit number
88       */
89      public static final int REG_DWORD_BIG_ENDIAN = 5;
90      /**
91       * Symbolic Link (unicode)
92       */
93      public static final int REG_LINK = 6;
94      /**
95       * Multiple Unicode strings
96       */
97      public static final int REG_MULTI_SZ = 7;
98      /**
99       * Resource list in the resource mapped to struct _CM_RESOURCE_LIST from winddk.h
100      * TODO implement
101      */
102     public static final int REG_RESOURCE_LIST = 8;
103     /**
104      * Resource list in the hardware description
105      * TODO implement
106      */
107     public static final int REG_FULL_RESOURCE_DESCRIPTOR = 9;
108     /** 64-bitnumber        
109      * TODO implement
110      */
111     public static final int REG_RESOURCE_REQUIREMENTS_LIST = 10,  REG_QWORD = 11;
112     /** 64-bit number (same as REG_QWORD)
113      * TODO implement
114      */
115     public static final int REG_QWORD_LITTLE_ENDIAN = 11;
116 
117     // YES THIS exists in the registry !!
118     // at least RegEdt32.exe (W2k) knows this 1448
119     public static String getHKeyName(int hKey) {
120         switch (hKey) {
121             case HKEY_CLASSES_ROOT:
122                 return "HKEY_CLASSES_ROOT";
123             case HKEY_CURRENT_USER:
124                 return "HKEY_CURRENT_USER";
125             case HKEY_LOCAL_MACHINE:
126                 return "HKEY_LOCAL_MACHINE";
127             case HKEY_USERS:
128                 return "HKEY_USERS";
129             case HKEY_PERFORMANCE_DATA:
130                 return "HKEY_PERFORMANCE_DATA";
131             case HKEY_PERFORMANCE_TEXT:
132                 return "HKEY_PERFORMANCE_TEXT";
133             case HKEY_PERFORMANCE_NLSTEXT:
134                 return "HKEY_PERFORMANCE_NLSTEXT";
135             case HKEY_CURRENT_CONFIG:
136                 return "HKEY_CURRENT_CONFIG";
137             case HKEY_DYN_DATA:
138                 return "HKEY_DYN_DATA";
139             default:
140                 throw new Win32Exception("hKey " + hKey + " is unknown.");
141         }
142     }
143 
144     public static String getValueTypeName(int valueType) {
145         switch (valueType) {
146             case REG_NONE:
147                 return "REG_NONE";
148             case REG_SZ:
149                 return "REG_SZ";
150             case REG_EXPAND_SZ:
151                 return "REG_EXPAND_SZ";
152             case REG_BINARY:
153                 return "REG_BINARY";
154             case REG_DWORD:
155                 return "REG_DWORD";
156             case REG_DWORD_BIG_ENDIAN:
157                 return "REG_DWORD_BIG_ENDIAN";
158             case REG_LINK:
159                 return "REG_LINK";
160             case REG_MULTI_SZ:
161                 return "REG_MULTI_SZ";
162             case REG_RESOURCE_LIST:
163                 return "REG_RESOURCE_LIST";
164             case REG_FULL_RESOURCE_DESCRIPTOR:
165                 return "REG_FULL_RESOURCE_DESCRIPTOR";
166             case REG_RESOURCE_REQUIREMENTS_LIST:
167                 return "REG_RESOURCE_REQUIREMENTS_LIST";
168             case REG_QWORD:
169                 return "REG_QWORD";
170             default:
171                 throw new Win32Exception("valueType " + valueType + " is unknown.");
172 
173         }
174     }
175 
176     public static int parseHKeyName(String name) {
177         if (name.equals("HKEY_CLASSES_ROOT")) {
178             return HKEY_CLASSES_ROOT;
179         } else if (name.equals("HKEY_CURRENT_USER")) {
180             return HKEY_CURRENT_USER;
181         } else if (name.equals("HKEY_LOCAL_MACHINE")) {
182             return HKEY_LOCAL_MACHINE;
183         } else if (name.equals("HKEY_USERS")) {
184             return HKEY_USERS;
185         } else if (name.equals("HKEY_PERFORMANCE_DATA")) {
186             return HKEY_PERFORMANCE_DATA;
187         } else if (name.equals("HKEY_PERFORMANCE_TEXT")) {
188             return HKEY_PERFORMANCE_TEXT;
189         } else if (name.equals("HKEY_PERFORMANCE_NLSTEXT")) {
190             return HKEY_PERFORMANCE_NLSTEXT;
191         } else if (name.equals("HKEY_CURRENT_CONFIG")) {
192             return HKEY_CURRENT_CONFIG;
193         } else if (name.equals("HKEY_DYN_DATA")) {
194             return HKEY_DYN_DATA;
195         } else {
196             throw new Win32Exception("Parsing hKey failed : hKey " + name + " is unknown.");
197         }
198     }
199 
200     public static int parseValueTypeName(String name) {
201         if (name.equals("REG_NONE")) {
202             return REG_NONE;
203         } else if (name.equals("REG_SZ")) {
204             return REG_SZ;
205         } else if (name.equals("REG_EXPAND_SZ")) {
206             return REG_EXPAND_SZ;
207         } else if (name.equals("REG_BINARY")) {
208             return REG_BINARY;
209         } else if (name.equals("REG_DWORD")) {
210             return REG_DWORD;
211         } else if (name.equals("REG_DWORD_BIG_ENDIAN")) {
212             return REG_DWORD_BIG_ENDIAN;
213         } else if (name.equals("REG_DWORD_LITTLE_ENDIAN")) {
214             return REG_DWORD_LITTLE_ENDIAN;
215         } else if (name.equals("REG_MULTI_SZ")) {
216             return REG_MULTI_SZ;
217         } else if (name.equals("REG_RESOURCE_LIST")) {
218             return REG_RESOURCE_LIST;
219         } else if (name.equals("REG_FULL_RESOURCE_DESCRIPTOR")) {
220             return REG_FULL_RESOURCE_DESCRIPTOR;
221         } else if (name.equals("REG_RESOURCE_REQUIREMENTS_LIST")) {
222             return REG_RESOURCE_REQUIREMENTS_LIST;
223         } else if (name.equals("REG_QWORD")) {
224             return REG_QWORD;
225         } else if (name.equals("REG_QWORD_LITTLE_ENDIAN")) {
226             return REG_QWORD_LITTLE_ENDIAN;
227         } else {
228             throw new Win32Exception("Parsing valueType failed : valueType " + name + " is unknown.");
229         }
230     }
231     private final int hKey;
232     private final String subKey;
233 
234     public Registry(int hKey) {
235         OvNativeLibLoader.loadLib();
236         this.hKey = hKey;
237         this.subKey = "";
238     }
239 
240     public Registry(int hKey, String subKey) {
241         OvNativeLibLoader.loadLib();
242         this.hKey = hKey;
243         this.subKey = subKey;
244     }
245 
246     public Registry(Registry reg, String subKey) {
247         OvNativeLibLoader.loadLib();
248         this.hKey = reg.hKey;
249         this.subKey = reg.subKey.length() > 0
250                 ? reg.subKey + "\\" + subKey
251                 : subKey;
252     }
253 
254     public void create() throws Win32Exception {
255         create(subKey, hKey);
256     }
257 
258     private native void create(String subKey, int hKey) throws Win32Exception;
259 
260     /**
261      * Create a new subKey as child of this subKey.
262      * 
263      * @param subKeyName
264      *            the name of the subkey to create
265      * @return the new created registry object
266      * @throws Win32Exception
267      */
268     public Registry createSubKey(String subKeyName) throws Win32Exception {
269         Registry result = new Registry(getHKey(), getSubKey() + "\\" + subKeyName);
270         result.create();
271         return result;
272     }
273 
274     public void delete() throws Win32Exception {
275         delete(subKey, hKey);
276     }
277 
278     private native void delete(String subKey, int hKey) throws Win32Exception;
279 
280     /**
281      * Deletes the subKey if it exists
282      * 
283      * @param subKeyName
284      */
285     public void deleteSubKey(String subKeyName) {
286         openSubKey(subKeyName).delete();
287     }
288 
289     public void deleteValue(String name) throws Win32Exception {
290         deleteValue(subKey, hKey, name);
291     }
292 
293     private native void deleteValue(String subKey, int hKey, String name)
294             throws Win32Exception;
295 
296     @Override
297     public boolean equals(Object other) {
298         if (other instanceof Registry) {
299             Registry otherRegistry = (Registry) other;
300             return (this.getHKey() == otherRegistry.getHKey()) && this.getSubKey().equals(otherRegistry.getSubKey());
301         } else {
302             return false;
303         }
304     }
305 
306     @Override
307     public int hashCode() {
308         int hash = 5;
309         hash = 23 * hash + this.hKey;
310         hash = 23 * hash + (this.subKey != null ? this.subKey.hashCode() : 0);
311         return hash;
312     }
313 
314     /*
315      * Key might exists, but cant be opend for read
316      *     @Deprecated Use canOpenWith(KEY_XXX)
317      */
318     @Deprecated
319     public boolean exists() {
320         return canOpenWith(KEY_READ);
321     }
322 
323     private native boolean canOpenWith(String subKey, int hKey, int flags);
324 
325     public boolean canOpenWith(int flags) {
326         return canOpenWith(subKey, hKey, flags);
327     }
328 
329     public BigDecimal getBigDecimalValue(String name) {
330         return new BigDecimal(getStringValue(name));
331     }
332 
333     public BigInteger getBigIntegerValue(String name) {
334         return new BigInteger(getStringValue(name));
335     }
336 
337     public boolean getBooleanValue(String name) throws Win32Exception {
338         return getREG_DWORD_Value(subKey, hKey, name) != 0;
339     }
340 
341     public byte[] getByteArrayValue(String name) {
342         return getREG_BINARY_Value(subKey, hKey, name);
343     }
344 
345     public byte getByteValue(String name) {
346         return (byte) getREG_DWORD_Value(subKey, hKey, name);
347     }
348 
349     /**
350      * internal storage format is Double.toString
351      * 
352      * @param name
353      * @return
354      */
355     public double getDoubleValue(String name) {
356         return Double.parseDouble(getStringValue(name));
357     }
358 
359     public String getExpandableString(String name, boolean doExpand)
360             throws Win32Exception {
361         String value = getREG_X_SZ_Value(subKey, hKey, name, REG_EXPAND_SZ);
362         if (doExpand) {
363             return Win32.expandEnvironmentStrings(value);
364         } else {
365             return value;
366         }
367     }
368 
369     /**
370      * internal storage format Float.toString
371      * 
372      * @param name
373      * @return
374      * @throws Win32Exception 
375      */
376     public float getFloatValue(String name) throws Win32Exception {
377         return Float.parseFloat(getStringValue(name));
378     }
379 
380     public int getHKey() {
381         return hKey;
382     }
383 
384     public int getIntValue(String name) {
385         return getREG_DWORD_Value(subKey, hKey, name);
386     }
387 
388     /**
389      * internal storage format Long.toString
390      * 
391      * @param name
392      * @return
393      */
394     public long getLongValue(String name) {
395         return Long.parseLong(getStringValue(name));
396     }
397 
398     private native byte[] getREG_BINARY_Value(String subKey, int hKey,
399             String name);
400 
401     private native int getREG_DWORD_Value(String subKey, int hKey, String name);
402 
403     private native String getREG_X_SZ_Value(String subKey, int hKey,
404             String name, int type);
405 
406     public short getShortValue(String name) {
407         return (short) getREG_DWORD_Value(subKey, hKey, name);
408     }
409 
410     /**
411      * if it is an REG_EXPAND_SZ should it be expanded??
412      * 
413      * @param name
414      * @return
415      */
416     public String getStringValue(String name) {
417         return getREG_X_SZ_Value(subKey, hKey, name, REG_SZ);
418     }
419 
420     public String[] getMultiStringValue(String name) {
421         List<String> result = new ArrayList<String>();
422         String s = getREG_X_SZ_Value(subKey, hKey, name, REG_MULTI_SZ);
423         int oldPos = 0;
424         for (int i = 0; i < s.length(); i++) {
425             if (s.charAt(i) == (char) 0) {
426                 result.add(s.substring(oldPos, i));
427                 oldPos = i + 1;
428             }
429         }
430         return result.toArray(new String[result.size()]);
431     }
432 
433     public String getSubKey() {
434         return subKey;
435     }
436 
437     public int getValueType(String name) {
438         return getValueType(subKey, hKey, name);
439     }
440 
441     private native int getValueType(String subKey, int hKey, String name);
442 
443     public boolean hasSubKey(String name) {
444         Registry reg = new Registry(this, name);
445         return reg.exists();
446     }
447 
448     public boolean hasSubKeys() throws Win32Exception {
449         return hasSubKeys(subKey, hKey);
450     }
451 
452     private native boolean hasSubKeys(String subKey, int hKey)
453             throws Win32Exception;
454 
455     public boolean hasValue(String name) throws Win32Exception {
456         return hasValue(subKey, hKey, name);
457     }
458 
459     private native boolean hasValue(String subKey, int hKey, String name)
460             throws Win32Exception;
461 
462     public boolean hasValues() throws Win32Exception {
463         return hasValues(subKey, hKey);
464     }
465 
466     private native boolean hasValues(String subKey, int hKey)
467             throws Win32Exception;
468 
469     /**
470      * Opens a child subKey of this subKey. You must check, if you can open the
471      * key with {@link #canOpenWith(String, int, int)} and the appropirate flag
472      * from the KEY_* constants. the Key might exists, but you have no right to
473      * read the key.
474      * 
475      * @param subKeyName
476      *            the name of the subkey to open
477      * @return the opend registry object
478      * @throws Win32Exception
479      */
480     public Registry openSubKey(String subKeyName) throws Win32Exception {
481         Registry result = new Registry(getHKey(), getSubKey() + (getSubKey().length() > 0 ? "\\" : "") + subKeyName);
482         return result;
483     }
484 
485     public void setExpandableString(String name, String value)
486             throws Win32Exception {
487         setREG_X_SZ_Value(subKey, hKey, name, value, value.length(),
488                 REG_EXPAND_SZ);
489     }
490 
491     private native void setREG_BINARY_Value(String subKey, int hKey,
492             String name, byte[] value) throws Win32Exception;
493 
494     private native void setREG_DWORD_Value(String subKey, int hKey,
495             String name, int value) throws Win32Exception;
496 
497     private native void setREG_X_SZ_Value(String subKey, int hKey, String name,
498             String value, int length, int type) throws Win32Exception;
499 
500     public void setValue(String name, BigDecimal value) {
501         setValue(name, value.toString());
502     }
503 
504     public void setValue(String name, BigInteger value) {
505         setValue(name, value.toString());
506     }
507 
508     public void setValue(String name, boolean value) throws Win32Exception {
509         setREG_DWORD_Value(subKey, hKey, name, value ? 1 : 0);
510     }
511 
512     public void setValue(String name, byte value) throws Win32Exception {
513         setREG_DWORD_Value(subKey, hKey, name, value);
514     }
515 
516     public void setValue(String name, byte[] value) throws Win32Exception {
517         setREG_BINARY_Value(subKey, hKey, name, value);
518     }
519 
520     public void setValue(String name, double value) throws Win32Exception {
521         setValue(name, Double.toString(value));
522     }
523 
524     public void setValue(String name, float value) throws Win32Exception {
525         setValue(name, Float.toString(value));
526     }
527 
528     public void setValue(String name, int value) throws Win32Exception {
529         setREG_DWORD_Value(subKey, hKey, name, value);
530     }
531 
532     public void setValue(String name, long value) throws Win32Exception {
533         setValue(name, Long.toString(value));
534     }
535 
536     public void setValue(String name, short value) throws Win32Exception {
537         setREG_DWORD_Value(subKey, hKey, name, value);
538     }
539 
540     public void setValue(String name, String value) throws Win32Exception {
541         setREG_X_SZ_Value(subKey, hKey, name, value, value.length(), REG_SZ);
542     }
543 
544     public void setValue(String name, String[] value) throws Win32Exception {
545         StringBuffer sb = new StringBuffer();
546         for (String s : value) {
547             sb.append(s);
548             sb.append((char) 0);
549         }
550         String nativeString = sb.toString();
551         setREG_X_SZ_Value(subKey, hKey, name, nativeString, nativeString.length(), REG_MULTI_SZ);
552     }
553 
554     public void setValue(String name, String value, int valueType)
555             throws Win32Exception {
556         switch (valueType) {
557             case REG_NONE:
558                 throw new Win32Exception(
559                         "setValue valueType \"REG_NONE\" not supported");
560             case REG_SZ:
561                 setREG_X_SZ_Value(subKey, hKey, name, value, REG_SZ, valueType);
562                 break;
563             case REG_EXPAND_SZ:
564                 setREG_X_SZ_Value(subKey, hKey, name, value, REG_SZ, valueType);
565                 break;
566             case REG_BINARY:
567                 throw new Win32Exception(
568                         "setValue valueType \"REG_LINK\" not supported");
569             // TODO greater than 2^31 ???
570             case REG_DWORD:
571                 setREG_DWORD_Value(subKey, hKey, name, (int) Long.parseLong(value));
572                 break;
573             // case REG_DWORD_LITTLE_ENDIAN: setREG_DWORD_Value(subKey, hKey,
574             // name, (int)Long.parseLong(value));
575             // break;
576             case REG_DWORD_BIG_ENDIAN:
577                 setREG_DWORD_Value(subKey, hKey, name, (int) Long.parseLong(value));
578                 break;
579             case REG_LINK:
580                 throw new Win32Exception(
581                         "setValue valueType \"REG_LINK\" not supported");
582             case REG_MULTI_SZ:
583                 throw new Win32Exception(
584                         "setValue valueType \"REG_MULTI_SZ\" not supported");
585             case REG_RESOURCE_LIST:
586                 throw new Win32Exception(
587                         "setValue valueType \"REG_RESOURCE_LIST\" not supported");
588             case REG_FULL_RESOURCE_DESCRIPTOR:
589                 throw new Win32Exception(
590                         "setValue valueType \"REG_FULL_RESOURCE_DESCRIPTOR\" not supported");
591             case REG_RESOURCE_REQUIREMENTS_LIST:
592                 throw new Win32Exception(
593                         "setValue valueType \"REG_RESOURCE_REQUIREMENTS_LIST\" not supported");
594             case REG_QWORD_LITTLE_ENDIAN:
595                 throw new Win32Exception(
596                         "setValue valueType \"REG_QWORD_LITTLE_ENDIAN\" not supported");
597         }
598     }
599 
600     public String[] subKeyNames() {
601         return subKeys(subKey, hKey);
602     }
603 
604     public Iterator<Registry> subKeys() {
605         return new SubKeyIterator(subKeys(subKey, hKey));
606     }
607 
608     private native String[] subKeys(String subKey, int hKey);
609 
610     @Override
611     public String toString() {
612         StringBuffer sb = new StringBuffer(getHKeyName(hKey));
613 
614         if (subKey.length() > 0) {
615             sb.append('\\').append(subKey);
616         }
617         return sb.toString();
618     }
619 
620     public String[] valueNames() {
621         return valueNames(subKey, hKey);
622     }
623 
624     private native String[] valueNames(String subKey, int hKey)
625             throws Win32Exception;
626 
627     public Iterator<Registry> iterator() {
628         return subKeys();
629     }
630 }