sigar/bindings/java/src/jni/javasigar.c

975 lines
24 KiB
C
Raw Normal View History

2004-06-22 06:37:04 +08:00
#include <jni.h>
#include "sigar.h"
#include "sigar_fileinfo.h"
#include "sigar_log.h"
#include <string.h>
#ifdef WIN32
#include <winsock.h>
#else
#include <errno.h>
#include <sys/types.h>
#include <stdlib.h>
#endif
#include "javasigar_generated.h"
#define JENV (*env)
#define SIGAR_PACKAGE "net/hyperic/sigar/"
#define SIGAR_JNI(m) JNICALL Java_net_hyperic_sigar_##m
#define SIGAR_FIND_CLASS(name) \
JENV->FindClass(env, SIGAR_PACKAGE name)
typedef struct {
jclass classref;
jfieldID *ids;
} jsigar_field_cache_t;
typedef struct {
JNIEnv *env;
jobject logger;
sigar_t *sigar;
jsigar_field_cache_t *fields[JSIGAR_FIELDS_MAX];
int open_status;
} jni_sigar_t;
#define dSIGAR_GET \
jni_sigar_t *jsigar = sigar_get_pointer(env, sigar_obj); \
sigar_t *sigar
#define dSIGAR_VOID \
dSIGAR_GET; \
if (!jsigar) return; \
sigar = jsigar->sigar
#define dSIGAR(val) \
dSIGAR_GET; \
if (!jsigar) return val; \
sigar = jsigar->sigar
static void sigar_throw_exception(JNIEnv *env, char *msg)
{
jclass errorClass = SIGAR_FIND_CLASS("SigarException");
JENV->ThrowNew(env, errorClass, msg);
}
static void sigar_throw_notimpl(JNIEnv *env, char *msg)
{
jclass errorClass = SIGAR_FIND_CLASS("SigarNotImplementedException");
JENV->ThrowNew(env, errorClass, msg);
}
static void sigar_throw_error(JNIEnv *env, sigar_t *sigar, int err)
{
jclass errorClass;
switch (err) {
#ifndef WIN32
case ENOENT:
errorClass = SIGAR_FIND_CLASS("SigarFileNotFoundException");
break;
#else
/*XXX*/
#endif
case SIGAR_ENOTIMPL:
errorClass = SIGAR_FIND_CLASS("SigarNotImplementedException");
break;
default:
errorClass = SIGAR_FIND_CLASS("SigarException");
break;
}
JENV->ThrowNew(env, errorClass,
sigar_strerror(sigar, err));
}
static jni_sigar_t *sigar_get_pointer(JNIEnv *env, jobject obj) {
jfieldID pointer_field;
jni_sigar_t *jsigar;
jclass cls;
cls = JENV->GetObjectClass(env, obj);
pointer_field = JENV->GetFieldID(env, cls, "sigarWrapper", "I");
jsigar = (jni_sigar_t *) JENV->GetIntField(env, obj, pointer_field);
if (!jsigar) {
sigar_throw_exception(env, "sigar has been closed");
return NULL;
}
if (jsigar->open_status != SIGAR_OK) {
sigar_throw_error(env, jsigar->sigar,
jsigar->open_status);
return NULL;
}
return jsigar;
}
static void sigar_set_pointer(JNIEnv *env, jobject obj, const void *ptr) {
jfieldID pointer_field;
int pointer_int;
jclass cls;
cls = JENV->GetObjectClass(env, obj);
pointer_field = JENV->GetFieldID(env, cls, "sigarWrapper", "I");
pointer_int = (int)ptr;
JENV->SetIntField(env, obj, pointer_field, pointer_int);
}
JNIEXPORT jstring SIGAR_JNI(Sigar_formatSize)
(JNIEnv *env, jclass cls, jlong size)
{
char buf[56];
sigar_format_size(size, buf);
return JENV->NewStringUTF(env, buf);
}
JNIEXPORT void SIGAR_JNI(Sigar_open)
(JNIEnv *env, jobject obj)
{
jni_sigar_t *jsigar = malloc(sizeof(*jsigar));
memset(jsigar, '\0', sizeof(*jsigar));
sigar_set_pointer(env, obj, jsigar);
/* this method is called by the constructor.
* if != SIGAR_OK save status and throw exception
* when methods are invoked (see sigar_get_pointer).
*/
if ((jsigar->open_status = sigar_open(&jsigar->sigar)) != SIGAR_OK) {
sigar_throw_error(env, jsigar->sigar, jsigar->open_status);
return;
}
}
JNIEXPORT jint SIGAR_JNI(Sigar_nativeClose)
(JNIEnv *env, jobject sigar_obj)
{
jint status;
int i;
dSIGAR(0);
/* only place it is possible this would be something other than
* SIGAR_OK is on win32 if RegCloseKey fails, which i don't think
* is possible either.
*/
status = sigar_close(sigar);
if (jsigar->logger != NULL) {
JENV->DeleteGlobalRef(env, jsigar->logger);
}
for (i=0; i<JSIGAR_FIELDS_MAX; i++) {
if (jsigar->fields[i]) {
JENV->DeleteGlobalRef(env,
jsigar->fields[i]->classref);
free(jsigar->fields[i]->ids);
free(jsigar->fields[i]);
}
}
free(jsigar);
sigar_set_pointer(env, sigar_obj, NULL);
return status;
}
JNIEXPORT jlong SIGAR_JNI(Sigar_getPid)
(JNIEnv *env, jobject sigar_obj)
{
dSIGAR(0);
return sigar_pid_get(sigar);
}
JNIEXPORT void SIGAR_JNI(Sigar_kill)
(JNIEnv *env, jobject sigar_obj, jlong pid, jint signum)
{
int status;
dSIGAR_VOID;
if ((status = sigar_proc_kill(pid, signum)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
}
}
#define SetStringField(env, obj, fieldID, val) \
SetObjectField(env, obj, fieldID, JENV->NewStringUTF(env, val))
static jstring jinet_ntoa(JNIEnv *env, sigar_t *sigar, sigar_uint64_t val) {
char addr_str[SIGAR_INET_ADDR_LEN];
sigar_inet_ntoa(sigar, val, addr_str);
return JENV->NewStringUTF(env, addr_str);
}
#define SetNetAddrField(env, obj, fieldID, val) \
SetObjectField(env, obj, fieldID, jinet_ntoa(env, sigar, val))
#include "javasigar_generated.c"
#define SIGAR_CLASS_SIG(name) \
"L" SIGAR_PACKAGE name ";"
#define SIGAR_ALLOC_OBJECT(name) \
JENV->AllocObject(env, SIGAR_FIND_CLASS(name))
enum {
FS_FIELD_DIRNAME,
FS_FIELD_DEVNAME,
FS_FIELD_SYS_TYPENAME,
FS_FIELD_TYPE,
FS_FIELD_TYPENAME,
FS_FIELD_MAX
};
#define STRING_SIG "Ljava/lang/String;"
JNIEXPORT jobjectArray SIGAR_JNI(Sigar_getFileSystemList)
(JNIEnv *env, jobject sigar_obj)
{
int status;
unsigned int i;
sigar_file_system_list_t fslist;
jobjectArray fsarray;
jfieldID ids[FS_FIELD_MAX];
jclass cls = SIGAR_FIND_CLASS("FileSystem");
dSIGAR(NULL);
if ((status = sigar_file_system_list_get(sigar, &fslist)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
ids[FS_FIELD_DIRNAME] =
JENV->GetFieldID(env, cls, "dirName", STRING_SIG);
ids[FS_FIELD_DEVNAME] =
JENV->GetFieldID(env, cls, "devName", STRING_SIG);
ids[FS_FIELD_TYPENAME] =
JENV->GetFieldID(env, cls, "typeName", STRING_SIG);
ids[FS_FIELD_SYS_TYPENAME] =
JENV->GetFieldID(env, cls, "sysTypeName", STRING_SIG);
ids[FS_FIELD_TYPE] =
JENV->GetFieldID(env, cls, "type", "I");
fsarray = JENV->NewObjectArray(env, fslist.number, cls, 0);
for (i=0; i<fslist.number; i++) {
sigar_file_system_t *fs = &(fslist.data)[i];
jobject fsobj = JENV->AllocObject(env, cls);
JENV->SetStringField(env, fsobj,
ids[FS_FIELD_DIRNAME],
fs->dir_name);
JENV->SetStringField(env, fsobj,
ids[FS_FIELD_DEVNAME],
fs->dev_name);
JENV->SetStringField(env, fsobj,
ids[FS_FIELD_SYS_TYPENAME],
fs->sys_type_name);
JENV->SetStringField(env, fsobj,
ids[FS_FIELD_TYPENAME],
fs->type_name);
JENV->SetIntField(env, fsobj,
ids[FS_FIELD_TYPE],
fs->type);
JENV->SetObjectArrayElement(env, fsarray, i, fsobj);
}
sigar_file_system_list_destroy(sigar, &fslist);
return fsarray;
}
JNIEXPORT jobjectArray SIGAR_JNI(Sigar_getCpuInfoList)
(JNIEnv *env, jobject sigar_obj)
{
int status;
unsigned int i;
sigar_cpu_infos_t cpu_infos;
jobjectArray cpuarray;
jclass cls = SIGAR_FIND_CLASS("CpuInfo");
dSIGAR(NULL);
if ((status = sigar_cpu_infos_get(sigar, &cpu_infos)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
JAVA_SIGAR_INIT_FIELDS_CPUINFO(cls);
cpuarray = JENV->NewObjectArray(env, cpu_infos.number, cls, 0);
for (i=0; i<cpu_infos.number; i++) {
jobject info_obj = JENV->AllocObject(env, cls);
JAVA_SIGAR_SET_FIELDS_CPUINFO(cls, info_obj,
cpu_infos.data[i]);
JENV->SetObjectArrayElement(env, cpuarray, i, info_obj);
}
sigar_cpu_infos_destroy(sigar, &cpu_infos);
return cpuarray;
}
JNIEXPORT jobjectArray SIGAR_JNI(Sigar_getCpuListNative)
(JNIEnv *env, jobject sigar_obj)
{
int status;
unsigned int i;
sigar_cpu_list_t cpulist;
jobjectArray cpuarray;
jclass cls = SIGAR_FIND_CLASS("Cpu");
dSIGAR(NULL);
if ((status = sigar_cpu_list_get(sigar, &cpulist)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
JAVA_SIGAR_INIT_FIELDS_CPU(cls);
cpuarray = JENV->NewObjectArray(env, cpulist.number, cls, 0);
for (i=0; i<cpulist.number; i++) {
jobject info_obj = JENV->AllocObject(env, cls);
JAVA_SIGAR_SET_FIELDS_CPU(cls, info_obj,
cpulist.data[i]);
JENV->SetObjectArrayElement(env, cpuarray, i, info_obj);
}
sigar_cpu_list_destroy(sigar, &cpulist);
return cpuarray;
}
JNIEXPORT jlongArray SIGAR_JNI(Sigar_getProcList)
(JNIEnv *env, jobject sigar_obj)
{
int status;
jlongArray procarray;
sigar_proc_list_t proclist;
jlong *pids = NULL;
dSIGAR(NULL);
if ((status = sigar_proc_list_get(sigar, &proclist)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
procarray = JENV->NewLongArray(env, proclist.number);
if (sizeof(jlong) == sizeof(sigar_pid_t)) {
pids = (jlong *)proclist.data;
}
else {
unsigned int i;
pids = (jlong *)malloc(sizeof(jlong) * proclist.number);
for (i=0; i<proclist.number; i++) {
pids[i] = proclist.data[i];
}
}
JENV->SetLongArrayRegion(env, procarray, 0,
proclist.number, pids);
if (pids != (jlong *)proclist.data) {
free(pids);
}
sigar_proc_list_destroy(sigar, &proclist);
return procarray;
}
JNIEXPORT jobjectArray SIGAR_JNI(Sigar_getProcArgs)
(JNIEnv *env, jobject sigar_obj, jlong pid)
{
int status;
unsigned int i;
sigar_proc_args_t procargs;
jobjectArray argsarray;
jclass stringclass = JENV->FindClass(env, "java/lang/String");
dSIGAR(NULL);
if ((status = sigar_proc_args_get(sigar, pid, &procargs)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
argsarray = JENV->NewObjectArray(env, procargs.number, stringclass, 0);
for (i=0; i<procargs.number; i++) {
jstring s = JENV->NewStringUTF(env, procargs.data[i]);
JENV->SetObjectArrayElement(env, argsarray, i, s);
}
sigar_proc_args_destroy(sigar, &procargs);
return argsarray;
}
typedef struct {
JNIEnv *env;
jobject map;
jmethodID id;
} jni_env_put_t;
static int jni_env_getall(void *data,
const char *key, int klen,
char *val, int vlen)
{
jni_env_put_t *put = (jni_env_put_t *)data;
JNIEnv *env = put->env;
JENV->CallObjectMethod(env, put->map, put->id,
JENV->NewStringUTF(env, key),
JENV->NewStringUTF(env, val));
return SIGAR_OK;
}
JNIEXPORT jobject SIGAR_JNI(ProcEnv_getAll)
(JNIEnv *env, jobject cls, jobject sigar_obj, jlong pid)
{
int status;
sigar_proc_env_t procenv;
jobject hashmap;
jni_env_put_t put;
jclass mapclass =
JENV->FindClass(env, "java/util/HashMap");
jmethodID mapid =
JENV->GetMethodID(env, mapclass, "<init>", "()V");
jmethodID putid =
JENV->GetMethodID(env, mapclass, "put",
"(Ljava/lang/Object;Ljava/lang/Object;)"
"Ljava/lang/Object;");
dSIGAR(NULL);
hashmap = JENV->NewObject(env, mapclass, mapid);
put.env = env;
put.id = putid;
put.map = hashmap;
procenv.type = SIGAR_PROC_ENV_ALL;
procenv.env_getter = jni_env_getall;
procenv.data = &put;
if ((status = sigar_proc_env_get(sigar, pid, &procenv)) != SIGAR_OK) {
JENV->DeleteLocalRef(env, hashmap);
sigar_throw_error(env, sigar, status);
return NULL;
}
return hashmap;
}
typedef struct {
JNIEnv *env;
const char *key;
int klen;
jstring val;
} jni_env_get_t;
static int jni_env_getvalue(void *data,
const char *key, int klen,
char *val, int vlen)
{
jni_env_get_t *get = (jni_env_get_t *)data;
JNIEnv *env = get->env;
if ((get->klen == klen) &&
(strcmp(get->key, key) == 0))
{
get->val = JENV->NewStringUTF(env, val);
return !SIGAR_OK; /* foundit; stop iterating */
}
return SIGAR_OK;
}
JNIEXPORT jstring SIGAR_JNI(ProcEnv_getValue)
(JNIEnv *env, jobject cls, jobject sigar_obj, jlong pid, jstring key)
{
int status;
sigar_proc_env_t procenv;
jni_env_get_t get;
dSIGAR(NULL);
get.env = env;
get.key = JENV->GetStringUTFChars(env, key, 0);
get.klen = JENV->GetStringUTFLength(env, key);
get.val = NULL;
procenv.type = SIGAR_PROC_ENV_KEY;
procenv.key = get.key;
procenv.klen = get.klen;
procenv.env_getter = jni_env_getvalue;
procenv.data = &get;
if ((status = sigar_proc_env_get(sigar, pid, &procenv)) != SIGAR_OK) {
JENV->ReleaseStringUTFChars(env, key, get.key);
sigar_throw_error(env, sigar, status);
return NULL;
}
JENV->ReleaseStringUTFChars(env, key, get.key);
return get.val;
}
JNIEXPORT jdoubleArray SIGAR_JNI(Sigar_getLoadAverage)
(JNIEnv *env, jobject sigar_obj)
{
int status;
jlongArray avgarray;
sigar_loadavg_t loadavg;
dSIGAR(NULL);
if ((status = sigar_loadavg_get(sigar, &loadavg)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
avgarray = JENV->NewDoubleArray(env, 3);
JENV->SetDoubleArrayRegion(env, avgarray, 0,
3, loadavg.loadavg);
return avgarray;
}
JNIEXPORT jobjectArray SIGAR_JNI(Sigar_getNetRouteList)
(JNIEnv *env, jobject sigar_obj)
{
int status;
unsigned int i;
jarray routearray;
jclass cls = SIGAR_FIND_CLASS("NetRoute");
sigar_net_route_list_t routelist;
dSIGAR(NULL);
if ((status = sigar_net_route_list_get(sigar, &routelist)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
JAVA_SIGAR_INIT_FIELDS_NETROUTE(cls);
routearray = JENV->NewObjectArray(env, routelist.number, cls, 0);
for (i=0; i<routelist.number; i++) {
jobject obj = JENV->AllocObject(env, cls);
JAVA_SIGAR_SET_FIELDS_NETROUTE(cls, obj, routelist.data[i]);
JENV->SetObjectArrayElement(env, routearray, i, obj);
}
sigar_net_route_list_destroy(sigar, &routelist);
return routearray;
}
JNIEXPORT jobjectArray SIGAR_JNI(Sigar_getNetConnectionList)
(JNIEnv *env, jobject sigar_obj, jint flags)
{
int status;
unsigned int i;
jarray connarray;
jclass cls = SIGAR_FIND_CLASS("NetConnection");
sigar_net_connection_list_t connlist;
dSIGAR(NULL);
status = sigar_net_connection_list_get(sigar, &connlist, flags);
if (status != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
JAVA_SIGAR_INIT_FIELDS_NETCONNECTION(cls);
connarray = JENV->NewObjectArray(env, connlist.number, cls, 0);
for (i=0; i<connlist.number; i++) {
jobject obj = JENV->AllocObject(env, cls);
JAVA_SIGAR_SET_FIELDS_NETCONNECTION(cls, obj, connlist.data[i]);
JENV->SetObjectArrayElement(env, connarray, i, obj);
}
sigar_net_connection_list_destroy(sigar, &connlist);
return connarray;
}
JNIEXPORT jstring SIGAR_JNI(NetConnection_getTypeString)
(JNIEnv *env, jobject obj)
{
jclass cls = JENV->GetObjectClass(env, obj);
jfieldID field = JENV->GetFieldID(env, cls, "type", "I");
jint type = JENV->GetIntField(env, obj, field);
return JENV->NewStringUTF(env,
sigar_net_connection_type_get(type));
}
/* XXX perhaps it would be better to duplicate these strings
* in java land as static final so we dont create a new String
* everytime.
*/
JNIEXPORT jstring SIGAR_JNI(FileInfo_getTypeString)
(JNIEnv *env, jclass cls, jint type)
{
return JENV->NewStringUTF(env,
sigar_file_attrs_type_string_get(type));
}
JNIEXPORT jstring SIGAR_JNI(FileInfo_getPermissionsString)
(JNIEnv *env, jclass cls, jlong perms)
{
char str[24];
return JENV->NewStringUTF(env,
sigar_file_attrs_permissions_string_get(perms,
str));
}
JNIEXPORT jint SIGAR_JNI(FileInfo_getMode)
(JNIEnv *env, jclass cls, jlong perms)
{
return sigar_file_attrs_mode_get(perms);
}
/*
* copy of the generated FileAttrs_nativeGet function
* but we call the lstat wrapper instead.
*/
JNIEXPORT void SIGAR_JNI(FileInfo_nativeGetLink)
(JNIEnv *env, jobject obj, jobject sigar_obj, jstring name)
{
sigar_file_attrs_t s;
int status;
jclass cls = JENV->GetObjectClass(env, obj);
const char *utf;
dSIGAR_VOID;
utf = JENV->GetStringUTFChars(env, name, 0);
status = sigar_link_attrs_get(sigar, utf, &s);
JENV->ReleaseStringUTFChars(env, name, utf);
if (status != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return;
}
JAVA_SIGAR_INIT_FIELDS_FILEATTRS(cls);
JAVA_SIGAR_SET_FIELDS_FILEATTRS(cls, obj, s);
}
JNIEXPORT jlong SIGAR_JNI(Sigar_getProcPort)
(JNIEnv *env, jobject sigar_obj, jlong port)
{
int status;
sigar_pid_t pid;
dSIGAR(0);
#if defined(__linux__) || defined(WIN32)
/* just thinking about implementing this on other platforms hurts */
if ((status = sigar_proc_port_get(sigar, (unsigned long)port, &pid)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
}
#else
status = SIGAR_ENOTIMPL;
pid = -1;
sigar_throw_error(env, sigar, status);
#endif
return pid;
}
JNIEXPORT jobjectArray SIGAR_JNI(Sigar_getNetInterfaceList)
(JNIEnv *env, jobject sigar_obj)
{
int status;
unsigned int i;
sigar_net_interface_list_t iflist;
jobjectArray ifarray;
jclass stringclass = JENV->FindClass(env, "java/lang/String");
dSIGAR(NULL);
if ((status = sigar_net_interface_list_get(sigar, &iflist)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
ifarray = JENV->NewObjectArray(env, iflist.number, stringclass, 0);
for (i=0; i<iflist.number; i++) {
jstring s = JENV->NewStringUTF(env, iflist.data[i]);
JENV->SetObjectArrayElement(env, ifarray, i, s);
}
sigar_net_interface_list_destroy(sigar, &iflist);
return ifarray;
}
JNIEXPORT jstring SIGAR_JNI(Sigar_getPasswordNative)
(JNIEnv *env, jclass classinstance, jstring prompt)
{
const char *prompt_str;
char *password;
if (getenv("NO_NATIVE_GETPASS")) {
sigar_throw_notimpl(env, "disabled with $NO_NATIVE_GETPASS");
return NULL;
}
prompt_str = JENV->GetStringUTFChars(env, prompt, 0);
password = sigar_password_get(prompt_str);
JENV->ReleaseStringUTFChars(env, prompt, prompt_str);
return JENV->NewStringUTF(env, password);
}
JNIEXPORT jstring SIGAR_JNI(Sigar_getFQDN)
(JNIEnv *env, jobject sigar_obj)
{
char fqdn[SIGAR_FQDN_LEN];
int status;
dSIGAR(NULL);
if ((status = sigar_fqdn_get(sigar, fqdn, sizeof(fqdn))) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
return JENV->NewStringUTF(env, fqdn);
}
#include "sigar_getline.h"
JNIEXPORT jstring SIGAR_JNI(util_Getline_getline)
(JNIEnv *env, jobject sigar_obj, jstring prompt)
{
const char *prompt_str;
char *line;
jboolean is_copy;
prompt_str = JENV->GetStringUTFChars(env, prompt, &is_copy);
line = sigar_getline((char *)prompt_str);
if (is_copy) {
JENV->ReleaseStringUTFChars(env, prompt, prompt_str);
}
if ((line == NULL) ||
sigar_getline_eof())
{
jclass eof_ex = JENV->FindClass(env, "java/io/EOFException");
JENV->ThrowNew(env, eof_ex, "");
return NULL;
}
return JENV->NewStringUTF(env, line);
}
JNIEXPORT void SIGAR_JNI(util_Getline_histadd)
(JNIEnv *env, jobject sigar_obj, jstring hist)
{
const char *hist_str;
jboolean is_copy;
hist_str = JENV->GetStringUTFChars(env, hist, &is_copy);
sigar_getline_histadd((char *)hist_str);
if (is_copy) {
JENV->ReleaseStringUTFChars(env, hist, hist_str);
}
}
JNIEXPORT void SIGAR_JNI(util_Getline_histinit)
(JNIEnv *env, jobject sigar_obj, jstring hist)
{
const char *hist_str;
jboolean is_copy;
hist_str = JENV->GetStringUTFChars(env, hist, &is_copy);
sigar_getline_histinit((char *)hist_str);
if (is_copy) {
JENV->ReleaseStringUTFChars(env, hist, hist_str);
}
}
static struct {
JNIEnv *env;
jobject obj;
jmethodID id;
jclass clazz;
} jsigar_completer;
static int jsigar_getline_completer(char *buffer, int offset, int *pos)
{
JNIEnv *env = jsigar_completer.env;
jstring jbuffer;
jstring completion;
const char *line;
int len, cur;
jboolean is_copy;
jbuffer = JENV->NewStringUTF(env, buffer);
completion =
JENV->CallObjectMethod(env, jsigar_completer.obj,
jsigar_completer.id, jbuffer);
if (JENV->ExceptionOccurred(env)) {
JENV->ExceptionDescribe(env);
return 0;
}
if (!completion) {
return 0;
}
line = JENV->GetStringUTFChars(env, completion, &is_copy);
len = JENV->GetStringUTFLength(env, completion);
cur = *pos;
if (len != cur) {
strcpy(buffer, line);
*pos = len;
}
if (is_copy) {
JENV->ReleaseStringUTFChars(env, completion, line);
}
return cur;
}
JNIEXPORT void SIGAR_JNI(util_Getline_setCompleter)
(JNIEnv *env, jclass classinstance, jobject completer)
{
if (completer == NULL) {
sigar_getline_completer_set(NULL);
return;
}
jsigar_completer.env = env;
jsigar_completer.obj = completer;
jsigar_completer.clazz = JENV->GetObjectClass(env, completer);
jsigar_completer.id =
JENV->GetMethodID(env, jsigar_completer.clazz,
"complete",
"(Ljava/lang/String;)Ljava/lang/String;");
sigar_getline_completer_set(jsigar_getline_completer);
}
JNIEXPORT void SIGAR_JNI(util_Getline_redraw)
(JNIEnv *env, jobject obj)
{
sigar_getline_redraw();
}
JNIEXPORT void SIGAR_JNI(util_Getline_reset)
(JNIEnv *env, jobject obj)
{
sigar_getline_reset();
}
static const char *log_methods[] = {
"fatal", /* SIGAR_LOG_FATAL */
"error", /* SIGAR_LOG_ERROR */
"warn", /* SIGAR_LOG_WARN */
"info", /* SIGAR_LOG_INFO */
"debug", /* SIGAR_LOG_DEBUG */
/* XXX trace is only in commons-logging??? */
"debug", /* SIGAR_LOG_TRACE */
};
static void jsigar_log_impl(sigar_t *sigar, void *data,
int level, char *message)
{
jni_sigar_t *jsigar = (jni_sigar_t *)data;
JNIEnv *env = jsigar->env;
jobject logger = jsigar->logger;
jobject message_obj;
/* XXX should cache method id lookups */
jmethodID id =
JENV->GetMethodID(env, JENV->GetObjectClass(env, logger),
log_methods[level],
"(Ljava/lang/Object;)V");
if (JENV->ExceptionOccurred(env)) {
JENV->ExceptionDescribe(env);
return;
}
message_obj = (jobject)JENV->NewStringUTF(env, message);
JENV->CallObjectMethod(env, logger, id, message_obj);
}
JNIEXPORT void SIGAR_JNI(SigarLog_setLogger)
(JNIEnv *env, jclass classinstance, jobject sigar_obj, jobject logger)
{
dSIGAR_VOID;
jsigar->env = env;
if (jsigar->logger != NULL) {
JENV->DeleteGlobalRef(env, jsigar->logger);
jsigar->logger = NULL;
}
if (logger) {
jsigar->logger = JENV->NewGlobalRef(env, logger);
sigar_log_impl_set(sigar, jsigar, jsigar_log_impl);
}
else {
sigar_log_impl_set(sigar, NULL, NULL);
}
}
JNIEXPORT void SIGAR_JNI(SigarLog_setLevel)
(JNIEnv *env, jclass classinstance, jobject sigar_obj, jint level)
{
dSIGAR_VOID;
sigar_log_level_set(sigar, level);
}