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