Home | History | Annotate | Download | only in common
      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 2006 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 void
     37 zjni_free_array(void **array, zjni_free_f freefunc)
     38 {
     39 	if (array != NULL) {
     40 		if (freefunc != NULL) {
     41 			int i;
     42 			for (i = 0; array[i] != NULL; i++) {
     43 				freefunc(array[i]);
     44 			}
     45 		}
     46 		free(array);
     47 	}
     48 }
     49 
     50 /*PRINTFLIKE2*/
     51 void
     52 zjni_throw_exception(JNIEnv *env, const char *fmt, ...)
     53 {
     54 	char error[1024];
     55 	va_list ap;
     56 	jclass class_UnsupportedOperationException;
     57 
     58 	va_start(ap, fmt);
     59 	(void) vsnprintf(error, sizeof (error), fmt, ap);
     60 	va_end(ap);
     61 
     62 	class_UnsupportedOperationException =
     63 	    (*env)->FindClass(env, "java/lang/UnsupportedOperationException");
     64 
     65 	(*env)->ThrowNew(env, class_UnsupportedOperationException, error);
     66 }
     67 
     68 jstring
     69 zjni_get_matched_string(JNIEnv *env, char *name, regmatch_t *match)
     70 {
     71 	jstring stringUTF = NULL;
     72 	if (match->rm_so != -1 && match->rm_eo != -1) {
     73 		char *end = name + match->rm_eo;
     74 		char tmp = *end;
     75 		*end = '\0';
     76 		stringUTF = (*env)->NewStringUTF(env, name + match->rm_so);
     77 		*end = tmp;
     78 	}
     79 	return (stringUTF);
     80 }
     81 
     82 void
     83 zjni_get_dataset_from_snapshot(const char *snapshot, char *dataset,
     84     size_t len)
     85 {
     86 	char *at;
     87 	(void) strncpy(dataset, snapshot, len);
     88 	at = strchr(dataset, '@');
     89 	if (at != NULL) {
     90 		*at = '\0';
     91 	}
     92 }
     93 
     94 /* Convert a zjni_Collection to a (Java) array */
     95 jobjectArray
     96 zjni_Collection_to_array(JNIEnv *env, zjni_Collection_t *list, char *class)
     97 {
     98 	/* Get size of zjni_Collection */
     99 	jint length = (*env)->CallIntMethod(
    100 	    env, ((zjni_Object_t *)list)->object,
    101 	    ((zjni_Collection_t *)list)->method_size);
    102 
    103 	/* Create array to hold elements of list */
    104 	jobjectArray array = (*env)->NewObjectArray(
    105 	    env, length, (*env)->FindClass(env, class), NULL);
    106 
    107 	/* Copy list elements to array */
    108 	return (*env)->CallObjectMethod(env, ((zjni_Object_t *)list)->object,
    109 	    ((zjni_Collection_t *)list)->method_toArray, array);
    110 }
    111 
    112 /* Create a zjni_Collection */
    113 void
    114 new_Collection(JNIEnv *env, zjni_Collection_t *collection)
    115 {
    116 	zjni_Object_t *object = (zjni_Object_t *)collection;
    117 
    118 	collection->method_add = (*env)->GetMethodID(
    119 	    env, object->class, "add", "(Ljava/lang/Object;)Z");
    120 
    121 	collection->method_size =
    122 	    (*env)->GetMethodID(env, object->class, "size", "()I");
    123 
    124 	collection->method_toArray =
    125 	    (*env)->GetMethodID(env, object->class, "toArray",
    126 		"([Ljava/lang/Object;)[Ljava/lang/Object;");
    127 }
    128 
    129 /* Create an zjni_ArrayList */
    130 void
    131 zjni_new_ArrayList(JNIEnv *env, zjni_ArrayList_t *list)
    132 {
    133 	zjni_Object_t *object = (zjni_Object_t *)list;
    134 
    135 	if (object->object == NULL) {
    136 		object->class = (*env)->FindClass(env, "java/util/ArrayList");
    137 
    138 		object->constructor =
    139 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
    140 
    141 		object->object = (*env)->NewObject(
    142 		    env, object->class, object->constructor);
    143 	}
    144 
    145 	new_Collection(env, (zjni_Collection_t *)list);
    146 }
    147 
    148 /* Create an zjni_DatasetSet */
    149 void
    150 zjni_new_DatasetSet(JNIEnv *env, zjni_DatasetSet_t *list)
    151 {
    152 	zjni_Object_t *object = (zjni_Object_t *)list;
    153 
    154 	if (object->object == NULL) {
    155 		object->class = (*env)->FindClass(
    156 		    env, "com/sun/zfs/common/util/DatasetSet");
    157 
    158 		object->constructor =
    159 		    (*env)->GetMethodID(env, object->class, "<init>", "()V");
    160 
    161 		object->object = (*env)->NewObject(
    162 		    env, object->class, object->constructor);
    163 	}
    164 
    165 	new_Collection(env, (zjni_Collection_t *)list);
    166 }
    167 
    168 jobject
    169 zjni_int_to_boolean(JNIEnv *env, uint64_t value)
    170 {
    171 	jclass class_Boolean = (*env)->FindClass(
    172 	    env, "java/lang/Boolean");
    173 
    174 	jfieldID id = (*env)->GetStaticFieldID(env, class_Boolean,
    175 	    value ? "TRUE" : "FALSE", "Ljava/lang/Boolean;");
    176 
    177 	return (*env)->GetStaticObjectField(env, class_Boolean, id);
    178 }
    179 
    180 jobject
    181 zjni_int_to_enum(JNIEnv *env, int value, char *class_name,
    182     char *default_field_name, zjni_field_mapping_t *mapping)
    183 {
    184 	int i;
    185 	char *field_name;
    186 	jclass class;
    187 	jfieldID id;
    188 	jobject field_value = NULL;
    189 	int found = 0;
    190 
    191 	for (i = 0; mapping[i].name != NULL; i++) {
    192 		if (value == mapping[i].value) {
    193 			field_name = mapping[i].name;
    194 			found = 1;
    195 			break;
    196 		}
    197 	}
    198 
    199 	if (!found) {
    200 		field_name = default_field_name;
    201 	}
    202 
    203 	if (field_name != NULL) {
    204 		char signature[1024];
    205 
    206 		(void) snprintf(signature, sizeof (signature), "L%s;",
    207 		    class_name);
    208 
    209 		class = (*env)->FindClass(env, class_name);
    210 		id = (*env)->GetStaticFieldID(
    211 		    env, class, field_name, signature);
    212 		field_value = (*env)->GetStaticObjectField(env, class, id);
    213 	}
    214 
    215 	return (field_value);
    216 }
    217 
    218 jobject
    219 zjni_str_to_long(JNIEnv *env, char *str)
    220 {
    221 	jobject value = NULL;
    222 	jclass class_Long = (*env)->FindClass(env, "java/lang/Long");
    223 
    224 	jmethodID method_valueOf = (*env)->GetStaticMethodID(env,
    225 	    class_Long, "valueOf", "(Ljava/lang/String;)Ljava/lang/Long;");
    226 
    227 	jstring utf = (*env)->NewStringUTF(env, str);
    228 
    229 	/* May throw a NumberFormatException */
    230 	value = (*env)->CallStaticObjectMethod(
    231 	    env, class_Long, method_valueOf, utf);
    232 
    233 	return (value);
    234 }
    235 
    236 jobject
    237 zjni_long_to_Long(JNIEnv *env, uint64_t value)
    238 {
    239 	jclass class_Long = (*env)->FindClass(env, "java/lang/Long");
    240 
    241 	jmethodID constructor_Long = (*env)->GetMethodID(
    242 	    env, class_Long, "<init>", "(J)V");
    243 
    244 	jobject obj = (*env)->NewObject(
    245 	    env, class_Long, constructor_Long, value);
    246 
    247 	return (obj);
    248 }
    249 
    250 jobject
    251 zjni_str_to_date(JNIEnv *env, char *str)
    252 {
    253 	jobject date = NULL;
    254 	jclass class_Long = (*env)->FindClass(env, "java/lang/Long");
    255 
    256 	jmethodID method_parseLong = (*env)->GetStaticMethodID(env,
    257 	    class_Long, "parseLong", "(Ljava/lang/String;)J");
    258 
    259 	jstring utf = (*env)->NewStringUTF(env, str);
    260 	if (utf != NULL) {
    261 
    262 		/* May throw a NumberFormatException */
    263 		jlong time = (*env)->CallStaticLongMethod(
    264 		    env, class_Long, method_parseLong, utf);
    265 
    266 		if ((*env)->ExceptionOccurred(env) == NULL) {
    267 
    268 			jclass class_Date = (*env)->FindClass(env,
    269 			    "java/util/Date");
    270 
    271 			jmethodID constructor_Date = (*env)->GetMethodID(
    272 			    env, class_Date, "<init>", "(J)V");
    273 
    274 			/* Date constructor takes epoch milliseconds */
    275 			time *= 1000;
    276 
    277 			date = (*env)->NewObject(
    278 			    env, class_Date, constructor_Date, time);
    279 		}
    280 	}
    281 
    282 	return (date);
    283 }
    284 
    285 jobjectArray
    286 zjni_c_string_array_to_java(JNIEnv *env, char **array, int n)
    287 {
    288 	int i;
    289 	jclass class_String = (*env)->FindClass(env, "java/lang/String");
    290 	jobjectArray jarray =
    291 	    (*env)->NewObjectArray(env, n, class_String, NULL);
    292 
    293 	for (i = 0; i < n; i++) {
    294 		jstring elementUTF = (*env)->NewStringUTF(env, array[i]);
    295 		(void) (*env)->SetObjectArrayElement(env, jarray, i,
    296 		    elementUTF);
    297 	}
    298 
    299 	return (jarray);
    300 }
    301 
    302 /*
    303  * Converts the non-null elements of the given Java String array into
    304  * a NULL-terminated char* array.  When done, each element and then
    305  * the array itself must be free()d.  Returns NULL if memory could not
    306  * be allocated.
    307  */
    308 char **
    309 zjni_java_string_array_to_c(JNIEnv *env, jobjectArray array)
    310 {
    311 	int i, n;
    312 	jsize length = (*env)->GetArrayLength(env, array);
    313 	char **result = (char **)calloc(length + 1, sizeof (char *));
    314 
    315 	if (result != NULL) {
    316 		for (i = 0, n = 0; i < length; i++) {
    317 			jboolean isCopy;
    318 
    319 			/* Retrive String from array */
    320 			jstring string = (*env)->GetObjectArrayElement(
    321 			    env, array, i);
    322 
    323 			if (string != NULL) {
    324 				/* Convert to char* */
    325 				const char *converted =
    326 				    (*env)->GetStringUTFChars(env, string,
    327 					&isCopy);
    328 
    329 				result[n] = strdup(converted);
    330 
    331 				if (isCopy == JNI_TRUE) {
    332 					/* Free chars in Java space */
    333 					(void) (*env)->ReleaseStringUTFChars(
    334 					    env, string, converted);
    335 				}
    336 
    337 				if (result[n++] == NULL) {
    338 					/* strdup failed */
    339 					zjni_free_array((void *)result, free);
    340 					break;
    341 				}
    342 			}
    343 		}
    344 
    345 		/* Terminate array */
    346 		result[n] = NULL;
    347 	}
    348 
    349 	return (result);
    350 }
    351 
    352 /*
    353  * Counts the number of elements in the given NULL-terminated array.
    354  * Does not include the terminating NULL in the count.
    355  */
    356 int
    357 zjni_count_elements(void **array)
    358 {
    359 	int i = 0;
    360 	if (array != NULL) {
    361 		for (; array[i] != NULL; i++);
    362 	}
    363 	return (i);
    364 }
    365 
    366 /*
    367  * Get a handle to the next nvpair with the specified name and data
    368  * type in the list following the given nvpair.
    369  *
    370  * This function is needed because the nvlist_lookup_* routines can
    371  * only be used with nvlists allocated with NV_UNIQUE_NAME or
    372  * NV_UNIQUE_NAME_TYPE, ie. lists of unique name/value pairs.
    373  *
    374  * Some variation of this function will likely appear in the libnvpair
    375  * library per 4981923.
    376  *
    377  * @param       nvl
    378  *              the nvlist_t to search
    379  *
    380  * @param       name
    381  *              the string key for the pair to find in the list, or
    382  *              NULL to match any name
    383  *
    384  * @param       type
    385  *              the data type for the pair to find in the list, or
    386  *              DATA_TYPE_UNKNOWN to match any type
    387  *
    388  * @param       nvp
    389  *              the pair to search from in the list, or NULL to search
    390  *              from the beginning of the list
    391  *
    392  * @return      the next nvpair in the list matching the given
    393  *              criteria, or NULL if no matching nvpair is found
    394  */
    395 nvpair_t *
    396 zjni_nvlist_walk_nvpair(nvlist_t *nvl, const char *name, data_type_t type,
    397     nvpair_t *nvp)
    398 {
    399 	/* For each nvpair in the list following nvp... */
    400 	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
    401 
    402 		/* Does this pair's name match the given name? */
    403 		if ((name == NULL || strcmp(nvpair_name(nvp), name) == 0) &&
    404 
    405 		    /* Does this pair's type match the given type? */
    406 		    (type == DATA_TYPE_UNKNOWN || type == nvpair_type(nvp))) {
    407 			return (nvp);
    408 		}
    409 	}
    410 
    411 	return (NULL);
    412 }
    413