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