jmethodID m_config;
jmethodID m_init;
- jmethodID m_read;
jmethodID m_write;
jmethodID m_shutdown;
};
typedef struct cjni_jvm_env_s cjni_jvm_env_t;
/* }}} */
+struct cjni_callback_info_s /* {{{ */
+{
+ jclass class;
+ jobject object;
+ jmethodID method;
+};
+typedef struct cjni_callback_info_s cjni_callback_info_t;
+/* }}} */
+
/*
* Global variables
*/
static java_plugin_t *java_plugins = NULL;
static size_t java_plugins_num = 0;
+/*
+ * Prototypes
+ *
+ * Mostly functions that are needed by the Java interface functions.
+ */
+static void cjni_callback_info_destroy (void *arg);
+static int cjni_read (user_data_t *user_data);
+
/*
* C to Java conversion functions
*/
/* Decrease reference counter on the java.lang.String object. */
(*jvm_env)->DeleteLocalRef (jvm_env, o_string);
- DEBUG ("java plugin: ctoj_string: ->%s (%s);",
- method_name, (string != NULL) ? string : "");
-
return (0);
} /* }}} int ctoj_string */
(*jvm_env)->CallVoidMethod (jvm_env, object_ptr, m_set, value);
- DEBUG ("java plugin: ctoj_int: ->%s (%i);",
- method_name, (int) value);
-
return (0);
} /* }}} int ctoj_int */
(*jvm_env)->CallVoidMethod (jvm_env, object_ptr, m_set, value);
- DEBUG ("java plugin: ctoj_long: ->%s (%"PRIi64");",
- method_name, (int64_t) value);
-
return (0);
} /* }}} int ctoj_long */
(*jvm_env)->CallVoidMethod (jvm_env, object_ptr, m_set, value);
- DEBUG ("java plugin: ctoj_double: ->%s (%g);",
- method_name, (double) value);
-
return (0);
} /* }}} int ctoj_double */
return (o_ocitem);
} /* }}} jobject ctoj_oconfig_item */
-/* Convert a data_set_t to a java.util.List<DataSource> */
+/* Convert a data_set_t to a org.collectd.api.DataSet */
static jobject ctoj_data_set (JNIEnv *jvm_env, const data_set_t *ds) /* {{{ */
{
- jclass c_arraylist;
+ jclass c_dataset;
jmethodID m_constructor;
jmethodID m_add;
+ jobject o_type;
jobject o_dataset;
int i;
- /* Look up the java.util.ArrayList class */
- c_arraylist = (*jvm_env)->FindClass (jvm_env, "java.util.ArrayList");
- if (c_arraylist == NULL)
+ /* Look up the org.collectd.api.DataSet class */
+ c_dataset = (*jvm_env)->FindClass (jvm_env, "org.collectd.api.DataSet");
+ if (c_dataset == NULL)
{
ERROR ("java plugin: ctoj_data_set: Looking up the "
- "java.util.ArrayList class failed.");
+ "org.collectd.api.DataSet class failed.");
return (NULL);
}
- /* Search for the `ArrayList (int capacity)' constructor. */
+ /* Search for the `DataSet (String type)' constructor. */
m_constructor = (*jvm_env)->GetMethodID (jvm_env,
- c_arraylist, "<init>", "()V");
+ c_dataset, "<init>", "(Ljava.lang.String;)V");
if (m_constructor == NULL)
{
ERROR ("java plugin: ctoj_data_set: Looking up the "
- "`ArrayList (void)' constructor failed.");
+ "`DataSet (String)' constructor failed.");
return (NULL);
}
- /* Search for the `boolean add (Object element)' method. */
+ /* Search for the `void addDataSource (DataSource)' method. */
m_add = (*jvm_env)->GetMethodID (jvm_env,
- c_arraylist, "add", "(Ljava/lang/Object;)Z");
+ c_dataset, "addDataSource", "(Lorg.collectd.api.DataSource;)V");
if (m_add == NULL)
{
ERROR ("java plugin: ctoj_data_set: Looking up the "
- "`add (Object)' method failed.");
+ "`addDataSource (DataSource)' method failed.");
return (NULL);
}
- o_dataset = (*jvm_env)->NewObject (jvm_env, c_arraylist, m_constructor);
+ o_type = (*jvm_env)->NewStringUTF (jvm_env, ds->type);
+ if (o_type == NULL)
+ {
+ ERROR ("java plugin: ctoj_data_set: Creating a String object failed.");
+ return (NULL);
+ }
+
+ o_dataset = (*jvm_env)->NewObject (jvm_env,
+ c_dataset, m_constructor, o_type);
if (o_dataset == NULL)
{
- ERROR ("java plugin: ctoj_data_set: "
- "Creating an ArrayList object failed.");
+ ERROR ("java plugin: ctoj_data_set: Creating a DataSet object failed.");
+ (*jvm_env)->DeleteLocalRef (jvm_env, o_type);
return (NULL);
}
+ /* Decrease reference counter on the java.lang.String object. */
+ (*jvm_env)->DeleteLocalRef (jvm_env, o_type);
+
for (i = 0; i < ds->ds_num; i++)
{
jobject o_datasource;
- jboolean status;
o_datasource = ctoj_data_source (jvm_env, ds->ds + i);
if (o_datasource == NULL)
return (NULL);
}
- status = (*jvm_env)->CallBooleanMethod (jvm_env,
- o_dataset, m_add, o_datasource);
- if (!status)
- {
- ERROR ("java plugin: ctoj_data_set: ArrayList.add returned FALSE.");
- (*jvm_env)->DeleteLocalRef (jvm_env, o_datasource);
- (*jvm_env)->DeleteLocalRef (jvm_env, o_dataset);
- return (NULL);
- }
+ (*jvm_env)->CallVoidMethod (jvm_env, o_dataset, m_add, o_datasource);
(*jvm_env)->DeleteLocalRef (jvm_env, o_datasource);
} /* for (i = 0; i < ds->ds_num; i++) */
static int ctoj_value_list_add_data_set (JNIEnv *jvm_env, /* {{{ */
jclass c_valuelist, jobject o_valuelist, const data_set_t *ds)
{
- jmethodID m_setdatasource;
+ jmethodID m_setdataset;
jobject o_dataset;
/* Look for the `void setDataSource (List<DataSource> ds)' method. */
- m_setdatasource = (*jvm_env)->GetMethodID (jvm_env, c_valuelist,
- "setDataSource", "(Ljava/util/List;)V");
- if (m_setdatasource == NULL)
+ m_setdataset = (*jvm_env)->GetMethodID (jvm_env, c_valuelist,
+ "setDataSet", "(Lorg.collectd.api.DataSet;)V");
+ if (m_setdataset == NULL)
{
ERROR ("java plugin: ctoj_value_list_add_data_set: "
- "Cannot find the `void setDataSource (List<DataSource> ds)' method.");
+ "Cannot find the `void setDataSet (DataSet)' method.");
return (-1);
}
- /* Create a List<DataSource> object. */
+ /* Create a DataSet object. */
o_dataset = ctoj_data_set (jvm_env, ds);
if (o_dataset == NULL)
{
/* Actually call the method. */
(*jvm_env)->CallVoidMethod (jvm_env,
- o_valuelist, m_setdatasource, o_dataset);
+ o_valuelist, m_setdataset, o_dataset);
/* Decrease reference counter on the List<DataSource> object. */
(*jvm_env)->DeleteLocalRef (jvm_env, o_dataset);
return (-1);
}
- DEBUG ("java plugin: jtoc_string: ->%s() = %s", method_name, c_str);
-
sstrncpy (buffer, c_str, buffer_size);
(*jvm_env)->ReleaseStringUTFChars (jvm_env, string_obj, c_str);
*ret_value = (*jvm_env)->CallLongMethod (jvm_env, object_ptr, method_id);
- DEBUG ("java plugin: jtoc_long: ->%s() = %li",
- method_name, (long int) *ret_value);
-
return (0);
} /* }}} int jtoc_long */
*ret_value = (*jvm_env)->CallDoubleMethod (jvm_env, object_ptr, method_id);
- DEBUG ("java plugin: jtoc_double: ->%s() = %g",
- method_name, (double) *ret_value);
-
return (0);
} /* }}} int jtoc_double */
return (0);
} /* }}} int jtoc_value_list */
+static cjni_callback_info_t *cjni_callback_info_create (JNIEnv *jvm_env, /* {{{ */
+ jobject obj, const char *method_name, const char *signature)
+{
+ cjni_callback_info_t *cbi;
+
+ cbi = (cjni_callback_info_t *) malloc (sizeof (*cbi));
+ if (cbi == NULL)
+ {
+ ERROR ("java plugin: cjni_callback_info_create: malloc failed.");
+ return (NULL);
+ }
+ memset (cbi, 0, sizeof (*cbi));
+
+ cbi->class = (*jvm_env)->GetObjectClass (jvm_env, obj);
+ if (cbi->class == NULL)
+ {
+ ERROR ("java plugin: cjni_callback_info_create: GetObjectClass failed.");
+ free (cbi);
+ return (NULL);
+ }
+
+ cbi->object = obj;
+
+ cbi->method = (*jvm_env)->GetMethodID (jvm_env, cbi->class,
+ method_name, signature);
+ if (cbi->method == NULL)
+ {
+ ERROR ("java plugin: cjni_callback_info_create: "
+ "Cannot find the `%s' method with signature `%s'.",
+ method_name, signature);
+ free (cbi);
+ return (NULL);
+ }
+
+ (*jvm_env)->NewGlobalRef (jvm_env, obj);
+
+ return (cbi);
+} /* }}} cjni_callback_info_t cjni_callback_info_create */
+
/*
* Functions accessible from Java
*/
return (o_dataset);
} /* }}} jint cjni_api_get_ds */
+static jint JNICALL cjni_api_register_read (JNIEnv *jvm_env, /* {{{ */
+ jobject this, jobject o_name, jobject o_read)
+{
+ const char *c_name;
+ user_data_t ud;
+ cjni_callback_info_t *cbi;
+
+ c_name = (*jvm_env)->GetStringUTFChars (jvm_env, o_name, 0);
+ if (c_name == NULL)
+ {
+ ERROR ("java plugin: cjni_api_register_read: GetStringUTFChars failed.");
+ return (-1);
+ }
+
+ cbi = cjni_callback_info_create (jvm_env, o_read, "Read", "()I");
+ if (cbi == NULL)
+ return (-1);
+
+ memset (&ud, 0, sizeof (ud));
+ ud.data = (void *) cbi;
+ ud.free_func = cjni_callback_info_destroy;
+
+ plugin_register_complex_read (c_name, cjni_read, &ud);
+
+ (*jvm_env)->ReleaseStringUTFChars (jvm_env, o_name, c_name);
+ (*jvm_env)->DeleteLocalRef (jvm_env, o_read);
+
+ return (0);
+} /* }}} jint cjni_api_register_read */
+
static JNINativeMethod jni_api_functions[] =
{
- { "DispatchValues", "(Lorg/collectd/api/ValueList;)I", cjni_api_dispatch_values },
- { "GetDS", "(Ljava/lang/String;)Ljava/util/List;", cjni_api_get_ds }
+ { "DispatchValues",
+ "(Lorg/collectd/api/ValueList;)I",
+ cjni_api_dispatch_values },
+
+ { "GetDS",
+ "(Ljava/lang/String;)Lorg/collectd/api/DataSet;",
+ cjni_api_get_ds },
+
+ { "RegisterRead",
+ "(Ljava/lang/String;Lorg/collectd/api/CollectdReadInterface;)I",
+ cjni_api_register_read }
};
static size_t jni_api_functions_num = sizeof (jni_api_functions)
/ sizeof (jni_api_functions[0]);
free (cjni_env);
} /* }}} void cjni_jvm_env_destroy */
+/*
+ * Delete a global reference, set by the various `Register*' functions.
+ */
+static void cjni_callback_info_destroy (void *arg) /* {{{ */
+{
+ JNIEnv *jni_env;
+ cjni_callback_info_t *cbi;
+
+ DEBUG ("java plugin: cjni_callback_info_destroy (arg = %p);", arg);
+
+ if (arg == NULL)
+ return;
+
+ jni_env = cjni_thread_attach ();
+ if (jni_env == NULL)
+ {
+ ERROR ("java plugin: cjni_callback_info_destroy: cjni_thread_attach failed.");
+ return;
+ }
+
+ cbi = (cjni_callback_info_t *) arg;
+
+ (*jni_env)->DeleteGlobalRef (jni_env, cbi->object);
+
+ cbi->method = NULL;
+ cbi->object = NULL;
+ cbi->class = NULL;
+ free (cbi);
+
+ cjni_thread_detach ();
+} /* }}} void cjni_callback_info_destroy */
+
static int cjni_config_add_jvm_arg (oconfig_item_t *ci) /* {{{ */
{
char **tmp;
jp->flags = 0;
jp->m_config = NULL;
jp->m_init = NULL;
- jp->m_read = NULL;
jp->m_write = NULL;
jp->m_shutdown = NULL;
return (0);
} /* }}} int cjni_shutdown */
-static int cjni_read_one_plugin (JNIEnv *jvm_env, java_plugin_t *jp) /* {{{ */
-{
- int status;
-
- if ((jp == NULL)
- || ((jp->flags & CJNI_FLAG_ENABLED) == 0)
- || (jp->m_read == NULL))
- return (0);
-
- DEBUG ("java plugin: Calling: %s.Read()", jp->class_name);
-
- status = (*jvm_env)->CallIntMethod (jvm_env, jp->object_ptr,
- jp->m_read);
- if (status != 0)
- {
- ERROR ("java plugin: cjni_read_one_plugin: "
- "Calling `Read' on an `%s' object failed with status %i.",
- jp->class_name, status);
- return (-1);
- }
-
- return (0);
-} /* }}} int cjni_read_one_plugin */
-
static int cjni_read (user_data_t *user_data) /* {{{ */
{
JNIEnv *jvm_env;
- java_plugin_t *jp;
+ cjni_callback_info_t *cbi;
int status;
if (jvm == NULL)
if (jvm_env == NULL)
return (-1);
- jp = (java_plugin_t *) user_data->data;
+ cbi = (cjni_callback_info_t *) user_data->data;
- cjni_read_one_plugin (jvm_env, jp);
+ status = (*jvm_env)->CallIntMethod (jvm_env, cbi->object,
+ cbi->method);
status = cjni_thread_detach ();
if (status != 0)
+ {
+ ERROR ("java plugin: cjni_read: cjni_thread_detach failed.");
return (-1);
+ }
- return (0);
+ return (status);
} /* }}} int cjni_read */
static int cjni_init_one_plugin (JNIEnv *jvm_env, java_plugin_t *jp) /* {{{ */
"jp->class_name = %s; jp->m_init = %p;",
jp->class_name, (void *) jp->m_init);
- jp->m_read = (*jvm_env)->GetMethodID (jvm_env, jp->class_ptr,
- "Read", "()I");
- DEBUG ("java plugin: cjni_init_one_plugin: "
- "jp->class_name = %s; jp->m_read = %p;",
- jp->class_name, (void *) jp->m_read);
-
jp->m_write = (*jvm_env)->GetMethodID (jvm_env, jp->class_ptr,
"Write", "(Lorg/collectd/api/ValueList;)I");
DEBUG ("java plugin: cjni_init_one_plugin: "
jp->flags |= CJNI_FLAG_ENABLED;
ssnprintf (plugin_name, sizeof (plugin_name), "java:%s", jp->class_name);
- if (jp->m_read != NULL)
- {
- user_data_t ud;
-
- memset (&ud, 0, sizeof (ud));
- ud.data = jp;
- ud.free_func = NULL;
-
- plugin_register_complex_read (plugin_name, cjni_read, &ud);
- }
if (jp->m_write != NULL)
{