xref: /onnv-gate/usr/src/lib/libzfs_jni/common/libzfs_jni_util.c (revision 789:b348f31ed315)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include "libzfs_jni_util.h"
30 #include <strings.h>
31 
32 /*
33  * Package-private functions
34  */
35 
36 /*PRINTFLIKE2*/
37 void
38 zjni_throw_exception(JNIEnv *env, const char *fmt, ...)
39 {
40 	char error[1024];
41 	va_list ap;
42 	jclass class_UnsupportedOperationException;
43 
44 	va_start(ap, fmt);
45 	(void) vsnprintf(error, sizeof (error), fmt, ap);
46 	va_end(ap);
47 
48 	class_UnsupportedOperationException =
49 	    (*env)->FindClass(env, "java/lang/UnsupportedOperationException");
50 
51 	(*env)->ThrowNew(env, class_UnsupportedOperationException, error);
52 }
53 
54 jstring
55 zjni_get_matched_string(JNIEnv *env, char *name, regmatch_t *match)
56 {
57 	jstring stringUTF = NULL;
58 	if (match->rm_so != -1 && match->rm_eo != -1) {
59 		char *end = name + match->rm_eo;
60 		char tmp = *end;
61 		*end = '\0';
62 		stringUTF = (*env)->NewStringUTF(env, name + match->rm_so);
63 		*end = tmp;
64 	}
65 	return (stringUTF);
66 }
67 
68 void
69 zjni_get_dataset_from_snapshot(const char *snapshot, char *dataset,
70     size_t len)
71 {
72 	char *at;
73 	(void) strncpy(dataset, snapshot, len);
74 	at = strchr(dataset, '@');
75 	if (at != NULL) {
76 		*at = '\0';
77 	}
78 }
79 
80 /* Convert a zjni_Collection to a (Java) array */
81 jobjectArray
82 zjni_Collection_to_array(JNIEnv *env, zjni_Collection_t *list, char *class)
83 {
84 	/* Get size of zjni_Collection */
85 	jint length = (*env)->CallIntMethod(
86 	    env, ((zjni_Object_t *)list)->object,
87 	    ((zjni_Collection_t *)list)->method_size);
88 
89 	/* Create array to hold elements of list */
90 	jobjectArray array = (*env)->NewObjectArray(
91 	    env, length, (*env)->FindClass(env, class), NULL);
92 
93 	/* Copy list elements to array */
94 	return (*env)->CallObjectMethod(env, ((zjni_Object_t *)list)->object,
95 	    ((zjni_Collection_t *)list)->method_toArray, array);
96 }
97 
98 /* Create a zjni_Collection */
99 void
100 new_Collection(JNIEnv *env, zjni_Collection_t *collection)
101 {
102 	zjni_Object_t *object = (zjni_Object_t *)collection;
103 
104 	collection->method_add = (*env)->GetMethodID(
105 	    env, object->class, "add", "(Ljava/lang/Object;)Z");
106 
107 	collection->method_size =
108 	    (*env)->GetMethodID(env, object->class, "size", "()I");
109 
110 	collection->method_toArray =
111 	    (*env)->GetMethodID(env, object->class, "toArray",
112 		"([Ljava/lang/Object;)[Ljava/lang/Object;");
113 }
114 
115 /* Create an zjni_ArrayList */
116 void
117 zjni_new_ArrayList(JNIEnv *env, zjni_ArrayList_t *list)
118 {
119 	zjni_Object_t *object = (zjni_Object_t *)list;
120 
121 	if (object->object == NULL) {
122 		object->class = (*env)->FindClass(env, "java/util/ArrayList");
123 
124 		object->constructor =
125 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
126 
127 		object->object = (*env)->NewObject(
128 		    env, object->class, object->constructor);
129 	}
130 
131 	new_Collection(env, (zjni_Collection_t *)list);
132 }
133 
134 /* Create an zjni_DatasetSet */
135 void
136 zjni_new_DatasetSet(JNIEnv *env, zjni_DatasetSet_t *list)
137 {
138 	zjni_Object_t *object = (zjni_Object_t *)list;
139 
140 	if (object->object == NULL) {
141 		object->class = (*env)->FindClass(
142 		    env, "com/sun/zfs/common/util/DatasetSet");
143 
144 		object->constructor =
145 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
146 
147 		object->object = (*env)->NewObject(
148 		    env, object->class, object->constructor);
149 	}
150 
151 	new_Collection(env, (zjni_Collection_t *)list);
152 }
153 
154 jobject
155 zjni_int_to_boolean(JNIEnv *env, uint64_t value)
156 {
157 	jclass class_Boolean = (*env)->FindClass(
158 	    env, "java/lang/Boolean");
159 
160 	jfieldID id = (*env)->GetStaticFieldID(env, class_Boolean,
161 	    value ? "TRUE" : "FALSE", "Ljava/lang/Boolean;");
162 
163 	return (*env)->GetStaticObjectField(env, class_Boolean, id);
164 }
165 
166 jobject
167 zjni_str_to_long(JNIEnv *env, char *str)
168 {
169 	jobject value = NULL;
170 	jclass class_Long = (*env)->FindClass(env, "java/lang/Long");
171 
172 	jmethodID method_valueOf = (*env)->GetStaticMethodID(env,
173 	    class_Long, "valueOf", "(Ljava/lang/String;)Ljava/lang/Long;");
174 
175 	jstring utf = (*env)->NewStringUTF(env, str);
176 
177 	/* May throw a NumberFormatException */
178 	value = (*env)->CallStaticObjectMethod(
179 	    env, class_Long, method_valueOf, utf);
180 
181 	return (value);
182 }
183 
184 jobject
185 zjni_long_to_Long(JNIEnv *env, uint64_t value)
186 {
187 	jclass class_Long = (*env)->FindClass(env, "java/lang/Long");
188 
189 	jmethodID constructor_Long = (*env)->GetMethodID(
190 	    env, class_Long, "<init>", "(J)V");
191 
192 	jobject obj = (*env)->NewObject(
193 	    env, class_Long, constructor_Long, value);
194 
195 	return (obj);
196 }
197 
198 jobject
199 zjni_str_to_date(JNIEnv *env, char *str)
200 {
201 	jobject date = NULL;
202 	jclass class_Long = (*env)->FindClass(env, "java/lang/Long");
203 
204 	jmethodID method_parseLong = (*env)->GetStaticMethodID(env,
205 	    class_Long, "parseLong", "(Ljava/lang/String;)J");
206 
207 	jstring utf = (*env)->NewStringUTF(env, str);
208 	if (utf != NULL) {
209 
210 		/* May throw a NumberFormatException */
211 		jlong time = (*env)->CallStaticLongMethod(
212 		    env, class_Long, method_parseLong, utf);
213 
214 		if ((*env)->ExceptionOccurred(env) == NULL) {
215 
216 			jclass class_Date = (*env)->FindClass(env,
217 			    "java/util/Date");
218 
219 			jmethodID constructor_Date = (*env)->GetMethodID(
220 			    env, class_Date, "<init>", "(J)V");
221 
222 			/* Date constructor takes epoch milliseconds */
223 			time *= 1000;
224 
225 			date = (*env)->NewObject(
226 			    env, class_Date, constructor_Date, time);
227 		}
228 	}
229 
230 	return (date);
231 }
232 
233 jobjectArray
234 zjni_string_array_to_String_array(JNIEnv *env, char **array, int n)
235 {
236 	int i;
237 	jclass class_String = (*env)->FindClass(env, "java/lang/String");
238 	jobjectArray jarray =
239 	    (*env)->NewObjectArray(env, n, class_String, NULL);
240 
241 	for (i = 0; i < n; i++) {
242 		jstring elementUTF = (*env)->NewStringUTF(env, array[i]);
243 		(void) (*env)->SetObjectArrayElement(env, jarray, i,
244 		    elementUTF);
245 	}
246 
247 	return (jarray);
248 }
249 
250 /*
251  * Counts the number of elements in the given NULL-terminated array.
252  * Does not include the terminating NULL in the count.
253  */
254 int
255 zjni_count_elements(void **array)
256 {
257 	int i = 0;
258 	if (array != NULL) {
259 		for (; array[i] != NULL; i++);
260 	}
261 	return (i);
262 }
263 
264 /*
265  * Get a handle to the next nvpair with the specified name and data
266  * type in the list following the given nvpair.
267  *
268  * This function is needed because the nvlist_lookup_* routines can
269  * only be used with nvlists allocated with NV_UNIQUE_NAME or
270  * NV_UNIQUE_NAME_TYPE, ie. lists of unique name/value pairs.
271  *
272  * Some variation of this function will likely appear in the libnvpair
273  * library per 4981923.
274  *
275  * @param       nvl
276  *              the nvlist_t to search
277  *
278  * @param       name
279  *              the string key for the pair to find in the list, or
280  *              NULL to match any name
281  *
282  * @param       type
283  *              the data type for the pair to find in the list, or
284  *              DATA_TYPE_UNKNOWN to match any type
285  *
286  * @param       nvp
287  *              the pair to search from in the list, or NULL to search
288  *              from the beginning of the list
289  *
290  * @return      the next nvpair in the list matching the given
291  *              criteria, or NULL if no matching nvpair is found
292  */
293 nvpair_t *
294 zjni_nvlist_walk_nvpair(nvlist_t *nvl, const char *name, data_type_t type,
295     nvpair_t *nvp)
296 {
297 	/* For each nvpair in the list following nvp... */
298 	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
299 
300 		/* Does this pair's name match the given name? */
301 		if ((name == NULL || strcmp(nvpair_name(nvp), name) == 0) &&
302 
303 		    /* Does this pair's type match the given type? */
304 		    (type == DATA_TYPE_UNKNOWN || type == nvpair_type(nvp))) {
305 			return (nvp);
306 		}
307 	}
308 
309 	return (NULL);
310 }
311