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/*
18 * java.lang.VMClassLoader
19 */
20#include "Dalvik.h"
21#include "native/InternalNativePriv.h"
22
23
24/*
25 * static Class defineClass(ClassLoader cl, String name,
26 *     byte[] data, int offset, int len, ProtectionDomain pd)
27 *     throws ClassFormatError
28 *
29 * Convert an array of bytes to a Class object.
30 */
31static void Dalvik_java_lang_VMClassLoader_defineClass(const u4* args,
32    JValue* pResult)
33{
34    Object* loader = (Object*) args[0];
35    StringObject* nameObj = (StringObject*) args[1];
36    const u1* data = (const u1*) args[2];
37    int offset = args[3];
38    int len = args[4];
39    Object* pd = (Object*) args[5];
40    char* name = NULL;
41
42    name = dvmCreateCstrFromString(nameObj);
43    LOGE("ERROR: defineClass(%p, %s, %p, %d, %d, %p)\n",
44        loader, name, data, offset, len, pd);
45    dvmThrowException("Ljava/lang/UnsupportedOperationException;",
46        "can't load this type of class file");
47
48    free(name);
49    RETURN_VOID();
50}
51
52/*
53 * static Class defineClass(ClassLoader cl, byte[] data, int offset,
54 *     int len, ProtectionDomain pd)
55 *     throws ClassFormatError
56 *
57 * Convert an array of bytes to a Class object. Deprecated version of
58 * previous method, lacks name parameter.
59 */
60static void Dalvik_java_lang_VMClassLoader_defineClass2(const u4* args,
61    JValue* pResult)
62{
63    Object* loader = (Object*) args[0];
64    const u1* data = (const u1*) args[1];
65    int offset = args[2];
66    int len = args[3];
67    Object* pd = (Object*) args[4];
68
69    LOGE("ERROR: defineClass(%p, %p, %d, %d, %p)\n",
70        loader, data, offset, len, pd);
71    dvmThrowException("Ljava/lang/UnsupportedOperationException;",
72        "can't load this type of class file");
73
74    RETURN_VOID();
75}
76
77/*
78 * static Class findLoadedClass(ClassLoader cl, String name)
79 */
80static void Dalvik_java_lang_VMClassLoader_findLoadedClass(const u4* args,
81    JValue* pResult)
82{
83    Object* loader = (Object*) args[0];
84    StringObject* nameObj = (StringObject*) args[1];
85    ClassObject* clazz = NULL;
86    char* name = NULL;
87    char* descriptor = NULL;
88
89    if (nameObj == NULL) {
90        dvmThrowException("Ljava/lang/NullPointerException;", NULL);
91        goto bail;
92    }
93
94    /*
95     * Get a UTF-8 copy of the string, and convert dots to slashes.
96     */
97    name = dvmCreateCstrFromString(nameObj);
98    if (name == NULL)
99        goto bail;
100
101    descriptor = dvmDotToDescriptor(name);
102    if (descriptor == NULL)
103        goto bail;
104
105    clazz = dvmLookupClass(descriptor, loader, false);
106    LOGVV("look: %s ldr=%p --> %p\n", descriptor, loader, clazz);
107
108bail:
109    free(name);
110    free(descriptor);
111    RETURN_PTR(clazz);
112}
113
114/*
115 * private static int getBootClassPathSize()
116 *
117 * Get the number of entries in the boot class path.
118 */
119static void Dalvik_java_lang_VMClassLoader_getBootClassPathSize(const u4* args,
120    JValue* pResult)
121{
122    int count = dvmGetBootPathSize();
123    RETURN_INT(count);
124}
125
126/*
127 * private static String getBootClassPathResource(String name, int index)
128 *
129 * Find a resource with a matching name in a boot class path entry.
130 *
131 * This mimics the previous VM interface, since we're sharing class libraries.
132 */
133static void Dalvik_java_lang_VMClassLoader_getBootClassPathResource(
134    const u4* args, JValue* pResult)
135{
136    StringObject* nameObj = (StringObject*) args[0];
137    StringObject* result;
138    int idx = args[1];
139    char* name;
140
141    name = dvmCreateCstrFromString(nameObj);
142    if (name == NULL)
143        RETURN_PTR(NULL);
144
145    result = dvmGetBootPathResource(name, idx);
146    free(name);
147    dvmReleaseTrackedAlloc((Object*)result, NULL);
148    RETURN_PTR(result);
149}
150
151/*
152 * static final Class getPrimitiveClass(char prim_type)
153 */
154static void Dalvik_java_lang_VMClassLoader_getPrimitiveClass(const u4* args,
155    JValue* pResult)
156{
157    int primType = args[0];
158
159    pResult->l = dvmFindPrimitiveClass(primType);
160}
161
162/*
163 * static Class loadClass(String name, boolean resolve)
164 *     throws ClassNotFoundException
165 *
166 * Load class using bootstrap class loader.
167 *
168 * Return the Class object associated with the class or interface with
169 * the specified name.
170 *
171 * "name" is in "binary name" format, e.g. "dalvik.system.Debug$1".
172 */
173static void Dalvik_java_lang_VMClassLoader_loadClass(const u4* args,
174    JValue* pResult)
175{
176    StringObject* nameObj = (StringObject*) args[0];
177    bool resolve = (args[1] != 0);
178    ClassObject* clazz;
179
180    clazz = dvmFindClassByName(nameObj, NULL, resolve);
181    assert(clazz == NULL || dvmIsClassLinked(clazz));
182    RETURN_PTR(clazz);
183}
184
185const DalvikNativeMethod dvm_java_lang_VMClassLoader[] = {
186    { "defineClass",        "(Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;",
187        Dalvik_java_lang_VMClassLoader_defineClass },
188    { "defineClass",        "(Ljava/lang/ClassLoader;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;",
189        Dalvik_java_lang_VMClassLoader_defineClass2 },
190    { "findLoadedClass",    "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;",
191        Dalvik_java_lang_VMClassLoader_findLoadedClass },
192    { "getBootClassPathSize", "()I",
193        Dalvik_java_lang_VMClassLoader_getBootClassPathSize },
194    { "getBootClassPathResource", "(Ljava/lang/String;I)Ljava/lang/String;",
195        Dalvik_java_lang_VMClassLoader_getBootClassPathResource },
196    { "getPrimitiveClass",  "(C)Ljava/lang/Class;",
197        Dalvik_java_lang_VMClassLoader_getPrimitiveClass },
198    { "loadClass",          "(Ljava/lang/String;Z)Ljava/lang/Class;",
199        Dalvik_java_lang_VMClassLoader_loadClass },
200    { NULL, NULL, NULL },
201};
202