1 /* 2 * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 #include <string.h> 26 #include <stdlib.h> 27 28 #include "jni.h" 29 #include "jni_util.h" 30 #include "jvm.h" 31 #include "io_util.h" 32 33 34 #include "openssl/opensslv.h" 35 #include "zlib.h" 36 #include "JNIHelp.h" 37 #include "cutils/log.h" 38 #if defined(__ANDROID__) 39 void android_get_LD_LIBRARY_PATH(char*, size_t); 40 #endif 41 42 #define NATIVE_METHOD(className, functionName, signature) \ 43 { #functionName, signature, (void*)(className ## _ ## functionName) } 44 45 #define PUTPROP(props, key, val) \ 46 if (1) { \ 47 jstring jkey = (*env)->NewStringUTF(env, key); \ 48 jstring jval = (*env)->NewStringUTF(env, val); \ 49 jobject r = (*env)->CallObjectMethod(env, props, putID, jkey, jval); \ 50 if ((*env)->ExceptionOccurred(env)) return NULL; \ 51 (*env)->DeleteLocalRef(env, jkey); \ 52 (*env)->DeleteLocalRef(env, jval); \ 53 (*env)->DeleteLocalRef(env, r); \ 54 } else ((void) 0) 55 56 /* "key" is a char type string with only ASCII character in it. 57 "val" is a nchar (typedefed in java_props.h) type string */ 58 59 #define PUTPROP_ForPlatformNString(props, key, val) \ 60 if (1) { \ 61 jstring jkey = (*env)->NewStringUTF(env, key); \ 62 jstring jval = GetStringPlatform(env, val); \ 63 jobject r = (*env)->CallObjectMethod(env, props, putID, jkey, jval); \ 64 if ((*env)->ExceptionOccurred(env)) return NULL; \ 65 (*env)->DeleteLocalRef(env, jkey); \ 66 (*env)->DeleteLocalRef(env, jval); \ 67 (*env)->DeleteLocalRef(env, r); \ 68 } else ((void) 0) 69 #define REMOVEPROP(props, key) \ 70 if (1) { \ 71 jstring jkey = JNU_NewStringPlatform(env, key); \ 72 jobject r = (*env)->CallObjectMethod(env, props, removeID, jkey); \ 73 if ((*env)->ExceptionOccurred(env)) return NULL; \ 74 (*env)->DeleteLocalRef(env, jkey); \ 75 (*env)->DeleteLocalRef(env, r); \ 76 } else ((void) 0) 77 #define GETPROP(props, key, jret) \ 78 if (1) { \ 79 jstring jkey = JNU_NewStringPlatform(env, key); \ 80 jret = (*env)->CallObjectMethod(env, props, getPropID, jkey); \ 81 if ((*env)->ExceptionOccurred(env)) return NULL; \ 82 (*env)->DeleteLocalRef(env, jkey); \ 83 } else ((void) 0) 84 85 #ifndef VENDOR /* Third party may overwrite this. */ 86 #define VENDOR "Oracle Corporation" 87 #define VENDOR_URL "http://java.oracle.com/" 88 #define VENDOR_URL_BUG "http://bugreport.sun.com/bugreport/" 89 #endif 90 91 #define JAVA_MAX_SUPPORTED_VERSION 51 92 #define JAVA_MAX_SUPPORTED_MINOR_VERSION 0 93 94 #ifdef JAVA_SPECIFICATION_VENDOR /* Third party may NOT overwrite this. */ 95 #error "ERROR: No override of JAVA_SPECIFICATION_VENDOR is allowed" 96 #else 97 #define JAVA_SPECIFICATION_VENDOR "Oracle Corporation" 98 #endif 99 100 /* 101 * The following three functions implement setter methods for 102 * java.lang.System.{in, out, err}. They are natively implemented 103 * because they violate the semantics of the language (i.e. set final 104 * variable). 105 */ 106 JNIEXPORT void JNICALL 107 System_setIn0(JNIEnv *env, jclass cla, jobject stream) 108 { 109 jfieldID fid = 110 (*env)->GetStaticFieldID(env,cla,"in","Ljava/io/InputStream;"); 111 if (fid == 0) 112 return; 113 (*env)->SetStaticObjectField(env,cla,fid,stream); 114 } 115 116 JNIEXPORT void JNICALL 117 System_setOut0(JNIEnv *env, jclass cla, jobject stream) 118 { 119 jfieldID fid = 120 (*env)->GetStaticFieldID(env,cla,"out","Ljava/io/PrintStream;"); 121 if (fid == 0) 122 return; 123 (*env)->SetStaticObjectField(env,cla,fid,stream); 124 } 125 126 JNIEXPORT void JNICALL 127 System_setErr0(JNIEnv *env, jclass cla, jobject stream) 128 { 129 jfieldID fid = 130 (*env)->GetStaticFieldID(env,cla,"err","Ljava/io/PrintStream;"); 131 if (fid == 0) 132 return; 133 (*env)->SetStaticObjectField(env,cla,fid,stream); 134 } 135 136 static void cpchars(jchar *dst, char *src, int n) 137 { 138 int i; 139 for (i = 0; i < n; i++) { 140 dst[i] = src[i]; 141 } 142 } 143 144 JNIEXPORT jstring JNICALL 145 System_mapLibraryName(JNIEnv *env, jclass ign, jstring libname) 146 { 147 int len; 148 int prefix_len = (int) strlen(JNI_LIB_PREFIX); 149 int suffix_len = (int) strlen(JNI_LIB_SUFFIX); 150 151 jchar chars[256]; 152 if (libname == NULL) { 153 JNU_ThrowNullPointerException(env, 0); 154 return NULL; 155 } 156 len = (*env)->GetStringLength(env, libname); 157 if (len > 240) { 158 JNU_ThrowIllegalArgumentException(env, "name too long"); 159 return NULL; 160 } 161 cpchars(chars, JNI_LIB_PREFIX, prefix_len); 162 (*env)->GetStringRegion(env, libname, 0, len, chars + prefix_len); 163 len += prefix_len; 164 cpchars(chars + len, JNI_LIB_SUFFIX, suffix_len); 165 len += suffix_len; 166 167 return (*env)->NewString(env, chars, len); 168 } 169 170 static jobjectArray System_specialProperties(JNIEnv* env, jclass ignored) { 171 jclass stringClass = (*env)->FindClass(env, "java/lang/String"); 172 jobjectArray result = (*env)->NewObjectArray(env, 4, stringClass, NULL); 173 174 char path[PATH_MAX]; 175 char* process_path = getcwd(path, sizeof(path)); 176 char user_dir[PATH_MAX + 10] = "user.dir="; 177 strncat(user_dir, process_path, PATH_MAX); 178 jstring user_dir_str = (*env)->NewStringUTF(env, user_dir); 179 if ((*env)->ExceptionCheck(env)) { 180 return NULL; 181 } 182 (*env)->SetObjectArrayElement(env, result, 0, user_dir_str); 183 if ((*env)->ExceptionCheck(env)) { 184 return NULL; 185 } 186 jstring zlib_str = (*env)->NewStringUTF(env, "android.zlib.version=" ZLIB_VERSION); 187 if ((*env)->ExceptionCheck(env)) { 188 return NULL; 189 } 190 (*env)->SetObjectArrayElement(env, result, 1, zlib_str); 191 if ((*env)->ExceptionCheck(env)) { 192 return NULL; 193 } 194 jstring ssl_str = (*env)->NewStringUTF(env, "android.openssl.version=" OPENSSL_VERSION_TEXT); 195 if ((*env)->ExceptionCheck(env)) { 196 return NULL; 197 } 198 (*env)->SetObjectArrayElement(env, result, 2, ssl_str); 199 if ((*env)->ExceptionCheck(env)) { 200 return NULL; 201 } 202 203 204 const char* library_path = getenv("LD_LIBRARY_PATH"); 205 #if defined(__ANDROID__) 206 if (library_path == NULL) { 207 android_get_LD_LIBRARY_PATH(path, sizeof(path)); 208 library_path = path; 209 } 210 #endif 211 if (library_path == NULL) { 212 library_path = ""; 213 } 214 char* java_path = malloc(strlen("java.library.path=") + strlen(library_path) + 1); 215 strcpy(java_path, "java.library.path="); 216 strcat(java_path, library_path); 217 jstring java_path_str = (*env)->NewStringUTF(env, java_path); 218 free((void*)java_path); 219 if ((*env)->ExceptionCheck(env)) { 220 return NULL; 221 } 222 (*env)->SetObjectArrayElement(env, result, 3, java_path_str); 223 if ((*env)->ExceptionCheck(env)) { 224 return NULL; 225 } 226 227 return result; 228 } 229 230 static void System_log(JNIEnv* env, jclass ignored, jchar type, jstring javaMessage, jthrowable exception) { 231 int priority; 232 switch (type) { 233 case 'D': case 'd': priority = ANDROID_LOG_DEBUG; break; 234 case 'E': case 'e': priority = ANDROID_LOG_ERROR; break; 235 case 'F': case 'f': priority = ANDROID_LOG_FATAL; break; 236 case 'I': case 'i': priority = ANDROID_LOG_INFO; break; 237 case 'S': case 's': priority = ANDROID_LOG_SILENT; break; 238 case 'V': case 'v': priority = ANDROID_LOG_VERBOSE; break; 239 case 'W': case 'w': priority = ANDROID_LOG_WARN; break; 240 default: priority = ANDROID_LOG_DEFAULT; break; 241 } 242 243 WITH_PLATFORM_STRING(env, javaMessage, message) { 244 if (message == NULL) { 245 // Since this function is used for last-gasp debugging output, be noisy on failure. 246 return; 247 } 248 LOG_PRI(priority, "System", "%s", message); 249 } END_PLATFORM_STRING(env, message); 250 251 if (exception != NULL) { 252 jniLogException(env, priority, "System", exception); 253 } 254 } 255 256 static jlong System_nanoTime(JNIEnv* env, jclass unused) { 257 struct timespec now; 258 clock_gettime(CLOCK_MONOTONIC, &now); 259 return now.tv_sec * 1000000000LL + now.tv_nsec; 260 } 261 262 static jlong System_currentTimeMillis(JNIEnv* env, jclass unused) { 263 return JVM_CurrentTimeMillis(NULL, NULL); 264 } 265 266 static JNINativeMethod gMethods[] = { 267 NATIVE_METHOD(System, mapLibraryName, "(Ljava/lang/String;)Ljava/lang/String;"), 268 NATIVE_METHOD(System, setErr0, "(Ljava/io/PrintStream;)V"), 269 NATIVE_METHOD(System, setOut0, "(Ljava/io/PrintStream;)V"), 270 NATIVE_METHOD(System, setIn0, "(Ljava/io/InputStream;)V"), 271 NATIVE_METHOD(System, specialProperties, "()[Ljava/lang/String;"), 272 NATIVE_METHOD(System, log, "(CLjava/lang/String;Ljava/lang/Throwable;)V"), 273 NATIVE_METHOD(System, currentTimeMillis, "()J"), 274 NATIVE_METHOD(System, nanoTime, "()J"), 275 }; 276 277 void register_java_lang_System(JNIEnv* env) { 278 jniRegisterNativeMethods(env, "java/lang/System", gMethods, NELEM(gMethods)); 279 } 280