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
System_setIn0(JNIEnv * env,jclass cla,jobject stream)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
System_setOut0(JNIEnv * env,jclass cla,jobject stream)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
System_setErr0(JNIEnv * env,jclass cla,jobject stream)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
cpchars(jchar * dst,char * src,int n)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
System_mapLibraryName(JNIEnv * env,jclass ign,jstring libname)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
System_specialProperties(JNIEnv * env,jclass ignored)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
System_log(JNIEnv * env,jclass ignored,jchar type,jstring javaMessage,jthrowable exception)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
System_nanoTime(JNIEnv * env,jclass unused)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
System_currentTimeMillis(JNIEnv * env,jclass unused)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
register_java_lang_System(JNIEnv * env)277 void register_java_lang_System(JNIEnv* env) {
278 jniRegisterNativeMethods(env, "java/lang/System", gMethods, NELEM(gMethods));
279 }
280