xref: /illumos-gate/usr/src/lib/libzfs_jni/common/libzfs_jni_property.c (revision 9adfa60d484ce2435f5af77cc99dcd4e692b6660)
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  	ZPROP_INVAL
92  };
93  
94  zfs_prop_t props_long[] = {
95  	ZFS_PROP_AVAILABLE,
96  	ZFS_PROP_CREATETXG,
97  	ZFS_PROP_QUOTA,
98  	ZFS_PROP_REFERENCED,
99  	ZFS_PROP_RESERVATION,
100  	ZFS_PROP_USED,
101  	ZFS_PROP_VOLSIZE,
102  	ZFS_PROP_REFQUOTA,
103  	ZFS_PROP_REFRESERVATION,
104  	ZFS_PROP_USERREFS,
105  	ZPROP_INVAL
106  };
107  
108  zfs_prop_t props_string[] = {
109  	ZFS_PROP_ORIGIN,
110  	/* ZFS_PROP_TYPE, */
111  	ZPROP_INVAL
112  };
113  
114  custom_prop_desct_t props_custom[] = {
115  	{ ZFS_PROP_ACLINHERIT, str_to_aclinherit, NULL,
116  	    ZFSJNI_PACKAGE_DATA "AclInheritProperty",
117  	    ZFSJNI_PACKAGE_DATA "AclInheritProperty$AclInherit" },
118  
119  	{ ZFS_PROP_ACLMODE, str_to_aclmode, NULL,
120  	    ZFSJNI_PACKAGE_DATA "AclModeProperty",
121  	    ZFSJNI_PACKAGE_DATA "AclModeProperty$AclMode" },
122  
123  	{ ZFS_PROP_CHECKSUM, str_to_checksum, NULL,
124  	    ZFSJNI_PACKAGE_DATA "ChecksumProperty",
125  	    ZFSJNI_PACKAGE_DATA "ChecksumProperty$Checksum" },
126  
127  	{ ZFS_PROP_COMPRESSION, str_to_compression, NULL,
128  	    ZFSJNI_PACKAGE_DATA "CompressionProperty",
129  	    ZFSJNI_PACKAGE_DATA "CompressionProperty$Compression" },
130  
131  	{ ZFS_PROP_COMPRESSRATIO, NULL, zjni_long_to_Long,
132  	    ZFSJNI_PACKAGE_DATA "CompressRatioProperty",
133  	    "java/lang/Long" },
134  
135  	{ ZFS_PROP_CREATION, zjni_str_to_date, NULL,
136  	    ZFSJNI_PACKAGE_DATA "CreationProperty",
137  	    "java/util/Date" },
138  
139  	{ ZFS_PROP_MOUNTPOINT, str_to_string, NULL,
140  	    ZFSJNI_PACKAGE_DATA "MountPointProperty",
141  	    "java/lang/String" },
142  
143  	{ ZFS_PROP_RECORDSIZE, NULL, zjni_long_to_Long,
144  	    ZFSJNI_PACKAGE_DATA "RecordSizeProperty",
145  	    "java/lang/Long" },
146  
147  	{ ZFS_PROP_SHARENFS, str_to_string, NULL,
148  	    ZFSJNI_PACKAGE_DATA "ShareNFSProperty",
149  	    "java/lang/String" },
150  
151  	{ ZFS_PROP_SNAPDIR, str_to_snapdir, NULL,
152  	    ZFSJNI_PACKAGE_DATA "SnapDirProperty",
153  	    ZFSJNI_PACKAGE_DATA "SnapDirProperty$SnapDir" },
154  
155  	{ ZFS_PROP_VOLBLOCKSIZE, NULL, zjni_long_to_Long,
156  	    ZFSJNI_PACKAGE_DATA "VolBlockSizeProperty",
157  	    "java/lang/Long" },
158  
159  	{ ZPROP_INVAL, NULL, NULL, NULL, NULL },
160  };
161  
162  /*
163   * Static functions
164   */
165  
166  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)167  create_BasicProperty(JNIEnv *env, zfs_handle_t *zhp, zfs_prop_t prop,
168      str_to_obj_f convert_str, uint64_to_obj_f convert_uint64,
169      char *propClass, char *valueClass)
170  {
171  	jobject propertyObject = NULL;
172  	char source[ZFS_MAX_DATASET_NAME_LEN];
173  	zprop_source_t srctype;
174  	jobject propValue = NULL;
175  
176  	if (convert_str != NULL) {
177  		char propbuf[ZFS_MAXPROPLEN];
178  		int result = zfs_prop_get(zhp, prop, propbuf,
179  		    sizeof (propbuf), &srctype, source, sizeof (source), 1);
180  
181  		if (result == 0)
182  			propValue = convert_str(env, propbuf);
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  	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 == ZPROP_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
create_BooleanProperty(JNIEnv * env,zfs_handle_t * zhp,zfs_prop_t prop)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
create_LongProperty(JNIEnv * env,zfs_handle_t * zhp,zfs_prop_t prop)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
create_StringProperty(JNIEnv * env,zfs_handle_t * zhp,zfs_prop_t prop)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
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)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_MAX_DATASET_NAME_LEN];
266  	zprop_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  	} else {
277  		uint64_t value;
278  		int result = zfs_prop_get_numeric(
279  		    zhp, prop, &value, &srctype, source, sizeof (source));
280  
281  		if (result == 0)
282  			propValue = convert_uint64(env, value);
283  	}
284  
285  	if (propValue != NULL) {
286  
287  		jmethodID constructor;
288  		char signature[1024];
289  		jclass class = (*env)->FindClass(env, propClass);
290  
291  		if (srctype == ZPROP_SRC_INHERITED) {
292  
293  			jstring propSource = (*env)->NewStringUTF(env, source);
294  
295  			(void) snprintf(signature, sizeof (signature),
296  			    "(L%s;Ljava/lang/String;)V", valueClass);
297  
298  			constructor = (*env)->GetMethodID(
299  			    env, class, "<init>", signature);
300  
301  			propertyObject = (*env)->NewObject(env,
302  			    class, constructor, propValue, propSource);
303  
304  		} else {
305  			jobject lineage = zjni_int_to_Lineage(env, srctype);
306  
307  			(void) snprintf(signature, sizeof (signature),
308  			    "(L%s;L" ZFSJNI_PACKAGE_DATA "Property$Lineage;)V",
309  			    valueClass);
310  
311  			constructor = (*env)->GetMethodID(
312  			    env, class, "<init>", signature);
313  
314  			propertyObject = (*env)->NewObject(env,
315  			    class, constructor, propValue, lineage);
316  		}
317  	}
318  
319  	return (propertyObject);
320  }
321  
322  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)323  create_default_BasicProperty(JNIEnv *env, zfs_prop_t prop,
324      str_to_obj_f convert_str, uint64_to_obj_f convert_uint64,
325      char *propClass, char *valueClass)
326  {
327  	jobject propertyObject = NULL;
328  
329  	if (!zfs_prop_readonly(prop)) {
330  		jobject propValue;
331  
332  		if (convert_str != NULL) {
333  			char *propbuf = (char *)zfs_prop_default_string(prop);
334  			propValue = convert_str(env, propbuf);
335  		} else {
336  			uint64_t value = zfs_prop_default_numeric(prop);
337  			propValue = convert_uint64(env, value);
338  		}
339  
340  		if (propValue != NULL) {
341  			char signature[1024];
342  			jmethodID constructor;
343  
344  			jstring propName =
345  			    (*env)->NewStringUTF(env, zfs_prop_to_name(prop));
346  
347  			jboolean readOnly = zfs_prop_readonly(prop) ?
348  			    JNI_TRUE : JNI_FALSE;
349  
350  			jclass class = (*env)->FindClass(env, propClass);
351  			jobject lineage =
352  			    zjni_int_to_Lineage(env, ZPROP_SRC_DEFAULT);
353  
354  			(void) snprintf(signature, sizeof (signature),
355  			    "(Ljava/lang/String;L%s;ZL" ZFSJNI_PACKAGE_DATA
356  			    "Property$Lineage;)V", valueClass);
357  
358  			constructor = (*env)->GetMethodID(
359  			    env, class, "<init>", signature);
360  
361  			propertyObject = (*env)->NewObject(
362  			    env, class, constructor,
363  			    propName, propValue, readOnly, lineage);
364  		}
365  	}
366  
367  	return (propertyObject);
368  }
369  
370  static jobject
create_default_BooleanProperty(JNIEnv * env,zfs_prop_t prop)371  create_default_BooleanProperty(JNIEnv *env, zfs_prop_t prop)
372  {
373  	return (create_default_BasicProperty(env, prop, NULL,
374  	    zjni_int_to_boolean, ZFSJNI_PACKAGE_DATA "BooleanProperty",
375  	    "java/lang/Boolean"));
376  }
377  
378  static jobject
create_default_LongProperty(JNIEnv * env,zfs_prop_t prop)379  create_default_LongProperty(JNIEnv *env, zfs_prop_t prop)
380  {
381  	return (create_default_BasicProperty(env, prop, NULL,
382  	    zjni_long_to_Long, ZFSJNI_PACKAGE_DATA "LongProperty",
383  	    "java/lang/Long"));
384  }
385  
386  static jobject
create_default_StringProperty(JNIEnv * env,zfs_prop_t prop)387  create_default_StringProperty(JNIEnv *env, zfs_prop_t prop)
388  {
389  	return (create_default_BasicProperty(env, prop, str_to_string, NULL,
390  	    ZFSJNI_PACKAGE_DATA "StringProperty", "java/lang/String"));
391  }
392  
393  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)394  create_default_ObjectProperty(JNIEnv *env, zfs_prop_t prop,
395      str_to_obj_f convert_str, uint64_to_obj_f convert_uint64,
396      char *propClass, char *valueClass)
397  {
398  	jobject propertyObject = NULL;
399  
400  	if (!zfs_prop_readonly(prop)) {
401  		jobject propValue;
402  
403  		if (convert_str != NULL) {
404  			char *propbuf = (char *)zfs_prop_default_string(prop);
405  			propValue = convert_str(env, propbuf);
406  		} else {
407  			uint64_t value = zfs_prop_default_numeric(prop);
408  			propValue = convert_uint64(env, value);
409  		}
410  
411  		if (propValue != NULL) {
412  			char signature[1024];
413  			jmethodID constructor;
414  
415  			jclass class = (*env)->FindClass(env, propClass);
416  			jobject lineage =
417  			    zjni_int_to_Lineage(env, ZPROP_SRC_DEFAULT);
418  
419  			(void) snprintf(signature, sizeof (signature),
420  			    "(L%s;L" ZFSJNI_PACKAGE_DATA "Property$Lineage;)V",
421  			    valueClass);
422  
423  			constructor = (*env)->GetMethodID(
424  			    env, class, "<init>", signature);
425  
426  			propertyObject = (*env)->NewObject(
427  			    env, class, constructor, propValue, lineage);
428  		}
429  	}
430  
431  	return (propertyObject);
432  }
433  
434  static jobject
str_to_enum_element(JNIEnv * env,char * str,char * valueClass)435  str_to_enum_element(JNIEnv *env, char *str, char *valueClass)
436  {
437  	char signature[1024];
438  	jmethodID method_valueOf;
439  
440  	jstring utf = (*env)->NewStringUTF(env, str);
441  	jclass class = (*env)->FindClass(env, valueClass);
442  
443  	(void) snprintf(signature, sizeof (signature),
444  	    "(Ljava/lang/String;)L%s;", valueClass);
445  
446  	method_valueOf = (*env)->GetStaticMethodID(
447  	    env, class, "valueOf", signature);
448  
449  	return (*env)->CallStaticObjectMethod(env, class, method_valueOf, utf);
450  }
451  
452  static jobject
str_to_aclinherit(JNIEnv * env,char * str)453  str_to_aclinherit(JNIEnv *env, char *str)
454  {
455  	return (str_to_enum_element(env, str,
456  	    ZFSJNI_PACKAGE_DATA "AclInheritProperty$AclInherit"));
457  }
458  
459  static jobject
str_to_aclmode(JNIEnv * env,char * str)460  str_to_aclmode(JNIEnv *env, char *str)
461  {
462  	return (str_to_enum_element(env, str,
463  	    ZFSJNI_PACKAGE_DATA "AclModeProperty$AclMode"));
464  }
465  
466  static jobject
str_to_checksum(JNIEnv * env,char * str)467  str_to_checksum(JNIEnv *env, char *str)
468  {
469  	return (str_to_enum_element(env, str,
470  	    ZFSJNI_PACKAGE_DATA "ChecksumProperty$Checksum"));
471  }
472  
473  static jobject
str_to_compression(JNIEnv * env,char * str)474  str_to_compression(JNIEnv *env, char *str)
475  {
476  	return (str_to_enum_element(env, str,
477  	    ZFSJNI_PACKAGE_DATA "CompressionProperty$Compression"));
478  }
479  
480  static jobject
str_to_snapdir(JNIEnv * env,char * str)481  str_to_snapdir(JNIEnv *env, char *str)
482  {
483  	return (str_to_enum_element(env, str,
484  	    ZFSJNI_PACKAGE_DATA "SnapDirProperty$SnapDir"));
485  }
486  
487  static jobject
str_to_string(JNIEnv * env,char * str)488  str_to_string(JNIEnv *env, char *str)
489  {
490  	return (*env)->NewStringUTF(env, str);
491  }
492  
493  /*
494   * Package-private functions
495   */
496  
497  jobject
zjni_get_default_property(JNIEnv * env,zfs_prop_t prop)498  zjni_get_default_property(JNIEnv *env, zfs_prop_t prop)
499  {
500  	int i;
501  	for (i = 0; props_boolean[i] != ZPROP_INVAL; i++) {
502  		if (prop == props_boolean[i]) {
503  			return (create_default_BooleanProperty(env, prop));
504  		}
505  	}
506  
507  	for (i = 0; props_long[i] != ZPROP_INVAL; i++) {
508  		if (prop == props_long[i]) {
509  			return (create_default_LongProperty(env, prop));
510  		}
511  	}
512  
513  	for (i = 0; props_string[i] != ZPROP_INVAL; i++) {
514  		if (prop == props_string[i]) {
515  			return (create_default_StringProperty(env, prop));
516  		}
517  	}
518  
519  	for (i = 0; props_custom[i].prop != ZPROP_INVAL; i++) {
520  		if (prop == props_custom[i].prop) {
521  			return create_default_ObjectProperty(env,
522  			    props_custom[i].prop,
523  			    props_custom[i].convert_str,
524  			    props_custom[i].convert_uint64,
525  			    props_custom[i].propClass,
526  			    props_custom[i].valueClass);
527  		}
528  	}
529  
530  	return (NULL);
531  }
532  
533  static int
zjni_get_property_from_name_cb(int prop,void * cb)534  zjni_get_property_from_name_cb(int 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 (ZPROP_CONT);
542  }
543  
544  zfs_prop_t
zjni_get_property_from_name(const char * name)545  zjni_get_property_from_name(const char *name)
546  {
547  	zfs_prop_t prop;
548  
549  	prop = zprop_iter(zjni_get_property_from_name_cb, (void *)name,
550  	    B_FALSE, B_FALSE, ZFS_TYPE_DATASET);
551  	return (prop == ZPROP_CONT ? ZPROP_INVAL : prop);
552  }
553  
554  jobject
zjni_int_to_Lineage(JNIEnv * env,zprop_source_t srctype)555  zjni_int_to_Lineage(JNIEnv *env, zprop_source_t srctype)
556  {
557  	/* zprop_source_t to Property$Lineage map */
558  	static zjni_field_mapping_t lineage_map[] = {
559  		{ ZPROP_SRC_NONE, "ZFS_PROP_LINEAGE_NOTINHERITABLE" },
560  		{ ZPROP_SRC_DEFAULT, "ZFS_PROP_LINEAGE_DEFAULT" },
561  		{ ZPROP_SRC_LOCAL, "ZFS_PROP_LINEAGE_LOCAL" },
562  		{ ZPROP_SRC_TEMPORARY, "ZFS_PROP_LINEAGE_TEMPORARY" },
563  		{ ZPROP_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
zjni_get_Dataset_properties(JNIEnv * env,zfs_handle_t * zhp)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] != ZPROP_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] != ZPROP_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] != ZPROP_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 != ZPROP_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