1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 /*
17 * Set up values for System.getProperties().
18 */
19 #include "Dalvik.h"
20
21 #include <stdlib.h>
22 #include <sys/utsname.h>
23 #include <limits.h>
24 #include <unistd.h>
25
26 /*
27 * Create some storage for properties read from the command line.
28 */
dvmPropertiesStartup(int maxProps)29 bool dvmPropertiesStartup(int maxProps)
30 {
31 gDvm.maxProps = maxProps;
32 if (maxProps > 0) {
33 gDvm.propList = (char**) malloc(maxProps * sizeof(char*));
34 if (gDvm.propList == NULL)
35 return false;
36 }
37 gDvm.numProps = 0;
38
39 return true;
40 }
41
42 /*
43 * Clean up.
44 */
dvmPropertiesShutdown(void)45 void dvmPropertiesShutdown(void)
46 {
47 int i;
48
49 for (i = 0; i < gDvm.numProps; i++)
50 free(gDvm.propList[i]);
51 free(gDvm.propList);
52 gDvm.propList = NULL;
53 }
54
55 /*
56 * Add a property specified on the command line. "argStr" has the form
57 * "name=value". "name" must have nonzero length.
58 *
59 * Returns "true" if argStr appears valid.
60 */
dvmAddCommandLineProperty(const char * argStr)61 bool dvmAddCommandLineProperty(const char* argStr)
62 {
63 char* mangle;
64 char* equals;
65
66 mangle = strdup(argStr);
67 equals = strchr(mangle, '=');
68 if (equals == NULL || equals == mangle) {
69 free(mangle);
70 return false;
71 }
72 *equals = '\0';
73
74 assert(gDvm.numProps < gDvm.maxProps);
75 gDvm.propList[gDvm.numProps++] = mangle;
76
77 return true;
78 }
79
80
81 /*
82 * Find the "put" method for this class.
83 *
84 * Returns NULL and throws an exception if not found.
85 */
getPut(ClassObject * clazz)86 static Method* getPut(ClassObject* clazz)
87 {
88 Method* put;
89
90 put = dvmFindVirtualMethodHierByDescriptor(clazz, "setProperty",
91 "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
92 if (put == NULL) {
93 dvmThrowException("Ljava/lang/RuntimeException;",
94 "could not find setProperty(String,String) in Properties");
95 /* fall through to return */
96 }
97 return put;
98 }
99
100 /*
101 * Set the value of the property.
102 */
setProperty(Object * propObj,Method * put,const char * key,const char * value)103 static void setProperty(Object* propObj, Method* put, const char* key,
104 const char* value)
105 {
106 StringObject* keyStr;
107 StringObject* valueStr;
108
109 if (value == NULL) {
110 /* unclear what to do; probably want to create prop w/ empty string */
111 value = "";
112 }
113
114 keyStr = dvmCreateStringFromCstr(key);
115 valueStr = dvmCreateStringFromCstr(value);
116 if (keyStr == NULL || valueStr == NULL) {
117 LOGW("setProperty string creation failed\n");
118 goto bail;
119 }
120
121 JValue unused;
122 dvmCallMethod(dvmThreadSelf(), put, propObj, &unused, keyStr, valueStr);
123
124 bail:
125 dvmReleaseTrackedAlloc((Object*) keyStr, NULL);
126 dvmReleaseTrackedAlloc((Object*) valueStr, NULL);
127 }
128
129 /*
130 * Create the VM-default system properties.
131 *
132 * We can do them here, or do them in interpreted code with lots of native
133 * methods to get bits and pieces. This is a bit smaller.
134 */
dvmCreateDefaultProperties(Object * propObj)135 void dvmCreateDefaultProperties(Object* propObj)
136 {
137 Method* put = getPut(propObj->clazz);
138
139 if (put == NULL)
140 return;
141
142 struct utsname info;
143 uname(&info);
144
145 /* constant strings that are used multiple times below */
146 const char *projectUrl = "http://www.android.com/";
147 const char *projectName = "The Android Project";
148
149 /*
150 * These are listed in the docs.
151 */
152
153 setProperty(propObj, put, "java.boot.class.path", gDvm.bootClassPathStr);
154 setProperty(propObj, put, "java.class.path", gDvm.classPathStr);
155 setProperty(propObj, put, "java.class.version", "46.0");
156 setProperty(propObj, put, "java.compiler", "");
157 setProperty(propObj, put, "java.ext.dirs", "");
158
159 if (getenv("JAVA_HOME") != NULL) {
160 setProperty(propObj, put, "java.home", getenv("JAVA_HOME"));
161 } else {
162 setProperty(propObj, put, "java.home", "/system");
163 }
164
165 setProperty(propObj, put, "java.io.tmpdir", "/tmp");
166 setProperty(propObj, put, "java.library.path", getenv("LD_LIBRARY_PATH"));
167
168 setProperty(propObj, put, "java.net.preferIPv6Addresses", "true");
169
170 setProperty(propObj, put, "java.vendor", projectName);
171 setProperty(propObj, put, "java.vendor.url", projectUrl);
172 setProperty(propObj, put, "java.version", "0");
173 setProperty(propObj, put, "java.vm.name", "Dalvik");
174 setProperty(propObj, put, "java.vm.specification.name",
175 "Dalvik Virtual Machine Specification");
176 setProperty(propObj, put, "java.vm.specification.vendor", projectName);
177 setProperty(propObj, put, "java.vm.specification.version", "0.9");
178 setProperty(propObj, put, "java.vm.vendor", projectName);
179
180 char tmpBuf[64];
181 sprintf(tmpBuf, "%d.%d.%d",
182 DALVIK_MAJOR_VERSION, DALVIK_MINOR_VERSION, DALVIK_BUG_VERSION);
183 setProperty(propObj, put, "java.vm.version", tmpBuf);
184
185 setProperty(propObj, put, "java.specification.name",
186 "Dalvik Core Library");
187 setProperty(propObj, put, "java.specification.vendor", projectName);
188 setProperty(propObj, put, "java.specification.version", "0.9");
189
190 setProperty(propObj, put, "os.arch", info.machine);
191 setProperty(propObj, put, "os.name", info.sysname);
192 setProperty(propObj, put, "os.version", info.release);
193 setProperty(propObj, put, "user.home", getenv("HOME"));
194 setProperty(propObj, put, "user.name", getenv("USER"));
195
196 char path[PATH_MAX];
197 setProperty(propObj, put, "user.dir", getcwd(path, sizeof(path)));
198
199 setProperty(propObj, put, "file.separator", "/");
200 setProperty(propObj, put, "line.separator", "\n");
201 setProperty(propObj, put, "path.separator", ":");
202
203 /*
204 * These show up elsewhere, so do them here too.
205 */
206 setProperty(propObj, put, "java.runtime.name", "Android Runtime");
207 setProperty(propObj, put, "java.runtime.version", "0.9");
208 setProperty(propObj, put, "java.vm.vendor.url", projectUrl);
209
210 setProperty(propObj, put, "file.encoding", "UTF-8");
211 setProperty(propObj, put, "user.language", "en");
212 setProperty(propObj, put, "user.region", "US");
213
214 /*
215 * These are unique to Android/Dalvik.
216 */
217 setProperty(propObj, put, "android.vm.dexfile", "true");
218 }
219
220 /*
221 * Add anything specified on the command line.
222 */
dvmSetCommandLineProperties(Object * propObj)223 void dvmSetCommandLineProperties(Object* propObj)
224 {
225 Method* put = getPut(propObj->clazz);
226 int i;
227
228 if (put == NULL)
229 return;
230
231 for (i = 0; i < gDvm.numProps; i++) {
232 const char* value;
233
234 /* value starts after the end of the key string */
235 for (value = gDvm.propList[i]; *value != '\0'; value++)
236 ;
237 setProperty(propObj, put, gDvm.propList[i], value+1);
238 }
239 }
240
241 /*
242 * Get a property by calling System.getProperty(key).
243 *
244 * Returns a newly-allocated string, or NULL on failure or key not found.
245 * (Unexpected failures will also raise an exception.)
246 */
dvmGetProperty(const char * key)247 char* dvmGetProperty(const char* key)
248 {
249 ClassObject* system;
250 Method* getProp;
251 StringObject* keyObj = NULL;
252 StringObject* valueObj;
253 char* result = NULL;
254
255 assert(key != NULL);
256
257 system = dvmFindSystemClass("Ljava/lang/System;");
258 if (system == NULL)
259 goto bail;
260
261 getProp = dvmFindDirectMethodByDescriptor(system, "getProperty",
262 "(Ljava/lang/String;)Ljava/lang/String;");
263 if (getProp == NULL) {
264 LOGW("Could not find getProperty(String) in java.lang.System\n");
265 goto bail;
266 }
267
268 keyObj = dvmCreateStringFromCstr(key);
269 if (keyObj == NULL)
270 goto bail;
271
272 JValue val;
273 dvmCallMethod(dvmThreadSelf(), getProp, NULL, &val, keyObj);
274 valueObj = (StringObject*) val.l;
275 if (valueObj == NULL)
276 goto bail;
277
278 result = dvmCreateCstrFromString(valueObj);
279 /* fall through with result */
280
281 bail:
282 dvmReleaseTrackedAlloc((Object*)keyObj, NULL);
283 return result;
284 }
285