2008-01-29 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / metadata / exception.c
1 /*
2  * exception.c: Exception handling
3  *
4  * Authors:
5  *      Paolo Molaro    (lupus@ximian.com)
6  *      Dietmar Maurer  (dietmar@ximian.com)
7  *      Dick Porter     (dick@ximian.com)
8  *      Miguel de Icaza (miguel@ximian.com)
9  *
10  * (C) 2001, 2002 Ximian, Inc.
11  */
12
13 #include <mono/metadata/exception.h>
14 #include <mono/metadata/object-internals.h>
15 #include <mono/metadata/appdomain.h>
16 #include <string.h>
17
18 /**
19  * mono_exception_from_name:
20  * @image: the Mono image where to look for the class
21  * @name_space: the namespace for the class
22  * @name: class name
23  *
24  * Creates an exception of the given namespace/name class in the
25  * current domain.
26  *
27  * Returns: the initialized exception instance.
28  */
29 MonoException *
30 mono_exception_from_name (MonoImage *image, const char *name_space,
31                           const char *name)
32 {
33         return mono_exception_from_name_domain (mono_domain_get (), image, name_space, name);
34 }
35
36 /**
37  * mono_exception_from_name_domain:
38  * @domain: Domain where the return object will be created.
39  * @image: the Mono image where to look for the class
40  * @name_space: the namespace for the class
41  * @name: class name
42  *
43  * Creates an exception object of the given namespace/name class on
44  * the given domain.
45  *
46  * Returns: the initialized exception instance.
47  */
48 MonoException *
49 mono_exception_from_name_domain (MonoDomain *domain, MonoImage *image, 
50                                  const char* name_space, const char *name)
51 {
52         MonoClass *klass;
53         MonoObject *o;
54
55         klass = mono_class_from_name (image, name_space, name);
56
57         o = mono_object_new (domain, klass);
58         g_assert (o != NULL);
59         
60         mono_runtime_object_init (o);
61
62         return (MonoException *)o;
63 }
64
65
66 /**
67  * mono_exception_from_token:
68  * @image: the Mono image where to look for the class
69  * @token: The type token of the class
70  *
71  * Creates an exception of the type given by @token.
72  *
73  * Returns: the initialized exception instance.
74  */
75 MonoException *
76 mono_exception_from_token (MonoImage *image, guint32 token)
77 {
78         MonoClass *klass;
79         MonoObject *o;
80
81         klass = mono_class_get (image, token);
82
83         o = mono_object_new (mono_domain_get (), klass);
84         g_assert (o != NULL);
85         
86         mono_runtime_object_init (o);
87
88         return (MonoException *)o;
89 }
90
91 /**
92  * mono_exception_from_name_two_strings:
93  * @image: the Mono image where to look for the class
94  * @name_space: the namespace for the class
95  * @name: class name
96  * @a1: first string argument to pass
97  * @a2: second string argument to pass
98  *
99  * Creates an exception from a constructor that takes two string
100  * arguments.
101  *
102  * Returns: the initialized exception instance.
103  */
104 MonoException *
105 mono_exception_from_name_two_strings (MonoImage *image, const char *name_space,
106                                       const char *name, MonoString *a1, MonoString *a2)
107 {
108         MonoDomain *domain = mono_domain_get ();
109         MonoClass *klass;
110         MonoMethod *method = NULL;
111         MonoObject *o;
112         int count = 1;
113         gpointer args [2];
114         gpointer iter;
115         MonoMethod *m;
116
117         if (a2 != NULL)
118                 count++;
119         
120         klass = mono_class_from_name (image, name_space, name);
121         o = mono_object_new (domain, klass);
122
123         iter = NULL;
124         while ((m = mono_class_get_methods (klass, &iter))) {
125                 MonoMethodSignature *sig;
126                 
127                 if (strcmp (".ctor", mono_method_get_name (m)))
128                         continue;
129                 sig = mono_method_signature (m);
130                 if (sig->param_count != count)
131                         continue;
132
133                 if (sig->params [0]->type != MONO_TYPE_STRING)
134                         continue;
135                 if (count == 2 && sig->params [1]->type != MONO_TYPE_STRING)
136                         continue;
137                 method = m;
138                 break;
139         }
140
141         args [0] = a1;
142         args [1] = a2;
143         mono_runtime_invoke (method, o, args, NULL);
144         return (MonoException *) o;
145 }
146
147 /**
148  * mono_exception_from_name_msg:
149  * @image: the Mono image where to look for the class
150  * @name_space: the namespace for the class
151  * @name: class name
152  * @msg: the message to embed inside the exception
153  *
154  * Creates an exception and initializes its message field.
155  *
156  * Returns: the initialized exception instance.
157  */
158 MonoException *
159 mono_exception_from_name_msg (MonoImage *image, const char *name_space,
160                               const char *name, const char *msg)
161 {
162         MonoException *ex;
163
164         ex = mono_exception_from_name (image, name_space, name);
165
166         if (msg)
167                 MONO_OBJECT_SETREF (ex, message, mono_string_new (mono_object_get_domain ((MonoObject*)ex), msg));
168
169         return ex;
170 }
171
172 /**
173  * mono_get_exception_divide_by_zero:
174  *
175  * Returns: a new instance of the System.DivideByZeroException
176  */
177 MonoException *
178 mono_get_exception_divide_by_zero ()
179 {
180         return mono_exception_from_name (mono_get_corlib (), "System",
181                                          "DivideByZeroException");
182 }
183
184 /**
185  * mono_get_exception_security:
186  *
187  * Returns: a new instance of the System.Security.SecurityException
188  */
189 MonoException *
190 mono_get_exception_security ()
191 {
192         return mono_exception_from_name (mono_get_corlib (), "System.Security",
193                                          "SecurityException");
194 }
195
196 /**
197  * mono_get_exception_thread_abort:
198  *
199  * Returns: a new instance of the System.Threading.ThreadAbortException.
200  */
201 MonoException *
202 mono_get_exception_thread_abort ()
203 {
204         return mono_exception_from_name (mono_get_corlib (), "System.Threading",
205                                          "ThreadAbortException");
206 }
207
208 /**
209  * mono_get_exception_thread_interrupted:
210  *
211  * Returns: a new instance of the System.Threading.ThreadInterruptedException.
212  */
213 MonoException *
214 mono_get_exception_thread_interrupted ()
215 {
216         return mono_exception_from_name (mono_get_corlib (), "System.Threading",
217                                          "ThreadInterruptedException");
218 }
219
220 /**
221  * mono_get_exception_arithmetic:
222  *
223  * Returns: a new instance of the System.ArithmeticException.
224  */
225 MonoException *
226 mono_get_exception_arithmetic ()
227 {
228         return mono_exception_from_name (mono_get_corlib (), "System",
229                                          "ArithmeticException");
230 }
231
232 /**
233  * mono_get_exception_overflow:
234  *
235  * Returns: a new instance of the System.OverflowException
236  */
237 MonoException *
238 mono_get_exception_overflow ()
239 {
240         return mono_exception_from_name (mono_get_corlib (), "System",
241                                          "OverflowException");
242 }
243
244 /**
245  * mono_get_exception_null_reference:
246  *
247  * Returns: a new instance of the System.NullReferenceException
248  */
249 MonoException *
250 mono_get_exception_null_reference ()
251 {
252         return mono_exception_from_name (mono_get_corlib (), "System",
253                                          "NullReferenceException");
254 }
255
256 /**
257  * mono_get_exception_execution_engine:
258  * @msg: the message to pass to the user
259  *
260  * Returns: a new instance of the System.ExecutionEngineException
261  */
262 MonoException *
263 mono_get_exception_execution_engine (const char *msg)
264 {
265         return mono_exception_from_name_msg (mono_get_corlib (), "System", "ExecutionEngineException", msg);
266 }
267
268 /**
269  * mono_get_exception_serialization:
270  * @msg: the message to pass to the user
271  *
272  * Returns: a new instance of the System.Runtime.Serialization.SerializationException
273  */
274 MonoException *
275 mono_get_exception_serialization (const char *msg)
276 {
277         return mono_exception_from_name_msg (mono_get_corlib (), "System.Runtime.Serialization", "SerializationException", msg);
278 }
279
280 /**
281  * mono_get_exception_invalid_cast:
282  *
283  * Returns: a new instance of the System.InvalidCastException
284  */
285 MonoException *
286 mono_get_exception_invalid_cast ()
287 {
288         return mono_exception_from_name (mono_get_corlib (), "System", "InvalidCastException");
289 }
290
291 /**
292  * mono_get_exception_invalid_operation:
293  * @msg: the message to pass to the user
294  *
295  * Returns: a new instance of the System.InvalidOperationException
296  */
297 MonoException *
298 mono_get_exception_invalid_operation (const char *msg)
299 {
300         return mono_exception_from_name_msg (mono_get_corlib (), "System",
301                                         "InvalidOperationException", msg);
302 }
303
304 /**
305  * mono_get_exception_index_out_of_range:
306  *
307  * Returns: a new instance of the System.IndexOutOfRangeException
308  */
309 MonoException *
310 mono_get_exception_index_out_of_range ()
311 {
312         return mono_exception_from_name (mono_get_corlib (), "System",
313                                          "IndexOutOfRangeException");
314 }
315
316 /**
317  * mono_get_exception_array_type_mismatch:
318  *
319  * Returns: a new instance of the System.ArrayTypeMismatchException
320  */
321 MonoException *
322 mono_get_exception_array_type_mismatch ()
323 {
324         return mono_exception_from_name (mono_get_corlib (), "System",
325                                          "ArrayTypeMismatchException");
326 }
327
328 /**
329  * mono_get_exception_type_load:
330  * @class_name: the name of the class that could not be loaded
331  * @assembly_name: the assembly where the class was looked up.
332  *
333  * Returns: a new instance of the System.TypeLoadException.
334  */
335 MonoException *
336 mono_get_exception_type_load (MonoString *class_name, char *assembly_name)
337 {
338         MonoString *s = assembly_name ? mono_string_new (mono_domain_get (), assembly_name) : mono_string_new (mono_domain_get (), "");
339
340         return mono_exception_from_name_two_strings (mono_get_corlib (), "System",
341                                                      "TypeLoadException", class_name, s);
342 }
343
344 /**
345  * mono_get_exception_not_implemented:
346  * @msg: the message to pass to the user
347  *
348  * Returns: a new instance of the System.NotImplementedException
349  */
350 MonoException *
351 mono_get_exception_not_implemented (const char *msg)
352 {
353         return mono_exception_from_name_msg (mono_get_corlib (), "System", "NotImplementedException", msg);
354 }
355
356 /**
357  * mono_get_exception_not_supported:
358  * @msg: the message to pass to the user
359  *
360  * Returns: a new instance of the System.NotSupportedException
361  */
362 MonoException *
363 mono_get_exception_not_supported (const char *msg)
364 {
365         return mono_exception_from_name_msg (mono_get_corlib (), "System", "NotSupportedException", msg);
366 }
367
368 /**
369  * mono_get_exception_missing_method:
370  * @class_name: the class where the lookup was performed.
371  * @member_name: the name of the missing method.
372  *
373  * Returns: a new instance of the System.MissingMethodException
374  */
375 MonoException *
376 mono_get_exception_missing_method (const char *class_name, const char *member_name)
377 {
378         MonoString *s1 = mono_string_new (mono_domain_get (), class_name);
379         MonoString *s2 = mono_string_new (mono_domain_get (), member_name);
380
381         return mono_exception_from_name_two_strings (mono_get_corlib (), "System",
382                                                      "MissingMethodException", s1, s2);
383 }
384
385 /**
386  * mono_get_exception_missing_field:
387  * @class_name: the class where the lookup was performed
388  * @member_name: the name of the missing method.
389  *
390  * Returns: a new instance of the System.MissingFieldException
391  */
392 MonoException *
393 mono_get_exception_missing_field (const char *class_name, const char *member_name)
394 {
395         MonoString *s1 = mono_string_new (mono_domain_get (), class_name);
396         MonoString *s2 = mono_string_new (mono_domain_get (), member_name);
397
398         return mono_exception_from_name_two_strings (mono_get_corlib (), "System",
399                                                      "MissingFieldException", s1, s2);
400 }
401
402 /**
403  * mono_get_exception_argument_null:
404  * @arg: the name of the argument that is null
405  *
406  * Returns: a new instance of the System.ArgumentNullException
407  */
408 MonoException*
409 mono_get_exception_argument_null (const char *arg)
410 {
411         MonoException *ex;
412
413         ex = mono_exception_from_name ( 
414                 mono_get_corlib (), "System", "ArgumentNullException");
415
416         if (arg) {
417                 MonoArgumentException *argex = (MonoArgumentException *)ex;
418                 MONO_OBJECT_SETREF (argex, param_name, mono_string_new (mono_object_get_domain ((MonoObject*)ex), arg));
419         }
420         
421         return ex;
422 }
423
424 /**
425  * mono_get_exception_argument:
426  * @arg: the name of the invalid argument.
427  *
428  * Returns: a new instance of the System.ArgumentException
429  */
430 MonoException *
431 mono_get_exception_argument (const char *arg, const char *msg)
432 {
433         MonoException *ex;
434
435         ex = mono_exception_from_name_msg (
436                 mono_get_corlib (), "System", "ArgumentException", msg);
437
438         if (arg) {
439                 MonoArgumentException *argex = (MonoArgumentException *)ex;
440                 MONO_OBJECT_SETREF (argex, param_name, mono_string_new (mono_object_get_domain ((MonoObject*)ex), arg));
441         }
442         
443         return ex;
444 }
445
446 /**
447  * mono_get_exception_argument_out_of_range:
448  * @arg: the name of the out of range argument.
449  *
450  * Returns: a new instance of the System.ArgumentOutOfRangeException
451  */
452 MonoException *
453 mono_get_exception_argument_out_of_range (const char *arg)
454 {
455         MonoException *ex;
456
457         ex = mono_exception_from_name (
458                 mono_get_corlib (), "System", "ArgumentOutOfRangeException");
459
460         if (arg) {
461                 MonoArgumentException *argex = (MonoArgumentException *)ex;
462                 MONO_OBJECT_SETREF (argex, param_name, mono_string_new (mono_object_get_domain ((MonoObject*)ex), arg));
463         }
464         
465         return ex;
466 }
467
468 /**
469  * mono_get_exception_thread_state:
470  * @msg: the message to present to the user
471  *
472  * Returns: a new instance of the System.Threading.ThreadStateException
473  */
474 MonoException *
475 mono_get_exception_thread_state (const char *msg)
476 {
477         return mono_exception_from_name_msg (
478                 mono_get_corlib (), "System.Threading", "ThreadStateException", msg);
479 }
480
481 /**
482  * mono_get_exception_io:
483  * @msg: the message to present to the user
484  *
485  * Returns: a new instance of the System.IO.IOException
486  */
487 MonoException *
488 mono_get_exception_io (const char *msg)
489 {
490         return mono_exception_from_name_msg ( 
491                 mono_get_corlib (), "System.IO", "IOException", msg);
492 }
493
494 /**
495  * mono_get_exception_file_not_found:
496  * @fname: the name of the file not found.
497  *
498  * Returns: a new instance of the System.IO.FileNotFoundException
499  */
500 MonoException *
501 mono_get_exception_file_not_found (MonoString *fname)
502 {
503         return mono_exception_from_name_two_strings (
504                 mono_get_corlib (), "System.IO", "FileNotFoundException", fname, fname);
505 }
506
507 /**
508  * mono_get_exception_file_not_found2:
509  * @msg: an informative message for the user.
510  * @fname: the name of the file not found.
511  *
512  * Returns: a new instance of the System.IO.FileNotFoundException
513  */
514 MonoException *
515 mono_get_exception_file_not_found2 (const char *msg, MonoString *fname)
516 {
517         MonoString *s = msg ? mono_string_new (mono_domain_get (), msg) : NULL;
518
519         return mono_exception_from_name_two_strings (
520                 mono_get_corlib (), "System.IO", "FileNotFoundException", s, fname);
521 }
522
523 /**
524  * mono_get_exception_type_initialization:
525  * @type_name: the name of the type that failed to initialize.
526  * @inner: the inner exception.
527  *
528  * Returns: a new instance of the System.TypeInitializationException
529  */
530 MonoException *
531 mono_get_exception_type_initialization (const gchar *type_name, MonoException *inner)
532 {
533         MonoClass *klass;
534         gpointer args [2];
535         MonoObject *exc;
536         MonoMethod *method;
537         gpointer iter;
538
539         klass = mono_class_from_name (mono_get_corlib (), "System", "TypeInitializationException");
540         g_assert (klass);
541
542         mono_class_init (klass);
543
544         /* TypeInitializationException only has 1 ctor with 2 args */
545         iter = NULL;
546         while ((method = mono_class_get_methods (klass, &iter))) {
547                 if (!strcmp (".ctor", mono_method_get_name (method)) && mono_method_signature (method)->param_count == 2)
548                         break;
549                 method = NULL;
550         }
551
552         g_assert (method);
553
554         args [0] = mono_string_new (mono_domain_get (), type_name);
555         args [1] = inner;
556
557         exc = mono_object_new (mono_domain_get (), klass);
558         mono_runtime_invoke (method, exc, args, NULL);
559
560         return (MonoException *) exc;
561 }
562
563 /**
564  * mono_get_exception_synchronization_lock:
565  * @inner: the inner exception.
566  *
567  * Returns: a new instance of the System.TypeInitializationException
568  */
569 MonoException *
570 mono_get_exception_synchronization_lock (const char *msg)
571 {
572         return mono_exception_from_name_msg (mono_get_corlib (), "System.Threading", "SynchronizationLockException", msg);
573 }
574
575 /**
576  * mono_get_exception_cannot_unload_appdomain:
577  * @inner: the inner exception.
578  *
579  * Returns: a new instance of the System.CannotUnloadAppDomainException
580  */
581 MonoException *
582 mono_get_exception_cannot_unload_appdomain (const char *msg)
583 {
584         return mono_exception_from_name_msg (mono_get_corlib (), "System", "CannotUnloadAppDomainException", msg);
585 }
586
587 /**
588  * mono_get_exception_appdomain_unloaded
589  *
590  * Returns: a new instance of the System.AppDomainUnloadedException
591  */
592 MonoException *
593 mono_get_exception_appdomain_unloaded (void)
594 {
595         return mono_exception_from_name (mono_get_corlib (), "System", "AppDomainUnloadedException");
596 }
597
598 /**
599  * mono_get_exception_bad_image_format:
600  * @msg: an informative message for the user.
601  *
602  * Returns: a new instance of the System.BadImageFormatException
603  */
604 MonoException *
605 mono_get_exception_bad_image_format (const char *msg)
606 {
607         return mono_exception_from_name_msg (mono_get_corlib (), "System", "BadImageFormatException", msg);
608 }       
609
610 /**
611  * mono_get_exception_bad_image_format2:
612  * @msg: an informative message for the user.
613  * @fname: The full name of the file with the invalid image.
614  *
615  * Returns: a new instance of the System.BadImageFormatException
616  */
617 MonoException *
618 mono_get_exception_bad_image_format2 (const char *msg, MonoString *fname)
619 {
620         MonoString *s = msg ? mono_string_new (mono_domain_get (), msg) : NULL;
621
622         return mono_exception_from_name_two_strings (
623                 mono_get_corlib (), "System", "BadImageFormatException", s, fname);
624 }
625
626 /**
627  * mono_get_exception_stack_overflow:
628  *
629  * Returns: a new instance of the System.StackOverflowException
630  */
631 MonoException *
632 mono_get_exception_stack_overflow (void)
633 {
634         return mono_exception_from_name (mono_get_corlib (), "System", "StackOverflowException");       
635 }
636
637 /**
638  * mono_get_exception_out_of_memory:
639  *
640  * Returns: a new instance of the System.OutOfMemoryException
641  */
642 MonoException *
643 mono_get_exception_out_of_memory (void)
644 {
645         return mono_exception_from_name (mono_get_corlib (), "System", "OutOfMemoryException");
646 }
647
648 /**
649  * mono_get_exception_reflection_type_load:
650  * @types: an array of types that were defined in the moduled loaded.
651  * @exceptions: an array of exceptions that were thrown during the type loading.
652  *
653  * Returns: a new instance of the System.Reflection.ReflectionTypeLoadException
654  */
655 MonoException *
656 mono_get_exception_reflection_type_load (MonoArray *types, MonoArray *exceptions)
657 {
658         MonoClass *klass;
659         gpointer args [2];
660         MonoObject *exc;
661         MonoMethod *method;
662
663         klass = mono_class_from_name (mono_get_corlib (), "System.Reflection", "ReflectionTypeLoadException");
664         g_assert (klass);
665         mono_class_init (klass);
666
667         method = mono_class_get_method_from_name (klass, ".ctor", 2);
668         g_assert (method);
669
670         args [0] = types;
671         args [1] = exceptions;
672
673         exc = mono_object_new (mono_domain_get (), klass);
674         mono_runtime_invoke (method, exc, args, NULL);
675
676         return (MonoException *) exc;
677 }