Home | History | Annotate | Download | only in native
      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__)
     42 void 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  */
    109 JNIEXPORT void JNICALL
    110 System_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 
    119 JNIEXPORT void JNICALL
    120 System_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 
    129 JNIEXPORT void JNICALL
    130 System_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 
    139 static 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 
    147 JNIEXPORT jstring JNICALL
    148 System_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 
    173 static 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 
    233 static 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 
    255 static 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 
    261 static jlong System_currentTimeMillis(JNIEnv* env, jclass unused) {
    262   return JVM_CurrentTimeMillis(NULL, NULL);
    263 }
    264 
    265 static 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 
    276 void register_java_lang_System(JNIEnv* env) {
    277   jniRegisterNativeMethods(env, "java/lang/System", gMethods, NELEM(gMethods));
    278 }
    279