1789Sahrens /*
2789Sahrens * CDDL HEADER START
3789Sahrens *
4789Sahrens * The contents of this file are subject to the terms of the
5789Sahrens * Common Development and Distribution License, Version 1.0 only
6789Sahrens * (the "License"). You may not use this file except in compliance
7789Sahrens * with the License.
8789Sahrens *
9789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10789Sahrens * or http://www.opensolaris.org/os/licensing.
11789Sahrens * See the License for the specific language governing permissions
12789Sahrens * and limitations under the License.
13789Sahrens *
14789Sahrens * When distributing Covered Code, include this CDDL HEADER in each
15789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16789Sahrens * If applicable, add the following below this CDDL HEADER, with the
17789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying
18789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner]
19789Sahrens *
20789Sahrens * CDDL HEADER END
21789Sahrens */
22789Sahrens /*
23*1206Stalley * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24789Sahrens * Use is subject to license terms.
25789Sahrens */
26789Sahrens
27789Sahrens #pragma ident "%Z%%M% %I% %E% SMI"
28789Sahrens
29789Sahrens #include "libzfs_jni_util.h"
30789Sahrens #include <strings.h>
31789Sahrens
32789Sahrens /*
33789Sahrens * Package-private functions
34789Sahrens */
35789Sahrens
36894Stalley void
zjni_free_array(void ** array,zjni_free_f freefunc)37894Stalley zjni_free_array(void **array, zjni_free_f freefunc)
38894Stalley {
39894Stalley if (array != NULL) {
40894Stalley if (freefunc != NULL) {
41894Stalley int i;
42894Stalley for (i = 0; array[i] != NULL; i++) {
43894Stalley freefunc(array[i]);
44894Stalley }
45894Stalley }
46894Stalley free(array);
47894Stalley }
48894Stalley }
49894Stalley
50789Sahrens /*PRINTFLIKE2*/
51789Sahrens void
zjni_throw_exception(JNIEnv * env,const char * fmt,...)52789Sahrens zjni_throw_exception(JNIEnv *env, const char *fmt, ...)
53789Sahrens {
54789Sahrens char error[1024];
55789Sahrens va_list ap;
56789Sahrens jclass class_UnsupportedOperationException;
57789Sahrens
58789Sahrens va_start(ap, fmt);
59789Sahrens (void) vsnprintf(error, sizeof (error), fmt, ap);
60789Sahrens va_end(ap);
61789Sahrens
62789Sahrens class_UnsupportedOperationException =
63789Sahrens (*env)->FindClass(env, "java/lang/UnsupportedOperationException");
64789Sahrens
65789Sahrens (*env)->ThrowNew(env, class_UnsupportedOperationException, error);
66789Sahrens }
67789Sahrens
68789Sahrens jstring
zjni_get_matched_string(JNIEnv * env,char * name,regmatch_t * match)69789Sahrens zjni_get_matched_string(JNIEnv *env, char *name, regmatch_t *match)
70789Sahrens {
71789Sahrens jstring stringUTF = NULL;
72789Sahrens if (match->rm_so != -1 && match->rm_eo != -1) {
73789Sahrens char *end = name + match->rm_eo;
74789Sahrens char tmp = *end;
75789Sahrens *end = '\0';
76789Sahrens stringUTF = (*env)->NewStringUTF(env, name + match->rm_so);
77789Sahrens *end = tmp;
78789Sahrens }
79789Sahrens return (stringUTF);
80789Sahrens }
81789Sahrens
82789Sahrens void
zjni_get_dataset_from_snapshot(const char * snapshot,char * dataset,size_t len)83789Sahrens zjni_get_dataset_from_snapshot(const char *snapshot, char *dataset,
84789Sahrens size_t len)
85789Sahrens {
86789Sahrens char *at;
87789Sahrens (void) strncpy(dataset, snapshot, len);
88789Sahrens at = strchr(dataset, '@');
89789Sahrens if (at != NULL) {
90789Sahrens *at = '\0';
91789Sahrens }
92789Sahrens }
93789Sahrens
94789Sahrens /* Convert a zjni_Collection to a (Java) array */
95789Sahrens jobjectArray
zjni_Collection_to_array(JNIEnv * env,zjni_Collection_t * list,char * class)96789Sahrens zjni_Collection_to_array(JNIEnv *env, zjni_Collection_t *list, char *class)
97789Sahrens {
98789Sahrens /* Get size of zjni_Collection */
99789Sahrens jint length = (*env)->CallIntMethod(
100789Sahrens env, ((zjni_Object_t *)list)->object,
101789Sahrens ((zjni_Collection_t *)list)->method_size);
102789Sahrens
103789Sahrens /* Create array to hold elements of list */
104789Sahrens jobjectArray array = (*env)->NewObjectArray(
105789Sahrens env, length, (*env)->FindClass(env, class), NULL);
106789Sahrens
107789Sahrens /* Copy list elements to array */
108789Sahrens return (*env)->CallObjectMethod(env, ((zjni_Object_t *)list)->object,
109789Sahrens ((zjni_Collection_t *)list)->method_toArray, array);
110789Sahrens }
111789Sahrens
112789Sahrens /* Create a zjni_Collection */
113789Sahrens void
new_Collection(JNIEnv * env,zjni_Collection_t * collection)114789Sahrens new_Collection(JNIEnv *env, zjni_Collection_t *collection)
115789Sahrens {
116789Sahrens zjni_Object_t *object = (zjni_Object_t *)collection;
117789Sahrens
118789Sahrens collection->method_add = (*env)->GetMethodID(
119789Sahrens env, object->class, "add", "(Ljava/lang/Object;)Z");
120789Sahrens
121789Sahrens collection->method_size =
122789Sahrens (*env)->GetMethodID(env, object->class, "size", "()I");
123789Sahrens
124789Sahrens collection->method_toArray =
125789Sahrens (*env)->GetMethodID(env, object->class, "toArray",
126789Sahrens "([Ljava/lang/Object;)[Ljava/lang/Object;");
127789Sahrens }
128789Sahrens
129789Sahrens /* Create an zjni_ArrayList */
130789Sahrens void
zjni_new_ArrayList(JNIEnv * env,zjni_ArrayList_t * list)131789Sahrens zjni_new_ArrayList(JNIEnv *env, zjni_ArrayList_t *list)
132789Sahrens {
133789Sahrens zjni_Object_t *object = (zjni_Object_t *)list;
134789Sahrens
135789Sahrens if (object->object == NULL) {
136789Sahrens object->class = (*env)->FindClass(env, "java/util/ArrayList");
137789Sahrens
138789Sahrens object->constructor =
139789Sahrens (*env)->GetMethodID(env, object->class, "<init>", "()V");
140789Sahrens
141789Sahrens object->object = (*env)->NewObject(
142789Sahrens env, object->class, object->constructor);
143789Sahrens }
144789Sahrens
145789Sahrens new_Collection(env, (zjni_Collection_t *)list);
146789Sahrens }
147789Sahrens
148789Sahrens /* Create an zjni_DatasetSet */
149789Sahrens void
zjni_new_DatasetSet(JNIEnv * env,zjni_DatasetSet_t * list)150789Sahrens zjni_new_DatasetSet(JNIEnv *env, zjni_DatasetSet_t *list)
151789Sahrens {
152789Sahrens zjni_Object_t *object = (zjni_Object_t *)list;
153789Sahrens
154789Sahrens if (object->object == NULL) {
155789Sahrens object->class = (*env)->FindClass(
156789Sahrens env, "com/sun/zfs/common/util/DatasetSet");
157789Sahrens
158789Sahrens object->constructor =
159789Sahrens (*env)->GetMethodID(env, object->class, "<init>", "()V");
160789Sahrens
161789Sahrens object->object = (*env)->NewObject(
162789Sahrens env, object->class, object->constructor);
163789Sahrens }
164789Sahrens
165789Sahrens new_Collection(env, (zjni_Collection_t *)list);
166789Sahrens }
167789Sahrens
168789Sahrens jobject
zjni_int_to_boolean(JNIEnv * env,uint64_t value)169789Sahrens zjni_int_to_boolean(JNIEnv *env, uint64_t value)
170789Sahrens {
171789Sahrens jclass class_Boolean = (*env)->FindClass(
172789Sahrens env, "java/lang/Boolean");
173789Sahrens
174789Sahrens jfieldID id = (*env)->GetStaticFieldID(env, class_Boolean,
175789Sahrens value ? "TRUE" : "FALSE", "Ljava/lang/Boolean;");
176789Sahrens
177789Sahrens return (*env)->GetStaticObjectField(env, class_Boolean, id);
178789Sahrens }
179789Sahrens
180789Sahrens jobject
zjni_int_to_enum(JNIEnv * env,int value,char * class_name,char * default_field_name,zjni_field_mapping_t * mapping)181*1206Stalley zjni_int_to_enum(JNIEnv *env, int value, char *class_name,
182*1206Stalley char *default_field_name, zjni_field_mapping_t *mapping)
183*1206Stalley {
184*1206Stalley int i;
185*1206Stalley char *field_name;
186*1206Stalley jclass class;
187*1206Stalley jfieldID id;
188*1206Stalley jobject field_value = NULL;
189*1206Stalley int found = 0;
190*1206Stalley
191*1206Stalley for (i = 0; mapping[i].name != NULL; i++) {
192*1206Stalley if (value == mapping[i].value) {
193*1206Stalley field_name = mapping[i].name;
194*1206Stalley found = 1;
195*1206Stalley break;
196*1206Stalley }
197*1206Stalley }
198*1206Stalley
199*1206Stalley if (!found) {
200*1206Stalley field_name = default_field_name;
201*1206Stalley }
202*1206Stalley
203*1206Stalley if (field_name != NULL) {
204*1206Stalley char signature[1024];
205*1206Stalley
206*1206Stalley (void) snprintf(signature, sizeof (signature), "L%s;",
207*1206Stalley class_name);
208*1206Stalley
209*1206Stalley class = (*env)->FindClass(env, class_name);
210*1206Stalley id = (*env)->GetStaticFieldID(
211*1206Stalley env, class, field_name, signature);
212*1206Stalley field_value = (*env)->GetStaticObjectField(env, class, id);
213*1206Stalley }
214*1206Stalley
215*1206Stalley return (field_value);
216*1206Stalley }
217*1206Stalley
218*1206Stalley jobject
zjni_str_to_long(JNIEnv * env,char * str)219789Sahrens zjni_str_to_long(JNIEnv *env, char *str)
220789Sahrens {
221789Sahrens jobject value = NULL;
222789Sahrens jclass class_Long = (*env)->FindClass(env, "java/lang/Long");
223789Sahrens
224789Sahrens jmethodID method_valueOf = (*env)->GetStaticMethodID(env,
225789Sahrens class_Long, "valueOf", "(Ljava/lang/String;)Ljava/lang/Long;");
226789Sahrens
227789Sahrens jstring utf = (*env)->NewStringUTF(env, str);
228789Sahrens
229789Sahrens /* May throw a NumberFormatException */
230789Sahrens value = (*env)->CallStaticObjectMethod(
231789Sahrens env, class_Long, method_valueOf, utf);
232789Sahrens
233789Sahrens return (value);
234789Sahrens }
235789Sahrens
236789Sahrens jobject
zjni_long_to_Long(JNIEnv * env,uint64_t value)237789Sahrens zjni_long_to_Long(JNIEnv *env, uint64_t value)
238789Sahrens {
239789Sahrens jclass class_Long = (*env)->FindClass(env, "java/lang/Long");
240789Sahrens
241789Sahrens jmethodID constructor_Long = (*env)->GetMethodID(
242789Sahrens env, class_Long, "<init>", "(J)V");
243789Sahrens
244789Sahrens jobject obj = (*env)->NewObject(
245789Sahrens env, class_Long, constructor_Long, value);
246789Sahrens
247789Sahrens return (obj);
248789Sahrens }
249789Sahrens
250789Sahrens jobject
zjni_str_to_date(JNIEnv * env,char * str)251789Sahrens zjni_str_to_date(JNIEnv *env, char *str)
252789Sahrens {
253789Sahrens jobject date = NULL;
254789Sahrens jclass class_Long = (*env)->FindClass(env, "java/lang/Long");
255789Sahrens
256789Sahrens jmethodID method_parseLong = (*env)->GetStaticMethodID(env,
257789Sahrens class_Long, "parseLong", "(Ljava/lang/String;)J");
258789Sahrens
259789Sahrens jstring utf = (*env)->NewStringUTF(env, str);
260789Sahrens if (utf != NULL) {
261789Sahrens
262789Sahrens /* May throw a NumberFormatException */
263789Sahrens jlong time = (*env)->CallStaticLongMethod(
264789Sahrens env, class_Long, method_parseLong, utf);
265789Sahrens
266789Sahrens if ((*env)->ExceptionOccurred(env) == NULL) {
267789Sahrens
268789Sahrens jclass class_Date = (*env)->FindClass(env,
269789Sahrens "java/util/Date");
270789Sahrens
271789Sahrens jmethodID constructor_Date = (*env)->GetMethodID(
272789Sahrens env, class_Date, "<init>", "(J)V");
273789Sahrens
274789Sahrens /* Date constructor takes epoch milliseconds */
275789Sahrens time *= 1000;
276789Sahrens
277789Sahrens date = (*env)->NewObject(
278789Sahrens env, class_Date, constructor_Date, time);
279789Sahrens }
280789Sahrens }
281789Sahrens
282789Sahrens return (date);
283789Sahrens }
284789Sahrens
285789Sahrens jobjectArray
zjni_c_string_array_to_java(JNIEnv * env,char ** array,int n)286894Stalley zjni_c_string_array_to_java(JNIEnv *env, char **array, int n)
287789Sahrens {
288789Sahrens int i;
289789Sahrens jclass class_String = (*env)->FindClass(env, "java/lang/String");
290789Sahrens jobjectArray jarray =
291789Sahrens (*env)->NewObjectArray(env, n, class_String, NULL);
292789Sahrens
293789Sahrens for (i = 0; i < n; i++) {
294789Sahrens jstring elementUTF = (*env)->NewStringUTF(env, array[i]);
295789Sahrens (void) (*env)->SetObjectArrayElement(env, jarray, i,
296789Sahrens elementUTF);
297789Sahrens }
298789Sahrens
299789Sahrens return (jarray);
300789Sahrens }
301789Sahrens
302789Sahrens /*
303894Stalley * Converts the non-null elements of the given Java String array into
304894Stalley * a NULL-terminated char* array. When done, each element and then
305894Stalley * the array itself must be free()d. Returns NULL if memory could not
306894Stalley * be allocated.
307894Stalley */
308894Stalley char **
zjni_java_string_array_to_c(JNIEnv * env,jobjectArray array)309894Stalley zjni_java_string_array_to_c(JNIEnv *env, jobjectArray array)
310894Stalley {
311894Stalley int i, n;
312894Stalley jsize length = (*env)->GetArrayLength(env, array);
313894Stalley char **result = (char **)calloc(length + 1, sizeof (char *));
314894Stalley
315894Stalley if (result != NULL) {
316894Stalley for (i = 0, n = 0; i < length; i++) {
317894Stalley jboolean isCopy;
318894Stalley
319894Stalley /* Retrive String from array */
320894Stalley jstring string = (*env)->GetObjectArrayElement(
321894Stalley env, array, i);
322894Stalley
323894Stalley if (string != NULL) {
324894Stalley /* Convert to char* */
325894Stalley const char *converted =
326894Stalley (*env)->GetStringUTFChars(env, string,
327894Stalley &isCopy);
328894Stalley
329894Stalley result[n] = strdup(converted);
330894Stalley
331894Stalley if (isCopy == JNI_TRUE) {
332894Stalley /* Free chars in Java space */
333894Stalley (void) (*env)->ReleaseStringUTFChars(
334894Stalley env, string, converted);
335894Stalley }
336894Stalley
337894Stalley if (result[n++] == NULL) {
338894Stalley /* strdup failed */
339894Stalley zjni_free_array((void *)result, free);
340894Stalley break;
341894Stalley }
342894Stalley }
343894Stalley }
344894Stalley
345894Stalley /* Terminate array */
346894Stalley result[n] = NULL;
347894Stalley }
348894Stalley
349894Stalley return (result);
350894Stalley }
351894Stalley
352894Stalley /*
353789Sahrens * Counts the number of elements in the given NULL-terminated array.
354789Sahrens * Does not include the terminating NULL in the count.
355789Sahrens */
356789Sahrens int
zjni_count_elements(void ** array)357789Sahrens zjni_count_elements(void **array)
358789Sahrens {
359789Sahrens int i = 0;
360789Sahrens if (array != NULL) {
361789Sahrens for (; array[i] != NULL; i++);
362789Sahrens }
363789Sahrens return (i);
364789Sahrens }
365789Sahrens
366789Sahrens /*
367789Sahrens * Get a handle to the next nvpair with the specified name and data
368789Sahrens * type in the list following the given nvpair.
369789Sahrens *
370789Sahrens * This function is needed because the nvlist_lookup_* routines can
371789Sahrens * only be used with nvlists allocated with NV_UNIQUE_NAME or
372789Sahrens * NV_UNIQUE_NAME_TYPE, ie. lists of unique name/value pairs.
373789Sahrens *
374789Sahrens * Some variation of this function will likely appear in the libnvpair
375789Sahrens * library per 4981923.
376789Sahrens *
377789Sahrens * @param nvl
378789Sahrens * the nvlist_t to search
379789Sahrens *
380789Sahrens * @param name
381789Sahrens * the string key for the pair to find in the list, or
382789Sahrens * NULL to match any name
383789Sahrens *
384789Sahrens * @param type
385789Sahrens * the data type for the pair to find in the list, or
386789Sahrens * DATA_TYPE_UNKNOWN to match any type
387789Sahrens *
388789Sahrens * @param nvp
389789Sahrens * the pair to search from in the list, or NULL to search
390789Sahrens * from the beginning of the list
391789Sahrens *
392789Sahrens * @return the next nvpair in the list matching the given
393789Sahrens * criteria, or NULL if no matching nvpair is found
394789Sahrens */
395789Sahrens nvpair_t *
zjni_nvlist_walk_nvpair(nvlist_t * nvl,const char * name,data_type_t type,nvpair_t * nvp)396789Sahrens zjni_nvlist_walk_nvpair(nvlist_t *nvl, const char *name, data_type_t type,
397789Sahrens nvpair_t *nvp)
398789Sahrens {
399789Sahrens /* For each nvpair in the list following nvp... */
400789Sahrens while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
401789Sahrens
402789Sahrens /* Does this pair's name match the given name? */
403789Sahrens if ((name == NULL || strcmp(nvpair_name(nvp), name) == 0) &&
404789Sahrens
405789Sahrens /* Does this pair's type match the given type? */
406789Sahrens (type == DATA_TYPE_UNKNOWN || type == nvpair_type(nvp))) {
407789Sahrens return (nvp);
408789Sahrens }
409789Sahrens }
410789Sahrens
411789Sahrens return (NULL);
412789Sahrens }
413