static size_t java_callbacks_num = 0;
static pthread_mutex_t java_callbacks_lock = PTHREAD_MUTEX_INITIALIZER;
+static oconfig_item_t *config_block = NULL;
+
/*
* Prototypes
*
jmethodID m_long_constructor;
/* Look up the java.lang.Long class */
- c_long = (*jvm_env)->FindClass (jvm_env, "java.lang.Long");
+ c_long = (*jvm_env)->FindClass (jvm_env, "java/lang/Long");
if (c_long == NULL)
{
ERROR ("java plugin: ctoj_jlong_to_number: Looking up the "
jmethodID m_double_constructor;
/* Look up the java.lang.Long class */
- c_double = (*jvm_env)->FindClass (jvm_env, "java.lang.Double");
+ c_double = (*jvm_env)->FindClass (jvm_env, "java/lang/Double");
if (c_double == NULL)
{
ERROR ("java plugin: ctoj_jdouble_to_number: Looking up the "
return (ctoj_jlong_to_number (jvm_env, (jlong) value.counter));
else if (ds_type == DS_TYPE_GAUGE)
return (ctoj_jdouble_to_number (jvm_env, (jdouble) value.gauge));
+ if (ds_type == DS_TYPE_DERIVE)
+ return (ctoj_jlong_to_number (jvm_env, (jlong) value.derive));
+ if (ds_type == DS_TYPE_ABSOLUTE)
+ return (ctoj_jlong_to_number (jvm_env, (jlong) value.absolute));
else
return (NULL);
} /* }}} jobject ctoj_value_to_number */
-/* Convert a data_source_t to a org.collectd.api.DataSource */
+/* Convert a data_source_t to a org/collectd/api/DataSource */
static jobject ctoj_data_source (JNIEnv *jvm_env, /* {{{ */
const data_source_t *dsrc)
{
/* Look up the DataSource class */
c_datasource = (*jvm_env)->FindClass (jvm_env,
- "org.collectd.api.DataSource");
+ "org/collectd/api/DataSource");
if (c_datasource == NULL)
{
ERROR ("java plugin: ctoj_data_source: "
- "FindClass (org.collectd.api.DataSource) failed.");
+ "FindClass (org/collectd/api/DataSource) failed.");
return (NULL);
}
return (o_datasource);
} /* }}} jobject ctoj_data_source */
-/* Convert a oconfig_value_t to a org.collectd.api.OConfigValue */
+/* Convert a oconfig_value_t to a org/collectd/api/OConfigValue */
static jobject ctoj_oconfig_value (JNIEnv *jvm_env, /* {{{ */
oconfig_value_t ocvalue)
{
o_argument = NULL;
c_ocvalue = (*jvm_env)->FindClass (jvm_env,
- "org.collectd.api.OConfigValue");
+ "org/collectd/api/OConfigValue");
if (c_ocvalue == NULL)
{
ERROR ("java plugin: ctoj_oconfig_value: "
- "FindClass (org.collectd.api.OConfigValue) failed.");
+ "FindClass (org/collectd/api/OConfigValue) failed.");
return (NULL);
}
return (o_ocvalue);
} /* }}} jobject ctoj_oconfig_value */
-/* Convert a oconfig_item_t to a org.collectd.api.OConfigItem */
+/* Convert a oconfig_item_t to a org/collectd/api/OConfigItem */
static jobject ctoj_oconfig_item (JNIEnv *jvm_env, /* {{{ */
const oconfig_item_t *ci)
{
jobject o_ocitem;
int i;
- c_ocitem = (*jvm_env)->FindClass (jvm_env, "org.collectd.api.OConfigItem");
+ c_ocitem = (*jvm_env)->FindClass (jvm_env, "org/collectd/api/OConfigItem");
if (c_ocitem == NULL)
{
ERROR ("java plugin: ctoj_oconfig_item: "
- "FindClass (org.collectd.api.OConfigItem) failed.");
+ "FindClass (org/collectd/api/OConfigItem) failed.");
return (NULL);
}
return (NULL);
}
- (*jvm_env)->CallVoidMethod (jvm_env, o_ocitem, m_addvalue, o_child);
+ (*jvm_env)->CallVoidMethod (jvm_env, o_ocitem, m_addchild, o_child);
(*jvm_env)->DeleteLocalRef (jvm_env, o_child);
} /* }}} for (i = 0; i < ci->children_num; i++) */
return (o_ocitem);
} /* }}} jobject ctoj_oconfig_item */
-/* Convert a data_set_t to a org.collectd.api.DataSet */
+/* 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_dataset;
jobject o_dataset;
int i;
- /* Look up the org.collectd.api.DataSet class */
- c_dataset = (*jvm_env)->FindClass (jvm_env, "org.collectd.api.DataSet");
+ /* 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 "
- "org.collectd.api.DataSet class failed.");
+ "org/collectd/api/DataSet class failed.");
return (NULL);
}
/* Search for the `DataSet (String type)' constructor. */
m_constructor = (*jvm_env)->GetMethodID (jvm_env,
- c_dataset, "<init>", "(Ljava.lang.String;)V");
+ c_dataset, "<init>", "(Ljava/lang/String;)V");
if (m_constructor == NULL)
{
ERROR ("java plugin: ctoj_data_set: Looking up the "
/* Search for the `void addDataSource (DataSource)' method. */
m_add = (*jvm_env)->GetMethodID (jvm_env,
- c_dataset, "addDataSource", "(Lorg.collectd.api.DataSource;)V");
+ c_dataset, "addDataSource", "(Lorg/collectd/api/DataSource;)V");
if (m_add == NULL)
{
ERROR ("java plugin: ctoj_data_set: Looking up the "
/* Look for the `void setDataSource (List<DataSource> ds)' method. */
m_setdataset = (*jvm_env)->GetMethodID (jvm_env, c_valuelist,
- "setDataSet", "(Lorg.collectd.api.DataSet;)V");
+ "setDataSet", "(Lorg/collectd/api/DataSet;)V");
if (m_setdataset == NULL)
{
ERROR ("java plugin: ctoj_value_list_add_data_set: "
return (0);
} /* }}} int ctoj_value_list_add_data_set */
-/* Convert a value_list_t (and data_set_t) to a org.collectd.api.ValueList */
+/* Convert a value_list_t (and data_set_t) to a org/collectd/api/ValueList */
static jobject ctoj_value_list (JNIEnv *jvm_env, /* {{{ */
const data_set_t *ds, const value_list_t *vl)
{
/* First, create a new ValueList instance..
* Look up the class.. */
c_valuelist = (*jvm_env)->FindClass (jvm_env,
- "org.collectd.api.ValueList");
+ "org/collectd/api/ValueList");
if (c_valuelist == NULL)
{
ERROR ("java plugin: ctoj_value_list: "
- "FindClass (org.collectd.api.ValueList) failed.");
+ "FindClass (org/collectd/api/ValueList) failed.");
return (NULL);
}
return (o_valuelist);
} /* }}} jobject ctoj_value_list */
-/* Convert a notification_t to a org.collectd.api.Notification */
+/* Convert a notification_t to a org/collectd/api/Notification */
static jobject ctoj_notification (JNIEnv *jvm_env, /* {{{ */
const notification_t *n)
{
/* First, create a new Notification instance..
* Look up the class.. */
c_notification = (*jvm_env)->FindClass (jvm_env,
- "org.collectd.api.Notification");
+ "org/collectd/api/Notification");
if (c_notification == NULL)
{
ERROR ("java plugin: ctoj_notification: "
- "FindClass (org.collectd.api.Notification) failed.");
+ "FindClass (org/collectd/api/Notification) failed.");
return (NULL);
}
class_ptr = (*jvm_env)->GetObjectClass (jvm_env, object_ptr);
- if (ds_type == DS_TYPE_COUNTER)
+ if (ds_type == DS_TYPE_GAUGE)
{
- jlong tmp_long;
+ jdouble tmp_double;
- status = jtoc_long (jvm_env, &tmp_long,
- class_ptr, object_ptr, "longValue");
+ status = jtoc_double (jvm_env, &tmp_double,
+ class_ptr, object_ptr, "doubleValue");
if (status != 0)
{
ERROR ("java plugin: jtoc_value: "
- "jtoc_long failed.");
+ "jtoc_double failed.");
return (-1);
}
- (*ret_value).counter = (counter_t) tmp_long;
+ (*ret_value).gauge = (gauge_t) tmp_double;
}
else
{
- jdouble tmp_double;
+ jlong tmp_long;
- status = jtoc_double (jvm_env, &tmp_double,
- class_ptr, object_ptr, "doubleValue");
+ status = jtoc_long (jvm_env, &tmp_long,
+ class_ptr, object_ptr, "longValue");
if (status != 0)
{
ERROR ("java plugin: jtoc_value: "
- "jtoc_double failed.");
+ "jtoc_long failed.");
return (-1);
}
- (*ret_value).gauge = (gauge_t) tmp_double;
+
+ if (ds_type == DS_TYPE_DERIVE)
+ (*ret_value).derive = (derive_t) tmp_long;
+ else if (ds_type == DS_TYPE_ABSOLUTE)
+ (*ret_value).absolute = (absolute_t) tmp_long;
+ else
+ (*ret_value).counter = (counter_t) tmp_long;
}
return (0);
return (0);
} /* }}} int jtoc_values_array */
-/* Convert a org.collectd.api.ValueList to a value_list_t. */
+/* Convert a org/collectd/api/ValueList to a value_list_t. */
static int jtoc_value_list (JNIEnv *jvm_env, value_list_t *vl, /* {{{ */
jobject object_ptr)
{
return (0);
} /* }}} int jtoc_value_list */
-/* Convert a org.collectd.api.Notification to a notification_t. */
+/* Convert a org/collectd/api/Notification to a notification_t. */
static int jtoc_notification (JNIEnv *jvm_env, notification_t *n, /* {{{ */
jobject object_ptr)
{
ud.data = (void *) cbi;
ud.free_func = cjni_callback_info_destroy;
- plugin_register_complex_read (cbi->name, cjni_read, &ud);
+ plugin_register_complex_read (/* group = */ NULL, cbi->name, cjni_read,
+ /* interval = */ NULL, &ud);
(*jvm_env)->DeleteLocalRef (jvm_env, o_read);
(*jvm_env)->ReleaseStringUTFChars (jvm_env, o_name, c_name);
- cbi->class = (*jvm_env)->GetObjectClass (jvm_env, o_callback);
+ cbi->object = (*jvm_env)->NewGlobalRef (jvm_env, o_callback);
+ if (cbi->object == NULL)
+ {
+ ERROR ("java plugin: cjni_callback_info_create: NewGlobalRef failed.");
+ free (cbi);
+ return (NULL);
+ }
+
+ cbi->class = (*jvm_env)->GetObjectClass (jvm_env, cbi->object);
if (cbi->class == NULL)
{
ERROR ("java plugin: cjni_callback_info_create: GetObjectClass failed.");
return (NULL);
}
- cbi->object = o_callback;
-
cbi->method = (*jvm_env)->GetMethodID (jvm_env, cbi->class,
method_name, method_signature);
if (cbi->method == NULL)
return (NULL);
}
- (*jvm_env)->NewGlobalRef (jvm_env, o_callback);
-
return (cbi);
} /* }}} cjni_callback_info_t cjni_callback_info_create */
jclass api_class_ptr;
int status;
- api_class_ptr = (*jvm_env)->FindClass (jvm_env, "org.collectd.api.Collectd");
+ api_class_ptr = (*jvm_env)->FindClass (jvm_env, "org/collectd/api/Collectd");
if (api_class_ptr == NULL)
{
- ERROR ("cjni_init_native: Cannot find API class `org.collectd.api.Collectd'.");
+ ERROR ("cjni_init_native: Cannot find the API class \"org.collectd.api"
+ ".Collectd\". Please set the correct class path "
+ "using 'JVMArg \"-Djava.class.path=...\"'.");
return (-1);
}
i, jvm_argv[i]);
vm_args.options[i].optionString = jvm_argv[i];
}
- /*
- vm_args.options[0].optionString = "-verbose:jni";
- vm_args.options[1].optionString = "-Djava.class.path=/home/octo/collectd/bindings/java";
- */
- status = JNI_CreateJavaVM (&jvm, (void **) &jvm_env, (void **) &vm_args);
+ status = JNI_CreateJavaVM (&jvm, (void *) &jvm_env, (void *) &vm_args);
if (status != 0)
{
ERROR ("java plugin: cjni_create_jvm: "
JNIEnv *jvm_env;
java_plugin_class_t *class;
jmethodID constructor_id;
+ jobject tmp_object;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
{
class->class = NULL;
class->object = NULL;
+ { /* Replace all dots ('.') with slashes ('/'). Dots are usually used
+ thorough the Java community, but (Sun's) `FindClass' and friends need
+ slashes. */
+ size_t i;
+ for (i = 0; class->name[i] != 0; i++)
+ if (class->name[i] == '.')
+ class->name[i] = '/';
+ }
+
DEBUG ("java plugin: Loading class %s", class->name);
class->class = (*jvm_env)->FindClass (jvm_env, class->name);
return (-1);
}
- class->object = (*jvm_env)->NewObject (jvm_env, class->class,
+ tmp_object = (*jvm_env)->NewObject (jvm_env, class->class,
constructor_id);
+ if (tmp_object != NULL)
+ class->object = (*jvm_env)->NewGlobalRef (jvm_env, tmp_object);
+ else
+ class->object = NULL;
if (class->object == NULL)
{
ERROR ("java plugin: cjni_config_load_plugin: "
return (-1);
}
- (*jvm_env)->NewGlobalRef (jvm_env, class->object);
cjni_thread_detach ();
java_classes_list_len++;
int status;
size_t i;
+ jclass class;
+ jmethodID method;
+
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
{
WARNING ("java plugin: `Plugin' blocks "
return (-1);
}
+ class = (*jvm_env)->GetObjectClass (jvm_env, cbi->object);
+ method = (*jvm_env)->GetMethodID (jvm_env, class,
+ "config", "(Lorg/collectd/api/OConfigItem;)I");
+
status = (*jvm_env)->CallIntMethod (jvm_env,
- cbi->object, cbi->method, o_ocitem);
+ cbi->object, method, o_ocitem);
(*jvm_env)->DeleteLocalRef (jvm_env, o_ocitem);
cjni_thread_detach ();
return (0);
} /* }}} int cjni_config_plugin_block */
-static int cjni_config (oconfig_item_t *ci) /* {{{ */
+static int cjni_config_perform (oconfig_item_t *ci) /* {{{ */
{
int success;
int errors;
}
return (0);
-} /* }}} int cjni_config */
+} /* }}} int cjni_config_perform */
+
+/* Copy the children of `ci' to the global `config_block' variable. */
+static int cjni_config_callback (oconfig_item_t *ci) /* {{{ */
+{
+ oconfig_item_t *ci_copy;
+ oconfig_item_t *tmp;
+
+ assert (ci != NULL);
+ if (ci->children_num == 0)
+ return (0); /* nothing to do */
+
+ ci_copy = oconfig_clone (ci);
+ if (ci_copy == NULL)
+ {
+ ERROR ("java plugin: oconfig_clone failed.");
+ return (-1);
+ }
+
+ if (config_block == NULL)
+ {
+ config_block = ci_copy;
+ return (0);
+ }
+
+ tmp = realloc (config_block->children,
+ (config_block->children_num + ci_copy->children_num) * sizeof (*tmp));
+ if (tmp == NULL)
+ {
+ ERROR ("java plugin: realloc failed.");
+ oconfig_free (ci_copy);
+ return (-1);
+ }
+ config_block->children = tmp;
+
+ /* Copy the pointers */
+ memcpy (config_block->children + config_block->children_num,
+ ci_copy->children,
+ ci_copy->children_num * sizeof (*ci_copy->children));
+ config_block->children_num += ci_copy->children_num;
+
+ /* Delete the pointers from the copy, so `oconfig_free' can't free them. */
+ memset (ci_copy->children, 0,
+ ci_copy->children_num * sizeof (*ci_copy->children));
+ ci_copy->children_num = 0;
+
+ oconfig_free (ci_copy);
+
+ return (0);
+} /* }}} int cjni_config_callback */
/* Free the data contained in the `user_data_t' pointer passed to `cjni_read'
* and `cjni_write'. In particular, delete the global reference to the Java
cjni_callback_info_t *cbi_factory;
const char *name;
jobject o_ci;
+ jobject o_tmp;
int type;
size_t i;
}
/* Then call the factory method so it creates a new object for us. */
- cbi_ret->object = (*jvm_env)->CallObjectMethod (jvm_env,
+ o_tmp = (*jvm_env)->CallObjectMethod (jvm_env,
cbi_factory->object, cbi_factory->method, o_ci);
- if (cbi_ret->object == NULL)
+ if (o_tmp == NULL)
{
ERROR ("java plugin: cjni_match_target_create: CallObjectMethod failed.");
BAIL_OUT (-1);
}
+ cbi_ret->object = (*jvm_env)->NewGlobalRef (jvm_env, o_tmp);
+ if (o_tmp == NULL)
+ {
+ ERROR ("java plugin: cjni_match_target_create: NewGlobalRef failed.");
+ BAIL_OUT (-1);
+ }
+
/* This is the class of the match. It is possibly different from the class of
* the match-factory! */
cbi_ret->class = (*jvm_env)->GetObjectClass (jvm_env, cbi_ret->object);
BAIL_OUT (-1);
}
- /* We have everything we hoped for. Now we add a new global reference so this
- * match isn't freed immediately after we return.. */
- (*jvm_env)->NewGlobalRef (jvm_env, cbi_ret->object);
-
/* Return the newly created match via the user_data pointer. */
*user_data = (void *) cbi_ret;
memset (&args, 0, sizeof (args));
args.version = JNI_VERSION_1_2;
- status = (*jvm)->AttachCurrentThread (jvm, (void **) &jvm_env, &args);
+ status = (*jvm)->AttachCurrentThread (jvm, (void *) &jvm_env, &args);
if (status != 0)
{
ERROR ("java plugin: cjni_shutdown: AttachCurrentThread failed with status %i.",
{
JNIEnv *jvm_env;
+ if ((config_block == NULL) && (jvm == NULL))
+ {
+ ERROR ("java plugin: cjni_init: No configuration block for "
+ "the java plugin was found.");
+ return (-1);
+ }
+
+ if (config_block != NULL)
+ {
+ int status;
+
+ status = cjni_config_perform (config_block);
+ oconfig_free (config_block);
+ config_block = NULL;
+ }
+
if (jvm == NULL)
{
ERROR ("java plugin: cjni_init: jvm == NULL");
void module_register (void)
{
- plugin_register_complex_config ("java", cjni_config);
+ plugin_register_complex_config ("java", cjni_config_callback);
plugin_register_init ("java", cjni_init);
plugin_register_shutdown ("java", cjni_shutdown);
} /* void module_register (void) */