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