xref: /illumos-gate/usr/src/lib/libzfs_jni/common/libzfs_jni_property.c (revision f48205be61a214698b763ff550ab9e657525104c)
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 	    }
182 	} else {
183 	    uint64_t value;
184 	    int result = zfs_prop_get_numeric(
185 		zhp, prop, &value, &srctype, source, sizeof (source));
186 
187 	    if (result == 0) {
188 		propValue = convert_uint64(env, value);
189 	    }
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 == ZFS_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 	zfs_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 	    }
277 	} else {
278 	    uint64_t value;
279 	    int result = zfs_prop_get_numeric(
280 		zhp, prop, &value, &srctype, source, sizeof (source));
281 
282 	    if (result == 0) {
283 		propValue = convert_uint64(env, value);
284 	    }
285 	}
286 
287 	if (propValue != NULL) {
288 
289 		jmethodID constructor;
290 		char signature[1024];
291 		jclass class = (*env)->FindClass(env, propClass);
292 
293 		if (srctype == ZFS_SRC_INHERITED) {
294 
295 			jstring propSource = (*env)->NewStringUTF(env, source);
296 
297 			(void) snprintf(signature, sizeof (signature),
298 			    "(L%s;Ljava/lang/String;)V", valueClass);
299 
300 			constructor = (*env)->GetMethodID(
301 			    env, class, "<init>", signature);
302 
303 			propertyObject = (*env)->NewObject(env,
304 			    class, constructor, propValue, propSource);
305 
306 		} else {
307 			jobject lineage = zjni_int_to_Lineage(env, srctype);
308 
309 			(void) snprintf(signature, sizeof (signature),
310 			    "(L%s;L" ZFSJNI_PACKAGE_DATA "Property$Lineage;)V",
311 			    valueClass);
312 
313 			constructor = (*env)->GetMethodID(
314 			    env, class, "<init>", signature);
315 
316 			propertyObject = (*env)->NewObject(env,
317 			    class, constructor, propValue, lineage);
318 		}
319 	}
320 
321 	return (propertyObject);
322 }
323 
324 static jobject
325 create_default_BasicProperty(JNIEnv *env, zfs_prop_t prop,
326     str_to_obj_f convert_str, uint64_to_obj_f convert_uint64,
327     char *propClass, char *valueClass)
328 {
329 	jobject propertyObject = NULL;
330 
331 	if (!zfs_prop_readonly(prop)) {
332 		jobject propValue;
333 
334 		if (convert_str != NULL) {
335 			char *propbuf = (char *)zfs_prop_default_string(prop);
336 			propValue = convert_str(env, propbuf);
337 		} else {
338 			uint64_t value = zfs_prop_default_numeric(prop);
339 			propValue = convert_uint64(env, value);
340 		}
341 
342 		if (propValue != NULL) {
343 			char signature[1024];
344 			jmethodID constructor;
345 
346 			jstring propName =
347 			    (*env)->NewStringUTF(env, zfs_prop_to_name(prop));
348 
349 			jboolean readOnly = zfs_prop_readonly(prop) ?
350 			    JNI_TRUE : JNI_FALSE;
351 
352 			jclass class = (*env)->FindClass(env, propClass);
353 			jobject lineage =
354 			    zjni_int_to_Lineage(env, ZFS_SRC_DEFAULT);
355 
356 			(void) snprintf(signature, sizeof (signature),
357 			    "(Ljava/lang/String;L%s;ZL" ZFSJNI_PACKAGE_DATA
358 			    "Property$Lineage;)V", valueClass);
359 
360 			constructor = (*env)->GetMethodID(
361 			    env, class, "<init>", signature);
362 
363 			propertyObject = (*env)->NewObject(
364 			    env, class, constructor,
365 			    propName, propValue, readOnly, lineage);
366 		}
367 	}
368 
369 	return (propertyObject);
370 }
371 
372 static jobject
373 create_default_BooleanProperty(JNIEnv *env, zfs_prop_t prop)
374 {
375 	return (create_default_BasicProperty(env, prop, NULL,
376 	    zjni_int_to_boolean, ZFSJNI_PACKAGE_DATA "BooleanProperty",
377 	    "java/lang/Boolean"));
378 }
379 
380 static jobject
381 create_default_LongProperty(JNIEnv *env, zfs_prop_t prop)
382 {
383 	return (create_default_BasicProperty(env, prop, NULL,
384 	    zjni_long_to_Long, ZFSJNI_PACKAGE_DATA "LongProperty",
385 	    "java/lang/Long"));
386 }
387 
388 static jobject
389 create_default_StringProperty(JNIEnv *env, zfs_prop_t prop)
390 {
391 	return (create_default_BasicProperty(env, prop, str_to_string, NULL,
392 	    ZFSJNI_PACKAGE_DATA "StringProperty", "java/lang/String"));
393 }
394 
395 static jobject
396 create_default_ObjectProperty(JNIEnv *env, zfs_prop_t prop,
397     str_to_obj_f convert_str, uint64_to_obj_f convert_uint64,
398     char *propClass, char *valueClass)
399 {
400 	jobject propertyObject = NULL;
401 
402 	if (!zfs_prop_readonly(prop)) {
403 		jobject propValue;
404 
405 		if (convert_str != NULL) {
406 			char *propbuf = (char *)zfs_prop_default_string(prop);
407 			propValue = convert_str(env, propbuf);
408 		} else {
409 			uint64_t value = zfs_prop_default_numeric(prop);
410 			propValue = convert_uint64(env, value);
411 		}
412 
413 		if (propValue != NULL) {
414 			char signature[1024];
415 			jmethodID constructor;
416 
417 			jclass class = (*env)->FindClass(env, propClass);
418 			jobject lineage =
419 			    zjni_int_to_Lineage(env, ZFS_SRC_DEFAULT);
420 
421 			(void) snprintf(signature, sizeof (signature),
422 			    "(L%s;L" ZFSJNI_PACKAGE_DATA "Property$Lineage;)V",
423 			    valueClass);
424 
425 			constructor = (*env)->GetMethodID(
426 			    env, class, "<init>", signature);
427 
428 			propertyObject = (*env)->NewObject(
429 			    env, class, constructor, propValue, lineage);
430 		}
431 	}
432 
433 	return (propertyObject);
434 }
435 
436 static jobject
437 str_to_enum_element(JNIEnv *env, char *str, char *valueClass)
438 {
439 	char signature[1024];
440 	jmethodID method_valueOf;
441 
442 	jstring utf = (*env)->NewStringUTF(env, str);
443 	jclass class = (*env)->FindClass(env, valueClass);
444 
445 	(void) snprintf(signature, sizeof (signature),
446 	    "(Ljava/lang/String;)L%s;", valueClass);
447 
448 	method_valueOf = (*env)->GetStaticMethodID(
449 	    env, class, "valueOf", signature);
450 
451 	return (*env)->CallStaticObjectMethod(env, class, method_valueOf, utf);
452 }
453 
454 static jobject
455 str_to_aclinherit(JNIEnv *env, char *str)
456 {
457 	return (str_to_enum_element(env, str,
458 	    ZFSJNI_PACKAGE_DATA "AclInheritProperty$AclInherit"));
459 }
460 
461 static jobject
462 str_to_aclmode(JNIEnv *env, char *str)
463 {
464 	return (str_to_enum_element(env, str,
465 	    ZFSJNI_PACKAGE_DATA "AclModeProperty$AclMode"));
466 }
467 
468 static jobject
469 str_to_checksum(JNIEnv *env, char *str)
470 {
471 	return (str_to_enum_element(env, str,
472 	    ZFSJNI_PACKAGE_DATA "ChecksumProperty$Checksum"));
473 }
474 
475 static jobject
476 str_to_compression(JNIEnv *env, char *str)
477 {
478 	return (str_to_enum_element(env, str,
479 	    ZFSJNI_PACKAGE_DATA "CompressionProperty$Compression"));
480 }
481 
482 static jobject
483 str_to_snapdir(JNIEnv *env, char *str)
484 {
485 	return (str_to_enum_element(env, str,
486 	    ZFSJNI_PACKAGE_DATA "SnapDirProperty$SnapDir"));
487 }
488 
489 static jobject
490 str_to_string(JNIEnv *env, char *str)
491 {
492 	return (*env)->NewStringUTF(env, str);
493 }
494 
495 /*
496  * Package-private functions
497  */
498 
499 jobject
500 zjni_get_default_property(JNIEnv *env, zfs_prop_t prop)
501 {
502 	int i;
503 	for (i = 0; props_boolean[i] != ZFS_PROP_INVAL; i++) {
504 		if (prop == props_boolean[i]) {
505 			return (create_default_BooleanProperty(env, prop));
506 		}
507 	}
508 
509 	for (i = 0; props_long[i] != ZFS_PROP_INVAL; i++) {
510 		if (prop == props_long[i]) {
511 			return (create_default_LongProperty(env, prop));
512 		}
513 	}
514 
515 	for (i = 0; props_string[i] != ZFS_PROP_INVAL; i++) {
516 		if (prop == props_string[i]) {
517 			return (create_default_StringProperty(env, prop));
518 		}
519 	}
520 
521 	for (i = 0; props_custom[i].prop != ZFS_PROP_INVAL; i++) {
522 		if (prop == props_custom[i].prop) {
523 		    return create_default_ObjectProperty(env,
524 			props_custom[i].prop, props_custom[i].convert_str,
525 			props_custom[i].convert_uint64,
526 			props_custom[i].propClass, props_custom[i].valueClass);
527 		}
528 	}
529 
530 	return (NULL);
531 }
532 
533 static zfs_prop_t
534 zjni_get_property_from_name_cb(zfs_prop_t 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 (ZFS_PROP_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 = zfs_prop_iter(zjni_get_property_from_name_cb, (void *)name,
550 	    B_FALSE);
551 	return (prop == ZFS_PROP_CONT ? ZFS_PROP_INVAL : prop);
552 }
553 
554 jobject
555 zjni_int_to_Lineage(JNIEnv *env, zfs_source_t srctype)
556 {
557 	/* zfs_source_t to Property$Lineage map */
558 	static zjni_field_mapping_t lineage_map[] = {
559 		{ ZFS_SRC_NONE, "ZFS_PROP_LINEAGE_NOTINHERITABLE" },
560 		{ ZFS_SRC_DEFAULT, "ZFS_PROP_LINEAGE_DEFAULT" },
561 		{ ZFS_SRC_LOCAL, "ZFS_PROP_LINEAGE_LOCAL" },
562 		{ ZFS_SRC_TEMPORARY, "ZFS_PROP_LINEAGE_TEMPORARY" },
563 		{ ZFS_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] != ZFS_PROP_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] != ZFS_PROP_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] != ZFS_PROP_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 != ZFS_PROP_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