xref: /onnv-gate/usr/src/lib/libzfs_jni/common/libzfs_jni_util.c (revision 1206:84469f0f684d)
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