Friday, February 16, 2007

Java: Preventing a child window's close operation from exiting the app.

I included a second JFrame in NetBeans, which I used as a child window. When the child window was closed, all windows were closed. I finally figured out that the default close operation needed to be either HIDE_ON_CLOSE or DISPOSE_ON_CLOSE. The default in Java is HIDE_ON_CLOSE, but in NetBeans is EXIT_ON_CLOSE.

I first changed this property in the main window code that invokes the child window, but then I looked at the Properties page for the child window. "defaultCloseOperation" is the first property. "DISPOSE" can be selected here.

From Sun Java Documentation

setDefaultCloseOperation

public void setDefaultCloseOperation(int operation)
Sets the operation that will happen by default when the user initiates a "close" on this frame. You must specify one of the following choices:

  • DO_NOTHING_ON_CLOSE (defined in WindowConstants): Don't do anything; require the program to handle the operation in the windowClosing method of a registered WindowListener object.
  • HIDE_ON_CLOSE (defined in WindowConstants): Automatically hide the frame after invoking any registered WindowListener objects.
  • DISPOSE_ON_CLOSE (defined in WindowConstants): Automatically hide and dispose the frame after invoking any registered WindowListener objects.
  • EXIT_ON_CLOSE (defined in JFrame): Exit the application using the System exit method. Use this only in applications.

The value is set to HIDE_ON_CLOSE by default.

Wednesday, February 14, 2007

Link to Random Image Password Generation

Saturday, February 10, 2007

Reducing redundant code by wrapping JNI functions.

My HelloWorldNative.c, with the "nativePrintObject" function reduced by wrapping the object and integer field retrieval:

JNIEXPORT void JNICALL Java_helloworld_Main_nativePrintObject(JNIEnv *env, jobject ths, jobject wsv)
{
jint ipAddress;
jstring jPageVisited;
char *pageVisited;
jstring jRefererURL;
char *refererURL;
jobject ipObject;

ipAddress = getIntegerField(env, wsv, "ipAddress");
printf(" wsv.ipAddress = %d.%d.%d.%d\n",
( ipAddress & 0xff000000 ) >> 24,
( ipAddress & 0x00ff0000 ) >> 16,
( ipAddress & 0x0000ff00 ) >> 8,
ipAddress & 0x000000ff);

if(!(jPageVisited = getStringField(env, wsv, "pageVisited"))) {
return;
}

pageVisited = (*env)->GetStringUTFChars(env, jPageVisited, 0);

if(!pageVisited) {
return;
}
printf(" wsv.pageVisted = %s\n", pageVisited);
(*env)->ReleaseStringUTFChars(env, jPageVisited, pageVisited);

if(!(jRefererURL = getStringField(env, wsv, "refererURL"))) {
return;
}

if(!(refererURL = (*env)->GetStringUTFChars(env, jRefererURL, 0))) {
return;
}
printf(" wsv.refererURL = %s\n", refererURL);
(*env)->ReleaseStringUTFChars(env, jRefererURL, refererURL);

if(!(ipObject = getObjectField(env, wsv, "ipAddr", "helloworld", "IPAddress"))) {
return;
}

printf(" wsv.ipAddr = %d.%d.%d.%d\n",
getIntegerField(env, ipObject, "byte1"),
getIntegerField(env, ipObject, "byte2"),
getIntegerField(env, ipObject, "byte3"),
getIntegerField(env, ipObject, "byte4")
);
}


jniUtils.h, the header for the JNI wrapper:

/*
* File: jniUtils.h
* Author: thomas
*
* Created on February 10, 2007, 5:30 PM
*/
#include <jni.h>

#ifndef _jniUtils_H
#define _jniUtils_H

#ifdef __cplusplus
extern "C" {
#endif
jint getIntegerField(JNIEnv *env, jobject ths, char *fieldName);
void putIntegerField(JNIEnv *env, jobject ths, char *fieldName, jint ji);
jstring getStringField(JNIEnv *env, jobject ths, char *fieldName);
jobject getObjectField(JNIEnv *env, jobject ths, char *fieldName,
char *objectPackage, char *objectClass);

#ifdef __cplusplus
}
#endif


#endif /* _jniUtils_H */


jniUtils.c, the wrapper for the JNI C interface. Note that not all types have been implemented. Also, error checking may not be performed in all scenarios. See that the "signature" for objects is broken up into package and class name.

#include <stdlib.h>
#include <string.h>
#include "jniUtils.h"

jint getIntegerField(JNIEnv *env, jobject ths, char *fieldName)
{
jclass c;
jfieldID fid;

c = (*env)->GetObjectClass(env, ths);
fid = (*env)->GetFieldID(env, c, fieldName, "I");
return (*env)->GetIntField(env, ths, fid);
}

void putIntegerField(JNIEnv *env, jobject ths, char *fieldName, jint ji)
{
jclass c;
jfieldID fid;

c = (*env)->GetObjectClass(env, ths);
fid = (*env)->GetFieldID(env, c, fieldName, "I");
(*env)->SetIntField(env, ths, fid, ji);
}

jstring getStringField(JNIEnv *env, jobject ths, char *fieldName)
{
jclass c;
jfieldID fid;

return (jstring) getObjectField(env, ths, fieldName, "java/lang", "String");
}

jobject getObjectField(JNIEnv *env, jobject ths, char *fieldName,
char *objectPackage, char *objectClass)
{
char *objectSignature;
jclass c;
jfieldID fid;
jobject objectField = 0;

objectSignature = (char *) malloc(strlen(objectPackage) + strlen(objectClass) + 10);

strcpy(objectSignature, "L");
strcat(objectSignature, objectPackage);
strcat(objectSignature, "/");
strcat(objectSignature, objectClass);
strcat(objectSignature, ";");
c = (*env)->GetObjectClass(env, ths);
fid = (*env)->GetFieldID(env, c, fieldName, objectSignature);

if(!fid) {
return 0;
}
objectField = (*env)->GetObjectField(env, ths, fid);

free(objectSignature);

return objectField;
}

Labels:

Passing an object including java Objects to a C library.

Very similar to including Java Strings:
The passed object, WebSiteVisit:
package helloworld;

/**
*
* @author thomas
*/
public class WebSiteVisit {
/** URL of the web page that linked user to this one */
public String refererURL;
public String pageVisited;
public int ipAddress;
IPAddress ipAddr;

/** Creates a new instance of WebSiteVisit */
public WebSiteVisit() {
}

public WebSiteVisit(String referer, String page, int ip) {
this.refererURL = referer;
this.ipAddress = ip;
this.pageVisited = page;
this.ipAddr = new IPAddress(ip);
}
}
The embedded object, IPAddress:
package helloworld;

/**
*
* @author thomas
*/
public class IPAddress {
public int byte1, byte2, byte3, byte4;
/** Creates a new instance of IPAddress */
public IPAddress() {
}
public IPAddress(int address) {
byte1 = (address & 0xff000000) >> 24;
byte2 = (address & 0x00ff0000) >> 16;
byte3 = (address & 0x0000ff00) >> 8;
byte4 = address & 0x000000ff;
}

}
The C source to the dynamic library, including the IPAddress object access.
JNIEXPORT void JNICALL Java_helloworld_Main_nativePrintNumber
(JNIEnv *env, jobject obj, jint ji)
{
jfieldID fid;
jint version;
jclass c;
c = (*env)->GetObjectClass(env, obj);
fid = (*env)->GetFieldID(env, c, "version_number", "I");
version = (*env)->GetIntField(env, obj, fid);
(*env)->SetIntField(env, obj, fid, ji*ji);
printf("::: %d, %d\n", fid, version);
hello_number(ji);
}
JNIEXPORT void JNICALL Java_helloworld_Main_nativePrintObject
(JNIEnv *env, jobject ths, jobject wsv)
{
jfieldID fid;
jint ipAddress;
jstring jPageVisited;
char *pageVisited;
jstring jRefererURL;
char *refererURL;
jclass c;
jobject ipObject;
jclass ipObjectClass;
jint byte1, byte2, byte3, byte4;

c = (*env)->GetObjectClass(env, wsv);

.
.
.

fid = (*env)->GetFieldID(env, c, "ipAddr", "Lhelloworld/IPAddress;");
if(!fid) {
return;
}
ipObject = (*env)->GetObjectField(env, wsv, fid);
ipObjectClass = (*env)->GetObjectClass(env, ipObject);

fid = (*env)->GetFieldID(env, ipObjectClass, "byte1", "I");
byte1 = (*env)->GetIntField(env, ipObject, fid);

fid = (*env)->GetFieldID(env, ipObjectClass, "byte2", "I");
byte2 = (*env)->GetIntField(env, ipObject, fid);

fid = (*env)->GetFieldID(env, ipObjectClass, "byte3", "I");
byte3 = (*env)->GetIntField(env, ipObject, fid);

fid = (*env)->GetFieldID(env, ipObjectClass, "byte4", "I");
byte4 = (*env)->GetIntField(env, ipObject, fid);

printf("wsv.ipAddr = %d.%d.%d.%d\ns", byte1, byte2, byte3, byte4);
}

Passing an object including java Strings to a C library using JNI.

Main.java, the class which calls the C function, passing the WebSiteVisit object

/**
*
* @author thomas
*/
public class Main {

private native void nativePrintObject(WebSiteVisit wsv);
/** Creates a new instance of Main */
public Main() {
}

static {
System.load("/home/thomas/testlib/HelloWorldNative/dist/HelloWorldNative.so");
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Main me = new Main();
WebSiteVisit a, b;
a = new WebSiteVisit("index.html", "subpage.html", 0x32389283);
b = new WebSiteVisit("subpage.html", "pagetwo.html", 0x32399283);

me.nativePrintObject(a);
me.nativePrintObject(b);
}

}
WebSiteVisit.java, the passed object:
package helloworld;

/**
*
* @author thomas
*/
public class WebSiteVisit {
/** URL of the web page that linked user to this one */
public String refererURL;
public String pageVisited;
public int ipAddress;

/** Creates a new instance of WebSiteVisit */
public WebSiteVisit() {
}

public WebSiteVisit(String referer, String page, int ip) {
this.refererURL = referer;
this.ipAddress = ip;
this.pageVisited = page;
}

}
The c function which receive the object:
JNIEXPORT void JNICALL Java_helloworld_Main_nativePrintObject
(JNIEnv *env, jobject ths, jobject wsv)
{
jfieldID fid;
jint ipAddress;
jstring jPageVisited;
char *pageVisited;
jstring jRefererURL;
char *refererURL;
jclass c;

c = (*env)->GetObjectClass(env, wsv);
fid = (*env)->GetFieldID(env, c, "ipAddress", "I");
ipAddress = (*env)->GetIntField(env, wsv, fid);
printf(" wsv.ipAddress = %d.%d.%d.%d\n",
( ipAddress & 0xff000000 ) >> 24,
( ipAddress & 0x00ff0000 ) >> 16,
( ipAddress & 0x0000ff00 ) >> 8,
ipAddress &amp; 0x000000ff);
fid = (*env)->GetFieldID(env, c, "pageVisited", "Ljava/lang/String;");
if(!fid) {
return;
}
jPageVisited = (*env)->GetObjectField(env, wsv, fid);
pageVisited = (*env)->GetStringUTFChars(env, jPageVisited, 0);

if(!pageVisited) {
return;
}
printf(" wsv.pageVisted = %s\n", pageVisited);

(*env)->ReleaseStringUTFChars(env, jPageVisited, pageVisited);

fid = (*env)->GetFieldID(env, c, "refererURL", "Ljava/lang/String;");
if(!fid) {
return;
}
jRefererURL = (*env)->GetObjectField(env, wsv, fid);
refererURL = (*env)->GetStringUTFChars(env, jRefererURL, 0);
printf(" wsv.refererURL = %s\n", refererURL);

(*env)->ReleaseStringUTFChars(env, jRefererURL, refererURL);
}

Passing an object including java Strings to a C library.

Main.java, the class which calls the C function, passing the WebSiteVisit object

/**
*
* @author thomas
*/
public class Main {

private native void nativePrintObject(WebSiteVisit wsv);
/** Creates a new instance of Main */
public Main() {
}

static {
System.load("/home/thomas/testlib/HelloWorldNative/dist/HelloWorldNative.so");
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Main me = new Main();
WebSiteVisit a, b;
a = new WebSiteVisit("index.html", "subpage.html", 0x32389283);
b = new WebSiteVisit("subpage.html", "pagetwo.html", 0x32399283);

me.nativePrintObject(a);
me.nativePrintObject(b);
}

}
WebSiteVisit.java, the passed object:
package helloworld;

/**
*
* @author thomas
*/
public class WebSiteVisit {
/** URL of the web page that linked user to this one */
public String refererURL;
public String pageVisited;
public int ipAddress;

/** Creates a new instance of WebSiteVisit */
public WebSiteVisit() {
}

public WebSiteVisit(String referer, String page, int ip) {
this.refererURL = referer;
this.ipAddress = ip;
this.pageVisited = page;
}

}
The c function which receive the object:
JNIEXPORT void JNICALL Java_helloworld_Main_nativePrintObject
(JNIEnv *env, jobject ths, jobject wsv)
{
jfieldID fid;
jint ipAddress;
jstring jPageVisited;
char *pageVisited;
jstring jRefererURL;
char *refererURL;
jclass c;

c = (*env)->GetObjectClass(env, wsv);
fid = (*env)->GetFieldID(env, c, "ipAddress", "I");
ipAddress = (*env)->GetIntField(env, wsv, fid);
printf(" wsv.ipAddress = %d.%d.%d.%d\n",
( ipAddress & 0xff000000 ) >> 24,
( ipAddress & 0x00ff0000 ) >> 16,
( ipAddress & 0x0000ff00 ) >> 8,
ipAddress & 0x000000ff);
fid = (*env)->GetFieldID(env, c, "pageVisited", "Ljava/lang/String;");
if(!fid) {
return;
}
jPageVisited = (*env)->GetObjectField(env, wsv, fid);
pageVisited = (*env)->GetStringUTFChars(env, jPageVisited, 0);

if(!pageVisited) {
return;
}
printf(" wsv.pageVisted = %s\n", pageVisited);

(*env)->ReleaseStringUTFChars(env, jPageVisited, pageVisited);

fid = (*env)->GetFieldID(env, c, "refererURL", "Ljava/lang/String;");
if(!fid) {
return;
}
jRefererURL = (*env)->GetObjectField(env, wsv, fid);
refererURL = (*env)->GetStringUTFChars(env, jRefererURL, 0);
printf(" wsv.refererURL = %s\n", refererURL);

(*env)->ReleaseStringUTFChars(env, jRefererURL, refererURL);
}

Java Native Interface - setting and retrieving object fields

My reference: Java Native Interface

This table was specifically handy:
Java Type JNI Type machine dependent
C/C++ typedef
SignatureCall...Method
Get...Field
booleanjbooleanunsigned char ZBoolean
byte jbyte signed char BByte
char jchar unsigned shortCChar
short jshort short SShort
int jint int IInt
long jlong long JLong
float jfloat float FFloat
double jdouble double DDouble
void void VVoid
nonprimitive jobject *...L...;Object

Examples
method definitionsignature
int m1 ()()I
double m2 (long l, char c)(JC)D
void m3 (String s, int[] a)(Ljava/lang/String;[I)V
String m4 (boolean b)(Z)Ljava/lang/String;
Object m4 (BigDecimal b)(Ljava/math/BigDecimal;)Ljava/lang/Object;

My code testing implementing this field access:

HelloWorldNative.c (builds into .so linked from Java)
JNIEXPORT void JNICALL Java_helloworld_Main_nativePrintNumber
(JNIEnv *env, jobject obj, jint ji)
{
jfieldID fid;
jint version;
jclass c;
c = (*env)->GetObjectClass(env, obj);
fid = (*env)->GetFieldID(env, c, "version_number", "I");
version = (*env)->GetIntField(env, obj, fid);
(*env)->SetIntField(env, obj, fid, ji*ji);
printf("::: %d, %d\n", fid, version);
hello_number(ji);
}
My Main.java, which the version_number integer field:
package helloworld;

/**
*
* @author thomas
*/
public class Main {
public int version_number;
private native void nativePrint();
private native void nativePrintNumber(int i);
/** Creates a new instance of Main */
public Main() {
version_number = 5;
}

static {
System.load("/home/thomas/testlib/HelloWorldNative/dist/HelloWorldNative.so");
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Main me = new Main();
me.nativePrint();
me.nativePrintNumber(2);
me.nativePrintNumber(5);
me.nativePrintNumber(3);
// TODO code application logic here
}
}

Friday, February 09, 2007

JNI Types and Data Structures

Attempting to continue from experiments begun here.

JNI Types and Data Structures