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#define LOG_TAG "libcore" 26 27#include <stdlib.h> 28#include <string.h> 29#include <time.h> 30 31#include <log/log.h> 32 33#include "io_util.h" 34#include "jni.h" 35#include "jni_util.h" 36#include "jvm.h" 37 38#include "openssl/opensslv.h" 39#include "zlib.h" 40#include <nativehelper/JNIHelp.h> 41#if defined(__ANDROID__) 42void android_get_LD_LIBRARY_PATH(char*, size_t); 43#endif 44 45#define NATIVE_METHOD(className, functionName, signature) \ 46{ #functionName, signature, (void*)(className ## _ ## functionName) } 47 48#define PUTPROP(props, key, val) \ 49 if (1) { \ 50 jstring jkey = (*env)->NewStringUTF(env, key); \ 51 jstring jval = (*env)->NewStringUTF(env, val); \ 52 jobject r = (*env)->CallObjectMethod(env, props, putID, jkey, jval); \ 53 if ((*env)->ExceptionOccurred(env)) return NULL; \ 54 (*env)->DeleteLocalRef(env, jkey); \ 55 (*env)->DeleteLocalRef(env, jval); \ 56 (*env)->DeleteLocalRef(env, r); \ 57 } else ((void) 0) 58 59/* "key" is a char type string with only ASCII character in it. 60 "val" is a nchar (typedefed in java_props.h) type string */ 61 62#define PUTPROP_ForPlatformNString(props, key, val) \ 63 if (1) { \ 64 jstring jkey = (*env)->NewStringUTF(env, key); \ 65 jstring jval = GetStringPlatform(env, val); \ 66 jobject r = (*env)->CallObjectMethod(env, props, putID, jkey, jval); \ 67 if ((*env)->ExceptionOccurred(env)) return NULL; \ 68 (*env)->DeleteLocalRef(env, jkey); \ 69 (*env)->DeleteLocalRef(env, jval); \ 70 (*env)->DeleteLocalRef(env, r); \ 71 } else ((void) 0) 72#define REMOVEPROP(props, key) \ 73 if (1) { \ 74 jstring jkey = JNU_NewStringPlatform(env, key); \ 75 jobject r = (*env)->CallObjectMethod(env, props, removeID, jkey); \ 76 if ((*env)->ExceptionOccurred(env)) return NULL; \ 77 (*env)->DeleteLocalRef(env, jkey); \ 78 (*env)->DeleteLocalRef(env, r); \ 79 } else ((void) 0) 80#define GETPROP(props, key, jret) \ 81 if (1) { \ 82 jstring jkey = JNU_NewStringPlatform(env, key); \ 83 (jret) = (*env)->CallObjectMethod(env, props, getPropID, jkey); \ 84 if ((*env)->ExceptionOccurred(env)) return NULL; \ 85 (*env)->DeleteLocalRef(env, jkey); \ 86 } else ((void) 0) 87 88#ifndef VENDOR /* Third party may overwrite this. */ 89#define VENDOR "Oracle Corporation" 90#define VENDOR_URL "http://java.oracle.com/" 91#define VENDOR_URL_BUG "http://bugreport.sun.com/bugreport/" 92#endif 93 94#define JAVA_MAX_SUPPORTED_VERSION 51 95#define JAVA_MAX_SUPPORTED_MINOR_VERSION 0 96 97#ifdef JAVA_SPECIFICATION_VENDOR /* Third party may NOT overwrite this. */ 98 #error "ERROR: No override of JAVA_SPECIFICATION_VENDOR is allowed" 99#else 100 #define JAVA_SPECIFICATION_VENDOR "Oracle Corporation" 101#endif 102 103/* 104 * The following three functions implement setter methods for 105 * java.lang.System.{in, out, err}. They are natively implemented 106 * because they violate the semantics of the language (i.e. set final 107 * variable). 108 */ 109JNIEXPORT void JNICALL 110System_setIn0(JNIEnv *env, jclass cla, jobject stream) 111{ 112 jfieldID fid = 113 (*env)->GetStaticFieldID(env,cla,"in","Ljava/io/InputStream;"); 114 if (fid == 0) 115 return; 116 (*env)->SetStaticObjectField(env,cla,fid,stream); 117} 118 119JNIEXPORT void JNICALL 120System_setOut0(JNIEnv *env, jclass cla, jobject stream) 121{ 122 jfieldID fid = 123 (*env)->GetStaticFieldID(env,cla,"out","Ljava/io/PrintStream;"); 124 if (fid == 0) 125 return; 126 (*env)->SetStaticObjectField(env,cla,fid,stream); 127} 128 129JNIEXPORT void JNICALL 130System_setErr0(JNIEnv *env, jclass cla, jobject stream) 131{ 132 jfieldID fid = 133 (*env)->GetStaticFieldID(env,cla,"err","Ljava/io/PrintStream;"); 134 if (fid == 0) 135 return; 136 (*env)->SetStaticObjectField(env,cla,fid,stream); 137} 138 139static void cpchars(jchar *dst, char *src, int n) 140{ 141 int i; 142 for (i = 0; i < n; i++) { 143 dst[i] = src[i]; 144 } 145} 146 147JNIEXPORT jstring JNICALL 148System_mapLibraryName(JNIEnv *env, jclass ign, jstring libname) 149{ 150 int len; 151 int prefix_len = (int) strlen(JNI_LIB_PREFIX); 152 int suffix_len = (int) strlen(JNI_LIB_SUFFIX); 153 154 jchar chars[256]; 155 if (libname == NULL) { 156 JNU_ThrowNullPointerException(env, 0); 157 return NULL; 158 } 159 len = (*env)->GetStringLength(env, libname); 160 if (len > 240) { 161 JNU_ThrowIllegalArgumentException(env, "name too long"); 162 return NULL; 163 } 164 cpchars(chars, JNI_LIB_PREFIX, prefix_len); 165 (*env)->GetStringRegion(env, libname, 0, len, chars + prefix_len); 166 len += prefix_len; 167 cpchars(chars + len, JNI_LIB_SUFFIX, suffix_len); 168 len += suffix_len; 169 170 return (*env)->NewString(env, chars, len); 171} 172 173static jobjectArray System_specialProperties(JNIEnv* env, jclass ignored) { 174 jclass stringClass = (*env)->FindClass(env, "java/lang/String"); 175 jobjectArray result = (*env)->NewObjectArray(env, 4, stringClass, NULL); 176 177 char path[PATH_MAX]; 178 char* process_path = getcwd(path, sizeof(path)); 179 char user_dir[PATH_MAX + 10] = "user.dir="; 180 strncat(user_dir, process_path, PATH_MAX); 181 jstring user_dir_str = (*env)->NewStringUTF(env, user_dir); 182 if ((*env)->ExceptionCheck(env)) { 183 return NULL; 184 } 185 (*env)->SetObjectArrayElement(env, result, 0, user_dir_str); 186 if ((*env)->ExceptionCheck(env)) { 187 return NULL; 188 } 189 jstring zlib_str = (*env)->NewStringUTF(env, "android.zlib.version=" ZLIB_VERSION); 190 if ((*env)->ExceptionCheck(env)) { 191 return NULL; 192 } 193 (*env)->SetObjectArrayElement(env, result, 1, zlib_str); 194 if ((*env)->ExceptionCheck(env)) { 195 return NULL; 196 } 197 jstring ssl_str = (*env)->NewStringUTF(env, "android.openssl.version=" OPENSSL_VERSION_TEXT); 198 if ((*env)->ExceptionCheck(env)) { 199 return NULL; 200 } 201 (*env)->SetObjectArrayElement(env, result, 2, ssl_str); 202 if ((*env)->ExceptionCheck(env)) { 203 return NULL; 204 } 205 206 207 const char* library_path = getenv("LD_LIBRARY_PATH"); 208#if defined(__ANDROID__) 209 if (library_path == NULL) { 210 android_get_LD_LIBRARY_PATH(path, sizeof(path)); 211 library_path = path; 212 } 213#endif 214 if (library_path == NULL) { 215 library_path = ""; 216 } 217 char* java_path = malloc(strlen("java.library.path=") + strlen(library_path) + 1); 218 strcpy(java_path, "java.library.path="); 219 strcat(java_path, library_path); 220 jstring java_path_str = (*env)->NewStringUTF(env, java_path); 221 free((void*)java_path); 222 if ((*env)->ExceptionCheck(env)) { 223 return NULL; 224 } 225 (*env)->SetObjectArrayElement(env, result, 3, java_path_str); 226 if ((*env)->ExceptionCheck(env)) { 227 return NULL; 228 } 229 230 return result; 231} 232 233static void System_log(JNIEnv* env, jclass ignored, jchar type, jstring javaMessage, jthrowable exception) { 234 int priority; 235 switch (type) { 236 case 'D': case 'd': priority = ANDROID_LOG_DEBUG; break; 237 case 'E': case 'e': priority = ANDROID_LOG_ERROR; break; 238 case 'F': case 'f': priority = ANDROID_LOG_FATAL; break; 239 case 'I': case 'i': priority = ANDROID_LOG_INFO; break; 240 case 'S': case 's': priority = ANDROID_LOG_SILENT; break; 241 case 'V': case 'v': priority = ANDROID_LOG_VERBOSE; break; 242 case 'W': case 'w': priority = ANDROID_LOG_WARN; break; 243 default: priority = ANDROID_LOG_DEFAULT; break; 244 } 245 246 WITH_PLATFORM_STRING(env, javaMessage, message) { 247 LOG_PRI(priority, "System", "%s", message); 248 } END_PLATFORM_STRING(env, message); 249 250 if (exception != NULL) { 251 jniLogException(env, priority, "System", exception); 252 } 253} 254 255static jlong System_nanoTime(JNIEnv* env, jclass unused) { 256 struct timespec now; 257 clock_gettime(CLOCK_MONOTONIC, &now); 258 return now.tv_sec * 1000000000LL + now.tv_nsec; 259} 260 261static jlong System_currentTimeMillis(JNIEnv* env, jclass unused) { 262 return JVM_CurrentTimeMillis(NULL, NULL); 263} 264 265static JNINativeMethod gMethods[] = { 266 NATIVE_METHOD(System, mapLibraryName, "(Ljava/lang/String;)Ljava/lang/String;"), 267 NATIVE_METHOD(System, setErr0, "(Ljava/io/PrintStream;)V"), 268 NATIVE_METHOD(System, setOut0, "(Ljava/io/PrintStream;)V"), 269 NATIVE_METHOD(System, setIn0, "(Ljava/io/InputStream;)V"), 270 NATIVE_METHOD(System, specialProperties, "()[Ljava/lang/String;"), 271 NATIVE_METHOD(System, log, "(CLjava/lang/String;Ljava/lang/Throwable;)V"), 272 NATIVE_METHOD(System, currentTimeMillis, "()J"), 273 NATIVE_METHOD(System, nanoTime, "()J"), 274}; 275 276void register_java_lang_System(JNIEnv* env) { 277 jniRegisterNativeMethods(env, "java/lang/System", gMethods, NELEM(gMethods)); 278} 279