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/*
23 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#ifndef	_DTJ_UTIL_H
28#define	_DTJ_UTIL_H
29
30#pragma ident	"%Z%%M%	%I%	%E% SMI"
31
32#include <jni.h>
33#include <libuutil.h>
34
35#ifdef	__cplusplus
36extern "C" {
37#endif
38
39/*
40 * dtj_util.h separates functionality that is generally useful from
41 * that which is specific to the Java DTrace API.  If moved to a separate
42 * library, this functionality could be shared by other JNI wrappers.
43 */
44
45#ifdef JNI_VERSION_1_4
46#define	JNI_VERSION JNI_VERSION_1_4
47#else
48#define	JNI_VERSION JNI_VERSION_1_2
49#endif
50
51#define	CONSTRUCTOR "<init>"
52#define	DTJ_MSG_SIZE 1024
53#define	DTJ_INVALID_PTR ((void *)-1)
54#define	DTJ_INVALID_STR ((const char *)-1)
55
56#define	WRAP_EXCEPTION(JENV)	dtj_wrap_exception((JENV), __FILE__, __LINE__)
57
58extern boolean_t g_dtj_util_debug;
59
60typedef enum dtj_status {
61	DTJ_OK = JNI_OK,
62	DTJ_ERR = JNI_ERR
63} dtj_status_t;
64
65typedef enum dtj_type {
66	JCLASS,
67	JMETHOD,
68	JMETHOD_STATIC,
69	JFIELD,
70	JFIELD_STATIC,
71	DTJ_TYPE_END = -1
72} dtj_type_t;
73
74/*
75 * Convenient description format for java classes, methods, and fields.  The
76 * java_class_t, java_method_t, and java_field_t structures derived from these
77 * descriptions are used to create a table of usable JNI jclass, jmethodID, and
78 * jfieldID instances.
79 */
80typedef struct dtj_table_entry {
81	dtj_type_t djte_type;	/* JNI type */
82	void *djte_addr;	/* jclass, jmethodID, or jfieldID address */
83	char *djte_name;	/* symbol name declared in Java */
84	char *djte_desc;	/* JNI descriptor (string format) */
85} dtj_table_entry_t;
86
87typedef struct dtj_java_class {
88	jclass *djc_ptr;	/* address in user-defined structure */
89	char *djc_name;		/* fully qualified '/' delimited class name */
90	uu_list_t *djc_methods;	/* element type (java_method_t *) */
91	uu_list_t *djc_fields;	/* element type (java_field_t *) */
92	uu_list_node_t djc_node;
93} dtj_java_class_t;
94
95typedef struct dtj_java_method {
96	jmethodID *djm_ptr;	/* address in user-defined structure */
97	char *djm_name;		/* method name in java source file */
98	char *djm_signature;	/* javap -s method signature string */
99	boolean_t djm_static;	/* flag indicating static qualifier */
100	uu_list_node_t djm_node;
101} dtj_java_method_t;
102
103typedef struct dtj_java_field {
104	jfieldID *djf_ptr;	/* address in user-defined structure */
105	char *djf_name;		/* field name in java source file */
106	char *djf_type;		/* javap -s field type string */
107	boolean_t djf_static;	/* flag indicating static qualifier */
108	uu_list_node_t djf_node;
109} dtj_java_field_t;
110
111/*
112 * Table of cached jclass, jmethodID, and jfieldID values usable across multiple
113 * native method calls and multiple threads.
114 *
115 * Suffix conventions:
116 *   jc  java class
117 *   jm  java method
118 *   jsm java static method
119 *   jf  java field
120 *   jsf java static field
121 */
122
123/* NativeException */
124extern jclass g_nx_jc;
125extern jmethodID g_nxinit_jm;
126
127/* java.io.Serializable */
128extern jclass g_serial_jc;
129
130/* java.lang.Number */
131extern jclass g_number_jc;
132extern jmethodID g_shortval_jm;
133extern jmethodID g_intval_jm;
134extern jmethodID g_longval_jm;
135
136/* java.lang.Byte */
137extern jclass g_byte_jc;
138extern jmethodID g_byteinit_jm;
139
140/* java.lang.Character */
141extern jclass g_char_jc;
142extern jmethodID g_charinit_jm;
143extern jmethodID g_charval_jm;
144
145/* java.lang.Short */
146extern jclass g_short_jc;
147extern jmethodID g_shortinit_jm;
148
149/* java.lang.Integer */
150extern jclass g_int_jc;
151extern jmethodID g_intinit_jm;
152
153/* java.lang.Long */
154extern jclass g_long_jc;
155extern jmethodID g_longinit_jm;
156
157/* java.math.BigInteger */
158extern jclass g_bigint_jc;
159extern jmethodID g_bigint_val_jsm;
160extern jmethodID g_bigint_div_jm;
161extern jmethodID g_bigint_shl_jm;
162extern jmethodID g_bigint_or_jm;
163extern jmethodID g_bigint_setbit_jm;
164
165/* java.lang.String */
166extern jclass g_string_jc;
167extern jmethodID g_strinit_bytes_jm;
168extern jmethodID g_strbytes_jm;
169extern jmethodID g_trim_jm;
170
171/* java.lang.StringBuffer */
172extern jclass g_buf_jc;
173extern jmethodID g_bufinit_jm;
174extern jmethodID g_buf_append_char_jm;
175extern jmethodID g_buf_append_int_jm;
176extern jmethodID g_buf_append_long_jm;
177extern jmethodID g_buf_append_str_jm;
178extern jmethodID g_buf_append_obj_jm;
179extern jmethodID g_buflen_jm;
180extern jmethodID g_bufsetlen_jm;
181
182/* java.lang.Object */
183extern jclass g_object_jc;
184extern jmethodID g_tostring_jm;
185extern jmethodID g_equals_jm;
186
187/* java.lang.Enum */
188extern jclass g_enum_jc;
189extern jmethodID g_enumname_jm;
190
191/* List */
192extern jclass g_list_jc;
193extern jmethodID g_listclear_jm;
194extern jmethodID g_listadd_jm;
195extern jmethodID g_listget_jm;
196extern jmethodID g_listsize_jm;
197
198/*
199 * Populates the common java class references and associated method and field
200 * IDs declared in this file (above) using the dtj_cache_jni_classes() method.
201 */
202extern dtj_status_t dtj_load_common(JNIEnv *);
203
204/*
205 * Populates the user-declared java class references and associated method and
206 * field IDs described in the given table.  Because the class references are
207 * created as global JNI references, the method and field IDs remain valid
208 * across multiple native method calls and across multiple threads.
209 *
210 * This function assumes that the given table of java class, method, and field
211 * descriptions is terminated by an entry with DTJ_TYPE_END, and that the
212 * method and field descriptions immediately follow the description of their
213 * containing class.
214 *
215 * Throws NoClassDefFoundError, NoSuchMethodError, or NoSuchFieldError if any
216 * dtj_table_entry_t in common_jni_table.c is incorrect.
217 */
218extern dtj_status_t dtj_cache_jni_classes(JNIEnv *, const dtj_table_entry_t *);
219
220/* Common utilities */
221
222/*
223 * The following functions each create a pending Java Error or Exception:
224 *
225 * OutOfMemoryError
226 * NullPointerException
227 * IllegalArgumentException
228 * IllegalStateException
229 * NoSuchElementException
230 * ClassCastException
231 * AssertionError
232 * org.opensolaris.os.dtrace.ResourceLimitException
233 *
234 * Control should be returned to Java immediately afterwards.
235 */
236extern void dtj_throw_out_of_memory(JNIEnv *, const char *, ...);
237extern void dtj_throw_null_pointer(JNIEnv *, const char *, ...);
238extern void dtj_throw_illegal_argument(JNIEnv *, const char *, ...);
239extern void dtj_throw_illegal_state(JNIEnv *, const char *, ...);
240extern void dtj_throw_no_such_element(JNIEnv *, const char *, ...);
241extern void dtj_throw_class_cast(JNIEnv *, const char *, ...);
242extern void dtj_throw_assertion(JNIEnv *, const char *, ...);
243extern void dtj_throw_resource_limit(JNIEnv *, const char *, ...);
244
245/*
246 * Attaches native filename and line number to the currently pending java
247 * exception, since that information is not present in the exception stack
248 * trace.
249 */
250extern void dtj_wrap_exception(JNIEnv *, const char *, int);
251
252/*
253 * Calls the toString() method of the given object and prints the value to
254 * stdout (useful for debugging).  If an exception is thrown in this function,
255 * it is described on stdout and cleared.  It's guaranteed that no exception is
256 * pending when this function returns.
257 */
258extern void dtj_print_object(JNIEnv *jenv, jobject obj);
259
260/*
261 * Gets a java.math.BigInteger representing a 64-bit unsigned integer.
262 */
263extern jobject dtj_uint64(JNIEnv *jenv, uint64_t);
264
265/*
266 * Gets a java.math.BigInteger representing a 128-bit integer given as 64 high
267 * bits (1st arg) and 64 low bits (2nd arg).
268 */
269extern jobject dtj_int128(JNIEnv *jenv, uint64_t, uint64_t);
270
271/*
272 * Gets a formatted String (local reference) from a format and a variable
273 * argument list of placeholder values.  Returns NULL if OutOfMemoryError is
274 * thrown.
275 */
276extern jstring dtj_format_string(JNIEnv *jenv, const char *fmt, ...);
277
278/*
279 * Internationalization support.  These functions taken (not verbatim) from
280 * Section 8.2 of The Java Native Interface by Sheng Liang, The Java Series.
281 * Use these functions for locale-specific strings such as file names.
282 */
283extern jstring dtj_NewStringNative(JNIEnv *jenv, const char *str);
284extern char *dtj_GetStringNativeChars(JNIEnv *jenv, jstring jstr);
285extern void dtj_ReleaseStringNativeChars(JNIEnv *jenv, jstring jstr,
286    const char *str);
287
288/*
289 * Converts the args array of main(String[] args) in Java into a native
290 * dynamically allocated array of strings.  The returned array must be
291 * deallocated by calling free_argv().  A java exception is pending if this
292 * function returns NULL (in that case, any allocations made up to the point of
293 * failure in get_argv() are automatically freed).
294 *
295 * Returns a NULL-terminated array that works with functions that expect a
296 * terminating NULL rather than relying on an element count.  The argc parameter
297 * is also overwritten with the number of returned array elements (not including
298 * the terminating NULL).
299 */
300extern char **dtj_get_argv(JNIEnv *jenv, jobjectArray args, int *argc);
301/*
302 * Tokenizes a command string to create a native dynamically allocated array of
303 * strings.  The first element of the returned array is assumed to be the name
304 * of the command, and subsequent elements are arguments to that command.
305 * Otherwise behaves exactly like get_argv() above, including requiring a
306 * subsequent call to free_argv() on the returned array.
307 * Throws NullPointerException if cmd is NULL.
308 * Throws IllegalArgumentException if cmd is empty.
309 */
310extern char **dtj_make_argv(JNIEnv *jenv, jstring cmd, int *argc);
311extern void dtj_free_argv(char **argv);
312
313
314/* Wrappers for uu_list_t */
315
316/*
317 * List element destructor.
318 * params: node pointer, user arg (may be NULL)
319 */
320typedef void dtj_value_destroy_f(void *, void *);
321
322/*
323 * uu_list_t generic entry type for pointers compared by pointer value, similar
324 * to Java's default Object.equals() implementation (referenced objects are
325 * equal only if they have the same address in memory).  Used with
326 * pointer_list_entry_cmp.
327 */
328typedef struct dtj_pointer_list_entry {
329	void *dple_ptr;
330	uu_list_node_t dple_node;
331} dtj_pointer_list_entry_t;
332
333typedef struct dtj_string_list_entry {
334	char *dsle_value;
335	uu_list_node_t dsle_node;
336} dtj_string_list_entry_t;
337
338/* Comparison functions, uu_compare_fn_t signature */
339extern int dtj_pointer_list_entry_cmp(const void *, const void *, void *);
340extern int dtj_string_list_entry_cmp(const void *, const void *, void *);
341
342/* Constructors */
343extern uu_list_t *dtj_pointer_list_create(void);
344extern dtj_pointer_list_entry_t *dtj_pointer_list_entry_create(void *);
345extern uu_list_t *dtj_string_list_create(void);
346extern dtj_string_list_entry_t *dtj_string_list_entry_create(const char *);
347
348/* Destructors */
349extern void dtj_pointer_list_entry_destroy(void *, dtj_value_destroy_f *,
350    void *);
351extern void dtj_string_list_entry_destroy(void *, void *);
352/*
353 * Convenience function destroys a uu_list_t and its values.
354 *
355 * param list: list to be destroyed, call is a no-op if list is NULL
356 * param value_destroy: optional destructor; if non-NULL, it is called on each
357 *	list value
358 * param arg: user argument to the optional destructor
359 */
360extern void dtj_list_destroy(uu_list_t *, dtj_value_destroy_f *, void *);
361extern void dtj_pointer_list_destroy(uu_list_t *, dtj_value_destroy_f *,
362    void *);
363extern void dtj_string_list_destroy(uu_list_t *);
364
365/*
366 * Convenience functions clear a uu_list_t without destroying it.  Destroys all
367 * list elements and leaves the list empty.  The *_list_destroy() functions
368 * implicitly clear the list before destroying it.
369 */
370extern void dtj_list_clear(uu_list_t *, dtj_value_destroy_f *, void *);
371extern void dtj_pointer_list_clear(uu_list_t *, dtj_value_destroy_f *,
372    void *);
373extern void dtj_string_list_clear(uu_list_t *);
374
375extern boolean_t dtj_list_empty(uu_list_t *);
376/* Return B_TRUE if successful, B_FALSE otherwise */
377extern boolean_t dtj_list_add(uu_list_t *, void *);
378extern boolean_t dtj_pointer_list_add(uu_list_t *, void *);
379extern boolean_t dtj_string_list_add(uu_list_t *, const char *);
380/* Return INVALID_PTR if list is empty (NULL is a valid list element) */
381extern void * dtj_pointer_list_first(uu_list_t *);
382extern void * dtj_pointer_list_last(uu_list_t *);
383/* Return INVALID_STR if list is empty (NULL is a valid list element) */
384extern const char *dtj_string_list_first(uu_list_t *);
385extern const char *dtj_string_list_last(uu_list_t *);
386/* Return INVALID_PTR at end of list (NULL is a valid list element) */
387extern void *dtj_pointer_list_walk_next(uu_list_walk_t *);
388/* Return INVALID_STR at end of list (NULL is a valid list element) */
389extern const char *dtj_string_list_walk_next(uu_list_walk_t *);
390
391#ifdef	__cplusplus
392}
393#endif
394
395#endif	/* _DTJ_UTIL_H */
396