OSDN Git Service

Test and fix for the ArrayList.addAll(), bug 2954.
[android-x86/dalvik.git] / vm / Properties.c
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  */
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  */
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  */
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  */
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  */
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, ALLOC_DEFAULT);
115     valueStr = dvmCreateStringFromCstr(value, ALLOC_DEFAULT);
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  */
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.vendor", projectName);
169     setProperty(propObj, put, "java.vendor.url", projectUrl);
170     setProperty(propObj, put, "java.version", "0");
171     setProperty(propObj, put, "java.vm.name", "Dalvik");
172     setProperty(propObj, put, "java.vm.specification.name",
173             "Dalvik Virtual Machine Specification");
174     setProperty(propObj, put, "java.vm.specification.vendor", projectName);
175     setProperty(propObj, put, "java.vm.specification.version", "0.9");
176     setProperty(propObj, put, "java.vm.vendor", projectName);
177
178     char tmpBuf[64];
179     sprintf(tmpBuf, "%d.%d.%d",
180         DALVIK_MAJOR_VERSION, DALVIK_MINOR_VERSION, DALVIK_BUG_VERSION);
181     setProperty(propObj, put, "java.vm.version", tmpBuf);
182
183     setProperty(propObj, put, "java.specification.name",
184             "Dalvik Core Library");
185     setProperty(propObj, put, "java.specification.vendor", projectName);
186     setProperty(propObj, put, "java.specification.version", "0.9");
187
188     #define OS_ARCH generic /* TODO: Use an "arch" header. */
189     #define OS_ARCH_QUOTE(x) #x
190     setProperty(propObj, put, "os.arch", OS_ARCH_QUOTE(OS_ARCH));
191     #undef OS_ARCH
192     #undef OS_ARCH_QUOTE
193
194     setProperty(propObj, put, "os.name", info.sysname);
195     setProperty(propObj, put, "os.version", info.release);
196     setProperty(propObj, put, "user.home", getenv("HOME"));
197     setProperty(propObj, put, "user.name", getenv("USER"));
198
199     char path[PATH_MAX];
200     setProperty(propObj, put, "user.dir", getcwd(path, sizeof(path)));
201
202     setProperty(propObj, put, "file.separator", "/");
203     setProperty(propObj, put, "line.separator", "\n");
204     setProperty(propObj, put, "path.separator", ":");
205     
206     /*
207      * These show up elsewhere, so do them here too.
208      */
209     setProperty(propObj, put, "java.runtime.name", "Android Runtime");
210     setProperty(propObj, put, "java.runtime.version", "0.9");
211     setProperty(propObj, put, "java.vm.vendor.url", projectUrl);
212
213     setProperty(propObj, put, "file.encoding", "UTF-8");
214     setProperty(propObj, put, "user.language", "en");
215     setProperty(propObj, put, "user.region", "US");
216
217     /*
218      * These are unique to Android/Dalvik.
219      */
220     setProperty(propObj, put, "android.vm.dexfile", "true");
221 }
222
223 /*
224  * Add anything specified on the command line.
225  */
226 void dvmSetCommandLineProperties(Object* propObj)
227 {
228     Method* put = getPut(propObj->clazz);
229     int i;
230
231     if (put == NULL)
232         return;
233
234     for (i = 0; i < gDvm.numProps; i++) {
235         const char* value;
236
237         /* value starts after the end of the key string */
238         for (value = gDvm.propList[i]; *value != '\0'; value++)
239             ;
240         setProperty(propObj, put, gDvm.propList[i], value+1);
241     }
242 }
243
244 /*
245  * Get a property by calling System.getProperty(key).
246  *
247  * Returns a newly-allocated string, or NULL on failure or key not found.
248  * (Unexpected failures will also raise an exception.)
249  */
250 char* dvmGetProperty(const char* key)
251 {
252     ClassObject* system;
253     Method* getProp;
254     StringObject* keyObj = NULL;
255     StringObject* valueObj;
256     char* result = NULL;
257
258     assert(key != NULL);
259
260     system = dvmFindSystemClass("Ljava/lang/System;");
261     if (system == NULL)
262         goto bail;
263
264     getProp = dvmFindDirectMethodByDescriptor(system, "getProperty",
265         "(Ljava/lang/String;)Ljava/lang/String;");
266     if (getProp == NULL) {
267         LOGW("Could not find getProperty(String) in java.lang.System\n");
268         goto bail;
269     }
270
271     keyObj = dvmCreateStringFromCstr(key, ALLOC_DEFAULT);
272     if (keyObj == NULL)
273         goto bail;
274
275     JValue val;
276     dvmCallMethod(dvmThreadSelf(), getProp, NULL, &val, keyObj);
277     valueObj = (StringObject*) val.l;
278     if (valueObj == NULL)
279         goto bail;
280
281     result = dvmCreateCstrFromString(valueObj);
282     /* fall through with result */
283
284 bail:
285     dvmReleaseTrackedAlloc((Object*)keyObj, NULL);
286     return result;
287 }
288