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