package jnicli;
import java.lang.reflect.*;
import java.util.*;
/**
* Interface to database using Java native interface.
* This class should be used by applications accessing database locally
*/
public class DatabaseJNI implements Database {
public void open(int accessType, String databaseName, String databasePath, long initSize, int transactionCommitDelay) {
db = jniOpen(accessType, databaseName, databasePath, initSize, transactionCommitDelay);
String table;
classes = new Hashtable();
while ((table = jniNextTable(db)) != null) {
try {
Class c = Class.forName(table);
ClassDescriptor desc = new ClassDescriptor(c);
classes.put(c, desc);
desc.td = jniUpdateTable(db, table, getTableDescriptor(desc));
} catch (ClassNotFoundException x) {
new CliException("Class '" + table + "' not found");
} catch (Exception x) {
new CliException(x.getMessage());
}
}
}
public void close() {
jniClose(db);
classes = null;
}
public Cursor select(Class table, String condition, int flags) {
ClassDescriptor desc = (ClassDescriptor)classes.get(table);
if (desc == null) {
throw new CliException("Table not found: " + table);
}
long result = jniSelect(db, desc.td, condition);
Cursor cursor;
if (remote || (flags & AUTOCOMMIT) != 0) {
cursor = new PrefetchedCursor(this, result, desc);
if ((flags & AUTOCOMMIT) != 0) {
jniCommit(db);
}
} else {
cursor = (flags & FOR_UPDATE) != 0
? (Cursor)new IncrementalCursorForUpdate(this, result, desc)
: (Cursor)new IncrementalCursor(this, result, desc);
}
return cursor;
}
Object unswizzleObject(long cursor, ClassDescriptor desc) {
int[] types = desc.types;
Field[] fields = desc.fields;
try {
Object obj = desc.newInstance();
for (int i = 0; i < types.length; i++) {
Field f = fields[i];
switch (types[i]) {
case TP_BOOL:
f.setBoolean(obj, jniGetByte(cursor) != 0);
continue;
case TP_CHAR:
f.setChar(obj, (char)jniGetShort(cursor));
continue;
case TP_INT1:
f.setByte(obj, jniGetByte(cursor));
continue;
case TP_INT2:
f.setShort(obj, jniGetShort(cursor));
continue;
case TP_INT4:
f.setInt(obj, jniGetInt(cursor));
continue;
case TP_INT8:
f.setLong(obj, jniGetLong(cursor));
continue;
case TP_REAL4:
f.setFloat(obj, Float.intBitsToFloat(jniGetInt(cursor)));
continue;
case TP_REAL8:
f.setDouble(obj, Double.longBitsToDouble(jniGetLong(cursor)));
continue;
case TP_STRING:
f.set(obj, jniGetString(cursor));
continue;
case TP_DATE:
{
long timestamp = jniGetLong(cursor);
f.set(obj, timestamp < 0 ? null : new Date(timestamp));
continue;
}
case TP_BOOL_ARRAY:
f.set(obj, jniGetBoolArray(cursor));
continue;
case TP_CHAR_ARRAY:
f.set(obj, jniGetCharArray(cursor));
continue;
case TP_INT1_ARRAY:
f.set(obj, jniGetByteArray(cursor));
continue;
case TP_INT2_ARRAY:
f.set(obj, jniGetShortArray(cursor));
continue;
case TP_INT4_ARRAY:
f.set(obj, jniGetIntArray(cursor));
continue;
case TP_INT8_ARRAY:
f.set(obj, jniGetLongArray(cursor));
continue;
case TP_REAL4_ARRAY:
f.set(obj, jniGetFloatArray(cursor));
continue;
case TP_REAL8_ARRAY:
f.set(obj, jniGetDoubleArray(cursor));
continue;
case TP_STRING_ARRAY:
f.set(obj, jniGetStringArray(cursor));
continue;
default:
throw new CliException("Invalid field type: " + types[i]);
}
}
return obj;
} catch (Exception x) {
throw new CliException(x.getMessage());
}
}
private long swizzleObject(ClassDescriptor desc, Object obj) {
long buf = jniCreateBuffer();
int[] types = desc.types;
Field[] fields = desc.fields;
try {
for (int i = 0; i < types.length; i++) {
Field f = fields[i];
switch (types[i]) {
case TP_BOOL:
jniSetByte(buf, (byte)(f.getBoolean(obj) ? 1 : 0));
continue;
case TP_CHAR:
jniSetShort(buf, (short)f.getChar(obj));
continue;
case TP_INT1:
jniSetByte(buf, f.getByte(obj));
continue;
case TP_INT2:
jniSetShort(buf, f.getShort(obj));
continue;
case TP_INT4:
jniSetInt(buf, f.getInt(obj));
continue;
case TP_INT8:
jniSetLong(buf, f.getLong(obj));
continue;
case TP_REAL4:
jniSetInt(buf, Float.floatToIntBits(f.getFloat(obj)));
continue;
case TP_REAL8:
jniSetLong(buf, Double.doubleToLongBits(f.getDouble(obj)));
continue;
case TP_STRING:
jniSetString(buf, (String)f.get(obj));
continue;
case TP_DATE:
{
Date d = (Date)f.get(obj);
jniSetLong(buf, d != null ? d.getTime() : -1);
continue;
}
case TP_BOOL_ARRAY:
jniSetBoolArray(buf, (boolean[])f.get(obj));
continue;
case TP_CHAR_ARRAY:
jniSetCharArray(buf, (char[])f.get(obj));
continue;
case TP_INT1_ARRAY:
jniSetByteArray(buf, (byte[])f.get(obj));
continue;
case TP_INT2_ARRAY:
jniSetShortArray(buf, (short[])f.get(obj));
continue;
case TP_INT4_ARRAY:
jniSetIntArray(buf, (int[])f.get(obj));
continue;
case TP_INT8_ARRAY:
jniSetLongArray(buf, (long[])f.get(obj));
continue;
case TP_REAL4_ARRAY:
jniSetFloatArray(buf, (float[])f.get(obj));
continue;
case TP_REAL8_ARRAY:
jniSetDoubleArray(buf, (double[])f.get(obj));
continue;
case TP_STRING_ARRAY:
jniSetStringArray(buf, (String[])f.get(obj));
continue;
default:
throw new CliException("Invalid field type: " + types[i]);
}
}
} catch (Exception x)