A Complete Example: Accessing the Windows Registry


In this section, we describe a full, working example that covers everything we discussed in this chapter: using native methods with strings, arrays, objects, constructor calls, and error handling. We show you how to put a Java platform wrapper around a subset of the ordinary C-based API used to work with the Windows registry. Of course, being a Windows-specific feature, a program using the Windows registry is inherently nonportable. For that reason, the standard Java library has no support for the registry, and it makes sense to use native methods to gain access to it.

Overview of the Windows Registry

The Windows registry is a data depository that holds configuration information for the Windows operating system and application programs. It provides a single point for administration and backup of system and application preferences.

On the downside, the registry is also a single point of failureif you mess up the registry, your computer may malfunction or even fail to boot! The sample program that we present in this section is safe, but if you plan to make any modifications to it, you should learn how to back up the registry before proceeding.

We don't suggest that you use the registry to store configuration parameters for your Java programs. The Java preferences API is a better solutionsee Volume 1, Chapter 10 for more information. We simply use the registry to demonstrate how to wrap a nontrivial native API into a Java class.

The principal tool for inspecting the registry is the registry editor. Because of the potential for error by naïve but enthusiastic users, there is no icon for launching the registry editor. Instead, start a DOS shell (or open the Start -> Run dialog box) and type regedit. Figure 11-3 shows the registry editor in action.

Figure 11-3. The registry editor


The left side shows the keys, which are arranged in a tree structure. Note that each key starts with one of the HKEY nodes like

 HKEY_CLASSES_ROOT HKEY_CURRENT_USER HKEY_LOCAL_MACHINE . . . 

The right side shows the name/value pairs that are associated with a particular key. For example, the key

 HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit\1.5 

has two name/value pairs, such as,

 JavaHome="c:\jdk1.5.0" MicroVersion="0" 

In this case, the values are strings. The values can also be integers or arrays of bytes.

A Java Platform Interface for Accessing the Registry

We implement a simple interface to access the registry from Java code, and then implement this interface with native code. Our interface allows only a few registry operations; to keep the code size down, we omitted other important operations such as adding, deleting, and enumerating keys. (It would be easy to add the remaining registry API functions.)

Even with the limited subset that we supply, you can

  • Enumerate all names stored in a key;

  • Read the value stored with a name;

  • Set the value stored with a name.

Here is the Java platform class that encapsulates a registry key.

 public class Win32RegKey {    public Win32RegKey(int theRoot, String thePath) { . . . }    public Enumeration names() { . . . }    public native Object getValue(String name);    public native void setValue(String name, Object value);    public static final int HKEY_CLASSES_ROOT = 0x80000000;    public static final int HKEY_CURRENT_USER = 0x80000001;    public static final int HKEY_LOCAL_MACHINE = 0x80000002;    . . . } 

The names method returns an enumeration that holds all the names stored with the key. You can get at them with the familiar hasMoreElements/nextElement methods. The getValue method returns an object that is either a string, an Integer object, or a byte array. The value parameter of the setValue method must also be of one of these three types.

Here is a simple function that lists the strings that are stored with the key

 HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit\1.5 

(You should change the key to the version of the JDK that is installed on your system.)

 public static void main(String[] args) {    Win32RegKey key = new Win32RegKey(Win32RegKey.HKEY_LOCAL_MACHINE,       "SOFTWARE\JavaSoft\Java Development Kit\1.5");    Enumeration<String> e = key.names();    while (e.hasMoreElements())    {       String name = e.nextElement();       System.out.println(name + "=" + key.getValue(name));    } } 

A typical output of this program is as follows:

 JavaHome=c:\jdk1.5.0 MicroVersion=0 

Implementation of Registry Access Functions as Native Methods

We need to implement three actions:

  • Get the value of a key;

  • Set the value of a key;

  • Iterate through the names of a key.

Fortunately, you have seen essentially all the tools that are required, such as the conversion between Java strings and arrays and those of C. And you saw how to raise a Java exception in case something goes wrong.

Two issues make these native methods more complex than the preceding examples. The getValue and setValue methods deal with the type Object, which can be one of String, Integer, or byte[]. The enumeration object stores the state between successive calls to hasMoreElements and nextElement.

Let us first look at the getValue method. The code (which is shown in Example 11-22) goes through the following steps.

1.

Open the registry key. To read their values, the registry API requires that keys be open.

2.

Query the type and size of the value that is associated with the name.

3.

Read the data into a buffer.

4.

If the type is REG_SZ (a string), then call NewStringUTF to create a new string with the value data.

5.

If the type is REG_DWORD (a 32-bit integer), then invoke the Integer constructor.

6.

If the type is REG_BINARY, then call NewByteArray to create a new byte array and call SetByteArrayRegion to copy the value data into the byte array.

7.

If the type is none of these or if an error occurred when an API function was called, throw an exception and carefully release all resources that had been acquired up to that point.

8.

Close the key and return the object (String, Integer, or byte[]) that had been created.

As you can see, this example illustrates quite nicely how to generate Java objects of different types.

In this native method, coping with the generic return type is not difficult. The jstring, jobject, or jarray reference is simply returned as a jobject. However, the setValue method receives a reference to an Object and must determine the Object's exact type in order to save the Object as a string, integer, or byte array. We can make this determination by querying the class of the value object, finding the class references for java.lang.String, java.lang.Integer, and byte[], and comparing them with the IsAssignableFrom function.

If class1 and class2 are two class references, then the call

 (*env)->IsAssignableFrom(env, class1, class2) 

returns JNI_TRUE when class1 and class2 are the same class or when class1 is a subclass of class2. In either case, references to objects of class1 can be cast to class2. For example, when

[View full width]

(*env)->IsAssignableFrom(env, (*env)->GetObjectClass(env, value), (*env)->FindClass(env, "[B"))

is true, then we know that value is a byte array.

Here is an overview of the code of the setValue method.

1.

Open the registry key for writing.

2.

Find the type of the value to write.

3.

If the type is String, call GetStringUTFChars to get a pointer to the characters. Also, obtain the string length.

4.

If the type is Integer, call the intValue method to get the integer stored in the wrapper object.

5.

If the type is byte[], call GetByteArrayElements to get a pointer to the bytes. Also, obtain the string length.

6.

Pass the data and length to the registry.

7.

Close the key. If the type is String or byte[], then also release the pointer to the characters or bytes.

Finally, let us turn to the native methods that enumerate keys. These are methods of the Win32RegKeyNameEnumeration class (see Example 11-21). When the enumeration process starts, we must open the key. For the duration of the enumeration, we must retain the key handle. That is, the key handle must be stored with the enumeration object. The key handle is of type DWORD, a 32-bit quantity, and, hence, can be stored in a Java integer. It is stored in the hkey field of the enumeration class. When the enumeration starts, the field is initialized with SetIntField. Subsequent calls read the value with GetIntField.

In this example, we store three other data items with the enumeration object. When the enumeration first starts, we can query the registry for the count of name/value pairs and the length of the longest name, which we need so we can allocate C character arrays to hold the names. These values are stored in the count and maxsize fields of the enumeration object. Finally, the index field is initialized with 1 to indicate the start of the enumeration, is set to 0 once the other instance fields are initialized, and is incremented after every enumeration step.

Let's walk through the native methods that support the enumeration. The hasMoreElements method is simple.

  1. Retrieve the index and count fields.

  2. If the index is -1, call the startNameEnumeration function, which opens the key, queries the count and maximum length, and initializes the hkey, count, maxsize, and index fields.

  3. Return JNI_TRUE if index is less than count; JNI_FALSE otherwise.

The nextElement method needs to work a little harder.

  1. Retrieve the index and count fields.

  2. If the index is -1, call the startNameEnumeration function, which opens the key, queries the count and maximum length, and initializes the hkey, count, maxsize, and index fields.

  3. If index equals count, throw a NoSuchElementException.

  4. Read the next name from the registry.

  5. Increment index.

  6. If index equals count, close the key.

Before compiling, remember to run javah on both Win32RegKey and Win32RegKeyNameEnumeration. The complete command line for Microsoft C++ is


cl -I jdk\include -I jdk\include\win32 -LD Win32RegKey.c advapi32.lib -FeWin32RegKey.dll

With Cygwin, use


gcc --mno-cygwin -D __int64="long long" -I jdk\include -I jdk\include\win32
   -I c:\cygwin\usr\include\w32api -shared -Wl,--add-stdcall-alias -o Win32RegKey.dll Win32RegKey.c

Example 11-23 shows a program to test our new registry functions. We add three name/value pairs, a string, an integer, and a byte array to the key.

 HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit\1.5 

You should edit the version number to match your JDK installation (or simply use some other existing registry key).

We then enumerate all names of that key and retrieve their values. The program will print

 JavaHome=c:\jdk1.5.0 MicroVersion=0 Default user=Harry Hacker Lucky number=13 Small primes=2 3 5 7 11 13 

Although adding these name/value pairs to that key probably does no harm, you may want to use the registry editor to remove them after running this program.

Example 11-21. Win32RegKey.java
  1. import java.util.*;  2.  3. /**  4.    A Win32RegKey object can be used to get and set values of  5.    a registry key in the Windows registry.  6. */  7. public class Win32RegKey  8. {  9.    /** 10.       Construct a registry key object. 11.       @param theRoot one of HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, 12.       HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CURRENT_CONFIG, 13.       HKEY_DYN_DATA 14.       @param thePath the registry key path 15.    */ 16.    public Win32RegKey(int theRoot, String thePath) 17.    { 18.       root = theRoot; 19.       path = thePath; 20.    } 21. 22.    /** 23.       Enumerates all names of registry entries under the path 24.       that this object describes. 25.       @return an enumeration listing all entry names 26.    */ 27.    public Enumeration<String> names() 28.    { 29.       return new Win32RegKeyNameEnumeration(root, path); 30.    } 31. 32.    /** 33.       Gets the value of a registry entry. 34.       @param name the entry name 35.       @return the associated value 36.    */ 37.    public native Object getValue(String name); 38. 39.    /** 40.       Sets the value of a registry entry. 41.       @param name the entry name 42.       @param value the new value 43.    */ 44.    public native void setValue(String name, Object value); 45. 46.    public static final int HKEY_CLASSES_ROOT = 0x80000000; 47.    public static final int HKEY_CURRENT_USER = 0x80000001; 48.    public static final int HKEY_LOCAL_MACHINE = 0x80000002; 49.    public static final int HKEY_USERS = 0x80000003; 50.    public static final int HKEY_CURRENT_CONFIG = 0x80000005; 51.    public static final int HKEY_DYN_DATA = 0x80000006; 52. 53.    private int root; 54.    private String path; 55. 56.    static 57.    { 58.       System.loadLibrary("Win32RegKey"); 59.    } 60. } 61. 62. class Win32RegKeyNameEnumeration implements Enumeration<String> 63. { 64.    Win32RegKeyNameEnumeration(int theRoot, String thePath) 65.    { 66.       root = theRoot; 67.       path = thePath; 68.    } 69. 70.    public native String nextElement(); 71.    public native boolean hasMoreElements(); 72. 73.    private int root; 74.    private String path; 75.    private int index = -1; 76.    private int hkey = 0; 77.    private int maxsize; 78.    private int count; 79. } 80. 81. class Win32RegKeyException extends RuntimeException 82. { 83.    public Win32RegKeyException() {} 84.    public Win32RegKeyException(String why) 85.    { 86.       super(why); 87.    } 88. } 

Example 11-22. Win32RegKey.c

[View full width]

   1. #include "Win32RegKey.h"   2. #include "Win32RegKeyNameEnumeration.h"   3. #include <string.h>   4. #include <stdlib.h>   5. #include <windows.h>   6.   7. JNIEXPORT jobject JNICALL Java_Win32RegKey_getValue(JNIEnv* env, jobject this_obj,  jobject name)   8. {   9.    const char* cname;  10.    jstring path;  11.    const char* cpath;  12.    HKEY hkey;  13.    DWORD type;  14.    DWORD size;  15.    jclass this_class;  16.    jfieldID id_root;  17.    jfieldID id_path;  18.    HKEY root;  19.    jobject ret;  20.    char* cret;  21.  22.    /* get the class */  23.    this_class = (*env)->GetObjectClass(env, this_obj);  24.  25.    /* get the field IDs */  26.    id_root = (*env)->GetFieldID(env, this_class, "root", "I");  27.    id_path = (*env)->GetFieldID(env, this_class, "path", "Ljava/lang/String;");  28.  29.    /* get the fields */  30.    root = (HKEY) (*env)->GetIntField(env, this_obj, id_root);  31.    path = (jstring)(*env)->GetObjectField(env, this_obj, id_path);  32.    cpath = (*env)->GetStringUTFChars(env, path, NULL);  33.  34.    /* open the registry key */  35.    if (RegOpenKeyEx(root, cpath, 0, KEY_READ, &hkey) != ERROR_SUCCESS)  36.    {  37.       (*env)->ThrowNew(env, (*env)->FindClass(env, "Win32RegKeyException"),  38.          "Open key failed");  39.       (*env)->ReleaseStringUTFChars(env, path, cpath);  40.       return NULL;  41.    }  42.  43.    (*env)->ReleaseStringUTFChars(env, path, cpath);  44.    cname = (*env)->GetStringUTFChars(env, name, NULL);  45.  46.    /* find the type and size of the value */  47.    if (RegQueryValueEx(hkey, cname, NULL, &type, NULL, &size) != ERROR_SUCCESS)  48.    {  49.       (*env)->ThrowNew(env, (*env)->FindClass(env, "Win32RegKeyException"),  50.          "Query value key failed");  51.       RegCloseKey(hkey);  52.       (*env)->ReleaseStringUTFChars(env, name, cname);  53.       return NULL;  54.    }  55.  56.    /* get memory to hold the value */  57.    cret = (char*)malloc(size);  58.  59.    /* read the value */  60.    if (RegQueryValueEx(hkey, cname, NULL, &type, cret, &size) != ERROR_SUCCESS)  61.    {  62.       (*env)->ThrowNew(env, (*env)->FindClass(env, "Win32RegKeyException"),  63.          "Query value key failed");  64.       free(cret);  65.       RegCloseKey(hkey);  66.       (*env)->ReleaseStringUTFChars(env, name, cname);  67.       return NULL;  68.    }  69.  70.    /* depending on the type, store the value in a string,  71.       integer or byte array */  72.    if (type == REG_SZ)  73.    {  74.       ret = (*env)->NewStringUTF(env, cret);  75.    }  76.    else if (type == REG_DWORD)  77.    {  78.       jclass class_Integer = (*env)->FindClass(env, "java/lang/Integer");  79.       /* get the method ID of the constructor */  80.       jmethodID id_Integer = (*env)->GetMethodID(env, class_Integer, "<init>", "(I)V");  81.       int value = *(int*) cret;  82.       /* invoke the constructor */  83.       ret = (*env)->NewObject(env, class_Integer, id_Integer, value);  84.    }  85.    else if (type == REG_BINARY)  86.    {  87.       ret = (*env)->NewByteArray(env, size);  88.       (*env)->SetByteArrayRegion(env, (jarray) ret, 0, size, cret);  89.    }  90.    else  91.    {  92.       (*env)->ThrowNew(env, (*env)->FindClass(env, "Win32RegKeyException"),  93.          "Unsupported value type");  94.       ret = NULL;  95.    }  96.  97.    free(cret);  98.    RegCloseKey(hkey);  99.    (*env)->ReleaseStringUTFChars(env, name, cname); 100. 101.    return ret; 102. } 103. 104. JNIEXPORT void JNICALL Java_Win32RegKey_setValue(JNIEnv* env, jobject this_obj, 105.    jstring name, jobject value) 106. { 107.    const char* cname; 108.    jstring path; 109.    const char* cpath; 110.    HKEY hkey; 111.    DWORD type; 112.    DWORD size; 113.    jclass this_class; 114.    jclass class_value; 115.    jclass class_Integer; 116.    jfieldID id_root; 117.    jfieldID id_path; 118.    HKEY root; 119.    const char* cvalue; 120.    int ivalue; 121. 122.    /* get the class */ 123.    this_class = (*env)->GetObjectClass(env, this_obj); 124. 125.    /* get the field IDs */ 126.    id_root = (*env)->GetFieldID(env, this_class, "root", "I"); 127.    id_path = (*env)->GetFieldID(env, this_class, "path", "Ljava/lang/String;"); 128. 129.    /* get the fields */ 130.    root = (HKEY)(*env)->GetIntField(env, this_obj, id_root); 131.    path = (jstring)(*env)->GetObjectField(env, this_obj, id_path); 132.    cpath = (*env)->GetStringUTFChars(env, path, NULL); 133. 134.    /* open the registry key */ 135.    if (RegOpenKeyEx(root, cpath, 0, KEY_WRITE, &hkey) != ERROR_SUCCESS) 136.    { 137.       (*env)->ThrowNew(env, (*env)->FindClass(env, "Win32RegKeyException"), 138.          "Open key failed"); 139.       (*env)->ReleaseStringUTFChars(env, path, cpath); 140.       return; 141.    } 142. 143.    (*env)->ReleaseStringUTFChars(env, path, cpath); 144.    cname = (*env)->GetStringUTFChars(env, name, NULL); 145. 146.    class_value = (*env)->GetObjectClass(env, value); 147.    class_Integer = (*env)->FindClass(env, "java/lang/Integer"); 148.    /* determine the type of the value object */ 149.    if ((*env)->IsAssignableFrom(env, class_value, (*env)->FindClass(env, "java/lang /String"))) 150.    { 151.       /* it is a string--get a pointer to the characters */ 152.       cvalue = (*env)->GetStringUTFChars(env, (jstring) value, NULL); 153.       type = REG_SZ; 154.       size = (*env)->GetStringLength(env, (jstring) value) +1; 155.    } 156.    else if ((*env)->IsAssignableFrom(env, class_value, class_Integer)) 157.    { 158.       /* it is an integer--call intValue to get the value */ 159.       jmethodID id_intValue = (*env)->GetMethodID(env, class_Integer, "intValue", "()I"); 160.       ivalue = (*env)->CallIntMethod(env, value, id_intValue); 161.       type = REG_DWORD; 162.       cvalue = (char*)&ivalue; 163.       size = 4; 164.    } 165.    else if ((*env)->IsAssignableFrom(env, class_value, (*env)->FindClass(env, "[B"))) 166.    { 167.       /* it is a byte array--get a pointer to the bytes */ 168.       type = REG_BINARY; 169.       cvalue = (char*)(*env)->GetByteArrayElements(env, (jarray) value, NULL); 170.       size = (*env)->GetArrayLength(env, (jarray) value); 171.    } 172.    else 173.    { 174.       /* we don't know how to handle this type */ 175.       (*env)->ThrowNew(env, (*env)->FindClass(env, "Win32RegKeyException"), 176.          "Unsupported value type"); 177.       RegCloseKey(hkey); 178.       (*env)->ReleaseStringUTFChars(env, name, cname); 179.       return; 180.    } 181. 182.    /* set the value */ 183.    if (RegSetValueEx(hkey, cname, 0, type, cvalue, size) != ERROR_SUCCESS) 184.    { 185.       (*env)->ThrowNew(env, (*env)->FindClass(env, "Win32RegKeyException"), 186.          "Set value failed"); 187.    } 188. 189.    RegCloseKey(hkey); 190.    (*env)->ReleaseStringUTFChars(env, name, cname); 191. 192.    /* if the value was a string or byte array, release the pointer */ 193.    if (type == REG_SZ) 194.    { 195.       (*env)->ReleaseStringUTFChars(env, (jstring) value, cvalue); 196.    } 197.    else if (type == REG_BINARY) 198.    { 199.       (*env)->ReleaseByteArrayElements(env, (jarray) value, (jbyte*) cvalue, 0); 200.    } 201. } 202. 203. /* helper function to start enumeration of names */ 204. static int startNameEnumeration(JNIEnv* env, jobject this_obj, jclass this_class) 205. { 206.    jfieldID id_index; 207.    jfieldID id_count; 208.    jfieldID id_root; 209.    jfieldID id_path; 210.    jfieldID id_hkey; 211.    jfieldID id_maxsize; 212. 213.    HKEY root; 214.    jstring path; 215.    const char* cpath; 216.    HKEY hkey; 217.    DWORD maxsize = 0; 218.    DWORD count = 0; 219. 220.    /* get the field IDs */ 221.    id_root = (*env)->GetFieldID(env, this_class, "root", "I"); 222.    id_path = (*env)->GetFieldID(env, this_class, "path", "Ljava/lang/String;"); 223.    id_hkey = (*env)->GetFieldID(env, this_class, "hkey", "I"); 224.    id_maxsize = (*env)->GetFieldID(env, this_class, "maxsize", "I"); 225.    id_index = (*env)->GetFieldID(env, this_class, "index", "I"); 226.    id_count = (*env)->GetFieldID(env, this_class, "count", "I"); 227. 228.    /* get the field values */ 229.    root = (HKEY)(*env)->GetIntField(env, this_obj, id_root); 230.    path = (jstring)(*env)->GetObjectField(env, this_obj, id_path); 231.    cpath = (*env)->GetStringUTFChars(env, path, NULL); 232. 233.    /* open the registry key */ 234.    if (RegOpenKeyEx(root, cpath, 0, KEY_READ, &hkey) != ERROR_SUCCESS) 235.    { 236.       (*env)->ThrowNew(env, (*env)->FindClass(env, "Win32RegKeyException"), 237.          "Open key failed"); 238.       (*env)->ReleaseStringUTFChars(env, path, cpath); 239.       return -1; 240.    } 241.    (*env)->ReleaseStringUTFChars(env, path, cpath); 242. 243.    /* query count and max length of names */ 244.    if (RegQueryInfoKey(hkey, NULL, NULL, NULL, NULL, NULL, NULL, &count, &maxsize, 245.           NULL, NULL, NULL) != ERROR_SUCCESS) 246.    { 247.       (*env)->ThrowNew(env, (*env)->FindClass(env, "Win32RegKeyException"), 248.          "Query info key failed"); 249.       RegCloseKey(hkey); 250.       return -1; 251.    } 252. 253.    /* set the field values */ 254.    (*env)->SetIntField(env, this_obj, id_hkey, (DWORD) hkey); 255.    (*env)->SetIntField(env, this_obj, id_maxsize, maxsize + 1); 256.    (*env)->SetIntField(env, this_obj, id_index, 0); 257.    (*env)->SetIntField(env, this_obj, id_count, count); 258.    return count; 259. } 260. 261. JNIEXPORT jboolean JNICALL Java_Win32RegKeyNameEnumeration_hasMoreElements(JNIEnv* env, 262.    jobject this_obj) 263. {  jclass this_class; 264.    jfieldID id_index; 265.    jfieldID id_count; 266.    int index; 267.    int count; 268.    /* get the class */ 269.    this_class = (*env)->GetObjectClass(env, this_obj); 270. 271.    /* get the field IDs */ 272.    id_index = (*env)->GetFieldID(env, this_class, "index", "I"); 273.    id_count = (*env)->GetFieldID(env, this_class, "count", "I"); 274. 275.    index = (*env)->GetIntField(env, this_obj, id_index); 276.    if (index == -1) /* first time */ 277.    { 278.       count = startNameEnumeration(env, this_obj, this_class); 279.       index = 0; 280.    } 281.    else 282.       count = (*env)->GetIntField(env, this_obj, id_count); 283.    return index < count; 284. } 285. 286. JNIEXPORT jobject JNICALL Java_Win32RegKeyNameEnumeration_nextElement(JNIEnv* env, 287.    jobject this_obj) 288. { 289.    jclass this_class; 290.    jfieldID id_index; 291.    jfieldID id_hkey; 292.    jfieldID id_count; 293.    jfieldID id_maxsize; 294. 295.    HKEY hkey; 296.    int index; 297.    int count; 298.    DWORD maxsize; 299. 300.    char* cret; 301.    jstring ret; 302. 303.    /* get the class */ 304.    this_class = (*env)->GetObjectClass(env, this_obj); 305. 306.    /* get the field IDs */ 307.    id_index = (*env)->GetFieldID(env, this_class, "index", "I"); 308.    id_count = (*env)->GetFieldID(env, this_class, "count", "I"); 309.    id_hkey = (*env)->GetFieldID(env, this_class, "hkey", "I"); 310.    id_maxsize = (*env)->GetFieldID(env, this_class, "maxsize", "I"); 311. 312.    index = (*env)->GetIntField(env, this_obj, id_index); 313.    if (index == -1) /* first time */ 314.    { 315.       count = startNameEnumeration(env, this_obj, this_class); 316.       index = 0; 317.    } 318.    else 319.       count = (*env)->GetIntField(env, this_obj, id_count); 320. 321.    if (index >= count) /* already at end */ 322.    { 323.       (*env)->ThrowNew(env, (*env)->FindClass(env, "java/util/NoSuchElementException"), 324.          "past end of enumeration"); 325.       return NULL; 326.    } 327. 328.    maxsize = (*env)->GetIntField(env, this_obj, id_maxsize); 329.    hkey = (HKEY)(*env)->GetIntField(env, this_obj, id_hkey); 330.    cret = (char*)malloc(maxsize); 331. 332.    /* find the next name */ 333.    if (RegEnumValue(hkey, index, cret, &maxsize, NULL, NULL, NULL, NULL) !=  ERROR_SUCCESS) 334.    { 335.       (*env)->ThrowNew(env, (*env)->FindClass(env, "Win32RegKeyException"), 336.          "Enum value failed"); 337.       free(cret); 338.       RegCloseKey(hkey); 339.       (*env)->SetIntField(env, this_obj, id_index, count); 340.       return NULL; 341.    } 342. 343.    ret = (*env)->NewStringUTF(env, cret); 344.    free(cret); 345. 346.    /* increment index */ 347.    index++; 348.    (*env)->SetIntField(env, this_obj, id_index, index); 349. 350.    if (index == count) /* at end */ 351.    { 352.       RegCloseKey(hkey); 353.    } 354. 355.    return ret; 356. } 

Example 11-23. Win32RegKeyTest.java
  1. import java.util.*;  2.  3. public class Win32RegKeyTest  4. {  5.    public static void main(String[] args)  6.    {  7.       Win32RegKey key = new Win32RegKey(  8.          Win32RegKey.HKEY_LOCAL_MACHINE, "SOFTWARE\\JavaSoft\\Java Development Kit\\1.5");  9. 10.       key.setValue("Default user", "Harry Hacker"); 11.       key.setValue("Lucky number", new Integer(13)); 12.       key.setValue("Small primes", new byte[] { 2, 3, 5, 7, 11 }); 13. 14.       Enumeration<String> e = key.names(); 15. 16.       while (e.hasMoreElements()) 17.       { 18.          String name = e.nextElement(); 19.          System.out.print(name + "="); 20. 21.          Object value = key.getValue(name); 22. 23.          if (value instanceof byte[]) 24.             for (byte b : (byte[]) value) System.out.print((b & 0xFF) + " "); 25.          else 26.             System.out.print(value); 27. 28.          System.out.println(); 29.       } 30.    } 31. } 


 Type Inquiry Functions 

  • jboolean IsAssignableFrom(JNIEnv *env, jclass cl1, jclass cl2)

    returns JNI_TRUE if objects of the first class can be assigned to objects of the second class; JNI_FALSE otherwise. This is the case in which the classes are the same, cl1 is a subclass of cl2, or cl2 represents an interface that is implemented by cl1 or one of its superclasses.

    Parameters:

    env

    The JNI interface pointer

     

    cl1, cl2

    Class references


  • jclass GetSuperClass(JNIEnv *env, jclass cl)

    returns the superclass of a class. If cl represents the class Object or an interface, returns NULL.

    Parameters:

    env

    The JNI interface pointer

     

    cl

    A class reference




    Core JavaT 2 Volume II - Advanced Features
    Building an On Demand Computing Environment with IBM: How to Optimize Your Current Infrastructure for Today and Tomorrow (MaxFacts Guidebook series)
    ISBN: 193164411X
    EAN: 2147483647
    Year: 2003
    Pages: 156
    Authors: Jim Hoskins

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net