2003-11-24 Zoltan Varga <vargaz@freemail.hu>
[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/class.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         MonoDomain *domain = mono_domain_get ();
33         MonoClass *klass;
34         MonoObject *o;
35
36         klass = mono_class_from_name (image, name_space, name);
37
38         o = mono_object_new (domain, klass);
39         g_assert (o != NULL);
40         
41         mono_runtime_object_init (o);
42
43         return (MonoException *)o;
44 }
45
46 /**
47  * mono_exception_from_name_two_strings:
48  * @image: the Mono image where to look for the class
49  * @name_space: the namespace for the class
50  * @name: class name
51  * @a1: first string argument to pass
52  * @a2: second string argument to pass
53  *
54  * Creates an exception from a constructor that takes two string
55  * arguments.
56  *
57  * Returns: the initialized exception instance.
58  */
59 static MonoException *
60 mono_exception_from_name_two_strings (MonoImage *image, const char *name_space,
61                                                                           const char *name, MonoString *a1, MonoString *a2)
62 {
63         MonoDomain *domain = mono_domain_get ();
64         MonoClass *klass;
65         MonoMethod *method = NULL;
66         MonoObject *o;
67         int i;
68         gpointer args [2];
69         
70         klass = mono_class_from_name (image, name_space, name);
71         o = mono_object_new (domain, klass);
72
73         for (i = 0; i < klass->method.count; ++i) {
74                 MonoMethodSignature *sig;
75                 
76                 if (strcmp (".ctor", klass->methods [i]->name))
77                         continue;
78                 sig = klass->methods [i]->signature;
79                 if (sig->param_count != 2)
80                         continue;
81
82                 if (sig->params [0]->type != MONO_TYPE_STRING ||
83                     sig->params [1]->type != MONO_TYPE_STRING)
84                         continue;
85                 method = klass->methods [i];
86         }
87
88         args [0] = a1;
89         args [1] = a2;
90         mono_runtime_invoke (method, o, args, NULL);
91         return (MonoException *) o;
92 }
93
94 /**
95  * mono_exception_from_name_msg:
96  * @image: the Mono image where to look for the class
97  * @name_space: the namespace for the class
98  * @name: class name
99  * @msg: the message to embed inside the exception
100  *
101  * Creates an exception and initializes its message field.
102  *
103  * Returns: the initialized exception instance.
104  */
105 static MonoException *
106 mono_exception_from_name_msg (MonoImage *image, const char *name_space,
107                                                           const char *name, const guchar *msg)
108 {
109         MonoException *ex;
110         MonoDomain *domain;
111
112     ex = mono_exception_from_name (image, name_space, name);
113
114         domain = ((MonoObject *)ex)->vtable->domain;
115
116         if (msg)
117                 ex->message = mono_string_new (domain, msg);
118
119         return ex;
120 }
121
122 MonoException *
123 mono_get_exception_divide_by_zero ()
124 {
125         return mono_exception_from_name (mono_defaults.corlib, "System",
126                                          "DivideByZeroException");
127 }
128
129 MonoException *
130 mono_get_exception_security ()
131 {
132         return mono_exception_from_name (mono_defaults.corlib, "System",
133                                          "SecurityException");
134 }
135
136 MonoException *
137 mono_get_exception_thread_abort ()
138 {
139         return mono_exception_from_name (mono_defaults.corlib, "System.Threading",
140                                          "ThreadAbortException");
141 }
142
143 MonoException *
144 mono_get_exception_arithmetic ()
145 {
146         return mono_exception_from_name (mono_defaults.corlib, "System",
147                                          "ArithmeticException");
148 }
149
150 MonoException *
151 mono_get_exception_overflow ()
152 {
153         return mono_exception_from_name (mono_defaults.corlib, "System",
154                                          "OverflowException");
155 }
156
157 MonoException *
158 mono_get_exception_null_reference ()
159 {
160         return mono_exception_from_name (mono_defaults.corlib, "System",
161                                          "NullReferenceException");
162 }
163
164 MonoException *
165 mono_get_exception_execution_engine (const guchar *msg)
166 {
167         return mono_exception_from_name_msg (mono_defaults.corlib, "System",
168                                                                                  "ExecutionEngineException", msg);
169 }
170
171 MonoException *
172 mono_get_exception_serialization (const guchar *msg)
173 {
174         return mono_exception_from_name_msg (mono_defaults.corlib, "System.Runtime.Serialization",
175                                                                                  "SerializationException", msg);
176 }
177
178 MonoException *
179 mono_get_exception_invalid_cast ()
180 {
181         return mono_exception_from_name (mono_defaults.corlib, "System",
182                                          "InvalidCastException");
183 }
184
185 MonoException *
186 mono_get_exception_index_out_of_range ()
187 {
188         return mono_exception_from_name (mono_defaults.corlib, "System",
189                                          "IndexOutOfRangeException");
190 }
191
192 MonoException *
193 mono_get_exception_array_type_mismatch ()
194 {
195         return mono_exception_from_name (mono_defaults.corlib, "System",
196                                          "ArrayTypeMismatchException");
197 }
198
199 MonoException *
200 mono_get_exception_type_load (MonoString *type_name)
201 {
202         MonoTypeLoadException *exc;
203         
204         exc = (MonoTypeLoadException *) mono_exception_from_name (mono_defaults.corlib,
205                                         "System",
206                                         "TypeLoadException");
207
208         exc->type_name = type_name;
209         return (MonoException *) exc;
210 }
211
212 MonoException *
213 mono_get_exception_not_implemented ()
214 {
215         return mono_exception_from_name (mono_defaults.corlib, "System",
216                                          "NotImplementedException");
217 }
218
219 MonoException *
220 mono_get_exception_missing_method ()
221 {
222         return mono_exception_from_name (mono_defaults.corlib, "System",
223                                          "MissingMethodException");
224 }
225
226 MonoException*
227 mono_get_exception_argument_null (const guchar *arg)
228 {
229         MonoException *ex;
230         MonoDomain *domain;
231
232         ex = mono_exception_from_name ( 
233                 mono_defaults.corlib, "System", "ArgumentNullException");
234
235         domain = ((MonoObject *)ex)->vtable->domain;
236
237         if (arg)
238                 ((MonoArgumentException *)ex)->param_name =
239                         mono_string_new (domain, arg);
240         
241         return ex;
242 }
243
244 MonoException *
245 mono_get_exception_argument (const guchar *arg, const guchar *msg)
246 {
247         MonoException *ex;
248         MonoDomain *domain;
249
250         ex = mono_exception_from_name_msg (
251                 mono_defaults.corlib, "System", "ArgumentException", msg);
252
253         domain = ((MonoObject *)ex)->vtable->domain;
254
255         if (arg)
256                 ((MonoArgumentException *)ex)->param_name =
257                         mono_string_new (domain, arg);
258         
259         return ex;
260 }
261
262 MonoException *
263 mono_get_exception_argument_out_of_range (const guchar *arg)
264 {
265         MonoException *ex;
266         MonoDomain *domain;
267
268         ex = mono_exception_from_name (
269                 mono_defaults.corlib, "System", "ArgumentOutOfRangeException");
270
271         domain = ((MonoObject *)ex)->vtable->domain;
272
273         if (arg)
274                 ((MonoArgumentException *)ex)->param_name =
275                         mono_string_new (domain, arg);
276         
277         return ex;
278 }
279
280 MonoException *
281 mono_get_exception_thread_state (const guchar *msg)
282 {
283         return mono_exception_from_name_msg (mono_defaults.corlib, 
284                                                                                  "System.Threading", "ThreadStateException",
285                                                                                  msg);
286 }
287
288 MonoException *
289 mono_get_exception_io (const guchar *msg)
290 {
291         return mono_exception_from_name_msg ( 
292                 mono_defaults.corlib, "System.IO", "IOException", msg);
293 }
294
295 MonoException *
296 mono_get_exception_file_not_found (MonoString *fname)
297 {
298         return mono_exception_from_name_two_strings (
299                 mono_defaults.corlib, "System.IO", "FileNotFoundException", fname, fname);
300 }
301
302 MonoException *
303 mono_get_exception_type_initialization (const gchar *type_name, MonoException *inner)
304 {
305         MonoClass *klass;
306         gpointer args [2];
307         MonoObject *exc;
308         MonoMethod *method;
309         gint i;
310
311         klass = mono_class_from_name (mono_defaults.corlib, "System", "TypeInitializationException");
312         g_assert (klass);
313
314         mono_class_init (klass);
315
316         /* TypeInitializationException only has 1 ctor with 2 args */
317         for (i = 0; i < klass->method.count; ++i) {
318                 method = klass->methods [i];
319                 if (!strcmp (".ctor", method->name) && method->signature->param_count == 2)
320                         break;
321                 method = NULL;
322         }
323
324         g_assert (method);
325
326         args [0] = mono_string_new (mono_domain_get (), type_name);
327         args [1] = inner;
328
329         exc = mono_object_new (mono_domain_get (), klass);
330         mono_runtime_invoke (method, exc, args, NULL);
331
332         return (MonoException *) exc;
333 }
334
335 MonoException *
336 mono_get_exception_synchronization_lock (const guchar *msg)
337 {
338         return mono_exception_from_name_msg (mono_defaults.corlib, "System.Threading", "SynchronizationLockException", msg);
339 }
340
341 MonoException *
342 mono_get_exception_cannot_unload_appdomain (const guchar *msg)
343 {
344         return mono_exception_from_name_msg (mono_defaults.corlib, "System", "CannotUnloadAppDomainException", msg);
345 }
346
347 MonoException *
348 mono_get_exception_appdomain_unloaded (void)
349 {
350         return mono_exception_from_name (mono_defaults.corlib, "System", "AppDomainUnloadedException");
351 }