📄 databasejni.java
字号:
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) { throw new CliException(x.getMessage()); } return buf; } public void update(long oid, Object obj) { Class c = obj.getClass(); ClassDescriptor desc = (ClassDescriptor)classes.get(c); if (desc == null) { throw new CliException("Table not found: " + c); } jniUpdate(db, oid, desc.td, swizzleObject(desc, obj)); } public long insert(Object obj) { Class c = obj.getClass(); String table = c.getName(); ClassDescriptor desc = (ClassDescriptor)classes.get(c); if (desc == null) { desc = new ClassDescriptor(c); classes.put(c, desc); desc.td = jniCreateTable(db, table, getTableDescriptor(desc)); } return jniInsert(db, desc.td, swizzleObject(desc, obj)); } public int delete(Class table, String condition) { ClassDescriptor desc = (ClassDescriptor)classes.get(table); if (desc == null) { throw new CliException("Table not found: " + table); } return jniDelete(db, desc.td, condition); } public void commit() { jniCommit(db); } public void rollback() { jniRollback(db); } public void lock() { jniLock(db); } public void attach() { jniAttach(db); } public void detach(int flags) { jniDetach(db, flags); } private long getTableDescriptor(ClassDescriptor desc) { String[] fieldNames = desc.getFieldNames(); try { ConstraintParser constraintParser = new ConstraintParser(fieldNames, desc.getConstraints()); return jniCreateTableDescriptor(db, desc.cls.getName(), fieldNames, desc.types, constraintParser.getReferencedTables(), constraintParser.getInverseFields(), constraintParser.getConstraintMasks()); } catch (Exception x) { throw new CliException(x.getMessage()); } } public void setThreadContext(long ctx) { jniSetThreadContext(db, ctx); } public long getThreadContext() { return jniGetThreadContext(db); } public DatabaseJNI() { this(false); } public DatabaseJNI(boolean remote) { this.remote = remote; } native long jniOpen(int accessType, String databaseName, String databasePath, long initSize, int transactionCommitDelay); native void jniClose(long db); native String jniNextTable(long db); native void jniSetByte(long buf, byte v); native void jniSetShort(long buf, short v); native void jniSetInt(long buf, int v); native void jniSetLong(long buf, long v); native void jniSetString(long buf, String v); native void jniSetBoolArray(long buf, boolean[] v); native void jniSetCharArray(long buf, char[] v); native void jniSetByteArray(long buf, byte[] v); native void jniSetShortArray(long buf, short[] v); native void jniSetIntArray(long buf, int[] v); native void jniSetLongArray(long buf, long[] v); native void jniSetFloatArray(long buf, float[] v); native void jniSetDoubleArray(long buf, double[] v); native void jniSetStringArray(long buf, String[] v); native long jniCreateBuffer(); native long jniCreateTable(long db, String table, long desc); native long jniUpdateTable(long db, String table, long desc); native long jniNext(long cursor); native byte jniGetByte(long cursor); native short jniGetShort(long cursor); native int jniGetInt(long cursor); native long jniGetLong(long cursor); native String jniGetString(long cursor); native boolean[] jniGetBoolArray(long cursor); native char[] jniGetCharArray(long cursor); native byte[] jniGetByteArray(long cursor); native short[] jniGetShortArray(long cursor); native int[] jniGetIntArray(long cursor); native long[] jniGetLongArray(long cursor); native float[] jniGetFloatArray(long cursor); native double[] jniGetDoubleArray(long cursor); native String[] jniGetStringArray(long cursor); native void jniCloseCursor(long cursor); native void jniUpdate(long db, long oid, long tableDescriptor, long buf); native long jniInsert(long db, long tableDescriptor, long buf); native long jniSelect(long db, long tableDescriptor, String condition); native int jniDelete(long db, long tableDescriptor, String condition); native int jniGetNumberOfSelectedRecords(long cursor); native void jniCommit(long db); native void jniRollback(long db); native void jniLock(long db); native long jniGetThreadContext(long db); native void jniSetThreadContext(long db, long context); native void jniAttach(long db); native void jniDetach(long db, int flags); native long jniCreateTableDescriptor(long db, String table, String[] fields, int[] types, String[] referencedTables, String[] inverseFields, int[] constraintMasks); static { //System.out.println("Before loading jnicli"); Runtime.getRuntime().loadLibrary("jnicli"); //System.out.println("After loading jnicli"); } final static int TP_BOOL = 1; final static int TP_CHAR = 2; final static int TP_INT1 = 3; final static int TP_INT2 = 4; final static int TP_INT4 = 5; final static int TP_INT8 = 6; final static int TP_REAL4 = 7; final static int TP_REAL8 = 8; final static int TP_STRING = 9; final static int TP_DATE = 10; final static int TP_BOOL_ARRAY = 11; final static int TP_CHAR_ARRAY = 12; final static int TP_INT1_ARRAY = 13; final static int TP_INT2_ARRAY = 14; final static int TP_INT4_ARRAY = 15; final static int TP_INT8_ARRAY = 16; final static int TP_REAL4_ARRAY = 17; final static int TP_REAL8_ARRAY = 18; final static int TP_STRING_ARRAY = 19; long db; Hashtable classes; boolean remote;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -