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