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 (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include "libzfs_jni_property.h"
     27 #include "libzfs_jni_util.h"
     28 #include <strings.h>
     29 
     30 /*
     31  * Types
     32  */
     33 
     34 /* Signature for function to convert string to a specific Java object */
     35 typedef jobject (*str_to_obj_f)(JNIEnv *, char *);
     36 
     37 /* Signature for function to convert uint64_t to a specific Java object */
     38 typedef jobject (*uint64_to_obj_f)(JNIEnv *, uint64_t);
     39 
     40 /*
     41  * Describes a property and the parameters needed to create a Java
     42  * Property object for it
     43  */
     44 typedef struct custom_prop_desct {
     45 	zfs_prop_t prop;
     46 	str_to_obj_f convert_str;
     47 	uint64_to_obj_f convert_uint64;
     48 	char *propClass;
     49 	char *valueClass;
     50 } custom_prop_desct_t;
     51 
     52 /*
     53  * Function prototypes
     54  */
     55 
     56 static jobject create_BasicProperty(JNIEnv *, zfs_handle_t *,
     57     zfs_prop_t, str_to_obj_f, uint64_to_obj_f, char *, char *);
     58 static jobject create_BooleanProperty(JNIEnv *, zfs_handle_t *, zfs_prop_t);
     59 static jobject create_LongProperty(JNIEnv *, zfs_handle_t *, zfs_prop_t);
     60 static jobject create_StringProperty(JNIEnv *, zfs_handle_t *, zfs_prop_t);
     61 static jobject create_ObjectProperty(JNIEnv *, zfs_handle_t *,
     62     zfs_prop_t, str_to_obj_f, uint64_to_obj_f, char *, char *);
     63 static jobject create_default_BasicProperty(JNIEnv *, zfs_prop_t,
     64     str_to_obj_f, uint64_to_obj_f, char *, char *);
     65 static jobject create_default_BooleanProperty(JNIEnv *, zfs_prop_t);
     66 static jobject create_default_LongProperty(JNIEnv *, zfs_prop_t);
     67 static jobject create_default_StringProperty(JNIEnv *, zfs_prop_t);
     68 static jobject create_default_ObjectProperty(
     69     JNIEnv *, zfs_prop_t, str_to_obj_f, uint64_to_obj_f, char *, char *);
     70 static jobject str_to_enum_element(JNIEnv *, char *, char *);
     71 static jobject str_to_aclinherit(JNIEnv *, char *);
     72 static jobject str_to_aclmode(JNIEnv *, char *);
     73 static jobject str_to_checksum(JNIEnv *, char *);
     74 static jobject str_to_compression(JNIEnv *, char *);
     75 static jobject str_to_snapdir(JNIEnv *, char *);
     76 static jobject str_to_string(JNIEnv *, char *);
     77 
     78 /*
     79  * Static data
     80  */
     81 
     82 zfs_prop_t props_boolean[] = {
     83 	ZFS_PROP_ATIME,
     84 	ZFS_PROP_DEVICES,
     85 	ZFS_PROP_EXEC,
     86 	ZFS_PROP_MOUNTED,
     87 	ZFS_PROP_READONLY,
     88 	ZFS_PROP_SETUID,
     89 	ZFS_PROP_ZONED,
     90 	ZFS_PROP_DEFER_DESTROY,
     91 	ZPROP_INVAL
     92 };
     93 
     94 zfs_prop_t props_long[] = {
     95 	ZFS_PROP_AVAILABLE,
     96 	ZFS_PROP_CREATETXG,
     97 	ZFS_PROP_QUOTA,
     98 	ZFS_PROP_REFERENCED,
     99 	ZFS_PROP_RESERVATION,
    100 	ZFS_PROP_USED,
    101 	ZFS_PROP_VOLSIZE,
    102 	ZFS_PROP_REFQUOTA,
    103 	ZFS_PROP_REFRESERVATION,
    104 	ZFS_PROP_USERREFS,
    105 	ZPROP_INVAL
    106 };
    107 
    108 zfs_prop_t props_string[] = {
    109 	ZFS_PROP_ORIGIN,
    110 	/* ZFS_PROP_TYPE, */
    111 	ZPROP_INVAL
    112 };
    113 
    114 custom_prop_desct_t props_custom[] = {
    115 	{ ZFS_PROP_ACLINHERIT, str_to_aclinherit, NULL,
    116 	    ZFSJNI_PACKAGE_DATA "AclInheritProperty",
    117 	    ZFSJNI_PACKAGE_DATA "AclInheritProperty$AclInherit" },
    118 
    119 	{ ZFS_PROP_ACLMODE, str_to_aclmode, NULL,
    120 	    ZFSJNI_PACKAGE_DATA "AclModeProperty",
    121 	    ZFSJNI_PACKAGE_DATA "AclModeProperty$AclMode" },
    122 
    123 	{ ZFS_PROP_CHECKSUM, str_to_checksum, NULL,
    124 	    ZFSJNI_PACKAGE_DATA "ChecksumProperty",
    125 	    ZFSJNI_PACKAGE_DATA "ChecksumProperty$Checksum" },
    126 
    127 	{ ZFS_PROP_COMPRESSION, str_to_compression, NULL,
    128 	    ZFSJNI_PACKAGE_DATA "CompressionProperty",
    129 	    ZFSJNI_PACKAGE_DATA "CompressionProperty$Compression" },
    130 
    131 	{ ZFS_PROP_COMPRESSRATIO, NULL, zjni_long_to_Long,
    132 	    ZFSJNI_PACKAGE_DATA "CompressRatioProperty",
    133 	    "java/lang/Long" },
    134 
    135 	{ ZFS_PROP_CREATION, zjni_str_to_date, NULL,
    136 	    ZFSJNI_PACKAGE_DATA "CreationProperty",
    137 	    "java/util/Date" },
    138 
    139 	{ ZFS_PROP_MOUNTPOINT, str_to_string, NULL,
    140 	    ZFSJNI_PACKAGE_DATA "MountPointProperty",
    141 	    "java/lang/String" },
    142 
    143 	{ ZFS_PROP_RECORDSIZE, NULL, zjni_long_to_Long,
    144 	    ZFSJNI_PACKAGE_DATA "RecordSizeProperty",
    145 	    "java/lang/Long" },
    146 
    147 	{ ZFS_PROP_SHARENFS, str_to_string, NULL,
    148 	    ZFSJNI_PACKAGE_DATA "ShareNFSProperty",
    149 	    "java/lang/String" },
    150 
    151 	{ ZFS_PROP_SNAPDIR, str_to_snapdir, NULL,
    152 	    ZFSJNI_PACKAGE_DATA "SnapDirProperty",
    153 	    ZFSJNI_PACKAGE_DATA "SnapDirProperty$SnapDir" },
    154 
    155 	{ ZFS_PROP_VOLBLOCKSIZE, NULL, zjni_long_to_Long,
    156 	    ZFSJNI_PACKAGE_DATA "VolBlockSizeProperty",
    157 	    "java/lang/Long" },
    158 
    159 	{ ZPROP_INVAL, NULL, NULL, NULL, NULL },
    160 };
    161 
    162 /*
    163  * Static functions
    164  */
    165 
    166 static jobject
    167 create_BasicProperty(JNIEnv *env, zfs_handle_t *zhp, zfs_prop_t prop,
    168     str_to_obj_f convert_str, uint64_to_obj_f convert_uint64,
    169     char *propClass, char *valueClass)
    170 {
    171 	jobject propertyObject = NULL;
    172 	char source[ZFS_MAXNAMELEN];
    173 	zprop_source_t srctype;
    174 	jobject propValue = NULL;
    175 
    176 	if (convert_str != NULL) {
    177 		char propbuf[ZFS_MAXPROPLEN];
    178 		int result = zfs_prop_get(zhp, prop, propbuf,
    179 		    sizeof (propbuf), &srctype, source, sizeof (source), 1);
    180 
    181 		if (result == 0)
    182 			propValue = convert_str(env, propbuf);
    183 	} else {
    184 		uint64_t value;
    185 		int result = zfs_prop_get_numeric(
    186 		    zhp, prop, &value, &srctype, source, sizeof (source));
    187 
    188 		if (result == 0)
    189 			propValue = convert_uint64(env, value);
    190 	}
    191 
    192 	if (propValue != NULL) {
    193 
    194 		jmethodID constructor;
    195 		char signature[1024];
    196 		jclass class = (*env)->FindClass(env, propClass);
    197 
    198 		jstring propName = (*env)->NewStringUTF(
    199 		    env, zfs_prop_to_name(prop));
    200 
    201 		jboolean readOnly = zfs_prop_readonly(prop) ?
    202 		    JNI_TRUE : JNI_FALSE;
    203 
    204 		if (srctype == ZPROP_SRC_INHERITED) {
    205 
    206 			jstring propSource = (*env)->NewStringUTF(env, source);
    207 
    208 			(void) snprintf(signature, sizeof (signature),
    209 			    "(Ljava/lang/String;L%s;ZLjava/lang/String;)V",
    210 			    valueClass);
    211 
    212 			constructor = (*env)->GetMethodID(
    213 			    env, class, "<init>", signature);
    214 
    215 			propertyObject = (*env)->NewObject(
    216 			    env, class, constructor, propName, propValue,
    217 			    readOnly, propSource);
    218 		} else {
    219 			jobject lineage = zjni_int_to_Lineage(env, srctype);
    220 
    221 			(void) snprintf(signature, sizeof (signature),
    222 			    "(Ljava/lang/String;L%s;ZL"
    223 			    ZFSJNI_PACKAGE_DATA "Property$Lineage;)V",
    224 			    valueClass);
    225 
    226 			constructor = (*env)->GetMethodID(
    227 			    env, class, "<init>", signature);
    228 
    229 			propertyObject = (*env)->NewObject(
    230 			    env, class, constructor, propName, propValue,
    231 			    readOnly, lineage);
    232 		}
    233 	}
    234 
    235 	return (propertyObject);
    236 }
    237 
    238 static jobject
    239 create_BooleanProperty(JNIEnv *env, zfs_handle_t *zhp, zfs_prop_t prop)
    240 {
    241 	return (create_BasicProperty(env, zhp, prop, NULL, zjni_int_to_boolean,
    242 	    ZFSJNI_PACKAGE_DATA "BooleanProperty", "java/lang/Boolean"));
    243 }
    244 
    245 static jobject
    246 create_LongProperty(JNIEnv *env, zfs_handle_t *zhp, zfs_prop_t prop)
    247 {
    248 	return (create_BasicProperty(env, zhp, prop, NULL, zjni_long_to_Long,
    249 	    ZFSJNI_PACKAGE_DATA "LongProperty", "java/lang/Long"));
    250 }
    251 
    252 static jobject
    253 create_StringProperty(JNIEnv *env, zfs_handle_t *zhp, zfs_prop_t prop)
    254 {
    255 	return (create_BasicProperty(env, zhp, prop, str_to_string, NULL,
    256 	    ZFSJNI_PACKAGE_DATA "StringProperty", "java/lang/String"));
    257 }
    258 
    259 static jobject
    260 create_ObjectProperty(JNIEnv *env, zfs_handle_t *zhp, zfs_prop_t prop,
    261     str_to_obj_f convert_str, uint64_to_obj_f convert_uint64,
    262     char *propClass, char *valueClass)
    263 {
    264 	jobject propertyObject = NULL;
    265 	char source[ZFS_MAXNAMELEN];
    266 	zprop_source_t srctype;
    267 	jobject propValue = NULL;
    268 
    269 	if (convert_str != NULL) {
    270 		char propbuf[ZFS_MAXPROPLEN];
    271 		int result = zfs_prop_get(zhp, prop, propbuf,
    272 		    sizeof (propbuf), &srctype, source, sizeof (source), 1);
    273 
    274 		if (result == 0)
    275 			propValue = convert_str(env, propbuf);
    276 	} else {
    277 		uint64_t value;
    278 		int result = zfs_prop_get_numeric(
    279 		    zhp, prop, &value, &srctype, source, sizeof (source));
    280 
    281 		if (result == 0)
    282 			propValue = convert_uint64(env, value);
    283 	}
    284 
    285 	if (propValue != NULL) {
    286 
    287 		jmethodID constructor;
    288 		char signature[1024];
    289 		jclass class = (*env)->FindClass(env, propClass);
    290 
    291 		if (srctype == ZPROP_SRC_INHERITED) {
    292 
    293 			jstring propSource = (*env)->NewStringUTF(env, source);
    294 
    295 			(void) snprintf(signature, sizeof (signature),
    296 			    "(L%s;Ljava/lang/String;)V", valueClass);
    297 
    298 			constructor = (*env)->GetMethodID(
    299 			    env, class, "<init>", signature);
    300 
    301 			propertyObject = (*env)->NewObject(env,
    302 			    class, constructor, propValue, propSource);
    303 
    304 		} else {
    305 			jobject lineage = zjni_int_to_Lineage(env, srctype);
    306 
    307 			(void) snprintf(signature, sizeof (signature),
    308 			    "(L%s;L" ZFSJNI_PACKAGE_DATA "Property$Lineage;)V",
    309 			    valueClass);
    310 
    311 			constructor = (*env)->GetMethodID(
    312 			    env, class, "<init>", signature);
    313 
    314 			propertyObject = (*env)->NewObject(env,
    315 			    class, constructor, propValue, lineage);
    316 		}
    317 	}
    318 
    319 	return (propertyObject);
    320 }
    321 
    322 static jobject
    323 create_default_BasicProperty(JNIEnv *env, zfs_prop_t prop,
    324     str_to_obj_f convert_str, uint64_to_obj_f convert_uint64,
    325     char *propClass, char *valueClass)
    326 {
    327 	jobject propertyObject = NULL;
    328 
    329 	if (!zfs_prop_readonly(prop)) {
    330 		jobject propValue;
    331 
    332 		if (convert_str != NULL) {
    333 			char *propbuf = (char *)zfs_prop_default_string(prop);
    334 			propValue = convert_str(env, propbuf);
    335 		} else {
    336 			uint64_t value = zfs_prop_default_numeric(prop);
    337 			propValue = convert_uint64(env, value);
    338 		}
    339 
    340 		if (propValue != NULL) {
    341 			char signature[1024];
    342 			jmethodID constructor;
    343 
    344 			jstring propName =
    345 			    (*env)->NewStringUTF(env, zfs_prop_to_name(prop));
    346 
    347 			jboolean readOnly = zfs_prop_readonly(prop) ?
    348 			    JNI_TRUE : JNI_FALSE;
    349 
    350 			jclass class = (*env)->FindClass(env, propClass);
    351 			jobject lineage =
    352 			    zjni_int_to_Lineage(env, ZPROP_SRC_DEFAULT);
    353 
    354 			(void) snprintf(signature, sizeof (signature),
    355 			    "(Ljava/lang/String;L%s;ZL" ZFSJNI_PACKAGE_DATA
    356 			    "Property$Lineage;)V", valueClass);
    357 
    358 			constructor = (*env)->GetMethodID(
    359 			    env, class, "<init>", signature);
    360 
    361 			propertyObject = (*env)->NewObject(
    362 			    env, class, constructor,
    363 			    propName, propValue, readOnly, lineage);
    364 		}
    365 	}
    366 
    367 	return (propertyObject);
    368 }
    369 
    370 static jobject
    371 create_default_BooleanProperty(JNIEnv *env, zfs_prop_t prop)
    372 {
    373 	return (create_default_BasicProperty(env, prop, NULL,
    374 	    zjni_int_to_boolean, ZFSJNI_PACKAGE_DATA "BooleanProperty",
    375 	    "java/lang/Boolean"));
    376 }
    377 
    378 static jobject
    379 create_default_LongProperty(JNIEnv *env, zfs_prop_t prop)
    380 {
    381 	return (create_default_BasicProperty(env, prop, NULL,
    382 	    zjni_long_to_Long, ZFSJNI_PACKAGE_DATA "LongProperty",
    383 	    "java/lang/Long"));
    384 }
    385 
    386 static jobject
    387 create_default_StringProperty(JNIEnv *env, zfs_prop_t prop)
    388 {
    389 	return (create_default_BasicProperty(env, prop, str_to_string, NULL,
    390 	    ZFSJNI_PACKAGE_DATA "StringProperty", "java/lang/String"));
    391 }
    392 
    393 static jobject
    394 create_default_ObjectProperty(JNIEnv *env, zfs_prop_t prop,
    395     str_to_obj_f convert_str, uint64_to_obj_f convert_uint64,
    396     char *propClass, char *valueClass)
    397 {
    398 	jobject propertyObject = NULL;
    399 
    400 	if (!zfs_prop_readonly(prop)) {
    401 		jobject propValue;
    402 
    403 		if (convert_str != NULL) {
    404 			char *propbuf = (char *)zfs_prop_default_string(prop);
    405 			propValue = convert_str(env, propbuf);
    406 		} else {
    407 			uint64_t value = zfs_prop_default_numeric(prop);
    408 			propValue = convert_uint64(env, value);
    409 		}
    410 
    411 		if (propValue != NULL) {
    412 			char signature[1024];
    413 			jmethodID constructor;
    414 
    415 			jclass class = (*env)->FindClass(env, propClass);
    416 			jobject lineage =
    417 			    zjni_int_to_Lineage(env, ZPROP_SRC_DEFAULT);
    418 
    419 			(void) snprintf(signature, sizeof (signature),
    420 			    "(L%s;L" ZFSJNI_PACKAGE_DATA "Property$Lineage;)V",
    421 			    valueClass);
    422 
    423 			constructor = (*env)->GetMethodID(
    424 			    env, class, "<init>", signature);
    425 
    426 			propertyObject = (*env)->NewObject(
    427 			    env, class, constructor, propValue, lineage);
    428 		}
    429 	}
    430 
    431 	return (propertyObject);
    432 }
    433 
    434 static jobject
    435 str_to_enum_element(JNIEnv *env, char *str, char *valueClass)
    436 {
    437 	char signature[1024];
    438 	jmethodID method_valueOf;
    439 
    440 	jstring utf = (*env)->NewStringUTF(env, str);
    441 	jclass class = (*env)->FindClass(env, valueClass);
    442 
    443 	(void) snprintf(signature, sizeof (signature),
    444 	    "(Ljava/lang/String;)L%s;", valueClass);
    445 
    446 	method_valueOf = (*env)->GetStaticMethodID(
    447 	    env, class, "valueOf", signature);
    448 
    449 	return (*env)->CallStaticObjectMethod(env, class, method_valueOf, utf);
    450 }
    451 
    452 static jobject
    453 str_to_aclinherit(JNIEnv *env, char *str)
    454 {
    455 	return (str_to_enum_element(env, str,
    456 	    ZFSJNI_PACKAGE_DATA "AclInheritProperty$AclInherit"));
    457 }
    458 
    459 static jobject
    460 str_to_aclmode(JNIEnv *env, char *str)
    461 {
    462 	return (str_to_enum_element(env, str,
    463 	    ZFSJNI_PACKAGE_DATA "AclModeProperty$AclMode"));
    464 }
    465 
    466 static jobject
    467 str_to_checksum(JNIEnv *env, char *str)
    468 {
    469 	return (str_to_enum_element(env, str,
    470 	    ZFSJNI_PACKAGE_DATA "ChecksumProperty$Checksum"));
    471 }
    472 
    473 static jobject
    474 str_to_compression(JNIEnv *env, char *str)
    475 {
    476 	return (str_to_enum_element(env, str,
    477 	    ZFSJNI_PACKAGE_DATA "CompressionProperty$Compression"));
    478 }
    479 
    480 static jobject
    481 str_to_snapdir(JNIEnv *env, char *str)
    482 {
    483 	return (str_to_enum_element(env, str,
    484 	    ZFSJNI_PACKAGE_DATA "SnapDirProperty$SnapDir"));
    485 }
    486 
    487 static jobject
    488 str_to_string(JNIEnv *env, char *str)
    489 {
    490 	return (*env)->NewStringUTF(env, str);
    491 }
    492 
    493 /*
    494  * Package-private functions
    495  */
    496 
    497 jobject
    498 zjni_get_default_property(JNIEnv *env, zfs_prop_t prop)
    499 {
    500 	int i;
    501 	for (i = 0; props_boolean[i] != ZPROP_INVAL; i++) {
    502 		if (prop == props_boolean[i]) {
    503 			return (create_default_BooleanProperty(env, prop));
    504 		}
    505 	}
    506 
    507 	for (i = 0; props_long[i] != ZPROP_INVAL; i++) {
    508 		if (prop == props_long[i]) {
    509 			return (create_default_LongProperty(env, prop));
    510 		}
    511 	}
    512 
    513 	for (i = 0; props_string[i] != ZPROP_INVAL; i++) {
    514 		if (prop == props_string[i]) {
    515 			return (create_default_StringProperty(env, prop));
    516 		}
    517 	}
    518 
    519 	for (i = 0; props_custom[i].prop != ZPROP_INVAL; i++) {
    520 		if (prop == props_custom[i].prop) {
    521 			return create_default_ObjectProperty(env,
    522 			    props_custom[i].prop,
    523 			    props_custom[i].convert_str,
    524 			    props_custom[i].convert_uint64,
    525 			    props_custom[i].propClass,
    526 			    props_custom[i].valueClass);
    527 		}
    528 	}
    529 
    530 	return (NULL);
    531 }
    532 
    533 static int
    534 zjni_get_property_from_name_cb(int prop, void *cb)
    535 {
    536 	const char *name = cb;
    537 
    538 	if (strcasecmp(name, zfs_prop_to_name(prop)) == 0)
    539 		return (prop);
    540 
    541 	return (ZPROP_CONT);
    542 }
    543 
    544 zfs_prop_t
    545 zjni_get_property_from_name(const char *name)
    546 {
    547 	zfs_prop_t prop;
    548 
    549 	prop = zprop_iter(zjni_get_property_from_name_cb, (void *)name,
    550 	    B_FALSE, B_FALSE, ZFS_TYPE_DATASET);
    551 	return (prop == ZPROP_CONT ? ZPROP_INVAL : prop);
    552 }
    553 
    554 jobject
    555 zjni_int_to_Lineage(JNIEnv *env, zprop_source_t srctype)
    556 {
    557 	/* zprop_source_t to Property$Lineage map */
    558 	static zjni_field_mapping_t lineage_map[] = {
    559 		{ ZPROP_SRC_NONE, "ZFS_PROP_LINEAGE_NOTINHERITABLE" },
    560 		{ ZPROP_SRC_DEFAULT, "ZFS_PROP_LINEAGE_DEFAULT" },
    561 		{ ZPROP_SRC_LOCAL, "ZFS_PROP_LINEAGE_LOCAL" },
    562 		{ ZPROP_SRC_TEMPORARY, "ZFS_PROP_LINEAGE_TEMPORARY" },
    563 		{ ZPROP_SRC_INHERITED, "ZFS_PROP_LINEAGE_INHERITED" }
    564 	};
    565 
    566 	return (zjni_int_to_enum(env, srctype,
    567 	    ZFSJNI_PACKAGE_DATA "Property$Lineage",
    568 	    "ZFS_PROP_LINEAGE_INHERITED", lineage_map));
    569 }
    570 
    571 jobjectArray
    572 zjni_get_Dataset_properties(JNIEnv *env, zfs_handle_t *zhp)
    573 {
    574 	jobject prop;
    575 	int i;
    576 
    577 	/* Create an array list for the properties */
    578 	zjni_ArrayList_t proplist_obj = {0};
    579 	zjni_ArrayList_t *proplist = &proplist_obj;
    580 	zjni_new_ArrayList(env, proplist);
    581 
    582 	for (i = 0; props_boolean[i] != ZPROP_INVAL; i++) {
    583 		/* Create property and add to list */
    584 		prop = create_BooleanProperty(env, zhp, props_boolean[i]);
    585 
    586 		/* Does this property apply to this object? */
    587 		if (prop != NULL) {
    588 
    589 			(*env)->CallBooleanMethod(
    590 			    env, ((zjni_Object_t *)proplist)->object,
    591 			    ((zjni_Collection_t *)proplist)->method_add, prop);
    592 		} else {
    593 
    594 			if ((*env)->ExceptionOccurred(env) != NULL) {
    595 				return (NULL);
    596 			}
    597 #ifdef	DEBUG
    598 			(void) fprintf(stderr, "Property %s is not appropriate "
    599 			    "for %s\n", zfs_prop_to_name(props_boolean[i]),
    600 			    zfs_get_name(zhp));
    601 #endif
    602 		}
    603 	}
    604 
    605 	for (i = 0; props_long[i] != ZPROP_INVAL; i++) {
    606 		/* Create property and add to list */
    607 		prop = create_LongProperty(env, zhp, props_long[i]);
    608 
    609 		/* Does this property apply to this object? */
    610 		if (prop != NULL) {
    611 
    612 			(*env)->CallBooleanMethod(
    613 			    env, ((zjni_Object_t *)proplist)->object,
    614 			    ((zjni_Collection_t *)proplist)->method_add, prop);
    615 		} else {
    616 			if ((*env)->ExceptionOccurred(env) != NULL) {
    617 				return (NULL);
    618 			}
    619 #ifdef	DEBUG
    620 			(void) fprintf(stderr, "Property %s is not appropriate "
    621 			    "for %s\n", zfs_prop_to_name(props_long[i]),
    622 			    zfs_get_name(zhp));
    623 #endif
    624 		}
    625 	}
    626 
    627 	for (i = 0; props_string[i] != ZPROP_INVAL; i++) {
    628 		/* Create property and add to list */
    629 		prop = create_StringProperty(env, zhp, props_string[i]);
    630 
    631 		/* Does this property apply to this object? */
    632 		if (prop != NULL) {
    633 
    634 			(*env)->CallBooleanMethod(
    635 			    env, ((zjni_Object_t *)proplist)->object,
    636 			    ((zjni_Collection_t *)proplist)->method_add, prop);
    637 		} else {
    638 			if ((*env)->ExceptionOccurred(env) != NULL) {
    639 				return (NULL);
    640 			}
    641 #ifdef	DEBUG
    642 			(void) fprintf(stderr, "Property %s is not appropriate "
    643 			    "for %s\n", zfs_prop_to_name(props_string[i]),
    644 			    zfs_get_name(zhp));
    645 #endif
    646 		}
    647 	}
    648 
    649 	for (i = 0; props_custom[i].prop != ZPROP_INVAL; i++) {
    650 		/* Create property and add to list */
    651 		prop = create_ObjectProperty(env, zhp, props_custom[i].prop,
    652 		    props_custom[i].convert_str, props_custom[i].convert_uint64,
    653 		    props_custom[i].propClass, props_custom[i].valueClass);
    654 
    655 		/* Does this property apply to this object? */
    656 		if (prop != NULL) {
    657 
    658 			(*env)->CallBooleanMethod(
    659 			    env, ((zjni_Object_t *)proplist)->object,
    660 			    ((zjni_Collection_t *)proplist)->method_add, prop);
    661 		} else {
    662 			if ((*env)->ExceptionOccurred(env) != NULL) {
    663 				return (NULL);
    664 			}
    665 #ifdef	DEBUG
    666 			(void) fprintf(stderr, "Property %s is not appropriate "
    667 			    "for %s\n", zfs_prop_to_name(props_custom[i].prop),
    668 			    zfs_get_name(zhp));
    669 #endif
    670 		}
    671 	}
    672 
    673 	return (zjni_Collection_to_array(env,
    674 	    (zjni_Collection_t *)proplist, ZFSJNI_PACKAGE_DATA "Property"));
    675 }
    676