swigutil_java.c
来自「linux subdivision ying gai ke yi le ba」· C语言 代码 · 共 1,257 行 · 第 1/3 页
C
1,257 行
/*
* swigutil_java.c: utility functions for the SWIG Java bindings
*
* ====================================================================
* Copyright (c) 2000-2004 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_client.h"
#include "svn_string.h"
#include "svn_delta.h"
#define SVN_SWIG_JAVA_DEFINE_CACHE
#include "swigutil_java.h"
/* FIXME: Need java.swg for the JCALL macros. The following was taken
from javahead.swg (which is included by java.swg). */
#ifndef JCALL0
#ifdef __cplusplus
# define JCALL0(func, jenv) jenv->func()
# define JCALL1(func, jenv, ar1) jenv->func(ar1)
# define JCALL2(func, jenv, ar1, ar2) jenv->func(ar1, ar2)
# define JCALL3(func, jenv, ar1, ar2, ar3) jenv->func(ar1, ar2, ar3)
# define JCALL4(func, jenv, ar1, ar2, ar3, ar4) \
jenv->func(ar1, ar2, ar3, ar4)
# define JCALL7(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7) \
jenv->func(ar1, ar2, ar3, ar4, ar5, ar6, ar7)
#else
# define JCALL0(func, jenv) (*jenv)->func(jenv)
# define JCALL1(func, jenv, ar1) (*jenv)->func(jenv, ar1)
# define JCALL2(func, jenv, ar1, ar2) (*jenv)->func(jenv, ar1, ar2)
# define JCALL3(func, jenv, ar1, ar2, ar3) (*jenv)->func(jenv, ar1, ar2, ar3)
# define JCALL4(func, jenv, ar1, ar2, ar3, ar4) \
(*jenv)->func(jenv, ar1, ar2, ar3, ar4)
# define JCALL7(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7) \
(*jenv)->func(jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7)
#endif
#endif
/* Convert an svn_error_t into a SubversionException */
static jthrowable convert_error(JNIEnv *jenv, svn_error_t *error)
{
jthrowable cause;
jthrowable exc;
jstring msg;
jstring file;
/* Is it wise to use recursion in an error handler? */
cause = (error->child) ? convert_error(jenv, error->child) : NULL;
/* ### need more error checking */
msg = JCALL1(NewStringUTF, jenv, error->message);
file = error->file ? JCALL1(NewStringUTF, jenv, error->file) : NULL;
exc = JCALL7(NewObject, jenv,
svn_swig_java_cls_subversionexception,
svn_swig_java_mid_subversionexception_init,
msg, cause,
(jlong) error->apr_err, file, (jlong) error->line);
return exc;
}
/* Convert an svn_error_t into a SubversionException
After conversion, the error will be cleared */
jthrowable svn_swig_java_convert_error(JNIEnv *jenv, svn_error_t *error)
{
jthrowable exc;
exc = convert_error(jenv, error);
svn_error_clear(error);
return exc;
}
/* 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 */
JNIEnv *jenv; /* Java native interface structure */
} item_baton;
typedef struct {
jobject handler; /* the window handler (a callable) */
apr_pool_t *pool; /* a pool for constructing errors */
JNIEnv *jenv; /* Java native interface structure */
} handler_baton;
static jobject make_pointer(JNIEnv* env, void *ptr)
{
/* Return a Long object contining the C pointer to the object
(SWIG/Java knows nothing of SWIG_NewPointerObj) */
jclass cls = JCALL1(FindClass, env, "java/lang/Long");
return JCALL3(NewObject, env, cls,
JCALL3(GetMethodID, env, cls, "<init>", "(J)V"), (jlong) ptr);
}
static jobject convert_hash(JNIEnv* jenv, apr_hash_t *hash,
jobject (*converter_func)(JNIEnv* env,
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));
jmethodID 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)(jenv, val, ctx);
JCALL4(CallObjectMethod, jenv, dict, put,
JCALL1(NewStringUTF, jenv, key), value);
JCALL1(DeleteLocalRef, jenv, value);
}
return dict;
}
void svn_swig_java_add_to_list(JNIEnv* jenv, apr_array_header_t *array,
jobject list)
{
/* TODO: This impl will be much like svn_swig_java_add_to_map */
}
void svn_swig_java_add_to_map(JNIEnv* jenv, apr_hash_t *hash, jobject map)
{
apr_hash_index_t *hi;
jclass cls = JCALL1(FindClass, jenv, "java/util/Map");
jmethodID put = JCALL3(GetMethodID, jenv, cls, "put",
"(Ljava/lang/Object;Ljava/lang/Object;)"
"Ljava/lang/Object;");
for (hi = apr_hash_first(NULL, hash); hi; hi = apr_hash_next(hi))
{
const void *key;
void *val;
jobject keyname, value, oldvalue;
apr_hash_this(hi, &key, NULL, &val);
keyname = JCALL1(NewStringUTF, jenv, key);
value = make_pointer(jenv, val);
oldvalue = JCALL4(CallObjectMethod, jenv, map, put, keyname, value);
JCALL1(DeleteLocalRef, jenv, value);
JCALL1(DeleteLocalRef, jenv, oldvalue);
JCALL1(DeleteLocalRef, jenv, keyname);
if (JCALL0(ExceptionOccurred, jenv))
return;
}
}
static jobject convert_to_swigtype(JNIEnv* jenv, void *value, void *ctx)
{
return make_pointer(jenv, value);
}
static jobject convert_svn_string_t(JNIEnv* jenv, void *value, void *ctx)
{
const svn_string_t *s = value;
/* This will copy the data */
return JCALL1(NewStringUTF, jenv, s->data);
}
jobject svn_swig_java_prophash_to_dict(JNIEnv *jenv, apr_hash_t *hash)
{
return convert_hash(jenv, hash, convert_svn_string_t, jenv);
}
jobject svn_swig_java_convert_hash(JNIEnv *jenv, apr_hash_t *hash)
{
return convert_hash(jenv, hash, convert_to_swigtype, NULL);
}
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 = JCALL1(NewStringUTF, jenv, 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;
jmethodID add;
if (strings->nelts > 0)
add = JCALL3(GetMethodID, jenv, cls, "add", "(i, Ljava/lang/Object;)Z");
for (i = 0; i < strings->nelts; ++i)
{
const char *s;
s = APR_ARRAY_IDX(strings, i, const char *);
obj = JCALL1(NewStringUTF, jenv, s);
if (obj == NULL)
goto error;
/* ### HELP: The format specifier might be 'I' instead of 'i' */
JCALL4(CallObjectMethod, jenv, list, add, i, obj);
JCALL1(DeleteLocalRef, jenv, obj);
}
return list;
error:
JCALL1(DeleteLocalRef, 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, "java/util/List");
jmethodID size = JCALL3(GetMethodID, jenv, cls, "size", "()I");
jmethodID get = JCALL3(GetMethodID, jenv, cls, "get",
"(I)Ljava/lang/Object;");
jclass illegalArgCls = JCALL1(FindClass, jenv,
"java/lang/IllegalArgumentException");
if (!JCALL2(IsInstanceOf, jenv, source, cls))
{
if (JCALL2(ThrowNew, jenv, illegalArgCls, "Not a List") != JNI_OK)
return NULL;
}
targlen = JCALL2(CallIntMethod, jenv, source, size);
temp = apr_array_make(pool, targlen, sizeof(const char *));
while (targlen--)
{
jobject o = JCALL3(CallObjectMethod, jenv, source, get, targlen);
const char * c_string;
if (o == NULL)
return NULL;
else if (!JCALL2(IsInstanceOf, jenv, o,
JCALL1(FindClass, jenv, "java/lang/String")))
{
JCALL1(DeleteLocalRef, jenv, o);
if (JCALL2(ThrowNew, jenv, illegalArgCls, "Not a String") != JNI_OK)
{
return NULL;
}
}
c_string = (*jenv)->GetStringUTFChars(jenv, o, 0);
APR_ARRAY_IDX(temp, targlen, const char *) = apr_pstrdup(pool, c_string);
(*jenv)->ReleaseStringUTFChars(jenv, o, c_string);
JCALL1(DeleteLocalRef, jenv, o);
}
return temp;
}
/* Convert a Java exception into a svn_error_t.
This function may only be called if there is
a pending exception. */
static svn_error_t * convert_exception(JNIEnv *jenv, apr_pool_t *pool)
{
svn_error_t *result;
apr_status_t status;
char *msg;
jthrowable exc;
/* Fetch the exception */
exc = JCALL0(ExceptionOccurred, jenv);
#ifdef SVN_DEBUG
/* Print the pending exception to stderr */
JCALL0(ExceptionDescribe, jenv);
#endif
/* Clear the exception */
JCALL0(ExceptionClear, jenv);
/* Interpret the exception:
java.lang.OutOfMemoryError -> APR_ENOMEM
other -> APR_EGENERAL */
/* ### Add other exceptions; use a table? */
if (JCALL2(IsInstanceOf, jenv, exc, svn_swig_java_cls_outofmemoryerror))
{
status = APR_ENOMEM;
msg = "JVM raised OutOfMemoryError";
}
else
{
status = APR_EGENERAL;
msg = "The Java callback raised an exception";
}
result = svn_error_create(status, NULL, msg);
/* Free the local reference */
JCALL1(DeleteLocalRef, jenv, exc);
return result;
}
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. */
JCALL1(NewGlobalRef, jenv, editor);
JCALL1(NewGlobalRef, jenv, baton);
/* note: we take the caller's reference to 'baton' */
newb->editor = JCALL1(NewGlobalRef, jenv, editor);
newb->baton = baton;
newb->pool = pool;
newb->jenv = jenv;
return newb;
}
static svn_error_t * close_baton(void *baton, const char *method)
{
item_baton *ib = baton;
jobject result;
JNIEnv *jenv = ib->jenv;
jclass cls = JCALL1(GetObjectClass, jenv, ib->editor);
jmethodID methodID;
/* 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. */
if (ib->baton)
{
methodID = JCALL3(GetMethodID, jenv, cls, method,
"(Ljava/lang/Object;)Ljava/lang/Object;");
result = JCALL3(CallObjectMethod, jenv, ib->editor, methodID, ib->baton);
}
else
{
methodID = JCALL3(GetMethodID, jenv, cls, method,
"()Ljava/lang/Object;");
result = JCALL2(CallObjectMethod, jenv, ib->editor, methodID);
}
if (result == NULL)
return convert_exception(ib->jenv, ib->pool);
/* there is no return value, so just toss this object */
JCALL1(DeleteGlobalRef, ib->jenv, 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. */
JCALL1(DeleteGlobalRef, ib->jenv, ib->editor);
JCALL1(DeleteGlobalRef, ib->jenv, ib->baton);
#ifdef SVN_DEBUG
ib->editor = ib->baton = NULL;
#endif
return SVN_NO_ERROR;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?