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, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 1998,2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 /*
30 * This file contains native methods for the Java SLP implementation.
31 * So far this is just the syslog function.
32 *
33 * The file also contains two support functions, one for throwing exceptions
34 * given a class name, and one for correctly converting unicode Strings to C
35 * byte arrays.
36 */
37
38 #include <malloc.h>
39 #include <jni.h>
40 #include <syslog.h>
41
42 #define CLASS_JAVA_LANG_OUTOFMEMORYERROR "java/lang/OutOfMemoryError"
43 #define CLASS_JAVA_LANG_STRING "java/lang/String"
44
45 #define METHOD_GETBYTES "getBytes"
46
47 #define SIG_JAVA_LANG_STRING_GETBYTES "()[B"
48
49 /*
50 * Given a class name of an exception and a message attempt to throw
51 * a new instance of the exception.
52 */
53 static void
JNU_ThrowByName(JNIEnv * env,const char * name,const char * msg)54 JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg)
55 {
56 jclass class = (*env)->FindClass(env, name);
57
58 /*
59 * If class is NULL FindClass() encountered a problem locating the
60 * desired class and has already called ThrowNew() with an
61 * exception.
62 */
63 if (class == NULL) {
64 return;
65 }
66
67 (*env)->ThrowNew(env, class, msg);
68 (*env)->DeleteLocalRef(env, class);
69 }
70
71 /*
72 * Convert a Java String into a native set of characters using the
73 * method String.getBytes(). This will ensure that the appropriate
74 * character set encoding will be used. This is necessary if the
75 * Java String uses unicode characters that cannot be easily
76 * encoded into native chars.
77 *
78 * The buffer returned must be released by using free() once it is
79 * finished with.
80 *
81 * This function returns NULL if an exception has been thrown during its
82 * execution.
83 */
84 static char
JNU_GetStringNativeChars(JNIEnv * env,jstring jstr)85 *JNU_GetStringNativeChars(JNIEnv *env, jstring jstr)
86 {
87 jclass class;
88 jmethodID method;
89 jint len;
90 jbyteArray bytes = NULL;
91 char *result = NULL;
92
93 /*
94 * Need a local reference for (1) FindClass(), (2) the bytes and
95 * (3) the FindClass() in ThrowByName() if all goes wrong.
96 */
97 if ((*env)->EnsureLocalCapacity(env, 3) < 0) {
98 JNU_ThrowByName(
99 env,
100 CLASS_JAVA_LANG_OUTOFMEMORYERROR,
101 NULL);
102
103 return (NULL);
104 }
105
106 class = (*env)->FindClass(env, CLASS_JAVA_LANG_STRING);
107
108 /*
109 * If class is NULL FindClass() encountered a problem locating the
110 * desired class and has already called ThrowNew() with an
111 * exception.
112 */
113 if (class == NULL) {
114 return (NULL);
115 }
116
117 method = (*env)->GetMethodID(
118 env,
119 class,
120 METHOD_GETBYTES,
121 SIG_JAVA_LANG_STRING_GETBYTES);
122
123 /*
124 * If method is NULL GetMethodID() encountered a problem
125 * locating the desired method and has already called
126 * ThrowNew() with an exception.
127 */
128 if (method != NULL) {
129 /*
130 * Call String.getBytes(), creating our temporary
131 * byte array
132 */
133 bytes = (*env)->CallObjectMethod(env, jstr, method);
134
135 /* See if CallObjectMethod() threw an exception */
136 if ((*env)->ExceptionCheck(env) == JNI_FALSE) {
137
138 len = (*env)->GetArrayLength(env, bytes);
139
140 /*
141 * Allocate a buffer for the native characters,
142 * need an extra char for string terminator.
143 * Note: calloc will provide the terminating
144 * '\0' for us.
145 */
146 result = (char *)calloc(len + 1, sizeof (char));
147
148 /*
149 * If allocation failed assume we are out of
150 * memory
151 */
152 if (result == NULL) {
153 JNU_ThrowByName(
154 env,
155 CLASS_JAVA_LANG_OUTOFMEMORYERROR,
156 NULL);
157 } else {
158 /*
159 * Copy the encoded bytes into the
160 * native string buffer
161 */
162 (*env)->GetByteArrayRegion(
163 env,
164 bytes,
165 0,
166 len,
167 (jbyte *)result);
168 }
169 }
170
171 if (bytes != NULL) {
172 (*env)->DeleteLocalRef(env, bytes);
173 }
174 }
175
176 /* Clean up by deleting the local references */
177 (*env)->DeleteLocalRef(env, class);
178
179 return (result);
180 }
181
182 /*
183 * Class: com_sun_slp_Syslog
184 * Method: syslog
185 * Signature: (ILjava/lang/String;)V
186 */
187 /* ARGSUSED */
188 JNIEXPORT
Java_com_sun_slp_Syslog_syslog(JNIEnv * env,jobject obj,jint priority,jstring jmsg)189 void JNICALL Java_com_sun_slp_Syslog_syslog(JNIEnv *env,
190 jobject obj,
191 jint priority,
192 jstring jmsg) {
193
194 char *msg = JNU_GetStringNativeChars(env, jmsg);
195
196 /*
197 * Check to see if the String conversion was successful,
198 * if it wasn't an exception will have already been thrown.
199 */
200 if (msg != NULL) {
201 openlog("slpd", LOG_PID, LOG_DAEMON);
202 syslog(priority, "%s", msg);
203 closelog();
204
205 free(msg);
206 }
207 }
208