fixed segfault in defineClass
[cacao.git] / src / native / vm / VMClassLoader.c
1 /* native/vm/VMClassLoader.c - java/lang/VMClassLoader
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Roman Obermaiser
28
29    Changes: Joseph Wenninger
30             Christian Thalinger
31
32    $Id: VMClassLoader.c 2188 2005-04-02 01:15:33Z edwin $
33
34 */
35
36
37 #include <sys/stat.h>
38
39 #include "config.h"
40 #include "types.h"
41 #include "mm/memory.h"
42 #include "native/jni.h"
43 #include "native/native.h"
44 #include "native/include/java_lang_Class.h"
45 #include "native/include/java_lang_String.h"
46 #include "native/include/java_lang_ClassLoader.h"
47 #include "native/include/java_security_ProtectionDomain.h"
48 #include "native/include/java_util_Vector.h"
49 #include "toolbox/logging.h"
50 #include "vm/class.h"
51 #include "vm/exceptions.h"
52 #include "vm/builtin.h"
53 #include "vm/loader.h"
54 #include "vm/options.h"
55 #include "vm/statistics.h"
56 #include "vm/stringlocal.h"
57 #include "vm/tables.h"
58 #include "vm/jit/asmpart.h"
59
60
61 /*
62  * Class:     java/lang/VMClassLoader
63  * Method:    defineClass
64  * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;
65  */
66 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_defineClass(JNIEnv *env, jclass clazz, java_lang_ClassLoader *this, java_lang_String *name, java_bytearray *buf, s4 off, s4 len, java_security_ProtectionDomain *pd)
67 {
68         classinfo   *c;
69         classinfo   *r;
70         classbuffer *cb;
71
72         if ((off < 0) || (len < 0) || ((off + len) > buf->header.size)) {
73                 *exceptionptr =
74                         new_exception(string_java_lang_IndexOutOfBoundsException);
75                 return NULL;
76         }
77
78         if (!name) {
79                 /* XXX we have to support this case (name is read from classbuffer) */
80                 log_text("defineClass(name == NULL,...) is not implemented, yet");
81                 *exceptionptr = new_nullpointerexception();
82                 return NULL;
83         }
84
85         /* convert '.' to '/' in java string */
86
87         c = class_new(javastring_toutf(name, true));
88
89 #if defined(USE_THREADS)
90         /* enter a monitor on the class */
91
92         builtin_monitorenter((java_objectheader *) c);
93 #endif
94
95 #if defined(STATISTICS)
96         /* measure time */
97
98         if (getloadingtime)
99                 loadingtime_start();
100 #endif
101
102         /* build a classbuffer with the given data */
103
104         cb = NEW(classbuffer);
105         cb->class = c;
106         cb->size = len;
107         cb->data = (u1 *) &buf->data[off];
108         cb->pos = cb->data - 1;
109
110         /* preset the defining classloader */
111
112         c->classloader = (java_objectheader *) this;
113
114         /* load the class from this buffer */
115
116         r = load_class_from_classbuffer(cb);
117
118         /* free memory */
119
120         FREE(cb, classbuffer);
121
122 #if defined(STATISTICS)
123         /* measure time */
124
125         if (getloadingtime)
126                 loadingtime_stop();
127 #endif
128
129 #if defined(USE_THREADS)
130         /* leave the monitor */
131
132         builtin_monitorexit((java_objectheader *) c);
133 #endif
134
135         /* exception? return! */
136
137         if (!r) {
138                 /* If return value is NULL, we had a problem and the class is not     */
139                 /* loaded. */
140
141                 c->loaded = false;
142
143                 /* now free the allocated memory, otherwise we could ran into a DOS */
144
145                 class_remove(c);
146
147                 return NULL;
148         }
149
150         /* set ProtectionDomain */
151
152         c->pd = pd;
153
154         use_class_as_object(c);
155
156         return (java_lang_Class *) c;
157 }
158
159
160 /*
161  * Class:     java/lang/VMClassLoader
162  * Method:    getPrimitiveClass
163  * Signature: (Ljava/lang/String;)Ljava/lang/Class;
164  */
165 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_getPrimitiveClass(JNIEnv *env, jclass clazz, java_lang_String *type)
166 {
167         classinfo *c;
168         utf       *u;
169
170         u = javastring_toutf(type, false);
171
172         /* illegal primitive classname specified */
173
174         if (!u) {
175                 *exceptionptr = new_exception(string_java_lang_ClassNotFoundException);
176                 return NULL;
177         }
178
179         /* get primitive class */
180
181         c = class_new(u);
182
183         if (!load_class_bootstrap(c) || !class_init(c))
184                 return NULL;
185
186         use_class_as_object(c);
187
188         return (java_lang_Class *) c;
189 }
190
191
192 /*
193  * Class:     java/lang/VMClassLoader
194  * Method:    resolveClass
195  * Signature: (Ljava/lang/Class;)V
196  */
197 JNIEXPORT void JNICALL Java_java_lang_VMClassLoader_resolveClass(JNIEnv *env, jclass clazz, java_lang_Class *c)
198 {
199         classinfo *ci;
200
201         ci = (classinfo *) c;
202
203         if (!ci) {
204                 *exceptionptr = new_nullpointerexception();
205                 return;
206         }
207
208         /* link the class */
209
210         if (!ci->linked)
211                 link_class(ci);
212
213         return;
214 }
215
216
217 /*
218  * Class:     java/lang/VMClassLoader
219  * Method:    loadClass
220  * Signature: (Ljava/lang/String;Z)Ljava/lang/Class;
221  */
222 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_loadClass(JNIEnv *env, jclass clazz, java_lang_String *name, jboolean resolve)
223 {
224         classinfo *c;
225         utf *u;
226
227         if (!name) {
228                 *exceptionptr = new_exception(string_java_lang_NullPointerException);
229                 return NULL;
230         }
231
232         /* create utf string in which '.' is replaced by '/' */
233
234         u = javastring_toutf(name, true);
235
236         /* create class */
237
238         c = class_new(u);
239
240         /* load class */
241
242         if (!load_class_bootstrap(c))
243                 goto exception;
244
245         /* resolve class -- if requested */
246         /* XXX TWISTI: we do not support REAL (at runtime) lazy linking */
247 /*      if (resolve) { */
248                 if (!link_class(c))
249                         goto exception;
250
251                 use_class_as_object(c);
252 /*      } */
253
254         return (java_lang_Class *) c;
255
256  exception:
257         c = (*exceptionptr)->vftbl->class;
258         
259         /* if the exception is a NoClassDefFoundError, we replace it with a
260            ClassNotFoundException, otherwise return the exception */
261
262         if (c == class_java_lang_NoClassDefFoundError) {
263                 /* clear exceptionptr, because builtin_new checks for 
264                    ExceptionInInitializerError */
265                 *exceptionptr = NULL;
266
267                 *exceptionptr =
268                         new_exception_javastring(string_java_lang_ClassNotFoundException, name);
269         }
270
271         return NULL;
272 }
273
274
275 /*
276  * Class:     java/lang/VMClassLoader
277  * Method:    nativeGetResources
278  * Signature: (Ljava/lang/String;)Ljava/util/Vector;
279  */
280 JNIEXPORT java_util_Vector* JNICALL Java_java_lang_VMClassLoader_nativeGetResources(JNIEnv *env, jclass clazz, java_lang_String *name)
281 {
282         jobject           o;
283         methodinfo       *m;
284         java_lang_String *path;
285         classpath_info   *cpi;
286         utf              *utfname;
287         char             *charname;
288         char             *tmppath;
289         s4                namelen;
290         s4                pathlen;
291         struct stat       buf;
292         jboolean          ret;
293
294         /* get the resource name as utf string */
295
296         utfname = javastring_toutf(name, false);
297
298         namelen = utf_strlen(utfname) + strlen("0");
299         charname = MNEW(char, namelen);
300
301         utf_sprint(charname, utfname);
302
303         /* new Vector() */
304
305         o = native_new_and_init(class_java_util_Vector);
306
307         if (!o)
308                 return NULL;
309
310         /* get v.add() method */
311
312         m = class_resolveclassmethod(class_java_util_Vector,
313                                                                  utf_new_char("add"),
314                                                                  utf_new_char("(Ljava/lang/Object;)Z"),
315                                                                  NULL,
316                                                                  true);
317
318         if (!m)
319                 return NULL;
320
321         for (cpi = classpath_entries; cpi != NULL; cpi = cpi->next) {
322                 /* clear path pointer */
323                 path = NULL;
324
325 #if defined(USE_ZLIB)
326                 if (cpi->type == CLASSPATH_ARCHIVE) {
327
328 #if defined(USE_THREADS)
329                         /* enter a monitor on zip/jar archives */
330
331                         builtin_monitorenter((java_objectheader *) cpi);
332 #endif
333
334                         if (cacao_locate(cpi->uf, utfname) == UNZ_OK) {
335                                 pathlen = strlen("jar:file://") + cpi->pathlen + strlen("!/") +
336                                         namelen + strlen("0");
337
338                                 tmppath = MNEW(char, pathlen);
339
340                                 sprintf(tmppath, "jar:file://%s!/%s", cpi->path, charname);
341                                 path = javastring_new_char(tmppath),
342
343                                 MFREE(tmppath, char, pathlen);
344                         }
345
346 #if defined(USE_THREADS)
347                         /* leave the monitor */
348
349                         builtin_monitorexit((java_objectheader *) cpi);
350 #endif
351
352                 } else {
353 #endif /* defined(USE_ZLIB) */
354                         pathlen = strlen("file://") + cpi->pathlen + namelen + strlen("0");
355
356                         tmppath = MNEW(char, pathlen);
357
358                         sprintf(tmppath, "file://%s%s", cpi->path, charname);
359
360                         if (stat(tmppath + strlen("file://") - 1, &buf) == 0)
361                                 path = javastring_new_char(tmppath),
362
363                         MFREE(tmppath, char, pathlen);
364 #if defined(USE_ZLIB)
365                 }
366 #endif
367
368                 /* if a resource was found, add it to the vector */
369
370                 if (path) {
371                         ret = (jboolean) asm_calljavafunction_int(m, o, path, NULL, NULL);
372
373                         if (!ret)
374                                 return NULL;
375                 }
376         }
377
378         return (java_util_Vector *) o;
379 }
380
381
382 /*
383  * These are local overrides for various environment variables in Emacs.
384  * Please do not remove this and leave it at the end of the file, where
385  * Emacs will automagically detect them.
386  * ---------------------------------------------------------------------
387  * Local variables:
388  * mode: c
389  * indent-tabs-mode: t
390  * c-basic-offset: 4
391  * tab-width: 4
392  * End:
393  */