2 * collectd - src/java.c
3 * Copyright (C) 2009 Florian octo Forster
4 * Copyright (C) 2008 Justo Alonso Achaques
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; only version 2 of the License is applicable.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * Florian octo Forster <octo at verplant.org>
21 * Justo Alonso Achaques <justo.alonso at gmail.com>
31 #if !defined(JNI_VERSION_1_2)
32 # error "Need JNI 1.2 compatible interface!"
38 struct java_plugin_s /* {{{ */
46 #define CJNI_FLAG_ENABLED 0x0001
53 typedef struct java_plugin_s java_plugin_t;
56 struct cjni_jvm_env_s /* {{{ */
59 int reference_counter;
61 typedef struct cjni_jvm_env_s cjni_jvm_env_t;
64 struct cjni_callback_info_s /* {{{ */
70 typedef struct cjni_callback_info_s cjni_callback_info_t;
76 static JavaVM *jvm = NULL;
77 static pthread_key_t jvm_env_key;
79 static char **jvm_argv = NULL;
80 static size_t jvm_argc = 0;
82 static java_plugin_t *java_plugins = NULL;
83 static size_t java_plugins_num = 0;
88 * Mostly functions that are needed by the Java interface functions.
90 static void cjni_callback_info_destroy (void *arg);
91 static int cjni_read (user_data_t *user_data);
92 static int cjni_write (const data_set_t *ds, const value_list_t *vl,
96 * C to Java conversion functions
98 static int ctoj_string (JNIEnv *jvm_env, /* {{{ */
100 jclass class_ptr, jobject object_ptr, const char *method_name)
105 /* Create a java.lang.String */
106 o_string = (*jvm_env)->NewStringUTF (jvm_env,
107 (string != NULL) ? string : "");
108 if (o_string == NULL)
110 ERROR ("java plugin: ctoj_string: NewStringUTF failed.");
114 /* Search for the `void setFoo (String s)' method. */
115 m_set = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
116 method_name, "(Ljava/lang/String;)V");
119 ERROR ("java plugin: ctoj_string: Cannot find method `void %s (String)'.",
121 (*jvm_env)->DeleteLocalRef (jvm_env, o_string);
125 /* Call the method. */
126 (*jvm_env)->CallVoidMethod (jvm_env, object_ptr, m_set, o_string);
128 /* Decrease reference counter on the java.lang.String object. */
129 (*jvm_env)->DeleteLocalRef (jvm_env, o_string);
132 } /* }}} int ctoj_string */
134 static int ctoj_int (JNIEnv *jvm_env, /* {{{ */
136 jclass class_ptr, jobject object_ptr, const char *method_name)
140 /* Search for the `void setFoo (int i)' method. */
141 m_set = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
142 method_name, "(I)V");
145 ERROR ("java plugin: ctoj_int: Cannot find method `void %s (int)'.",
150 (*jvm_env)->CallVoidMethod (jvm_env, object_ptr, m_set, value);
153 } /* }}} int ctoj_int */
155 static int ctoj_long (JNIEnv *jvm_env, /* {{{ */
157 jclass class_ptr, jobject object_ptr, const char *method_name)
161 /* Search for the `void setFoo (long l)' method. */
162 m_set = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
163 method_name, "(J)V");
166 ERROR ("java plugin: ctoj_long: Cannot find method `void %s (long)'.",
171 (*jvm_env)->CallVoidMethod (jvm_env, object_ptr, m_set, value);
174 } /* }}} int ctoj_long */
176 static int ctoj_double (JNIEnv *jvm_env, /* {{{ */
178 jclass class_ptr, jobject object_ptr, const char *method_name)
182 /* Search for the `void setFoo (double d)' method. */
183 m_set = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
184 method_name, "(D)V");
187 ERROR ("java plugin: ctoj_double: Cannot find method `void %s (double)'.",
192 (*jvm_env)->CallVoidMethod (jvm_env, object_ptr, m_set, value);
195 } /* }}} int ctoj_double */
197 /* Convert a jlong to a java.lang.Number */
198 static jobject ctoj_jlong_to_number (JNIEnv *jvm_env, jlong value) /* {{{ */
201 jmethodID m_long_constructor;
203 /* Look up the java.lang.Long class */
204 c_long = (*jvm_env)->FindClass (jvm_env, "java.lang.Long");
207 ERROR ("java plugin: ctoj_jlong_to_number: Looking up the "
208 "java.lang.Long class failed.");
212 m_long_constructor = (*jvm_env)->GetMethodID (jvm_env,
213 c_long, "<init>", "(J)V");
214 if (m_long_constructor == NULL)
216 ERROR ("java plugin: ctoj_jlong_to_number: Looking up the "
217 "`Long (long)' constructor failed.");
221 return ((*jvm_env)->NewObject (jvm_env,
222 c_long, m_long_constructor, value));
223 } /* }}} jobject ctoj_jlong_to_number */
225 /* Convert a jdouble to a java.lang.Number */
226 static jobject ctoj_jdouble_to_number (JNIEnv *jvm_env, jdouble value) /* {{{ */
229 jmethodID m_double_constructor;
231 /* Look up the java.lang.Long class */
232 c_double = (*jvm_env)->FindClass (jvm_env, "java.lang.Double");
233 if (c_double == NULL)
235 ERROR ("java plugin: ctoj_jdouble_to_number: Looking up the "
236 "java.lang.Double class failed.");
240 m_double_constructor = (*jvm_env)->GetMethodID (jvm_env,
241 c_double, "<init>", "(D)V");
242 if (m_double_constructor == NULL)
244 ERROR ("java plugin: ctoj_jdouble_to_number: Looking up the "
245 "`Double (double)' constructor failed.");
249 return ((*jvm_env)->NewObject (jvm_env,
250 c_double, m_double_constructor, value));
251 } /* }}} jobject ctoj_jdouble_to_number */
253 /* Convert a value_t to a java.lang.Number */
254 static jobject ctoj_value_to_number (JNIEnv *jvm_env, /* {{{ */
255 value_t value, int ds_type)
257 if (ds_type == DS_TYPE_COUNTER)
258 return (ctoj_jlong_to_number (jvm_env, (jlong) value.counter));
259 else if (ds_type == DS_TYPE_GAUGE)
260 return (ctoj_jdouble_to_number (jvm_env, (jdouble) value.gauge));
263 } /* }}} jobject ctoj_value_to_number */
265 /* Convert a data_source_t to a org.collectd.api.DataSource */
266 static jobject ctoj_data_source (JNIEnv *jvm_env, /* {{{ */
267 const data_source_t *dsrc)
270 jmethodID m_datasource_constructor;
271 jobject o_datasource;
274 /* Look up the DataSource class */
275 c_datasource = (*jvm_env)->FindClass (jvm_env,
276 "org.collectd.api.DataSource");
277 if (c_datasource == NULL)
279 ERROR ("java plugin: ctoj_data_source: "
280 "FindClass (org.collectd.api.DataSource) failed.");
284 /* Lookup the `ValueList ()' constructor. */
285 m_datasource_constructor = (*jvm_env)->GetMethodID (jvm_env, c_datasource,
287 if (m_datasource_constructor == NULL)
289 ERROR ("java plugin: ctoj_data_source: Cannot find the "
290 "`DataSource ()' constructor.");
294 /* Create a new instance. */
295 o_datasource = (*jvm_env)->NewObject (jvm_env, c_datasource,
296 m_datasource_constructor);
297 if (o_datasource == NULL)
299 ERROR ("java plugin: ctoj_data_source: "
300 "Creating a new DataSource instance failed.");
304 /* Set name via `void setName (String name)' */
305 status = ctoj_string (jvm_env, dsrc->name,
306 c_datasource, o_datasource, "setName");
309 ERROR ("java plugin: ctoj_data_source: "
310 "ctoj_string (setName) failed.");
311 (*jvm_env)->DeleteLocalRef (jvm_env, o_datasource);
315 /* Set type via `void setType (int type)' */
316 status = ctoj_int (jvm_env, dsrc->type,
317 c_datasource, o_datasource, "setType");
320 ERROR ("java plugin: ctoj_data_source: "
321 "ctoj_int (setType) failed.");
322 (*jvm_env)->DeleteLocalRef (jvm_env, o_datasource);
326 /* Set min via `void setMin (double min)' */
327 status = ctoj_double (jvm_env, dsrc->min,
328 c_datasource, o_datasource, "setMin");
331 ERROR ("java plugin: ctoj_data_source: "
332 "ctoj_double (setMin) failed.");
333 (*jvm_env)->DeleteLocalRef (jvm_env, o_datasource);
337 /* Set max via `void setMax (double max)' */
338 status = ctoj_double (jvm_env, dsrc->max,
339 c_datasource, o_datasource, "setMax");
342 ERROR ("java plugin: ctoj_data_source: "
343 "ctoj_double (setMax) failed.");
344 (*jvm_env)->DeleteLocalRef (jvm_env, o_datasource);
348 return (o_datasource);
349 } /* }}} jobject ctoj_data_source */
351 /* Convert a oconfig_value_t to a org.collectd.api.OConfigValue */
352 static jobject ctoj_oconfig_value (JNIEnv *jvm_env, /* {{{ */
353 oconfig_value_t ocvalue)
356 jmethodID m_ocvalue_constructor;
360 m_ocvalue_constructor = NULL;
363 c_ocvalue = (*jvm_env)->FindClass (jvm_env,
364 "org.collectd.api.OConfigValue");
365 if (c_ocvalue == NULL)
367 ERROR ("java plugin: ctoj_oconfig_value: "
368 "FindClass (org.collectd.api.OConfigValue) failed.");
372 if (ocvalue.type == OCONFIG_TYPE_BOOLEAN)
374 jboolean tmp_boolean;
376 tmp_boolean = (ocvalue.value.boolean == 0) ? JNI_FALSE : JNI_TRUE;
378 m_ocvalue_constructor = (*jvm_env)->GetMethodID (jvm_env, c_ocvalue,
380 if (m_ocvalue_constructor == NULL)
382 ERROR ("java plugin: ctoj_oconfig_value: Cannot find the "
383 "`OConfigValue (boolean)' constructor.");
387 return ((*jvm_env)->NewObject (jvm_env,
388 c_ocvalue, m_ocvalue_constructor, tmp_boolean));
389 } /* if (ocvalue.type == OCONFIG_TYPE_BOOLEAN) */
390 else if (ocvalue.type == OCONFIG_TYPE_STRING)
392 m_ocvalue_constructor = (*jvm_env)->GetMethodID (jvm_env, c_ocvalue,
393 "<init>", "(Ljava/lang/String;)V");
394 if (m_ocvalue_constructor == NULL)
396 ERROR ("java plugin: ctoj_oconfig_value: Cannot find the "
397 "`OConfigValue (String)' constructor.");
401 o_argument = (*jvm_env)->NewStringUTF (jvm_env, ocvalue.value.string);
402 if (o_argument == NULL)
404 ERROR ("java plugin: ctoj_oconfig_value: "
405 "Creating a String object failed.");
409 else if (ocvalue.type == OCONFIG_TYPE_NUMBER)
411 m_ocvalue_constructor = (*jvm_env)->GetMethodID (jvm_env, c_ocvalue,
412 "<init>", "(Ljava/lang/Number;)V");
413 if (m_ocvalue_constructor == NULL)
415 ERROR ("java plugin: ctoj_oconfig_value: Cannot find the "
416 "`OConfigValue (Number)' constructor.");
420 o_argument = ctoj_jdouble_to_number (jvm_env,
421 (jdouble) ocvalue.value.number);
422 if (o_argument == NULL)
424 ERROR ("java plugin: ctoj_oconfig_value: "
425 "Creating a Number object failed.");
434 assert (m_ocvalue_constructor != NULL);
435 assert (o_argument != NULL);
437 o_ocvalue = (*jvm_env)->NewObject (jvm_env,
438 c_ocvalue, m_ocvalue_constructor, o_argument);
439 if (o_ocvalue == NULL)
441 ERROR ("java plugin: ctoj_oconfig_value: "
442 "Creating an OConfigValue object failed.");
443 (*jvm_env)->DeleteLocalRef (jvm_env, o_argument);
447 (*jvm_env)->DeleteLocalRef (jvm_env, o_argument);
449 } /* }}} jobject ctoj_oconfig_value */
451 /* Convert a oconfig_item_t to a org.collectd.api.OConfigItem */
452 static jobject ctoj_oconfig_item (JNIEnv *jvm_env, /* {{{ */
453 const oconfig_item_t *ci)
456 jmethodID m_ocitem_constructor;
457 jmethodID m_addvalue;
458 jmethodID m_addchild;
463 c_ocitem = (*jvm_env)->FindClass (jvm_env, "org.collectd.api.OConfigItem");
464 if (c_ocitem == NULL)
466 ERROR ("java plugin: ctoj_oconfig_item: "
467 "FindClass (org.collectd.api.OConfigItem) failed.");
471 /* Get the required methods: m_ocitem_constructor, m_addvalue, and m_addchild
473 m_ocitem_constructor = (*jvm_env)->GetMethodID (jvm_env, c_ocitem,
474 "<init>", "(Ljava/lang/String;)V");
475 if (m_ocitem_constructor == NULL)
477 ERROR ("java plugin: ctoj_oconfig_item: Cannot find the "
478 "`OConfigItem (String)' constructor.");
482 m_addvalue = (*jvm_env)->GetMethodID (jvm_env, c_ocitem,
483 "addValue", "(Lorg/collectd/api/OConfigValue;)V");
484 if (m_addvalue == NULL)
486 ERROR ("java plugin: ctoj_oconfig_item: Cannot find the "
487 "`addValue (OConfigValue)' method.");
491 m_addchild = (*jvm_env)->GetMethodID (jvm_env, c_ocitem,
492 "addChild", "(Lorg/collectd/api/OConfigItem;)V");
493 if (m_addchild == NULL)
495 ERROR ("java plugin: ctoj_oconfig_item: Cannot find the "
496 "`addChild (OConfigItem)' method.");
501 /* Create a String object with the key.
502 * Needed for calling the constructor. */
503 o_key = (*jvm_env)->NewStringUTF (jvm_env, ci->key);
506 ERROR ("java plugin: ctoj_oconfig_item: "
507 "Creating String object failed.");
511 /* Create an OConfigItem object */
512 o_ocitem = (*jvm_env)->NewObject (jvm_env,
513 c_ocitem, m_ocitem_constructor, o_key);
514 if (o_ocitem == NULL)
516 ERROR ("java plugin: ctoj_oconfig_item: "
517 "Creating an OConfigItem object failed.");
518 (*jvm_env)->DeleteLocalRef (jvm_env, o_key);
522 /* We don't need the String object any longer.. */
523 (*jvm_env)->DeleteLocalRef (jvm_env, o_key);
525 /* Call OConfigItem.addValue for each value */
526 for (i = 0; i < ci->values_num; i++) /* {{{ */
530 o_value = ctoj_oconfig_value (jvm_env, ci->values[i]);
533 ERROR ("java plugin: ctoj_oconfig_item: "
534 "Creating an OConfigValue object failed.");
535 (*jvm_env)->DeleteLocalRef (jvm_env, o_ocitem);
539 (*jvm_env)->CallVoidMethod (jvm_env, o_ocitem, m_addvalue, o_value);
540 (*jvm_env)->DeleteLocalRef (jvm_env, o_value);
541 } /* }}} for (i = 0; i < ci->values_num; i++) */
543 /* Call OConfigItem.addChild for each child */
544 for (i = 0; i < ci->children_num; i++) /* {{{ */
548 o_child = ctoj_oconfig_item (jvm_env, ci->children + i);
551 ERROR ("java plugin: ctoj_oconfig_item: "
552 "Creating an OConfigItem object failed.");
553 (*jvm_env)->DeleteLocalRef (jvm_env, o_ocitem);
557 (*jvm_env)->CallVoidMethod (jvm_env, o_ocitem, m_addvalue, o_child);
558 (*jvm_env)->DeleteLocalRef (jvm_env, o_child);
559 } /* }}} for (i = 0; i < ci->children_num; i++) */
562 } /* }}} jobject ctoj_oconfig_item */
564 /* Convert a data_set_t to a org.collectd.api.DataSet */
565 static jobject ctoj_data_set (JNIEnv *jvm_env, const data_set_t *ds) /* {{{ */
568 jmethodID m_constructor;
574 /* Look up the org.collectd.api.DataSet class */
575 c_dataset = (*jvm_env)->FindClass (jvm_env, "org.collectd.api.DataSet");
576 if (c_dataset == NULL)
578 ERROR ("java plugin: ctoj_data_set: Looking up the "
579 "org.collectd.api.DataSet class failed.");
583 /* Search for the `DataSet (String type)' constructor. */
584 m_constructor = (*jvm_env)->GetMethodID (jvm_env,
585 c_dataset, "<init>", "(Ljava.lang.String;)V");
586 if (m_constructor == NULL)
588 ERROR ("java plugin: ctoj_data_set: Looking up the "
589 "`DataSet (String)' constructor failed.");
593 /* Search for the `void addDataSource (DataSource)' method. */
594 m_add = (*jvm_env)->GetMethodID (jvm_env,
595 c_dataset, "addDataSource", "(Lorg.collectd.api.DataSource;)V");
598 ERROR ("java plugin: ctoj_data_set: Looking up the "
599 "`addDataSource (DataSource)' method failed.");
603 o_type = (*jvm_env)->NewStringUTF (jvm_env, ds->type);
606 ERROR ("java plugin: ctoj_data_set: Creating a String object failed.");
610 o_dataset = (*jvm_env)->NewObject (jvm_env,
611 c_dataset, m_constructor, o_type);
612 if (o_dataset == NULL)
614 ERROR ("java plugin: ctoj_data_set: Creating a DataSet object failed.");
615 (*jvm_env)->DeleteLocalRef (jvm_env, o_type);
619 /* Decrease reference counter on the java.lang.String object. */
620 (*jvm_env)->DeleteLocalRef (jvm_env, o_type);
622 for (i = 0; i < ds->ds_num; i++)
624 jobject o_datasource;
626 o_datasource = ctoj_data_source (jvm_env, ds->ds + i);
627 if (o_datasource == NULL)
629 ERROR ("java plugin: ctoj_data_set: ctoj_data_source (%s.%s) failed",
630 ds->type, ds->ds[i].name);
631 (*jvm_env)->DeleteLocalRef (jvm_env, o_dataset);
635 (*jvm_env)->CallVoidMethod (jvm_env, o_dataset, m_add, o_datasource);
637 (*jvm_env)->DeleteLocalRef (jvm_env, o_datasource);
638 } /* for (i = 0; i < ds->ds_num; i++) */
641 } /* }}} jobject ctoj_data_set */
643 static int ctoj_value_list_add_value (JNIEnv *jvm_env, /* {{{ */
644 value_t value, int ds_type,
645 jclass class_ptr, jobject object_ptr)
647 jmethodID m_addvalue;
650 m_addvalue = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
651 "addValue", "(Ljava/lang/Number;)V");
652 if (m_addvalue == NULL)
654 ERROR ("java plugin: ctoj_value_list_add_value: "
655 "Cannot find method `void addValue (Number)'.");
659 o_number = ctoj_value_to_number (jvm_env, value, ds_type);
660 if (o_number == NULL)
662 ERROR ("java plugin: ctoj_value_list_add_value: "
663 "ctoj_value_to_number failed.");
667 (*jvm_env)->CallVoidMethod (jvm_env, object_ptr, m_addvalue, o_number);
669 (*jvm_env)->DeleteLocalRef (jvm_env, o_number);
672 } /* }}} int ctoj_value_list_add_value */
674 static int ctoj_value_list_add_data_set (JNIEnv *jvm_env, /* {{{ */
675 jclass c_valuelist, jobject o_valuelist, const data_set_t *ds)
677 jmethodID m_setdataset;
680 /* Look for the `void setDataSource (List<DataSource> ds)' method. */
681 m_setdataset = (*jvm_env)->GetMethodID (jvm_env, c_valuelist,
682 "setDataSet", "(Lorg.collectd.api.DataSet;)V");
683 if (m_setdataset == NULL)
685 ERROR ("java plugin: ctoj_value_list_add_data_set: "
686 "Cannot find the `void setDataSet (DataSet)' method.");
690 /* Create a DataSet object. */
691 o_dataset = ctoj_data_set (jvm_env, ds);
692 if (o_dataset == NULL)
694 ERROR ("java plugin: ctoj_value_list_add_data_set: "
695 "ctoj_data_set (%s) failed.", ds->type);
699 /* Actually call the method. */
700 (*jvm_env)->CallVoidMethod (jvm_env,
701 o_valuelist, m_setdataset, o_dataset);
703 /* Decrease reference counter on the List<DataSource> object. */
704 (*jvm_env)->DeleteLocalRef (jvm_env, o_dataset);
707 } /* }}} int ctoj_value_list_add_data_set */
709 static jobject ctoj_value_list (JNIEnv *jvm_env, /* {{{ */
710 const data_set_t *ds, const value_list_t *vl)
713 jmethodID m_valuelist_constructor;
718 /* First, create a new ValueList instance..
719 * Look up the class.. */
720 c_valuelist = (*jvm_env)->FindClass (jvm_env,
721 "org.collectd.api.ValueList");
722 if (c_valuelist == NULL)
724 ERROR ("java plugin: ctoj_value_list: "
725 "FindClass (org.collectd.api.ValueList) failed.");
729 /* Lookup the `ValueList ()' constructor. */
730 m_valuelist_constructor = (*jvm_env)->GetMethodID (jvm_env, c_valuelist,
732 if (m_valuelist_constructor == NULL)
734 ERROR ("java plugin: ctoj_value_list: Cannot find the "
735 "`ValueList ()' constructor.");
739 /* Create a new instance. */
740 o_valuelist = (*jvm_env)->NewObject (jvm_env, c_valuelist,
741 m_valuelist_constructor);
742 if (o_valuelist == NULL)
744 ERROR ("java plugin: ctoj_value_list: Creating a new ValueList instance "
749 status = ctoj_value_list_add_data_set (jvm_env,
750 c_valuelist, o_valuelist, ds);
753 ERROR ("java plugin: ctoj_value_list: "
754 "ctoj_value_list_add_data_set failed.");
755 (*jvm_env)->DeleteLocalRef (jvm_env, o_valuelist);
759 /* Set the strings.. */
760 #define SET_STRING(str,method_name) do { \
761 status = ctoj_string (jvm_env, str, \
762 c_valuelist, o_valuelist, method_name); \
764 ERROR ("java plugin: ctoj_value_list: jtoc_string (%s) failed.", \
766 (*jvm_env)->DeleteLocalRef (jvm_env, o_valuelist); \
770 SET_STRING (vl->host, "setHost");
771 SET_STRING (vl->plugin, "setPlugin");
772 SET_STRING (vl->plugin_instance, "setPluginInstance");
773 SET_STRING (vl->type, "setType");
774 SET_STRING (vl->type_instance, "setTypeInstance");
778 /* Set the `time' member. Java stores time in milliseconds. */
779 status = ctoj_long (jvm_env, ((jlong) vl->time) * ((jlong) 1000),
780 c_valuelist, o_valuelist, "setTime");
783 ERROR ("java plugin: ctoj_value_list: ctoj_long (setTime) failed.");
784 (*jvm_env)->DeleteLocalRef (jvm_env, o_valuelist);
788 /* Set the `interval' member.. */
789 status = ctoj_long (jvm_env, (jlong) vl->interval,
790 c_valuelist, o_valuelist, "setInterval");
793 ERROR ("java plugin: ctoj_value_list: ctoj_long (setInterval) failed.");
794 (*jvm_env)->DeleteLocalRef (jvm_env, o_valuelist);
798 for (i = 0; i < vl->values_len; i++)
800 status = ctoj_value_list_add_value (jvm_env, vl->values[i], ds->ds[i].type,
801 c_valuelist, o_valuelist);
804 ERROR ("java plugin: ctoj_value_list: "
805 "ctoj_value_list_add_value failed.");
806 (*jvm_env)->DeleteLocalRef (jvm_env, o_valuelist);
811 return (o_valuelist);
812 } /* }}} int ctoj_value_list */
815 * Java to C conversion functions
817 static int jtoc_string (JNIEnv *jvm_env, /* {{{ */
818 char *buffer, size_t buffer_size,
819 jclass class_ptr, jobject object_ptr, const char *method_name)
825 method_id = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
826 method_name, "()Ljava/lang/String;");
827 if (method_id == NULL)
829 ERROR ("java plugin: jtoc_string: Cannot find method `String %s ()'.",
834 string_obj = (*jvm_env)->CallObjectMethod (jvm_env, object_ptr, method_id);
835 if (string_obj == NULL)
837 ERROR ("java plugin: jtoc_string: CallObjectMethod (%s) failed.",
842 c_str = (*jvm_env)->GetStringUTFChars (jvm_env, string_obj, 0);
845 ERROR ("java plugin: jtoc_string: GetStringUTFChars failed.");
846 (*jvm_env)->DeleteLocalRef (jvm_env, string_obj);
850 sstrncpy (buffer, c_str, buffer_size);
852 (*jvm_env)->ReleaseStringUTFChars (jvm_env, string_obj, c_str);
853 (*jvm_env)->DeleteLocalRef (jvm_env, string_obj);
856 } /* }}} int jtoc_string */
858 static int jtoc_long (JNIEnv *jvm_env, /* {{{ */
860 jclass class_ptr, jobject object_ptr, const char *method_name)
864 method_id = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
866 if (method_id == NULL)
868 ERROR ("java plugin: jtoc_long: Cannot find method `long %s ()'.",
873 *ret_value = (*jvm_env)->CallLongMethod (jvm_env, object_ptr, method_id);
876 } /* }}} int jtoc_long */
878 static int jtoc_double (JNIEnv *jvm_env, /* {{{ */
880 jclass class_ptr, jobject object_ptr, const char *method_name)
884 method_id = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
886 if (method_id == NULL)
888 ERROR ("java plugin: jtoc_string: Cannot find method `double %s ()'.",
893 *ret_value = (*jvm_env)->CallDoubleMethod (jvm_env, object_ptr, method_id);
896 } /* }}} int jtoc_double */
898 static int jtoc_value (JNIEnv *jvm_env, /* {{{ */
899 value_t *ret_value, int ds_type, jobject object_ptr)
904 class_ptr = (*jvm_env)->GetObjectClass (jvm_env, object_ptr);
906 if (ds_type == DS_TYPE_COUNTER)
910 status = jtoc_long (jvm_env, &tmp_long,
911 class_ptr, object_ptr, "longValue");
914 ERROR ("java plugin: jtoc_value: "
915 "jtoc_long failed.");
918 (*ret_value).counter = (counter_t) tmp_long;
924 status = jtoc_double (jvm_env, &tmp_double,
925 class_ptr, object_ptr, "doubleValue");
928 ERROR ("java plugin: jtoc_value: "
929 "jtoc_double failed.");
932 (*ret_value).gauge = (gauge_t) tmp_double;
936 } /* }}} int jtoc_value */
938 static int jtoc_values_array (JNIEnv *jvm_env, /* {{{ */
939 const data_set_t *ds, value_list_t *vl,
940 jclass class_ptr, jobject object_ptr)
942 jmethodID m_getvalues;
945 jobjectArray o_number_array;
951 values_num = ds->ds_num;
954 o_number_array = NULL;
957 #define BAIL_OUT(status) \
959 if (o_number_array != NULL) \
960 (*jvm_env)->DeleteLocalRef (jvm_env, o_number_array); \
961 if (o_list != NULL) \
962 (*jvm_env)->DeleteLocalRef (jvm_env, o_list); \
965 /* Call: List<Number> ValueList.getValues () */
966 m_getvalues = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
967 "getValues", "()Ljava/util/List;");
968 if (m_getvalues == NULL)
970 ERROR ("java plugin: jtoc_values_array: "
971 "Cannot find method `List getValues ()'.");
975 o_list = (*jvm_env)->CallObjectMethod (jvm_env, object_ptr, m_getvalues);
978 ERROR ("java plugin: jtoc_values_array: "
979 "CallObjectMethod (getValues) failed.");
983 /* Call: Number[] List.toArray () */
984 m_toarray = (*jvm_env)->GetMethodID (jvm_env,
985 (*jvm_env)->GetObjectClass (jvm_env, o_list),
986 "toArray", "()[Ljava/lang/Object;");
987 if (m_toarray == NULL)
989 ERROR ("java plugin: jtoc_values_array: "
990 "Cannot find method `Object[] toArray ()'.");
994 o_number_array = (*jvm_env)->CallObjectMethod (jvm_env, o_list, m_toarray);
995 if (o_number_array == NULL)
997 ERROR ("java plugin: jtoc_values_array: "
998 "CallObjectMethod (toArray) failed.");
1002 values = calloc (values_num, sizeof (value_t));
1005 ERROR ("java plugin: jtoc_values_array: calloc failed.");
1009 for (i = 0; i < values_num; i++)
1014 o_number = (*jvm_env)->GetObjectArrayElement (jvm_env,
1015 o_number_array, (jsize) i);
1016 if (o_number == NULL)
1018 ERROR ("java plugin: jtoc_values_array: "
1019 "GetObjectArrayElement (%i) failed.", i);
1023 status = jtoc_value (jvm_env, values + i, ds->ds[i].type, o_number);
1026 ERROR ("java plugin: jtoc_values_array: "
1027 "jtoc_value (%i) failed.", i);
1030 } /* for (i = 0; i < values_num; i++) */
1032 vl->values = values;
1033 vl->values_len = values_num;
1036 (*jvm_env)->DeleteLocalRef (jvm_env, o_number_array);
1037 (*jvm_env)->DeleteLocalRef (jvm_env, o_list);
1039 } /* }}} int jtoc_values_array */
1041 /* Convert a org.collectd.api.ValueList to a value_list_t. */
1042 static int jtoc_value_list (JNIEnv *jvm_env, value_list_t *vl, /* {{{ */
1048 const data_set_t *ds;
1050 class_ptr = (*jvm_env)->GetObjectClass (jvm_env, object_ptr);
1051 if (class_ptr == NULL)
1053 ERROR ("java plugin: jtoc_value_list: GetObjectClass failed.");
1057 #define SET_STRING(buffer,method) do { \
1058 status = jtoc_string (jvm_env, buffer, sizeof (buffer), \
1059 class_ptr, object_ptr, method); \
1060 if (status != 0) { \
1061 ERROR ("java plugin: jtoc_value_list: jtoc_string (%s) failed.", \
1066 SET_STRING(vl->type, "getType");
1068 ds = plugin_get_ds (vl->type);
1071 ERROR ("java plugin: jtoc_value_list: Data-set `%s' is not defined. "
1072 "Please consult the types.db(5) manpage for mor information.",
1077 SET_STRING(vl->host, "getHost");
1078 SET_STRING(vl->plugin, "getPlugin");
1079 SET_STRING(vl->plugin_instance, "getPluginInstance");
1080 SET_STRING(vl->type_instance, "getTypeInstance");
1084 status = jtoc_long (jvm_env, &tmp_long, class_ptr, object_ptr, "getTime");
1087 ERROR ("java plugin: jtoc_value_list: jtoc_long (getTime) failed.");
1090 /* Java measures time in milliseconds. */
1091 vl->time = (time_t) (tmp_long / ((jlong) 1000));
1093 status = jtoc_long (jvm_env, &tmp_long,
1094 class_ptr, object_ptr, "getInterval");
1097 ERROR ("java plugin: jtoc_value_list: jtoc_long (getInterval) failed.");
1100 vl->interval = (int) tmp_long;
1102 status = jtoc_values_array (jvm_env, ds, vl, class_ptr, object_ptr);
1105 ERROR ("java plugin: jtoc_value_list: jtoc_values_array failed.");
1110 } /* }}} int jtoc_value_list */
1112 static cjni_callback_info_t *cjni_callback_info_create (JNIEnv *jvm_env, /* {{{ */
1113 jobject obj, const char *method_name, const char *signature)
1115 cjni_callback_info_t *cbi;
1117 cbi = (cjni_callback_info_t *) malloc (sizeof (*cbi));
1120 ERROR ("java plugin: cjni_callback_info_create: malloc failed.");
1123 memset (cbi, 0, sizeof (*cbi));
1125 cbi->class = (*jvm_env)->GetObjectClass (jvm_env, obj);
1126 if (cbi->class == NULL)
1128 ERROR ("java plugin: cjni_callback_info_create: GetObjectClass failed.");
1135 cbi->method = (*jvm_env)->GetMethodID (jvm_env, cbi->class,
1136 method_name, signature);
1137 if (cbi->method == NULL)
1139 ERROR ("java plugin: cjni_callback_info_create: "
1140 "Cannot find the `%s' method with signature `%s'.",
1141 method_name, signature);
1146 (*jvm_env)->NewGlobalRef (jvm_env, obj);
1149 } /* }}} cjni_callback_info_t cjni_callback_info_create */
1152 * Functions accessible from Java
1154 static jint JNICALL cjni_api_dispatch_values (JNIEnv *jvm_env, /* {{{ */
1155 jobject this, jobject java_vl)
1157 value_list_t vl = VALUE_LIST_INIT;
1160 DEBUG ("cjni_api_dispatch_values: java_vl = %p;", (void *) java_vl);
1162 status = jtoc_value_list (jvm_env, &vl, java_vl);
1165 ERROR ("java plugin: cjni_api_dispatch_values: jtoc_value_list failed.");
1169 status = plugin_dispatch_values (&vl);
1174 } /* }}} jint cjni_api_dispatch_values */
1176 static jobject JNICALL cjni_api_get_ds (JNIEnv *jvm_env, /* {{{ */
1177 jobject this, jobject o_string_type)
1179 const char *ds_name;
1180 const data_set_t *ds;
1183 ds_name = (*jvm_env)->GetStringUTFChars (jvm_env, o_string_type, 0);
1184 if (ds_name == NULL)
1186 ERROR ("java plugin: cjni_api_get_ds: GetStringUTFChars failed.");
1190 ds = plugin_get_ds (ds_name);
1191 DEBUG ("java plugin: cjni_api_get_ds: "
1192 "plugin_get_ds (%s) = %p;", ds_name, (void *) ds);
1194 (*jvm_env)->ReleaseStringUTFChars (jvm_env, o_string_type, ds_name);
1199 o_dataset = ctoj_data_set (jvm_env, ds);
1201 } /* }}} jint cjni_api_get_ds */
1203 static jint JNICALL cjni_api_register_read (JNIEnv *jvm_env, /* {{{ */
1204 jobject this, jobject o_name, jobject o_read)
1208 cjni_callback_info_t *cbi;
1210 c_name = (*jvm_env)->GetStringUTFChars (jvm_env, o_name, 0);
1213 ERROR ("java plugin: cjni_api_register_read: GetStringUTFChars failed.");
1217 cbi = cjni_callback_info_create (jvm_env, o_read, "Read", "()I");
1221 memset (&ud, 0, sizeof (ud));
1222 ud.data = (void *) cbi;
1223 ud.free_func = cjni_callback_info_destroy;
1225 plugin_register_complex_read (c_name, cjni_read, &ud);
1227 DEBUG ("java plugin: New read callback registered: %s", c_name);
1229 (*jvm_env)->ReleaseStringUTFChars (jvm_env, o_name, c_name);
1230 (*jvm_env)->DeleteLocalRef (jvm_env, o_read);
1233 } /* }}} jint cjni_api_register_read */
1235 static jint JNICALL cjni_api_register_write (JNIEnv *jvm_env, /* {{{ */
1236 jobject this, jobject o_name, jobject o_read)
1240 cjni_callback_info_t *cbi;
1242 c_name = (*jvm_env)->GetStringUTFChars (jvm_env, o_name, 0);
1245 ERROR ("java plugin: cjni_api_register_write: GetStringUTFChars failed.");
1249 cbi = cjni_callback_info_create (jvm_env, o_read,
1250 "Write", "(Lorg/collectd/api/ValueList;)I");
1254 memset (&ud, 0, sizeof (ud));
1255 ud.data = (void *) cbi;
1256 ud.free_func = cjni_callback_info_destroy;
1258 plugin_register_write (c_name, cjni_write, &ud);
1260 DEBUG ("java plugin: New write callback registered: %s", c_name);
1262 (*jvm_env)->ReleaseStringUTFChars (jvm_env, o_name, c_name);
1263 (*jvm_env)->DeleteLocalRef (jvm_env, o_read);
1266 } /* }}} jint cjni_api_register_write */
1268 static JNINativeMethod jni_api_functions[] =
1271 "(Lorg/collectd/api/ValueList;)I",
1272 cjni_api_dispatch_values },
1275 "(Ljava/lang/String;)Lorg/collectd/api/DataSet;",
1279 "(Ljava/lang/String;Lorg/collectd/api/CollectdReadInterface;)I",
1280 cjni_api_register_read },
1283 "(Ljava/lang/String;Lorg/collectd/api/CollectdWriteInterface;)I",
1284 cjni_api_register_write }
1286 static size_t jni_api_functions_num = sizeof (jni_api_functions)
1287 / sizeof (jni_api_functions[0]);
1292 static JNIEnv *cjni_thread_attach (void) /* {{{ */
1294 cjni_jvm_env_t *cjni_env;
1297 cjni_env = pthread_getspecific (jvm_env_key);
1298 if (cjni_env == NULL)
1300 /* This pointer is free'd in `cjni_jvm_env_destroy'. */
1301 cjni_env = (cjni_jvm_env_t *) malloc (sizeof (*cjni_env));
1302 if (cjni_env == NULL)
1304 ERROR ("java plugin: cjni_thread_attach: malloc failed.");
1307 memset (cjni_env, 0, sizeof (*cjni_env));
1308 cjni_env->reference_counter = 0;
1309 cjni_env->jvm_env = NULL;
1311 pthread_setspecific (jvm_env_key, cjni_env);
1314 if (cjni_env->reference_counter > 0)
1316 cjni_env->reference_counter++;
1317 jvm_env = cjni_env->jvm_env;
1322 JavaVMAttachArgs args;
1324 assert (cjni_env->jvm_env == NULL);
1326 memset (&args, 0, sizeof (args));
1327 args.version = JNI_VERSION_1_2;
1329 status = (*jvm)->AttachCurrentThread (jvm, (void *) &jvm_env, (void *) &args);
1332 ERROR ("java plugin: cjni_thread_attach: AttachCurrentThread failed "
1333 "with status %i.", status);
1337 cjni_env->reference_counter = 1;
1338 cjni_env->jvm_env = jvm_env;
1341 DEBUG ("java plugin: cjni_thread_attach: cjni_env->reference_counter = %i",
1342 cjni_env->reference_counter);
1343 assert (jvm_env != NULL);
1345 } /* }}} JNIEnv *cjni_thread_attach */
1347 static int cjni_thread_detach (void) /* {{{ */
1349 cjni_jvm_env_t *cjni_env;
1352 cjni_env = pthread_getspecific (jvm_env_key);
1353 if (cjni_env == NULL)
1355 ERROR ("java plugin: cjni_thread_detach: pthread_getspecific failed.");
1359 assert (cjni_env->reference_counter > 0);
1360 assert (cjni_env->jvm_env != NULL);
1362 cjni_env->reference_counter--;
1363 DEBUG ("java plugin: cjni_thread_detach: cjni_env->reference_counter = %i",
1364 cjni_env->reference_counter);
1366 if (cjni_env->reference_counter > 0)
1369 status = (*jvm)->DetachCurrentThread (jvm);
1372 ERROR ("java plugin: cjni_thread_detach: DetachCurrentThread failed "
1373 "with status %i.", status);
1376 cjni_env->reference_counter = 0;
1377 cjni_env->jvm_env = NULL;
1380 } /* }}} JNIEnv *cjni_thread_attach */
1382 static void cjni_jvm_env_destroy (void *args) /* {{{ */
1384 cjni_jvm_env_t *cjni_env;
1389 cjni_env = (cjni_jvm_env_t *) args;
1391 if (cjni_env->reference_counter > 0)
1393 ERROR ("java plugin: cjni_jvm_env_destroy: "
1394 "cjni_env->reference_counter = %i;", cjni_env->reference_counter);
1397 if (cjni_env->jvm_env != NULL)
1399 ERROR ("java plugin: cjni_jvm_env_destroy: cjni_env->jvm_env = %p;",
1400 (void *) cjni_env->jvm_env);
1403 /* The pointer is allocated in `cjni_thread_attach' */
1405 } /* }}} void cjni_jvm_env_destroy */
1408 * Delete a global reference, set by the various `Register*' functions.
1410 static void cjni_callback_info_destroy (void *arg) /* {{{ */
1413 cjni_callback_info_t *cbi;
1415 DEBUG ("java plugin: cjni_callback_info_destroy (arg = %p);", arg);
1420 jni_env = cjni_thread_attach ();
1421 if (jni_env == NULL)
1423 ERROR ("java plugin: cjni_callback_info_destroy: cjni_thread_attach failed.");
1427 cbi = (cjni_callback_info_t *) arg;
1429 (*jni_env)->DeleteGlobalRef (jni_env, cbi->object);
1436 cjni_thread_detach ();
1437 } /* }}} void cjni_callback_info_destroy */
1439 static int cjni_config_add_jvm_arg (oconfig_item_t *ci) /* {{{ */
1443 if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
1445 WARNING ("java plugin: `JVMArg' needs exactly one string argument.");
1449 tmp = (char **) realloc (jvm_argv, sizeof (char *) * (jvm_argc + 1));
1452 ERROR ("java plugin: realloc failed.");
1457 jvm_argv[jvm_argc] = strdup (ci->values[0].value.string);
1458 if (jvm_argv[jvm_argc] == NULL)
1460 ERROR ("java plugin: strdup failed.");
1466 } /* }}} int cjni_config_add_jvm_arg */
1468 static int cjni_config_load_plugin (oconfig_item_t *ci) /* {{{ */
1472 if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
1474 WARNING ("java plugin: `LoadPlugin' needs exactly one string argument.");
1478 jp = (java_plugin_t *) realloc (java_plugins,
1479 sizeof (*java_plugins) * (java_plugins_num + 1));
1482 ERROR ("java plugin: realloc failed.");
1486 jp = java_plugins + java_plugins_num;
1488 memset (jp, 0, sizeof (*jp));
1489 jp->class_name = strdup (ci->values[0].value.string);
1490 if (jp->class_name == NULL)
1492 ERROR ("java plugin: strdup failed.");
1496 jp->class_ptr = NULL;
1497 jp->object_ptr = NULL;
1500 jp->m_config = NULL;
1502 jp->m_shutdown = NULL;
1507 } /* }}} int cjni_config_load_plugin */
1509 static int cjni_config_plugin_block (oconfig_item_t *ci) /* {{{ */
1512 const char *class_name;
1514 if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
1516 WARNING ("java plugin: `Plugin' blocks "
1517 "need exactly one string argument.");
1521 class_name = ci->values[0].value.string;
1522 for (i = 0; i < java_plugins_num; i++)
1523 if (strcmp (java_plugins[i].class_name, class_name) == 0)
1526 if (i >= java_plugins_num)
1528 WARNING ("java plugin: Configuration block for the `%s' plugin found, "
1529 "but the plugin has not been loaded. Please note, that the class "
1530 "name is case-sensitive!",
1535 if (java_plugins[i].ci != NULL)
1537 WARNING ("java plugin: There are more than one <Plugin> blocks for the "
1538 "`%s' plugin. This is currently not supported - only the first block "
1544 java_plugins[i].ci = oconfig_clone (ci);
1545 if (java_plugins[i].ci == NULL)
1547 ERROR ("java plugin: cjni_config_plugin_block: "
1548 "oconfig_clone failed for `%s'.",
1553 DEBUG ("java plugin: cjni_config_plugin_block: "
1554 "Successfully copied config for `%s'.",
1558 } /* }}} int cjni_config_plugin_block */
1560 static int cjni_config (oconfig_item_t *ci) /* {{{ */
1570 for (i = 0; i < ci->children_num; i++)
1572 oconfig_item_t *child = ci->children + i;
1574 if (strcasecmp ("JVMArg", child->key) == 0)
1576 status = cjni_config_add_jvm_arg (child);
1582 else if (strcasecmp ("LoadPlugin", child->key) == 0)
1584 status = cjni_config_load_plugin (child);
1590 else if (strcasecmp ("Plugin", child->key) == 0)
1592 status = cjni_config_plugin_block (child);
1600 WARNING ("java plugin: Option `%s' not allowed here.", child->key);
1605 if ((success == 0) && (errors > 0))
1607 ERROR ("java plugin: All statements failed.");
1612 } /* }}} int cjni_config */
1614 static int cjni_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */
1618 cjni_callback_info_t *cbi;
1624 ERROR ("java plugin: cjni_write: jvm == NULL");
1628 if ((ud == NULL) || (ud->data == NULL))
1630 ERROR ("java plugin: cjni_write: Invalid user data.");
1634 jvm_env = cjni_thread_attach ();
1635 if (jvm_env == NULL)
1638 cbi = (cjni_callback_info_t *) ud->data;
1640 vl_java = ctoj_value_list (jvm_env, ds, vl);
1641 if (vl_java == NULL)
1643 ERROR ("java plugin: cjni_write: ctoj_value_list failed.");
1647 status = (*jvm_env)->CallIntMethod (jvm_env,
1648 cbi->object, cbi->method, vl_java);
1650 (*jvm_env)->DeleteLocalRef (jvm_env, vl_java);
1652 status = cjni_thread_detach ();
1655 ERROR ("java plugin: cjni_write: cjni_thread_detach failed.");
1660 } /* }}} int cjni_write */
1662 static int cjni_shutdown_one_plugin (JNIEnv *jvm_env, /* {{{ */
1668 || ((jp->flags & CJNI_FLAG_ENABLED) == 0)
1669 || (jp->m_shutdown == NULL))
1672 status = (*jvm_env)->CallIntMethod (jvm_env, jp->object_ptr,
1676 ERROR ("cjni_shutdown_one_plugin: Destroying an `%s' object failed "
1677 "with status %i.", jp->class_name, status);
1680 jp->flags &= ~CJNI_FLAG_ENABLED;
1683 } /* }}} int cjni_shutdown_one_plugin */
1685 static int cjni_shutdown_plugins (JNIEnv *jvm_env) /* {{{ */
1689 for (j = 0; j < java_plugins_num; j++)
1690 cjni_shutdown_one_plugin (jvm_env, &java_plugins[j]);
1693 } /* }}} int cjni_shutdown_plugins */
1695 static int cjni_shutdown (void) /* {{{ */
1698 JavaVMAttachArgs args;
1706 memset (&args, 0, sizeof (args));
1707 args.version = JNI_VERSION_1_2;
1709 status = (*jvm)->AttachCurrentThread (jvm, (void **) &jvm_env, &args);
1712 ERROR ("java plugin: cjni_shutdown: AttachCurrentThread failed with status %i.",
1717 cjni_shutdown_plugins (jvm_env);
1719 (*jvm)->DestroyJavaVM (jvm);
1723 pthread_key_delete (jvm_env_key);
1725 for (i = 0; i < jvm_argc; i++)
1727 sfree (jvm_argv[i]);
1732 for (i = 0; i < java_plugins_num; i++)
1734 sfree (java_plugins[i].class_name);
1735 oconfig_free (java_plugins[i].ci);
1737 sfree (java_plugins);
1738 java_plugins_num = 0;
1741 } /* }}} int cjni_shutdown */
1743 static int cjni_read (user_data_t *ud) /* {{{ */
1746 cjni_callback_info_t *cbi;
1751 ERROR ("java plugin: cjni_read: jvm == NULL");
1755 if ((ud == NULL) || (ud->data == NULL))
1757 ERROR ("java plugin: cjni_read: Invalid user data.");
1761 jvm_env = cjni_thread_attach ();
1762 if (jvm_env == NULL)
1765 cbi = (cjni_callback_info_t *) ud->data;
1767 status = (*jvm_env)->CallIntMethod (jvm_env, cbi->object,
1770 status = cjni_thread_detach ();
1773 ERROR ("java plugin: cjni_read: cjni_thread_detach failed.");
1778 } /* }}} int cjni_read */
1780 static int cjni_init_one_plugin (JNIEnv *jvm_env, java_plugin_t *jp) /* {{{ */
1782 jmethodID constructor_id;
1785 jp->class_ptr = (*jvm_env)->FindClass (jvm_env, jp->class_name);
1786 if (jp->class_ptr == NULL)
1788 ERROR ("cjni_init_one_plugin: FindClass (%s) failed.",
1793 constructor_id = (*jvm_env)->GetMethodID (jvm_env, jp->class_ptr,
1795 if (constructor_id == NULL)
1797 ERROR ("cjni_init_one_plugin: Could not find the constructor for `%s'.",
1802 jp->object_ptr = (*jvm_env)->NewObject (jvm_env, jp->class_ptr,
1804 if (jp->object_ptr == NULL)
1806 ERROR ("cjni_init_one_plugin: Could create a new `%s' object.",
1811 jp->m_config = (*jvm_env)->GetMethodID (jvm_env, jp->class_ptr,
1812 "Config", "(Lorg/collectd/api/OConfigItem;)I");
1813 DEBUG ("java plugin: cjni_init_one_plugin: "
1814 "jp->class_name = %s; jp->m_config = %p;",
1815 jp->class_name, (void *) jp->m_config);
1817 jp->m_init = (*jvm_env)->GetMethodID (jvm_env, jp->class_ptr,
1819 DEBUG ("java plugin: cjni_init_one_plugin: "
1820 "jp->class_name = %s; jp->m_init = %p;",
1821 jp->class_name, (void *) jp->m_init);
1823 jp->m_shutdown = (*jvm_env)->GetMethodID (jvm_env, jp->class_ptr,
1825 DEBUG ("java plugin: cjni_init_one_plugin: "
1826 "jp->class_name = %s; jp->m_shutdown = %p;",
1827 jp->class_name, (void *) jp->m_shutdown);
1831 if (jp->m_config == NULL)
1833 WARNING ("java plugin: Configuration for the `%s' plugin is present, "
1834 "but plugin doesn't provide a configuration method.",
1837 else /* if (jp->m_config != NULL) */
1841 o_ocitem = ctoj_oconfig_item (jvm_env, jp->ci);
1842 if (o_ocitem == NULL)
1844 ERROR ("java plugin: Creating an OConfigItem object failed. "
1845 "Can't pass configuration information to the `%s' plugin!",
1848 else /* if (o_ocitem != NULL) */
1850 status = (*jvm_env)->CallIntMethod (jvm_env,
1851 jp->object_ptr, jp->m_config, o_ocitem);
1854 ERROR ("java plugin: cjni_init_one_plugin: "
1855 "Configuring the `%s' object failed with status %i.",
1856 jp->class_name, status);
1857 (*jvm_env)->DeleteLocalRef (jvm_env, o_ocitem);
1860 (*jvm_env)->DeleteLocalRef (jvm_env, o_ocitem);
1861 } /* if (o_ocitem != NULL) */
1862 } /* if (jp->m_config != NULL) */
1863 } /* if (jp->ci != NULL) */
1865 if (jp->m_init != NULL)
1867 status = (*jvm_env)->CallIntMethod (jvm_env, jp->object_ptr,
1871 ERROR ("java plugin: cjni_init_one_plugin: "
1872 "Initializing `%s' object failed with status %i.",
1873 jp->class_name, status);
1877 jp->flags |= CJNI_FLAG_ENABLED;
1880 } /* }}} int cjni_init_one_plugin */
1882 static int cjni_init_plugins (JNIEnv *jvm_env) /* {{{ */
1889 for (j = 0; j < java_plugins_num; j++)
1891 cjni_init_one_plugin (jvm_env, &java_plugins[j]);
1893 if (java_plugins[j].m_shutdown != NULL)
1897 if (have_shutdown > 0)
1898 plugin_register_shutdown ("java", cjni_shutdown);
1901 } /* }}} int cjni_init_plugins */
1903 static int cjni_init_native (JNIEnv *jvm_env) /* {{{ */
1905 jclass api_class_ptr;
1908 api_class_ptr = (*jvm_env)->FindClass (jvm_env, "org.collectd.api.CollectdAPI");
1909 if (api_class_ptr == NULL)
1911 ERROR ("cjni_init_native: Cannot find API class `org.collectd.api.CollectdAPI'.");
1915 status = (*jvm_env)->RegisterNatives (jvm_env, api_class_ptr,
1916 jni_api_functions, (jint) jni_api_functions_num);
1919 ERROR ("cjni_init_native: RegisterNatives failed with status %i.", status);
1924 } /* }}} int cjni_init_native */
1926 static int cjni_init (void) /* {{{ */
1929 JavaVMInitArgs vm_args;
1930 JavaVMOption vm_options[jvm_argc];
1938 status = pthread_key_create (&jvm_env_key, cjni_jvm_env_destroy);
1941 ERROR ("java plugin: cjni_init: pthread_key_create failed "
1942 "with status %i.", status);
1948 memset (&vm_args, 0, sizeof (vm_args));
1949 vm_args.version = JNI_VERSION_1_2;
1950 vm_args.options = vm_options;
1951 vm_args.nOptions = (jint) jvm_argc;
1953 for (i = 0; i < jvm_argc; i++)
1955 DEBUG ("java plugin: cjni_init: jvm_argv[%zu] = %s", i, jvm_argv[i]);
1956 vm_args.options[i].optionString = jvm_argv[i];
1959 vm_args.options[0].optionString = "-verbose:jni";
1960 vm_args.options[1].optionString = "-Djava.class.path=/home/octo/collectd/bindings/java";
1963 status = JNI_CreateJavaVM (&jvm, (void **) &jvm_env, (void **) &vm_args);
1966 ERROR ("cjni_init: JNI_CreateJavaVM failed with status %i.",
1970 assert (jvm != NULL);
1971 assert (jvm_env != NULL);
1973 /* Call RegisterNatives */
1974 status = cjni_init_native (jvm_env);
1977 ERROR ("cjni_init: cjni_init_native failed.");
1981 cjni_init_plugins (jvm_env);
1984 } /* }}} int cjni_init */
1986 void module_register (void)
1988 plugin_register_complex_config ("java", cjni_config);
1989 plugin_register_init ("java", cjni_init);
1990 } /* void module_register (void) */
1992 /* vim: set sw=2 sts=2 et fdm=marker : */