[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: SWIG Java bindings

From: Daniel Rall <dlr_at_finemaltcoding.com>
Date: 2002-10-16 18:17:10 CEST

Morten Ludvigsen <morten_2ps_dk@yahoo.co.uk> writes:

> Is anyone actively working on SWIG-Java bindings?
>
> If not I think I will take a crack at it :-)

Hi Morten. I've done a small amount of work on them. What I have is
swigging successfully, but may not compile (haven't tried yet) and
surely won't run (a lot of it is still incomplete/stubbed/broken). I
hope it's a useful starting place for you, and am very interested in
seeing some diffs with what ever progress you find time to make.
Hopefully I'll have time to help out a little more as well.

-- 
Daniel Rall <dlr@finemaltcoding.com>
Index: ./svn_types.i
===================================================================
--- ./svn_types.i
+++ ./svn_types.i	Wed Oct 16 09:01:38 2002
@@ -83,6 +83,9 @@
     $1 = PyString_AS_STRING($input);
     $2 = PyString_GET_SIZE($input);
 }
+%typemap(java, in) (const char *PTR, apr_size_t LEN) {
+    /* FIXME: This is just a stub -- implement JNI code! */
+}
 
 /* -----------------------------------------------------------------------
    Define a generic arginit mapping for pools.
Index: ./svn_string.i
===================================================================
--- ./svn_string.i
+++ ./svn_string.i	Wed Oct 16 09:01:03 2002
@@ -42,6 +42,10 @@
     }
     $result = t_output_helper($result, s);
 }
+%typemap(java,argout,fragment="t_output_helper") RET_STRING {
+    /* FIXME: This is just a stub -- implement JNI code! */
+    return NULL;
+}
 
 /* -----------------------------------------------------------------------
    TYPE: svn_stringbuf_t
@@ -137,5 +141,8 @@
     if ($1 == NULL)
         return NULL;
 }
+%typemap(java,in) const apr_array_header_t *STRINGLIST {
+    /* FIXME: This is just a stub -- implement JNI code! */
+}
 
 /* ----------------------------------------------------------------------- */
Index: ./svn_fs.i
===================================================================
--- ./svn_fs.i
+++ ./svn_fs.i	Fri Oct 11 19:46:41 2002
@@ -113,4 +113,8 @@
 #ifdef SWIGPYTHON
 #include "swigutil_py.h"
 #endif
+
+#ifdef SWIGJAVA
+#include "swigutil_java.h"
+#endif
 %}
Index: ./swigutil_java.c
===================================================================
--- ./swigutil_java.c
+++ ./swigutil_java.c	Fri Oct 11 19:24:04 2002
@@ -0,0 +1,602 @@
+/*
+ * swigutil_java.c: utility functions for the SWIG Java bindings
+ *
+ * ====================================================================
+ * Copyright (c) 2000-2002 CollabNet.  All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution.  The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals.  For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+
+#include <jni.h>
+
+#include <apr_pools.h>
+#include <apr_hash.h>
+
+#include "svn_string.h"
+#include "svn_delta.h"
+
+#include "swigutil_java.h"
+
+
+/* this baton is used for the editor, directory, and file batons. */
+typedef struct {
+  jobject editor;     /* the editor handling the callbacks */
+  jobject baton;      /* the dir/file baton (or NULL for edit baton) */
+  apr_pool_t *pool;     /* pool to use for errors */
+} item_baton;
+
+typedef struct {
+  jobject handler;    /* the window handler (a callable) */
+  apr_pool_t *pool;     /* a pool for constructing errors */
+} handler_baton;
+
+
+static jobject make_pointer(const char *typename, void *ptr)
+{
+  /* ### cache the swig_type_info at some point? */
+  return SWIG_NewPointerObj(ptr, SWIG_TypeQuery(typename), 0);
+}
+
+/* for use by the "O&" format specifier */
+static jobject make_ob_pool(void *ptr)
+{
+  return make_pointer("apr_pool_t *", ptr);
+}
+
+/* for use by the "O&" format specifier */
+static jobject make_ob_window(void *ptr)
+{
+  return make_pointer("svn_txdelta_window_t *", ptr);
+}
+
+static jobject convert_hash(apr_hash_t *hash,
+                            jobject  (*converter_func)(void *value,
+                                                       void *ctx),
+                            void *ctx)
+{
+  apr_hash_index_t *hi;
+  jclass cls = JCALL1(FindClass, jenv, "java/util/HashMap");
+  jobject dict = JCALL3(NewObject, jenv, cls,
+                        JCALL3(GetMethodID, jenv, cls, "<init>", "(I)V"),
+                        (jint) apr_hash_count(hash));
+  jmethoID put = JCALL3(GetMethodID, jenv, cls, "put",
+                        "(Ljava/lang/Object;Ljava/lang/Object;)"
+                        "Ljava/lang/Object;"),
+
+  if (dict == NULL)
+    return NULL;
+
+  for (hi = apr_hash_first(NULL, hash); hi; hi = apr_hash_next(hi))
+    {
+      const void *key;
+      void *val;
+      jobject value;
+
+      apr_hash_this(hi, &key, NULL, &val);
+      value = (*converter_func)(val, ctx);
+      JCALL3(CallObjectMethod, jenv, put,
+              JCALL2(NewString, jenv, key, strlen(key)), value);
+      JCALL1(DeleteLocalRef, jenv, value);
+    }
+
+  return dict;
+}
+
+static jobject convert_to_swigtype(void *value, void *ctx)
+{
+  /* ctx is a 'swig_type_info *' */
+  return SWIG_NewPointerObj(value, ctx, 0);
+}
+
+static jobject convert_svn_string_t(void *value, void *ctx)
+{
+  JNIEnv *jenv = (JNIEnv *) ctx;
+  const svn_string_t *s = value;
+
+  /* ### borrowing from value in the pool. or should we copy? note
+     ### that copying is "safest" */
+
+  return JCALL2(NewString, jenv, s->data, s->len);
+}
+
+
+jobject svn_swig_java_prophash_to_dict(JNIEnv *jenv, apr_hash_t *hash)
+{
+  return convert_hash(hash, convert_svn_string_t, jenv);
+}
+
+jobject svn_swig_java_convert_hash(JNIEnv *jenv, apr_hash_t *hash, swig_type_info *type)
+{
+  return convert_hash(hash, convert_to_swigtype, type);
+}
+
+jobject svn_swig_java_c_strings_to_list(JNIEnv *jenv, char **strings)
+{
+  jclass cls = JCALL1(FindClass, jenv, "java/util/ArrayList");
+  jobject list = JCALL2(NewObject, jenv, cls,
+                        JCALL3(GetMethodID, jenv, cls, "<init>", "()V"));
+  jmethodID add = JCALL3(GetMethodID, jenv, cls, "add", "(Ljava/lang/Object;)Z");
+  char *s;
+  jobject obj;
+  while ((s = *strings++) != NULL)
+    {
+      obj = JCALL2(NewString, jenv, s, strlen(s));
+
+      if (obj == NULL)
+          goto error;
+
+      JCALL3(CallBooleanMethod, jenv, list, add, obj);
+
+      JCALL1(DeleteLocalRef, jenv, obj);
+    }
+
+  return list;
+
+ error:
+  JCALL1(DeleteLocalRef, jenv, list);
+  return NULL;
+}
+
+jobject svn_swig_java_array_to_list(JNIEnv *jenv, const apr_array_header_t *strings)
+{
+  jclass cls = JCALL1(FindClass, jenv, "java/util/ArrayList");
+  jobject list = JCALL3(NewObject, jenv, cls,
+                        JCALL3(GetMethodID, jenv, cls, "<init>", "(I)V"),
+                        strings->nelts);
+  int i;
+  jobject obj;
+
+  for (i = 0; i < strings->nelts; ++i)
+    {
+      const char *s;
+
+      s = APR_ARRAY_IDX(strings, i, const char *);
+      obj = JCALL2(NewString, jenv, s, strlen(s));
+      if (obj == NULL)
+        goto error;
+      PyList_SET_ITEM(list, i, obj);
+      JCALL1(DeleteLocaleRef, jenv, obj);
+    }
+
+  return list;
+
+ error:
+  JCALL1(DeleteLocaleRef, jenv, list);
+  return NULL;
+}
+
+const apr_array_header_t *svn_swig_java_strings_to_array(JNIEnv *jenv,
+                                                         jobject source,
+                                                         apr_pool_t *pool)
+{
+  int targlen;
+  apr_array_header_t *temp;
+
+  jclass cls = JCALL1(FindClass, jenv, "lang/util/List");
+  jmethodID size = JCALL3(GetMethodID, jenv, cls, "size", "()I");
+  jmethodID get = JCALL3(GetMethodID, jenv, cls, "get",
+                         "(I)Ljava/lang/Object;");
+  if (!JCALL2(IsInstanceOf, jenv, source, cls))
+    {
+      /* FIXME: Resport by error (perhaps by throw an Exception)
+         PyErr_SetString(PyExc_TypeError, "not a sequence"); */
+      return NULL;
+    }
+  targlen = JCALL2(CallIntegerMethod, jenv, source, size);
+  temp = apr_array_make(pool, targlen, sizeof(const char *));
+  while (targlen--)
+    {
+      jobject o = JCALL3(CallObjectMethod, jenv, source, get, targlen);
+      if (o == NULL)
+          return NULL;
+      if (!PyString_Check(o))
+        {
+          JCALL1(DeleteLocalRef, jenv, o);
+          /* FIXME: Resport by error (perhaps by throw an Exception)
+             PyErr_SetString(PyExc_TypeError, "not a sequence"); */
+          return NULL;
+        }
+      APR_ARRAY_IDX(temp, targlen, const char *) = PyString_AS_STRING(o);
+      JCALL1(DeleteLocalRef, jenv, o);
+    }
+  return temp;
+}
+
+
+static svn_error_t * convert_java_error(JNIEnv *jenv, apr_pool_t *pool)
+{
+  /* ### need to fetch the Python error and map it to an svn_error_t */
+
+  return svn_error_create(APR_EGENERAL, 0, NULL, pool,
+                          "the Python callback raised an exception");
+}
+
+static item_baton * make_baton(JNIEnv *jenv, apr_pool_t *pool,
+                               jobject editor, jobject baton)
+{
+  item_baton *newb = apr_palloc(pool, sizeof(*newb));
+
+  /* one more reference to the editor. */
+  Py_INCREF(editor);
+
+  /* note: we take the caller's reference to 'baton' */
+
+  newb->editor = editor;
+  newb->baton = baton;
+  newb->pool = pool;
+
+  return newb;
+}
+
+static svn_error_t * close_baton(JNIEnv *jenv, void *baton, const char *method)
+{
+  item_baton *ib = baton;
+  jobject result;
+
+  /* If there is no baton object, then it is an edit_baton, and we should
+     not bother to pass an object. Note that we still shove a NULL onto
+     the stack, but the format specified just won't reference it.  */
+  /* ### python doesn't have 'const' on the method name and format */
+  if ((result = PyObject_CallMethod(ib->editor, (char *)method,
+                                    ib->baton ? (char *)"O" : NULL,
+                                    ib->baton)) == NULL)
+    {
+      return convert_python_error(ib->pool);
+    }
+
+  /* there is no return value, so just toss this object (probably Py_None) */
+  Py_DECREF(result);
+
+  /* We're now done with the baton. Since there isn't really a free, all
+     we need to do is note that its objects are no longer referenced by
+     the baton.  */
+  Py_DECREF(ib->editor);
+  Py_XDECREF(ib->baton);
+
+#ifdef SVN_DEBUG
+  ib->editor = ib->baton = NULL;
+#endif
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_set_target_revision(void *edit_baton,
+                                               svn_revnum_t target_revision)
+{
+  item_baton *ib = edit_baton;
+  jobject result;
+
+  /* ### python doesn't have 'const' on the method name and format */
+  if ((result = PyObject_CallMethod(ib->editor, (char *)"set_target_revision",
+                                    (char *)"l", target_revision)) == NULL)
+    {
+      return convert_python_error(ib->pool);
+    }
+
+  /* there is no return value, so just toss this object (probably Py_None) */
+  Py_DECREF(result);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_open_root(void *edit_baton,
+                                     svn_revnum_t base_revision,
+                                     apr_pool_t *dir_pool,
+                                     void **root_baton)
+{
+  item_baton *ib = edit_baton;
+  jobject result;
+
+  /* ### python doesn't have 'const' on the method name and format */
+  if ((result = PyObject_CallMethod(ib->editor, (char *)"open_root",
+                                    (char *)"lO&", base_revision,
+                                    make_ob_pool, dir_pool)) == NULL)
+    {
+      return convert_python_error(dir_pool);
+    }
+
+  /* make_baton takes our 'result' reference */
+  *root_baton = make_baton(dir_pool, ib->editor, result);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_delete_entry(const char *path,
+                                        svn_revnum_t revision,
+                                        void *parent_baton,
+                                        apr_pool_t *pool)
+{
+  item_baton *ib = parent_baton;
+  jobject result;
+
+  /* ### python doesn't have 'const' on the method name and format */
+  if ((result = PyObject_CallMethod(ib->editor, (char *)"delete_entry",
+                                    (char *)"slOO&", path, revision, ib->baton,
+                                    make_ob_pool, pool)) == NULL)
+    {
+      return convert_python_error(pool);
+    }
+
+  /* there is no return value, so just toss this object (probably Py_None) */
+  Py_DECREF(result);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_add_directory(const char *path,
+                                         void *parent_baton,
+                                         const char *copyfrom_path,
+                                         svn_revnum_t copyfrom_revision,
+                                         apr_pool_t *dir_pool,
+                                         void **child_baton)
+{
+  item_baton *ib = parent_baton;
+  jobject result;
+
+  /* ### python doesn't have 'const' on the method name and format */
+  if ((result = PyObject_CallMethod(ib->editor, (char *)"add_directory",
+                                    (char *)"sOslO&", path, ib->baton,
+                                    copyfrom_path, copyfrom_revision,
+                                    make_ob_pool, dir_pool)) == NULL)
+    {
+      return convert_python_error(dir_pool);
+    }
+
+  /* make_baton takes our 'result' reference */
+  *child_baton = make_baton(dir_pool, ib->editor, result);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_open_directory(const char *path,
+                                          void *parent_baton,
+                                          svn_revnum_t base_revision,
+                                          apr_pool_t *dir_pool,
+                                          void **child_baton)
+{
+  item_baton *ib = parent_baton;
+  jobject result;
+
+  /* ### python doesn't have 'const' on the method name and format */
+  if ((result = PyObject_CallMethod(ib->editor, (char *)"open_directory",
+                                    (char *)"sOlO&", path, ib->baton,
+                                    base_revision,
+                                    make_ob_pool, dir_pool)) == NULL)
+    {
+      return convert_python_error(dir_pool);
+    }
+
+  /* make_baton takes our 'result' reference */
+  *child_baton = make_baton(dir_pool, ib->editor, result);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_change_dir_prop(void *dir_baton,
+                                           const char *name,
+                                           const svn_string_t *value,
+                                           apr_pool_t *pool)
+{
+  item_baton *ib = dir_baton;
+  jobject result;
+
+  /* ### python doesn't have 'const' on the method name and format */
+  if ((result = PyObject_CallMethod(ib->editor, (char *)"change_dir_prop",
+                                    (char *)"Oss#O&", ib->baton, name,
+                                    value->data, value->len,
+                                    make_ob_pool, pool)) == NULL)
+    {
+      return convert_python_error(pool);
+    }
+
+  /* there is no return value, so just toss this object (probably Py_None) */
+  Py_DECREF(result);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_close_directory(void *dir_baton)
+{
+  return close_baton(dir_baton, "close_directory");
+}
+
+static svn_error_t * thunk_add_file(const char *path,
+                                    void *parent_baton,
+                                    const char *copyfrom_path,
+                                    svn_revnum_t copyfrom_revision,
+                                    apr_pool_t *file_pool,
+                                    void **file_baton)
+{
+  item_baton *ib = parent_baton;
+  jobject result;
+
+  /* ### python doesn't have 'const' on the method name and format */
+  if ((result = PyObject_CallMethod(ib->editor, (char *)"add_file",
+                                    (char *)"sOslO&", path, ib->baton,
+                                    copyfrom_path, copyfrom_revision,
+                                    make_ob_pool, file_pool)) == NULL)
+    {
+      return convert_python_error(file_pool);
+    }
+
+  /* make_baton takes our 'result' reference */
+  *file_baton = make_baton(file_pool, ib->editor, result);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_open_file(const char *path,
+                                     void *parent_baton,
+                                     svn_revnum_t base_revision,
+                                     apr_pool_t *file_pool,
+                                     void **file_baton)
+{
+  item_baton *ib = parent_baton;
+  jobject result;
+
+  /* ### python doesn't have 'const' on the method name and format */
+  if ((result = PyObject_CallMethod(ib->editor, (char *)"open_file",
+                                    (char *)"sOlO&", path, ib->baton,
+                                    base_revision,
+                                    make_ob_pool, file_pool)) == NULL)
+    {
+      return convert_python_error(file_pool);
+    }
+
+  /* make_baton takes our 'result' reference */
+  *file_baton = make_baton(file_pool, ib->editor, result);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_window_handler(svn_txdelta_window_t *window,
+                                          void *baton)
+{
+  handler_baton *hb = baton;
+  jobject result;
+
+  if (window == NULL)
+    {
+      /* the last call; it closes the handler */
+
+      /* invoke the handler with None for the window */
+      /* ### python doesn't have 'const' on the format */
+      result = PyObject_CallFunction(hb->handler, (char *)"O", Py_None);
+
+      /* we no longer need to refer to the handler object */
+      Py_DECREF(hb->handler);
+    }
+  else
+    {
+      /* invoke the handler with the window */
+      /* ### python doesn't have 'const' on the format */
+      result = PyObject_CallFunction(hb->handler,
+                                     (char *)"O&", make_ob_window, window);
+    }
+
+  if (result == NULL)
+    return convert_python_error(hb->pool);
+
+  /* there is no return value, so just toss this object (probably Py_None) */
+  Py_DECREF(result);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_apply_textdelta(
+    void *file_baton, 
+    svn_txdelta_window_handler_t *handler,
+    void **h_baton)
+{
+  item_baton *ib = file_baton;
+  jobject result;
+
+  /* ### python doesn't have 'const' on the method name and format */
+  if ((result = PyObject_CallMethod(ib->editor, (char *)"apply_textdelta",
+                                    (char *)"O", ib->baton)) == NULL)
+    {
+      return convert_python_error(ib->pool);
+    }
+
+  if (result == Py_None)
+    {
+      Py_DECREF(result);
+      *handler = NULL;
+      *h_baton = NULL;
+    }
+  else
+    {
+      handler_baton *hb = apr_palloc(ib->pool, sizeof(*hb));
+
+      /* return the thunk for invoking the handler. the baton takes our
+         'result' reference. */
+      hb->handler = result;
+      hb->pool = ib->pool;
+
+      *handler = thunk_window_handler;
+      *h_baton = hb;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_change_file_prop(void *file_baton,
+                                            const char *name,
+                                            const svn_string_t *value,
+                                            apr_pool_t *pool)
+{
+  item_baton *ib = file_baton;
+  jobject result;
+
+  /* ### python doesn't have 'const' on the method name and format */
+  if ((result = PyObject_CallMethod(ib->editor, (char *)"change_file_prop",
+                                    (char *)"Oss#O&", ib->baton, name,
+                                    value->data, value->len,
+                                    make_ob_pool, pool)) == NULL)
+    {
+      return convert_python_error(pool);
+    }
+
+  /* there is no return value, so just toss this object (probably Py_None) */
+  Py_DECREF(result);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_close_file(void *file_baton)
+{
+  return close_baton(file_baton, "close_file");
+}
+
+static svn_error_t * thunk_close_edit(void *edit_baton)
+{
+  return close_baton(edit_baton, "close_edit");
+}
+
+static svn_error_t * thunk_abort_edit(void *edit_baton)
+{
+  return close_baton(edit_baton, "abort_edit");
+}
+
+static const svn_delta_editor_t thunk_editor = {
+  thunk_set_target_revision,
+  thunk_open_root,
+  thunk_delete_entry,
+  thunk_add_directory,
+  thunk_open_directory,
+  thunk_change_dir_prop,
+  thunk_close_directory,
+  thunk_add_file,
+  thunk_open_file,
+  thunk_apply_textdelta,
+  thunk_change_file_prop,
+  thunk_close_file,
+  thunk_close_edit,
+  thunk_abort_edit
+};
+
+void svn_swig_java_make_editor(JNIEnv *jenv,
+                               const svn_delta_editor_t **editor,
+                               void **edit_baton,
+                               jobject java_editor,
+                               apr_pool_t *pool)
+{
+  *editor = &thunk_editor;
+  *edit_baton = make_baton(pool, java_editor, NULL);
+}
+
+/* ----------------------------------------------------------------
+ * local variables:
+ * eval: (load-file "../../../tools/dev/svn-dev.el")
+ * end:
+ */
Index: ./svn_client.i
===================================================================
--- ./svn_client.i
+++ ./svn_client.i	Wed Oct 16 09:15:22 2002
@@ -98,6 +98,12 @@
     }
     $result = t_output_helper($result, list);
 }
+%typemap(java,argout) apr_hash_t **statushash {
+    /* FIXME: Use JNI equiv of Java type SWIGTYPE_p_svn_wc_status_t */
+    $result = t_output_helper(
+        $result,
+        svn_swig_java_convert_hash(*$1, SWIGTYPE_p_svn_wc_status_t));
+}
 
 /* -----------------------------------------------------------------------
    handle the "statushash" OUTPUT param for svn_client_status()
@@ -128,6 +134,10 @@
 #ifdef SWIGPYTHON
 #include "swigutil_py.h"
 #endif
+
+#ifdef SWIGJAVA
+#include "swigutil_java.h"
+#endif
 %}
 
 %include svn_client.h
Index: ./swigutil_java.h
===================================================================
--- ./swigutil_java.h
+++ ./swigutil_java.h	Fri Oct 11 19:24:04 2002
@@ -0,0 +1,103 @@
+/*
+ * swigutil_java.h :  utility functions and stuff for the SWIG Java bindings
+ *
+ * ====================================================================
+ * Copyright (c) 2000-2002 CollabNet.  All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution.  The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals.  For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+
+#ifndef SVN_SWIG_SWIGUTIL_JAVA_H
+#define SVN_SWIG_SWIGUTIL_JAVA_H
+
+#include <jni.h>
+
+#include <apr.h>
+#include <apr_pools.h>
+#include <apr_strings.h>
+#include <apr_hash.h>
+#include <apr_tables.h>
+
+#include "svn_types.h"
+#include "svn_string.h"
+#include "svn_delta.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* If this file is being included outside of a wrapper file, then need to
+   create stubs for some of the SWIG types. */
+
+/* if SWIGEXPORT is defined, then we're in a wrapper. otherwise, we need
+   the prototypes and type definitions. */
+#ifndef SWIGEXPORT
+#define SVN_NEED_SWIG_TYPES
+#endif
+
+#ifdef SVN_NEED_SWIG_TYPES
+
+typedef struct _unnamed swig_type_info;
+jobject *SWIG_NewPointerObj(JNIEnv *jenv, void *, swig_type_info *, int own);
+swig_type_info *SWIG_TypeQuery(JNIEnv *jenv, const char *name);
+
+#endif /* SVN_NEED_SWIG_TYPES */
+
+
+/* helper function to convert an apr_hash_t* (char* -> svnstring_t*) to
+   a Java Map */
+jobject svn_swig_java_prophash_to_dict(JNIEnv *jenv, apr_hash_t *hash);
+
+/* convert a hash of 'const char *' -> TYPE into a Java Map */
+jobject svn_swig_java_convert_hash(JNIEnv *jenv, apr_hash_t *hash,
+                                   swig_type_info *type);
+
+/* helper function to convert a 'char **' into a Java List of String
+   objects */
+jobject svn_swig_java_c_strings_to_list(JNIEnv *jenv, char **strings);
+
+/* helper function to convert an array of 'const char *' to a Java List of
+   String objects */
+jobject svn_swig_java_array_to_list(JNIEnv *jenv,
+                                    const apr_array_header_t *strings);
+
+/* helper function to convert a Java List of String objects into an
+   'apr_array_header_t *' of 'const char *' objects.  Note that the
+   objects must remain alive -- the values are not copied. This is
+   appropriate for incoming arguments which are defined to last the
+   duration of the function's execution.  */
+const apr_array_header_t *svn_swig_java_strings_to_array(JNIEnv *jenv,
+                                                         jobject source,
+                                                         apr_pool_t *pool);
+
+/* make a editor that "thunks" from C callbacks up to Java */
+void svn_swig_java_make_editor(JNIEnv *jenv,
+                               const svn_delta_editor_t **editor,
+                               void **edit_baton,
+                               jobject java_editor,
+                               apr_pool_t *pool);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif  /* SVN_SWIG_SWIGUTIL_JAVA_H */
+
+
+/* ----------------------------------------------------------------
+ * local variables:
+ * eval: (load-file "../../../tools/dev/svn-dev.el")
+ * end:
+ */
Index: ./util.i
===================================================================
--- ./util.i
+++ ./util.i	Fri Oct 11 19:46:41 2002
@@ -189,4 +189,8 @@
 #ifdef SWIGPYTHON
 #include "swigutil_py.h"
 #endif
+
+#ifdef SWIGJAVA
+#include "swigutil_java.h"
+#endif
 %}
Index: ./svn_repos.i
===================================================================
--- ./svn_repos.i
+++ ./svn_repos.i	Fri Oct 11 19:46:41 2002
@@ -62,4 +62,8 @@
 #ifdef SWIGPYTHON
 #include "swigutil_py.h"
 #endif
+
+#ifdef SWIGJAVA
+#include "swigutil_java.h"
+#endif
 %}
Index: ./svn_delta.i
===================================================================
--- ./svn_delta.i
+++ ./svn_delta.i	Fri Oct 11 19:46:41 2002
@@ -82,4 +82,8 @@
 #ifdef SWIGPYTHON
 #include "swigutil_py.h"
 #endif
+
+#ifdef SWIGJAVA
+#include "swigutil_java.h"
+#endif
 %}
Index: ./apr.i
===================================================================
--- ./apr.i
+++ ./apr.i	Wed Oct 16 08:15:40 2002
@@ -62,6 +62,12 @@
 %typemap(python,argout,fragment="t_output_helper") apr_time_t * {
     $result = t_output_helper($result, PyLong_FromLongLong(*$1));
 }
+%typemap(java,argout) apr_time_t * {
+    jclass cls = JCALL1(FindClass, jenv, "java/lang/Long");
+    jmethodID ctor = JCALL3(GetMethodID, jenv, cls, "<init>", "(J)V");
+    jobject l = JCALL3(NewObject, jenv, cls, ctor, (jlong) *$1);
+    $result = t_output_helper($result, JCALL1(NewGlobalRef, jenv, l));
+}
 
 /* -----------------------------------------------------------------------
    create some INOUT typemaps for apr_size_t
@@ -73,6 +79,12 @@
     temp = (apr_size_t) PyInt_AsLong($input);
     $1 = &temp;
 }
+%typemap(java,in) apr_size_t *INOUT (apr_size_t temp) {
+    jclass cls = JCALL1(FindClass, jenv, "java/lang/Long");
+    jmethodID mid = JCALL3(GetStaticMethodID, jenv, cls, "longValue", "()J");
+    temp = (apr_size_t) JCALL2(CallStaticLongMethod, jenv, mid, $input);
+    $1 = &temp;
+}
 
 /* -----------------------------------------------------------------------
    create an OUTPUT argument typemap for an apr_hash_t **
@@ -93,6 +105,12 @@
     Py_DECREF($result);
     $result = svn_swig_py_prophash_to_dict(*$1);
 }
+%typemap(java,argout) apr_hash_t **PROPHASH {
+    /* toss prior result, get new result from the hash */
+    JCALL1(DeleteGlobalRef, jenv, $result);
+    $result = JCALL1(NewGlobalRef, jenv,
+                     svn_swig_java_prophash_to_dict(jenv, *$1));
+}
 
 /* -----------------------------------------------------------------------
    apr_file_t ** is always an OUT param
@@ -105,6 +123,13 @@
     $result = t_output_helper(
         $result,
         SWIG_NewPointerObj(*$1, $*1_descriptor, 0));
+}
+%typemap(java,argout) apr_file_t ** {
+    /* HELP: Is there a JNI equivalent of SWIG_NewPointerObj, or is
+       this actually a cross-language typemap? */
+    $result = t_output_helper(
+        $result,
+        SWIG_NewPointerObj(*$1, $*1_descriptor, 0));
 }
 
 /* ----------------------------------------------------------------------- */
Index: ./Makefile
===================================================================
--- ./Makefile
+++ ./Makefile	Wed Oct 16 09:14:06 2002
@@ -0,0 +1,15 @@
+# TODO: Use -swiglig argument to avoid the need for SWIG-internal paths.
+SWIG_CMD=/usr/local/swig/bin/swig -c -java -noproxy -module 'svn_jni' -I'.' -I'../../include' -I'/home/dlr/src/apache.org/apr/include' -I'/usr/local/swig/lib/swig1.3' -I'/usr/local/swig/lib/swig1.3/java'
+
+build-java: swig-java
+
+swig-java:
+	for source in *.i; do \
+	  target="`echo -n $$source | perl -pe 's/..$$/.jni.c/'`"; \
+	  $(SWIG_CMD) -o $$target $$source; \
+	done; unset target source
+
+clean: swig-java-clean
+
+swig-java-clean:
+	rm -f *.jni.c *.java
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Wed Oct 16 18:17:47 2002

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.