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