2005-03-10 Sebastien Pouliot <sebastien@ximian.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.
25  *
26  * Returns: the initialized exception instance.
27  */
28 MonoException *
29 mono_exception_from_name (MonoImage *image, const char *name_space,
30                           const char *name)
31 {
32         return mono_exception_from_name_domain (mono_domain_get (), image, name_space, name);
33 }
34
35 MonoException *
36 mono_exception_from_name_domain (MonoDomain *domain, MonoImage *image, 
37                                  const char* name_space, const char *name)
38 {
39         MonoClass *klass;
40         MonoObject *o;
41
42         klass = mono_class_from_name (image, name_space, name);
43
44         o = mono_object_new (domain, klass);
45         g_assert (o != NULL);
46         
47         mono_runtime_object_init (o);
48
49         return (MonoException *)o;
50 }
51
52
53 /**
54  * mono_exception_from_token:
55  * @image: the Mono image where to look for the class
56  * @token: The type token of the class
57  *
58  * Creates an exception of the type given by @token.
59  *
60  * Returns: the initialized exception instance.
61  */
62 MonoException *
63 mono_exception_from_token (MonoImage *image, guint32 token)
64 {
65         MonoClass *klass;
66         MonoObject *o;
67
68         klass = mono_class_get (image, token);
69
70         o = mono_object_new (mono_domain_get (), klass);
71         g_assert (o != NULL);
72         
73         mono_runtime_object_init (o);
74
75         return (MonoException *)o;
76 }
77
78 /**
79  * mono_exception_from_name_two_strings:
80  * @image: the Mono image where to look for the class
81  * @name_space: the namespace for the class
82  * @name: class name
83  * @a1: first string argument to pass
84  * @a2: second string argument to pass
85  *
86  * Creates an exception from a constructor that takes two string
87  * arguments.
88  *
89  * Returns: the initialized exception instance.
90  */
91 MonoException *
92 mono_exception_from_name_two_strings (MonoImage *image, const char *name_space,
93                                       const char *name, MonoString *a1, MonoString *a2)
94 {
95         MonoDomain *domain = mono_domain_get ();
96         MonoClass *klass;
97         MonoMethod *method = NULL;
98         MonoObject *o;
99         int count = 1;
100         gpointer args [2];
101         gpointer iter;
102         MonoMethod *m;
103
104         if (a2 != NULL)
105                 count++;
106         
107         klass = mono_class_from_name (image, name_space, name);
108         o = mono_object_new (domain, klass);
109
110         iter = NULL;
111         while ((m = mono_class_get_methods (klass, &iter))) {
112                 MonoMethodSignature *sig;
113                 
114                 if (strcmp (".ctor", mono_method_get_name (m)))
115                         continue;
116                 sig = mono_method_signature (m);
117                 if (sig->param_count != count)
118                         continue;
119
120                 if (sig->params [0]->type != MONO_TYPE_STRING)
121                         continue;
122                 if (count == 2 && sig->params [1]->type != MONO_TYPE_STRING)
123                         continue;
124                 method = m;
125         }
126
127         args [0] = a1;
128         args [1] = a2;
129         mono_runtime_invoke (method, o, args, NULL);
130         return (MonoException *) o;
131 }
132
133 /**
134  * mono_exception_from_name_msg:
135  * @image: the Mono image where to look for the class
136  * @name_space: the namespace for the class
137  * @name: class name
138  * @msg: the message to embed inside the exception
139  *
140  * Creates an exception and initializes its message field.
141  *
142  * Returns: the initialized exception instance.
143  */
144 MonoException *
145 mono_exception_from_name_msg (MonoImage *image, const char *name_space,
146                               const char *name, const guchar *msg)
147 {
148         MonoException *ex;
149
150         ex = mono_exception_from_name (image, name_space, name);
151
152         if (msg)
153                 ex->message = mono_string_new (mono_object_get_domain ((MonoObject*)ex), msg);
154
155         return ex;
156 }
157
158 MonoException *
159 mono_get_exception_divide_by_zero ()
160 {
161         return mono_exception_from_name (mono_get_corlib (), "System",
162                                          "DivideByZeroException");
163 }
164
165 MonoException *
166 mono_get_exception_security ()
167 {
168         return mono_exception_from_name (mono_get_corlib (), "System.Security",
169                                          "SecurityException");
170 }
171
172 MonoException *
173 mono_get_exception_thread_abort ()
174 {
175         return mono_exception_from_name (mono_get_corlib (), "System.Threading",
176                                          "ThreadAbortException");
177 }
178
179 MonoException *
180 mono_get_exception_arithmetic ()
181 {
182         return mono_exception_from_name (mono_get_corlib (), "System",
183                                          "ArithmeticException");
184 }
185
186 MonoException *
187 mono_get_exception_overflow ()
188 {
189         return mono_exception_from_name (mono_get_corlib (), "System",
190                                          "OverflowException");
191 }
192
193 MonoException *
194 mono_get_exception_null_reference ()
195 {
196         return mono_exception_from_name (mono_get_corlib (), "System",
197                                          "NullReferenceException");
198 }
199
200 MonoException *
201 mono_get_exception_execution_engine (const guchar *msg)
202 {
203         return mono_exception_from_name_msg (mono_get_corlib (), "System",
204                                                                                  "ExecutionEngineException", msg);
205 }
206
207 MonoException *
208 mono_get_exception_serialization (const guchar *msg)
209 {
210         return mono_exception_from_name_msg (mono_get_corlib (), "System.Runtime.Serialization",
211                                                                                  "SerializationException", msg);
212 }
213
214 MonoException *
215 mono_get_exception_invalid_cast ()
216 {
217         return mono_exception_from_name (mono_get_corlib (), "System",
218                                          "InvalidCastException");
219 }
220
221 MonoException *
222 mono_get_exception_invalid_operation (const guchar *msg)
223 {
224         return mono_exception_from_name_msg (mono_get_corlib (), "System",
225                                         "InvalidOperationException", msg);
226 }
227
228 MonoException *
229 mono_get_exception_index_out_of_range ()
230 {
231         return mono_exception_from_name (mono_get_corlib (), "System",
232                                          "IndexOutOfRangeException");
233 }
234
235 MonoException *
236 mono_get_exception_array_type_mismatch ()
237 {
238         return mono_exception_from_name (mono_get_corlib (), "System",
239                                          "ArrayTypeMismatchException");
240 }
241
242 MonoException *
243 mono_get_exception_type_load (MonoString *type_name)
244 {
245         MonoTypeLoadException *exc;
246         
247         exc = (MonoTypeLoadException *) mono_exception_from_name (mono_get_corlib (),
248                                         "System",
249                                         "TypeLoadException");
250
251         exc->type_name = type_name;
252         return (MonoException *) exc;
253 }
254
255 MonoException *
256 mono_get_exception_not_implemented (const guchar *msg)
257 {
258         MonoException *ex;
259         
260         ex = mono_exception_from_name (mono_get_corlib (), "System",
261                                        "NotImplementedException");
262
263         if (msg)
264                 ex->message = mono_string_new (mono_object_get_domain ((MonoObject*)ex), msg);
265
266         return ex;
267 }
268
269 MonoException *
270 mono_get_exception_missing_method ()
271 {
272         return mono_exception_from_name (mono_get_corlib (), "System",
273                                          "MissingMethodException");
274 }
275
276 MonoException*
277 mono_get_exception_argument_null (const guchar *arg)
278 {
279         MonoException *ex;
280
281         ex = mono_exception_from_name ( 
282                 mono_get_corlib (), "System", "ArgumentNullException");
283
284         if (arg)
285                 ((MonoArgumentException *)ex)->param_name =
286                         mono_string_new (mono_object_get_domain ((MonoObject*)ex), arg);
287         
288         return ex;
289 }
290
291 MonoException *
292 mono_get_exception_argument (const guchar *arg, const guchar *msg)
293 {
294         MonoException *ex;
295
296         ex = mono_exception_from_name_msg (
297                 mono_get_corlib (), "System", "ArgumentException", msg);
298
299         if (arg)
300                 ((MonoArgumentException *)ex)->param_name =
301                         mono_string_new (mono_object_get_domain ((MonoObject*)ex), arg);
302         
303         return ex;
304 }
305
306 MonoException *
307 mono_get_exception_argument_out_of_range (const guchar *arg)
308 {
309         MonoException *ex;
310
311         ex = mono_exception_from_name (
312                 mono_get_corlib (), "System", "ArgumentOutOfRangeException");
313
314         if (arg)
315                 ((MonoArgumentException *)ex)->param_name =
316                         mono_string_new (mono_object_get_domain ((MonoObject*)ex), arg);
317         
318         return ex;
319 }
320
321 MonoException *
322 mono_get_exception_thread_state (const guchar *msg)
323 {
324         return mono_exception_from_name_msg (
325                 mono_get_corlib (), "System.Threading", "ThreadStateException", msg);
326 }
327
328 MonoException *
329 mono_get_exception_io (const guchar *msg)
330 {
331         return mono_exception_from_name_msg ( 
332                 mono_get_corlib (), "System.IO", "IOException", msg);
333 }
334
335 MonoException *
336 mono_get_exception_file_not_found (MonoString *fname)
337 {
338         return mono_exception_from_name_two_strings (
339                 mono_get_corlib (), "System.IO", "FileNotFoundException", fname, fname);
340 }
341
342 MonoException *
343 mono_get_exception_file_not_found2 (const guchar *msg, MonoString *fname)
344 {
345         MonoString *s = mono_string_new (mono_domain_get (), msg);
346
347         return mono_exception_from_name_two_strings (
348                 mono_get_corlib (), "System.IO", "FileNotFoundException", s, fname);
349 }
350
351 MonoException *
352 mono_get_exception_type_initialization (const gchar *type_name, MonoException *inner)
353 {
354         MonoClass *klass;
355         gpointer args [2];
356         MonoObject *exc;
357         MonoMethod *method;
358         gpointer iter;
359
360         klass = mono_class_from_name (mono_get_corlib (), "System", "TypeInitializationException");
361         g_assert (klass);
362
363         mono_class_init (klass);
364
365         /* TypeInitializationException only has 1 ctor with 2 args */
366         iter = NULL;
367         while ((method = mono_class_get_methods (klass, &iter))) {
368                 if (!strcmp (".ctor", mono_method_get_name (method)) && mono_method_signature (method)->param_count == 2)
369                         break;
370                 method = NULL;
371         }
372
373         g_assert (method);
374
375         args [0] = mono_string_new (mono_domain_get (), type_name);
376         args [1] = inner;
377
378         exc = mono_object_new (mono_domain_get (), klass);
379         mono_runtime_invoke (method, exc, args, NULL);
380
381         return (MonoException *) exc;
382 }
383
384 MonoException *
385 mono_get_exception_synchronization_lock (const guchar *msg)
386 {
387         return mono_exception_from_name_msg (mono_get_corlib (), "System.Threading", "SynchronizationLockException", msg);
388 }
389
390 MonoException *
391 mono_get_exception_cannot_unload_appdomain (const guchar *msg)
392 {
393         return mono_exception_from_name_msg (mono_get_corlib (), "System", "CannotUnloadAppDomainException", msg);
394 }
395
396 MonoException *
397 mono_get_exception_appdomain_unloaded (void)
398 {
399         return mono_exception_from_name (mono_get_corlib (), "System", "AppDomainUnloadedException");
400 }
401
402 MonoException *
403 mono_get_exception_bad_image_format (const guchar *msg)
404 {
405         return mono_exception_from_name_msg (mono_get_corlib (), "System", "BadImageFormatException", msg);
406 }       
407
408 MonoException *
409 mono_get_exception_stack_overflow (void)
410 {
411         return mono_exception_from_name (mono_get_corlib (), "System", "StackOverflowException");       
412 }
413
414 MonoException *
415 mono_get_exception_reflection_type_load (MonoArray *types, MonoArray *exceptions)
416 {
417         MonoClass *klass;
418         gpointer args [2];
419         MonoObject *exc;
420         MonoMethod *method;
421
422         klass = mono_class_from_name (mono_get_corlib (), "System.Reflection", "ReflectionTypeLoadException");
423         g_assert (klass);
424         mono_class_init (klass);
425
426         method = mono_class_get_method_from_name (klass, ".ctor", 2);
427         g_assert (method);
428
429         args [0] = types;
430         args [1] = exceptions;
431
432         exc = mono_object_new (mono_domain_get (), klass);
433         mono_runtime_invoke (method, exc, args, NULL);
434
435         return (MonoException *) exc;
436 }