summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@wiredtiger.com>2012-07-07 01:27:47 +1000
committerMichael Cahill <michael.cahill@wiredtiger.com>2012-07-07 01:27:47 +1000
commit5791f5b8647e9d8623ace70b92f5af196cf43bc2 (patch)
treec873b2989d23116a19ec8cecacc6458cad34005b
parent1fb879844911a83588db25a2ce23a7b7cd104e28 (diff)
downloadmongo-5791f5b8647e9d8623ace70b92f5af196cf43bc2.tar.gz
imported patch java-api
--HG-- rename : lang/python/Makefile.am => lang/java/Makefile.am rename : lang/python/wiredtiger.i => lang/java/wiredtiger.i
-rw-r--r--build_posix/Make.subdirs1
-rw-r--r--build_posix/aclocal/options.m416
-rw-r--r--build_posix/configure.ac.in5
-rw-r--r--examples/java/Makefile.am0
-rw-r--r--examples/java/ex_access.java17
-rw-r--r--lang/java/DbException.java7
-rw-r--r--lang/java/Makefile.am31
-rw-r--r--lang/java/wiredtiger.i326
8 files changed, 401 insertions, 2 deletions
diff --git a/build_posix/Make.subdirs b/build_posix/Make.subdirs
index cd60340426f..a993569fcc2 100644
--- a/build_posix/Make.subdirs
+++ b/build_posix/Make.subdirs
@@ -11,6 +11,7 @@ ext/collators/reverse
ext/compressors/bzip2_compress BZIP2
ext/compressors/nop_compress
ext/compressors/snappy_compress SNAPPY
+lang/java JAVA
lang/python PYTHON
test/checkpoint
test/fops
diff --git a/build_posix/aclocal/options.m4 b/build_posix/aclocal/options.m4
index 64f0f0bacb3..f235b5024e8 100644
--- a/build_posix/aclocal/options.m4
+++ b/build_posix/aclocal/options.m4
@@ -46,10 +46,24 @@ no) wt_cv_enable_diagnostic=no;;
esac
AC_MSG_RESULT($wt_cv_enable_diagnostic)
+AC_MSG_CHECKING(if --enable-java option specified)
+AC_ARG_ENABLE(java,
+ [AC_HELP_STRING([--enable-java],
+ [Configure the Java API.])], r=$enableval, r=no)
+case "$r" in
+no) wt_cv_enable_java=no;;
+*) if test "$enable_shared" = "no"; then
+ AC_MSG_ERROR([--enable-java requires shared libraries])
+ fi
+ wt_cv_enable_java=yes;;
+esac
+AC_MSG_RESULT($wt_cv_enable_java)
+AM_CONDITIONAL([JAVA], [test x$wt_cv_enable_java = xyes])
+
AC_MSG_CHECKING(if --enable-python option specified)
AC_ARG_ENABLE(python,
[AC_HELP_STRING([--enable-python],
- [Configure for python symbols.])], r=$enableval, r=no)
+ [Configure the python API.])], r=$enableval, r=no)
case "$r" in
no) wt_cv_enable_python=no;;
*) if test "$enable_shared" = "no"; then
diff --git a/build_posix/configure.ac.in b/build_posix/configure.ac.in
index 2255e8f2329..3f12afe4c04 100644
--- a/build_posix/configure.ac.in
+++ b/build_posix/configure.ac.in
@@ -50,9 +50,12 @@ fi
AM_CONDITIONAL([DEBUG], [test "$wt_cv_enable_debug" = "yes"])
-# Python API
+# Java and Python APIs
if test "$wt_cv_enable_python" = "yes"; then
AM_PATH_PYTHON([2.6])
+fi
+
+if test "$wt_cv_enable_java" = "yes" -o "$wt_cv_enable_python" = "yes"; then
AC_PATH_PROG([SWIG], [swig], [swig])
fi
diff --git a/examples/java/Makefile.am b/examples/java/Makefile.am
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/examples/java/Makefile.am
diff --git a/examples/java/ex_access.java b/examples/java/ex_access.java
new file mode 100644
index 00000000000..568919ed9c7
--- /dev/null
+++ b/examples/java/ex_access.java
@@ -0,0 +1,17 @@
+import com.wiredtiger.db.*;
+
+public class ex_access {
+ public static void main(String[] args) {
+ Connection conn = wiredtiger.open("WT_HOME", "create");
+ Session s = conn.open_session(null);
+ s.create("table:t", "key_format=S,value_format=u");
+ Cursor c = s.open_cursor("table:t", null, null);
+ c.set_key("foo");
+ c.set_value("bar".getBytes());
+ c.insert();
+ c.reset();
+ while (c.next() == 0)
+ System.out.println("Got: " + c.get_key());
+ conn.close(null);
+ }
+}
diff --git a/lang/java/DbException.java b/lang/java/DbException.java
new file mode 100644
index 00000000000..8daf0da4c6f
--- /dev/null
+++ b/lang/java/DbException.java
@@ -0,0 +1,7 @@
+package com.wiredtiger.db;
+
+public class DbException extends Exception {
+ public DbException(String msg) {
+ super(msg);
+ }
+}
diff --git a/lang/java/Makefile.am b/lang/java/Makefile.am
new file mode 100644
index 00000000000..344754046ee
--- /dev/null
+++ b/lang/java/Makefile.am
@@ -0,0 +1,31 @@
+JAVA_HOME = `/usr/libexec/java_home`
+
+INCLUDES = -I$(abs_top_builddir) \
+ -I$(JAVA_HOME)/include \
+ -I$(JAVA_HOME)/include/`uname | tr A-Z a-z`
+
+JAVASRC = $(top_srcdir)/lang/java
+BUILT_SOURCES = $(JAVASRC)/wiredtiger_wrap.c
+SWIG_SOURCES = $(JAVASRC)/wiredtiger.i
+
+javadir = $(datadir)/java
+dist_java_JAVA = \
+ Connection.java \
+ Cursor.java \
+ DbException.java \
+ SearchStatus.java \
+ Session.java \
+ wiredtiger.java \
+ wiredtigerConstants.java \
+ wiredtigerJNI.java
+java_LTLIBRARIES = libwiredtiger_java.la
+
+# Some warnings when compiling the generated code are unavoidable
+CFLAGS += -w
+libwiredtiger_java_la_SOURCES = $(BUILT_SOURCES) $(SWIG_SOURCES)
+#libwiredtiger_java_la_LDFLAGS = -module
+libwiredtiger_java_la_LIBADD = $(abs_top_builddir)/libwiredtiger.la
+
+$(JAVASRC)/wiredtiger_wrap.c: $(top_srcdir)/src/include/wiredtiger.in $(SWIG_SOURCES)
+ (cd $(JAVASRC) && \
+ $(SWIG) -Wall -v -java -nodefaultctor -nodefaultdtor -package com.wiredtiger.db -I$(abs_top_builddir) -o wiredtiger_wrap.c wiredtiger.i)
diff --git a/lang/java/wiredtiger.i b/lang/java/wiredtiger.i
new file mode 100644
index 00000000000..9c9a02ca5fb
--- /dev/null
+++ b/lang/java/wiredtiger.i
@@ -0,0 +1,326 @@
+/*-
+ * Copyright (c) 2008-2012 WiredTiger, Inc.
+ * All rights reserved.
+ *
+ * See the file LICENSE for redistribution information.
+ *
+ * wiredtiger.i
+ * The SWIG interface file defining the wiredtiger Java API.
+ */
+
+%module wiredtiger
+
+%include "enums.swg"
+%include "typemaps.i"
+
+%pragma(java) jniclasscode=%{
+ static {
+ try {
+ System.loadLibrary("wiredtiger_java");
+ } catch (UnsatisfiedLinkError e) {
+ System.err.println("Native code library failed to load. \n" + e);
+ System.exit(1);
+ }
+ }
+%}
+
+%{
+static void throwDbException(JNIEnv *jenv, const char *msg) {
+ jclass excep = (*jenv)->FindClass(jenv, "com/wiredtiger/db/DbException");
+ if (excep)
+ (*jenv)->ThrowNew(jenv, excep, msg);
+}
+%}
+
+/* No finalizers */
+%typemap(javafinalize) SWIGTYPE ""
+
+/* Event handlers are not supported in Java. */
+%typemap(in, numinputs=0) WT_EVENT_HANDLER * %{ $1 = NULL; %}
+
+/* Allow silently passing the Java object and JNIEnv into our code. */
+%typemap(in, numinputs=0) jobject *jthis %{ $1 = jarg1_; %}
+%typemap(in, numinputs=0) JNIEnv * %{ $1 = jenv; %}
+
+/* 64 bit typemaps. */
+%typemap(jni) uint64_t "jlong"
+%typemap(jtype) uint64_t "long"
+%typemap(jstype) uint64_t "long"
+
+%typemap(javain) uint64_t "$javainput"
+%typemap(javaout) uint64_t {
+ return $jnicall;
+}
+
+/* Return byte[] from cursor.get_value */
+%typemap(jni) WT_ITEM * "jbyteArray"
+%typemap(jtype) WT_ITEM * "byte[]"
+%typemap(jstype) WT_ITEM * "byte[]"
+
+%typemap(javain) WT_ITEM * "$javainput"
+%typemap(javaout) WT_ITEM * {
+ return $jnicall;
+}
+
+%typemap(in) WT_ITEM * (WT_ITEM item) %{
+ $1 = &item;
+ $1->data = (*jenv)->GetByteArrayElements(jenv, $input, 0);
+ $1->size = (*jenv)->GetArrayLength(jenv, $input);
+%}
+
+%typemap(argout) WT_ITEM * %{
+ (*jenv)->ReleaseByteArrayElements(jenv, $input, $1->data, 0);
+%}
+
+%typemap(out) WT_ITEM * %{
+ if (($result = (*jenv)->NewByteArray(jenv, $1->size)) != NULL) {
+ (*jenv)->SetByteArrayRegion(jenv,
+ $result, 0, $1->size, $1->data);
+ }
+%}
+
+/* Don't require empty config strings. */
+%typemap(default) const char *config %{ $1 = NULL; %}
+
+%typemap(out) int %{
+ if ($1 != 0 && $1 != WT_NOTFOUND) {
+ throwDbException(jenv, wiredtiger_strerror($1));
+ return $null;
+ }
+ $result = $1;
+%}
+
+/*
+ * Extra 'self' elimination.
+ * The methods we're wrapping look like this:
+ * struct __wt_xxx {
+ * int method(WT_XXX *, ...otherargs...);
+ * };
+ * To SWIG, that is equivalent to:
+ * int method(struct __wt_xxx *self, WT_XXX *, ...otherargs...);
+ * and we use consecutive argument matching of typemaps to convert two args to
+ * one.
+ */
+%define SELFHELPER(type, name)
+%typemap(in, numinputs=0) type *name "$1 = *(type **)&jarg1;"
+%enddef
+
+SELFHELPER(struct __wt_connection, connection)
+SELFHELPER(struct __wt_session, session)
+SELFHELPER(struct __wt_cursor, cursor)
+
+/* WT_CURSOR customization. */
+/* First, replace the varargs get / set methods with Java equivalents. */
+%ignore __wt_cursor::get_key;
+%ignore __wt_cursor::get_value;
+%ignore __wt_cursor::set_key;
+%ignore __wt_cursor::set_value;
+%ignore __wt_cursor::insert;
+%ignore __wt_cursor::remove;
+%ignore __wt_cursor::search;
+%ignore __wt_cursor::search_near;
+%ignore __wt_cursor::update;
+%javamethodmodifiers __wt_cursor::next "protected";
+%rename (next_wrap) __wt_cursor::next;
+%javamethodmodifiers __wt_cursor::prev "protected";
+%rename (prev_wrap) __wt_cursor::prev;
+
+/* SWIG magic to turn Java byte strings into data / size. */
+%apply (char *STRING, int LENGTH) { (char *data, int size) };
+
+/* Status from search_near */
+%javaconst(1);
+%inline %{
+enum SearchStatus { FOUND, NOTFOUND, SMALLER, LARGER };
+%}
+
+%extend __wt_cursor {
+ %javamethodmodifiers get_key_wrap "protected";
+ WT_ITEM *get_key_wrap() {
+ WT_ITEM k;
+ (void)$self->get_key($self, &k);
+ return &$self->key;
+ }
+
+ %javamethodmodifiers get_value_wrap "protected";
+ WT_ITEM *get_value_wrap() {
+ WT_ITEM v;
+ (void)$self->get_value($self, &v);
+ return &$self->value;
+ }
+
+ %javamethodmodifiers insert_wrap "protected";
+ int insert_wrap(WT_ITEM *k, WT_ITEM *v) {
+ $self->set_key($self, k);
+ $self->set_value($self, v);
+ return $self->insert($self);
+ }
+
+ %javamethodmodifiers remove_wrap "protected";
+ int remove_wrap(WT_ITEM *k) {
+ $self->set_key($self, k);
+ return $self->remove($self);
+ }
+
+ %javamethodmodifiers search_wrap "protected";
+ int search_wrap(WT_ITEM *k) {
+ $self->set_key($self, k);
+ return $self->search($self);
+ }
+
+ %javamethodmodifiers search_near_wrap "protected";
+ enum SearchStatus search_near_wrap(JNIEnv *jenv, WT_ITEM *k) {
+ int cmp, ret;
+
+ $self->set_key($self, k);
+ ret = $self->search_near(self, &cmp);
+ if (ret != 0 && ret != WT_NOTFOUND)
+ throwDbException(jenv, wiredtiger_strerror(ret));
+ if (ret == 0)
+ return (cmp == 0 ? FOUND : cmp < 0 ? SMALLER : LARGER);
+ return (NOTFOUND);
+ }
+
+ %javamethodmodifiers update_wrap "protected";
+ int update_wrap(WT_ITEM *k, WT_ITEM *v) {
+ $self->set_key($self, k);
+ $self->set_value($self, v);
+ return $self->insert($self);
+ }
+}
+
+%typemap(javacode) struct __wt_cursor %{
+ protected byte[] key;
+ protected byte[] value;
+
+ public void set_key(String key) {
+ this.key = key.getBytes();
+ }
+
+ public String get_key() {
+ return new String(key);
+ }
+
+ public void set_value(byte[] value) {
+ this.value = value;
+ }
+
+ public byte[] get_value() {
+ return this.value;
+ }
+
+ public int insert() {
+ return insert_wrap(key, value);
+ }
+
+ public int update() {
+ return update_wrap(key, value);
+ }
+
+ public int remove() {
+ return remove_wrap(key);
+ }
+
+ public int next() {
+ int ret = next_wrap();
+ key = (ret == 0) ? get_key_wrap() : null;
+ value = (ret == 0) ? get_value_wrap() : null;
+ return ret;
+ }
+
+ public int prev() {
+ int ret = prev_wrap();
+ key = (ret == 0) ? get_key_wrap() : null;
+ value = (ret == 0) ? get_value_wrap() : null;
+ return ret;
+ }
+ public int search() {
+ int ret = search_wrap(key);
+ key = (ret == 0) ? get_key_wrap() : null;
+ value = (ret == 0) ? get_value_wrap() : null;
+ return ret;
+ }
+
+ public SearchStatus search_near() {
+ SearchStatus ret = search_near_wrap(key);
+ key = (ret != SearchStatus.NOTFOUND) ? get_key_wrap() : null;
+ value = (ret != SearchStatus.NOTFOUND) ? get_value_wrap() : null;
+ return ret;
+ }
+%}
+
+/* Remove / rename parts of the C API that we don't want in Java. */
+%immutable __wt_cursor::session;
+%immutable __wt_cursor::uri;
+%immutable __wt_cursor::key_format;
+%immutable __wt_cursor::value_format;
+%immutable __wt_session::connection;
+
+%ignore __wt_collator;
+%ignore __wt_connection::add_collator;
+%ignore __wt_compressor;
+%ignore __wt_connection::add_compressor;
+%ignore __wt_data_source;
+%ignore __wt_connection::add_data_source;
+%ignore __wt_event_handler;
+%ignore __wt_extractor;
+%ignore __wt_connection::add_extractor;
+%ignore __wt_item;
+%ignore __wt_session::msg_printf;
+
+%ignore wiredtiger_struct_pack;
+%ignore wiredtiger_struct_packv;
+%ignore wiredtiger_struct_size;
+%ignore wiredtiger_struct_sizev;
+%ignore wiredtiger_struct_unpack;
+%ignore wiredtiger_struct_unpackv;
+
+%ignore wiredtiger_version;
+
+%ignore wiredtiger_extension_init;
+
+%ignore wiredtiger_open;
+%rename(open) wiredtiger_open_wrap;
+%ignore __wt_connection::open_session;
+%rename(open_session) __wt_connection::open_session_wrap;
+%ignore __wt_session::open_cursor;
+%rename(open_cursor) __wt_session::open_cursor_wrap;
+
+%rename(Cursor) __wt_cursor;
+%rename(Session) __wt_session;
+%rename(Connection) __wt_connection;
+
+%include "wiredtiger.h"
+
+/* Return new connections, sessions and cursors. */
+%inline {
+WT_CONNECTION *wiredtiger_open_wrap(JNIEnv *jenv, const char *home, const char *config) {
+ WT_CONNECTION *conn = NULL;
+ int ret;
+ if ((ret = wiredtiger_open(home, NULL, config, &conn)) != 0)
+ throwDbException(jenv, wiredtiger_strerror(ret));
+ return conn;
+}
+}
+
+%extend __wt_connection {
+ WT_SESSION *open_session_wrap(JNIEnv *jenv, const char *config) {
+ WT_SESSION *session = NULL;
+ int ret;
+ if ((ret = $self->open_session($self, NULL, config, &session)) != 0)
+ throwDbException(jenv, wiredtiger_strerror(ret));
+ return session;
+ }
+}
+
+%extend __wt_session {
+ WT_CURSOR *open_cursor_wrap(JNIEnv *jenv, const char *uri, WT_CURSOR *to_dup, const char *config) {
+ WT_CURSOR *cursor = NULL;
+ int ret;
+ if ((ret = $self->open_cursor($self, uri, to_dup, config, &cursor)) != 0)
+ throwDbException(jenv, wiredtiger_strerror(ret));
+ else
+ cursor->flags |= WT_CURSTD_RAW;
+ return cursor;
+ }
+}