xref: /titanic_50/usr/src/lib/libzfs_jni/common/libzfs_jni_property.c (revision 1a4cea1bca45d5775aeb88646a63db027947246f)
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  * Copyright (c) 2015 by Delphix. All rights reserved.
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 	ZFS_PROP_FOLLOW,
92 	ZPROP_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_REFQUOTA,
104 	ZFS_PROP_REFRESERVATION,
105 	ZFS_PROP_USERREFS,
106 	ZPROP_INVAL
107 };
108 
109 zfs_prop_t props_string[] = {
110 	ZFS_PROP_ORIGIN,
111 	/* ZFS_PROP_TYPE, */
112 	ZPROP_INVAL
113 };
114 
115 custom_prop_desct_t props_custom[] = {
116 	{ ZFS_PROP_ACLINHERIT, str_to_aclinherit, NULL,
117 	    ZFSJNI_PACKAGE_DATA "AclInheritProperty",
118 	    ZFSJNI_PACKAGE_DATA "AclInheritProperty$AclInherit" },
119 
120 	{ ZFS_PROP_ACLMODE, str_to_aclmode, NULL,
121 	    ZFSJNI_PACKAGE_DATA "AclModeProperty",
122 	    ZFSJNI_PACKAGE_DATA "AclModeProperty$AclMode" },
123 
124 	{ ZFS_PROP_CHECKSUM, str_to_checksum, NULL,
125 	    ZFSJNI_PACKAGE_DATA "ChecksumProperty",
126 	    ZFSJNI_PACKAGE_DATA "ChecksumProperty$Checksum" },
127 
128 	{ ZFS_PROP_COMPRESSION, str_to_compression, NULL,
129 	    ZFSJNI_PACKAGE_DATA "CompressionProperty",
130 	    ZFSJNI_PACKAGE_DATA "CompressionProperty$Compression" },
131 
132 	{ ZFS_PROP_COMPRESSRATIO, NULL, zjni_long_to_Long,
133 	    ZFSJNI_PACKAGE_DATA "CompressRatioProperty",
134 	    "java/lang/Long" },
135 
136 	{ ZFS_PROP_CREATION, zjni_str_to_date, NULL,
137 	    ZFSJNI_PACKAGE_DATA "CreationProperty",
138 	    "java/util/Date" },
139 
140 	{ ZFS_PROP_MOUNTPOINT, str_to_string, NULL,
141 	    ZFSJNI_PACKAGE_DATA "MountPointProperty",
142 	    "java/lang/String" },
143 
144 	{ ZFS_PROP_RECORDSIZE, NULL, zjni_long_to_Long,
145 	    ZFSJNI_PACKAGE_DATA "RecordSizeProperty",
146 	    "java/lang/Long" },
147 
148 	{ ZFS_PROP_SHARENFS, str_to_string, NULL,
149 	    ZFSJNI_PACKAGE_DATA "ShareNFSProperty",
150 	    "java/lang/String" },
151 
152 	{ ZFS_PROP_SNAPDIR, str_to_snapdir, NULL,
153 	    ZFSJNI_PACKAGE_DATA "SnapDirProperty",
154 	    ZFSJNI_PACKAGE_DATA "SnapDirProperty$SnapDir" },
155 
156 	{ ZFS_PROP_VOLBLOCKSIZE, NULL, zjni_long_to_Long,
157 	    ZFSJNI_PACKAGE_DATA "VolBlockSizeProperty",
158 	    "java/lang/Long" },
159 
160 	{ ZPROP_INVAL, NULL, NULL, NULL, NULL },
161 };
162 
163 /*
164  * Static functions
165  */
166 
167 static jobject
create_BasicProperty(JNIEnv * env,zfs_handle_t * zhp,zfs_prop_t prop,str_to_obj_f convert_str,uint64_to_obj_f convert_uint64,char * propClass,char * valueClass)168 create_BasicProperty(JNIEnv *env, zfs_handle_t *zhp, zfs_prop_t prop,
169     str_to_obj_f convert_str, uint64_to_obj_f convert_uint64,
170     char *propClass, char *valueClass)
171 {
172 	jobject propertyObject = NULL;
173 	char source[ZFS_MAX_DATASET_NAME_LEN];
174 	zprop_source_t srctype;
175 	jobject propValue = NULL;
176 
177 	if (convert_str != NULL) {
178 		char propbuf[ZFS_MAXPROPLEN];
179 		int result = zfs_prop_get(zhp, prop, propbuf,
180 		    sizeof (propbuf), &srctype, source, sizeof (source), 1);
181 
182 		if (result == 0)
183 			propValue = convert_str(env, propbuf);
184 	} else {
185 		uint64_t value;
186 		int result = zfs_prop_get_numeric(
187 		    zhp, prop, &value, &srctype, source, sizeof (source));
188 
189 		if (result == 0)
190 			propValue = convert_uint64(env, value);
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 == ZPROP_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_int_to_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
create_BooleanProperty(JNIEnv * env,zfs_handle_t * zhp,zfs_prop_t prop)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
create_LongProperty(JNIEnv * env,zfs_handle_t * zhp,zfs_prop_t prop)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
create_StringProperty(JNIEnv * env,zfs_handle_t * zhp,zfs_prop_t prop)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
create_ObjectProperty(JNIEnv * env,zfs_handle_t * zhp,zfs_prop_t prop,str_to_obj_f convert_str,uint64_to_obj_f convert_uint64,char * propClass,char * valueClass)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_MAX_DATASET_NAME_LEN];
267 	zprop_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 	} 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 	if (propValue != NULL) {
287 
288 		jmethodID constructor;
289 		char signature[1024];
290 		jclass class = (*env)->FindClass(env, propClass);
291 
292 		if (srctype == ZPROP_SRC_INHERITED) {
293 
294 			jstring propSource = (*env)->NewStringUTF(env, source);
295 
296 			(void) snprintf(signature, sizeof (signature),
297 			    "(L%s;Ljava/lang/String;)V", valueClass);
298 
299 			constructor = (*env)->GetMethodID(
300 			    env, class, "<init>", signature);
301 
302 			propertyObject = (*env)->NewObject(env,
303 			    class, constructor, propValue, propSource);
304 
305 		} else {
306 			jobject lineage = zjni_int_to_Lineage(env, srctype);
307 
308 			(void) snprintf(signature, sizeof (signature),
309 			    "(L%s;L" ZFSJNI_PACKAGE_DATA "Property$Lineage;)V",
310 			    valueClass);
311 
312 			constructor = (*env)->GetMethodID(
313 			    env, class, "<init>", signature);
314 
315 			propertyObject = (*env)->NewObject(env,
316 			    class, constructor, propValue, lineage);
317 		}
318 	}
319 
320 	return (propertyObject);
321 }
322 
323 static jobject
create_default_BasicProperty(JNIEnv * env,zfs_prop_t prop,str_to_obj_f convert_str,uint64_to_obj_f convert_uint64,char * propClass,char * valueClass)324 create_default_BasicProperty(JNIEnv *env, zfs_prop_t prop,
325     str_to_obj_f convert_str, uint64_to_obj_f convert_uint64,
326     char *propClass, char *valueClass)
327 {
328 	jobject propertyObject = NULL;
329 
330 	if (!zfs_prop_readonly(prop)) {
331 		jobject propValue;
332 
333 		if (convert_str != NULL) {
334 			char *propbuf = (char *)zfs_prop_default_string(prop);
335 			propValue = convert_str(env, propbuf);
336 		} else {
337 			uint64_t value = zfs_prop_default_numeric(prop);
338 			propValue = convert_uint64(env, value);
339 		}
340 
341 		if (propValue != NULL) {
342 			char signature[1024];
343 			jmethodID constructor;
344 
345 			jstring propName =
346 			    (*env)->NewStringUTF(env, zfs_prop_to_name(prop));
347 
348 			jboolean readOnly = zfs_prop_readonly(prop) ?
349 			    JNI_TRUE : JNI_FALSE;
350 
351 			jclass class = (*env)->FindClass(env, propClass);
352 			jobject lineage =
353 			    zjni_int_to_Lineage(env, ZPROP_SRC_DEFAULT);
354 
355 			(void) snprintf(signature, sizeof (signature),
356 			    "(Ljava/lang/String;L%s;ZL" ZFSJNI_PACKAGE_DATA
357 			    "Property$Lineage;)V", valueClass);
358 
359 			constructor = (*env)->GetMethodID(
360 			    env, class, "<init>", signature);
361 
362 			propertyObject = (*env)->NewObject(
363 			    env, class, constructor,
364 			    propName, propValue, readOnly, lineage);
365 		}
366 	}
367 
368 	return (propertyObject);
369 }
370 
371 static jobject
create_default_BooleanProperty(JNIEnv * env,zfs_prop_t prop)372 create_default_BooleanProperty(JNIEnv *env, zfs_prop_t prop)
373 {
374 	return (create_default_BasicProperty(env, prop, NULL,
375 	    zjni_int_to_boolean, ZFSJNI_PACKAGE_DATA "BooleanProperty",
376 	    "java/lang/Boolean"));
377 }
378 
379 static jobject
create_default_LongProperty(JNIEnv * env,zfs_prop_t prop)380 create_default_LongProperty(JNIEnv *env, zfs_prop_t prop)
381 {
382 	return (create_default_BasicProperty(env, prop, NULL,
383 	    zjni_long_to_Long, ZFSJNI_PACKAGE_DATA "LongProperty",
384 	    "java/lang/Long"));
385 }
386 
387 static jobject
create_default_StringProperty(JNIEnv * env,zfs_prop_t prop)388 create_default_StringProperty(JNIEnv *env, zfs_prop_t prop)
389 {
390 	return (create_default_BasicProperty(env, prop, str_to_string, NULL,
391 	    ZFSJNI_PACKAGE_DATA "StringProperty", "java/lang/String"));
392 }
393 
394 static jobject
create_default_ObjectProperty(JNIEnv * env,zfs_prop_t prop,str_to_obj_f convert_str,uint64_to_obj_f convert_uint64,char * propClass,char * valueClass)395 create_default_ObjectProperty(JNIEnv *env, zfs_prop_t prop,
396     str_to_obj_f convert_str, uint64_to_obj_f convert_uint64,
397     char *propClass, char *valueClass)
398 {
399 	jobject propertyObject = NULL;
400 
401 	if (!zfs_prop_readonly(prop)) {
402 		jobject propValue;
403 
404 		if (convert_str != NULL) {
405 			char *propbuf = (char *)zfs_prop_default_string(prop);
406 			propValue = convert_str(env, propbuf);
407 		} else {
408 			uint64_t value = zfs_prop_default_numeric(prop);
409 			propValue = convert_uint64(env, value);
410 		}
411 
412 		if (propValue != NULL) {
413 			char signature[1024];
414 			jmethodID constructor;
415 
416 			jclass class = (*env)->FindClass(env, propClass);
417 			jobject lineage =
418 			    zjni_int_to_Lineage(env, ZPROP_SRC_DEFAULT);
419 
420 			(void) snprintf(signature, sizeof (signature),
421 			    "(L%s;L" ZFSJNI_PACKAGE_DATA "Property$Lineage;)V",
422 			    valueClass);
423 
424 			constructor = (*env)->GetMethodID(
425 			    env, class, "<init>", signature);
426 
427 			propertyObject = (*env)->NewObject(
428 			    env, class, constructor, propValue, lineage);
429 		}
430 	}
431 
432 	return (propertyObject);
433 }
434 
435 static jobject
str_to_enum_element(JNIEnv * env,char * str,char * valueClass)436 str_to_enum_element(JNIEnv *env, char *str, char *valueClass)
437 {
438 	char signature[1024];
439 	jmethodID method_valueOf;
440 
441 	jstring utf = (*env)->NewStringUTF(env, str);
442 	jclass class = (*env)->FindClass(env, valueClass);
443 
444 	(void) snprintf(signature, sizeof (signature),
445 	    "(Ljava/lang/String;)L%s;", valueClass);
446 
447 	method_valueOf = (*env)->GetStaticMethodID(
448 	    env, class, "valueOf", signature);
449 
450 	return (*env)->CallStaticObjectMethod(env, class, method_valueOf, utf);
451 }
452 
453 static jobject
str_to_aclinherit(JNIEnv * env,char * str)454 str_to_aclinherit(JNIEnv *env, char *str)
455 {
456 	return (str_to_enum_element(env, str,
457 	    ZFSJNI_PACKAGE_DATA "AclInheritProperty$AclInherit"));
458 }
459 
460 static jobject
str_to_aclmode(JNIEnv * env,char * str)461 str_to_aclmode(JNIEnv *env, char *str)
462 {
463 	return (str_to_enum_element(env, str,
464 	    ZFSJNI_PACKAGE_DATA "AclModeProperty$AclMode"));
465 }
466 
467 static jobject
str_to_checksum(JNIEnv * env,char * str)468 str_to_checksum(JNIEnv *env, char *str)
469 {
470 	return (str_to_enum_element(env, str,
471 	    ZFSJNI_PACKAGE_DATA "ChecksumProperty$Checksum"));
472 }
473 
474 static jobject
str_to_compression(JNIEnv * env,char * str)475 str_to_compression(JNIEnv *env, char *str)
476 {
477 	return (str_to_enum_element(env, str,
478 	    ZFSJNI_PACKAGE_DATA "CompressionProperty$Compression"));
479 }
480 
481 static jobject
str_to_snapdir(JNIEnv * env,char * str)482 str_to_snapdir(JNIEnv *env, char *str)
483 {
484 	return (str_to_enum_element(env, str,
485 	    ZFSJNI_PACKAGE_DATA "SnapDirProperty$SnapDir"));
486 }
487 
488 static jobject
str_to_string(JNIEnv * env,char * str)489 str_to_string(JNIEnv *env, char *str)
490 {
491 	return (*env)->NewStringUTF(env, str);
492 }
493 
494 /*
495  * Package-private functions
496  */
497 
498 jobject
zjni_get_default_property(JNIEnv * env,zfs_prop_t prop)499 zjni_get_default_property(JNIEnv *env, zfs_prop_t prop)
500 {
501 	int i;
502 	for (i = 0; props_boolean[i] != ZPROP_INVAL; i++) {
503 		if (prop == props_boolean[i]) {
504 			return (create_default_BooleanProperty(env, prop));
505 		}
506 	}
507 
508 	for (i = 0; props_long[i] != ZPROP_INVAL; i++) {
509 		if (prop == props_long[i]) {
510 			return (create_default_LongProperty(env, prop));
511 		}
512 	}
513 
514 	for (i = 0; props_string[i] != ZPROP_INVAL; i++) {
515 		if (prop == props_string[i]) {
516 			return (create_default_StringProperty(env, prop));
517 		}
518 	}
519 
520 	for (i = 0; props_custom[i].prop != ZPROP_INVAL; i++) {
521 		if (prop == props_custom[i].prop) {
522 			return create_default_ObjectProperty(env,
523 			    props_custom[i].prop,
524 			    props_custom[i].convert_str,
525 			    props_custom[i].convert_uint64,
526 			    props_custom[i].propClass,
527 			    props_custom[i].valueClass);
528 		}
529 	}
530 
531 	return (NULL);
532 }
533 
534 static int
zjni_get_property_from_name_cb(int prop,void * cb)535 zjni_get_property_from_name_cb(int prop, void *cb)
536 {
537 	const char *name = cb;
538 
539 	if (strcasecmp(name, zfs_prop_to_name(prop)) == 0)
540 		return (prop);
541 
542 	return (ZPROP_CONT);
543 }
544 
545 zfs_prop_t
zjni_get_property_from_name(const char * name)546 zjni_get_property_from_name(const char *name)
547 {
548 	zfs_prop_t prop;
549 
550 	prop = zprop_iter(zjni_get_property_from_name_cb, (void *)name,
551 	    B_FALSE, B_FALSE, ZFS_TYPE_DATASET);
552 	return (prop == ZPROP_CONT ? ZPROP_INVAL : prop);
553 }
554 
555 jobject
zjni_int_to_Lineage(JNIEnv * env,zprop_source_t srctype)556 zjni_int_to_Lineage(JNIEnv *env, zprop_source_t srctype)
557 {
558 	/* zprop_source_t to Property$Lineage map */
559 	static zjni_field_mapping_t lineage_map[] = {
560 		{ ZPROP_SRC_NONE, "ZFS_PROP_LINEAGE_NOTINHERITABLE" },
561 		{ ZPROP_SRC_DEFAULT, "ZFS_PROP_LINEAGE_DEFAULT" },
562 		{ ZPROP_SRC_LOCAL, "ZFS_PROP_LINEAGE_LOCAL" },
563 		{ ZPROP_SRC_TEMPORARY, "ZFS_PROP_LINEAGE_TEMPORARY" },
564 		{ ZPROP_SRC_INHERITED, "ZFS_PROP_LINEAGE_INHERITED" }
565 	};
566 
567 	return (zjni_int_to_enum(env, srctype,
568 	    ZFSJNI_PACKAGE_DATA "Property$Lineage",
569 	    "ZFS_PROP_LINEAGE_INHERITED", lineage_map));
570 }
571 
572 jobjectArray
zjni_get_Dataset_properties(JNIEnv * env,zfs_handle_t * zhp)573 zjni_get_Dataset_properties(JNIEnv *env, zfs_handle_t *zhp)
574 {
575 	jobject prop;
576 	int i;
577 
578 	/* Create an array list for the properties */
579 	zjni_ArrayList_t proplist_obj = {0};
580 	zjni_ArrayList_t *proplist = &proplist_obj;
581 	zjni_new_ArrayList(env, proplist);
582 
583 	for (i = 0; props_boolean[i] != ZPROP_INVAL; i++) {
584 		/* Create property and add to list */
585 		prop = create_BooleanProperty(env, zhp, props_boolean[i]);
586 
587 		/* Does this property apply to this object? */
588 		if (prop != NULL) {
589 
590 			(*env)->CallBooleanMethod(
591 			    env, ((zjni_Object_t *)proplist)->object,
592 			    ((zjni_Collection_t *)proplist)->method_add, prop);
593 		} else {
594 
595 			if ((*env)->ExceptionOccurred(env) != NULL) {
596 				return (NULL);
597 			}
598 #ifdef	DEBUG
599 			(void) fprintf(stderr, "Property %s is not appropriate "
600 			    "for %s\n", zfs_prop_to_name(props_boolean[i]),
601 			    zfs_get_name(zhp));
602 #endif
603 		}
604 	}
605 
606 	for (i = 0; props_long[i] != ZPROP_INVAL; i++) {
607 		/* Create property and add to list */
608 		prop = create_LongProperty(env, zhp, props_long[i]);
609 
610 		/* Does this property apply to this object? */
611 		if (prop != NULL) {
612 
613 			(*env)->CallBooleanMethod(
614 			    env, ((zjni_Object_t *)proplist)->object,
615 			    ((zjni_Collection_t *)proplist)->method_add, prop);
616 		} else {
617 			if ((*env)->ExceptionOccurred(env) != NULL) {
618 				return (NULL);
619 			}
620 #ifdef	DEBUG
621 			(void) fprintf(stderr, "Property %s is not appropriate "
622 			    "for %s\n", zfs_prop_to_name(props_long[i]),
623 			    zfs_get_name(zhp));
624 #endif
625 		}
626 	}
627 
628 	for (i = 0; props_string[i] != ZPROP_INVAL; i++) {
629 		/* Create property and add to list */
630 		prop = create_StringProperty(env, zhp, props_string[i]);
631 
632 		/* Does this property apply to this object? */
633 		if (prop != NULL) {
634 
635 			(*env)->CallBooleanMethod(
636 			    env, ((zjni_Object_t *)proplist)->object,
637 			    ((zjni_Collection_t *)proplist)->method_add, prop);
638 		} else {
639 			if ((*env)->ExceptionOccurred(env) != NULL) {
640 				return (NULL);
641 			}
642 #ifdef	DEBUG
643 			(void) fprintf(stderr, "Property %s is not appropriate "
644 			    "for %s\n", zfs_prop_to_name(props_string[i]),
645 			    zfs_get_name(zhp));
646 #endif
647 		}
648 	}
649 
650 	for (i = 0; props_custom[i].prop != ZPROP_INVAL; i++) {
651 		/* Create property and add to list */
652 		prop = create_ObjectProperty(env, zhp, props_custom[i].prop,
653 		    props_custom[i].convert_str, props_custom[i].convert_uint64,
654 		    props_custom[i].propClass, props_custom[i].valueClass);
655 
656 		/* Does this property apply to this object? */
657 		if (prop != NULL) {
658 
659 			(*env)->CallBooleanMethod(
660 			    env, ((zjni_Object_t *)proplist)->object,
661 			    ((zjni_Collection_t *)proplist)->method_add, prop);
662 		} else {
663 			if ((*env)->ExceptionOccurred(env) != NULL) {
664 				return (NULL);
665 			}
666 #ifdef	DEBUG
667 			(void) fprintf(stderr, "Property %s is not appropriate "
668 			    "for %s\n", zfs_prop_to_name(props_custom[i].prop),
669 			    zfs_get_name(zhp));
670 #endif
671 		}
672 	}
673 
674 	return (zjni_Collection_to_array(env,
675 	    (zjni_Collection_t *)proplist, ZFSJNI_PACKAGE_DATA "Property"));
676 }
677