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