Warnings cleanup
[mono.git] / mcs / class / corlib / System / Exception.cs
1 //
2 // System.Exception.cs
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //   Patrik Torstensson
7 //
8 // (C) Ximian, Inc.  http://www.ximian.com
9 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System.Collections;
32 using System.Diagnostics;
33 using System.Reflection;
34 using System.Text;
35 using System.Runtime.InteropServices;
36 using System.Runtime.CompilerServices;
37 using System.Runtime.Serialization;
38 using System.Security.Permissions;
39
40 namespace System
41 {
42         [Serializable]
43 #if NET_2_0
44         [ComVisible(true)]
45         [ComDefaultInterface (typeof (_Exception))]
46         [ClassInterface (ClassInterfaceType.None)]
47 #else
48         [ClassInterface (ClassInterfaceType.AutoDual)]
49 #endif
50         public class Exception : ISerializable 
51 #if NET_2_0
52         , _Exception
53 #endif
54         {
55 #pragma warning disable 169, 649
56                 #region Sync with object-internals.h
57                 IntPtr [] trace_ips;
58                 Exception inner_exception;
59                 internal string message;
60                 string help_link;
61                 string class_name;
62                 string stack_trace;
63                 string remote_stack_trace;
64                 int remote_stack_index;
65                 internal int hresult = -2146233088;
66                 string source;
67                 IDictionary _data;
68                 #endregion
69 #pragma warning restore 169, 649                
70
71                 public Exception ()
72                 {
73                 }
74
75                 public Exception (string message)
76                 {
77                         this.message = message;
78                 }
79
80                 protected Exception (SerializationInfo info, StreamingContext context)
81                 {
82                         if (info == null)
83                                 throw new ArgumentNullException ("info");
84
85                         class_name          = info.GetString ("ClassName");
86                         message             = info.GetString ("Message");
87                         help_link           = info.GetString ("HelpURL");
88                         stack_trace         = info.GetString ("StackTraceString");
89                         remote_stack_trace  = info.GetString ("RemoteStackTraceString");
90                         remote_stack_index  = info.GetInt32  ("RemoteStackIndex");
91                         hresult             = info.GetInt32  ("HResult");
92                         source              = info.GetString ("Source");
93                         inner_exception     = (Exception) info.GetValue ("InnerException", typeof (Exception));
94
95 #if NET_2_0
96                         try {
97                                 _data = (IDictionary) info.GetValue ("Data", typeof (IDictionary));
98                         } catch (SerializationException) {
99                                 // member did not exist in .NET 1.x
100                         }
101 #endif
102
103                 }
104
105                 public Exception (string message, Exception innerException)
106                 {
107                         inner_exception = innerException;
108                         this.message = message;
109                 }
110
111                 public Exception InnerException {
112                         get { return inner_exception; }
113                 }
114
115                 public virtual string HelpLink {
116                         get { return help_link; }
117                         set { help_link = value; }
118                 }
119
120                 protected int HResult {
121                         get { return hresult; }
122                         set { hresult = value; }
123                 }
124
125                 internal void SetMessage (string s)
126                 {
127                         message = s;
128                 }
129
130                 internal void SetStackTrace (string s)
131                 {
132                         stack_trace = s;
133                 }
134
135                 string ClassName {
136                         get {
137                                 if (class_name == null)
138                                         class_name = GetType ().ToString ();
139                                 return class_name;
140                         }
141                 }
142
143                 public virtual string Message {
144                         get {
145                                 if (message == null)
146 #if NET_2_0
147                                         message = string.Format (Locale.GetText ("Exception of type '{0}' was thrown."),
148 #else
149                                         message = string.Format (Locale.GetText ("Exception of type {0} was thrown."),
150 #endif
151                                                 ClassName);
152
153                                 return message;
154                         }
155                 }
156
157                 public virtual string Source {
158 #if ONLY_1_1
159                         [ReflectionPermission (SecurityAction.Assert, TypeInformation = true)]
160 #endif
161                         get {
162                                 if (source == null) {
163                                         StackTrace st = new StackTrace (this, true);
164                                         if (st.FrameCount > 0) {
165                                                 StackFrame sf = st.GetFrame (0);
166                                                 if (st != null) {
167                                                         MethodBase method = sf.GetMethod ();
168                                                         if (method != null) {
169                                                                 source = method.DeclaringType.Assembly.UnprotectedGetName ().Name;
170                                                         }
171                                                 }
172                                         }
173                                 }
174
175                                 // source can be null
176                                 return source;
177                         }
178
179                         set {
180                                 source = value;
181                         }
182                 }
183
184                 public virtual string StackTrace {
185                         get {
186                                 if (stack_trace == null) {
187                                         if (trace_ips == null)
188                                                 /* Not thrown yet */
189                                                 return null;
190
191                                         StackTrace st = new StackTrace (this, 0, true, true);
192
193                                         StringBuilder sb = new StringBuilder ();
194
195                                         string newline = String.Format ("{0}  {1} ", Environment.NewLine, Locale.GetText ("at"));
196                                         string unknown = Locale.GetText ("<unknown method>");
197
198                                         for (int i = 0; i < st.FrameCount; i++) {
199                                                 StackFrame frame = st.GetFrame (i);
200                                                 if (i == 0)
201                                                         sb.AppendFormat ("  {0} ", Locale.GetText ("at"));
202                                                 else
203                                                         sb.Append (newline);
204
205                                                 if (frame.GetMethod () == null) {
206                                                         string internal_name = frame.GetInternalMethodName ();
207                                                         if (internal_name != null)
208                                                                 sb.Append (internal_name);
209                                                         else
210                                                                 sb.AppendFormat ("<0x{0:x5}> {1}", frame.GetNativeOffset (), unknown);
211                                                 } else {
212                                                         GetFullNameForStackTrace (sb, frame.GetMethod ());
213
214                                                         if (frame.GetILOffset () == -1)
215                                                                 sb.AppendFormat (" <0x{0:x5}> ", frame.GetNativeOffset ());
216                                                         else
217                                                                 sb.AppendFormat (" [0x{0:x5}] ", frame.GetILOffset ());
218
219                                                         string fileName = frame.GetFileName ();
220                                                         if (fileName != null)
221                                                                 sb.AppendFormat ("in {0}:{1} ", fileName, frame.GetFileLineNumber ());
222                                                         }
223                                         }
224                                         stack_trace = sb.ToString ();
225                                 }
226
227                                 return stack_trace;
228                         }
229                 }
230
231                 public MethodBase TargetSite {
232 #if ONLY_1_1
233                         [ReflectionPermission (SecurityAction.Demand, TypeInformation = true)]
234 #endif
235                         get {
236                                 StackTrace st = new StackTrace (this, true);
237                                 if (st.FrameCount > 0)
238                                         return st.GetFrame (0).GetMethod ();
239                                 
240                                 return null;
241                         }
242                 }
243
244 #if NET_2_0
245                 public virtual IDictionary Data {
246                         get {
247                                 if (_data == null) {
248                                         // default to empty dictionary
249                                         _data = (IDictionary) new Hashtable ();
250                                 }
251                                 return _data;
252                         }
253                 }
254 #endif
255
256                 public virtual Exception GetBaseException ()
257                 {
258                         Exception inner = inner_exception;
259                                 
260                         while (inner != null)
261                         {
262                                 if (inner.InnerException != null)
263                                         inner = inner.InnerException;
264                                 else
265                                         return inner;
266                         }
267
268                         return this;
269                 }
270
271 #if ONLY_1_1
272                 [ReflectionPermission (SecurityAction.Assert, TypeInformation = true)]
273 #endif
274                 [SecurityPermission (SecurityAction.LinkDemand, SerializationFormatter = true)]
275                 public virtual void GetObjectData (SerializationInfo info, StreamingContext context)
276                 {
277                         if (info == null)
278                                 throw new ArgumentNullException ("info");
279
280                         info.AddValue ("ClassName", ClassName);
281                         info.AddValue ("Message", message);
282                         info.AddValue ("InnerException", inner_exception);
283                         info.AddValue ("HelpURL", help_link);
284                         info.AddValue ("StackTraceString", StackTrace);
285                         info.AddValue ("RemoteStackTraceString", remote_stack_trace);
286                         info.AddValue ("RemoteStackIndex", remote_stack_index);
287                         info.AddValue ("HResult", hresult);
288                         info.AddValue ("Source", Source);
289                         info.AddValue ("ExceptionMethod", null);
290 #if NET_2_0
291                         info.AddValue ("Data", _data, typeof (IDictionary));
292 #endif
293                 }
294
295 #if ONLY_1_1
296                 [ReflectionPermission (SecurityAction.Assert, TypeInformation = true)]
297 #endif
298                 public override string ToString ()
299                 {
300                         System.Text.StringBuilder result = new System.Text.StringBuilder (ClassName);
301                         result.Append (": ").Append (Message);
302
303                         if (null != remote_stack_trace)
304                                 result.Append (remote_stack_trace);
305                                 
306                         if (inner_exception != null) 
307                         {
308                                 result.Append (" ---> ").Append (inner_exception.ToString ());
309                                 result.Append (Environment.NewLine);
310                                 result.Append (Locale.GetText ("  --- End of inner exception stack trace ---"));
311                         }
312
313                         if (StackTrace != null)
314                                 result.Append (Environment.NewLine).Append (StackTrace);
315                         return result.ToString();
316                 }
317
318                 internal Exception FixRemotingException ()
319                 {
320                         string message = (0 == remote_stack_index) ?
321                                 Locale.GetText ("{0}{0}Server stack trace: {0}{1}{0}{0}Exception rethrown at [{2}]: {0}") :
322                                 Locale.GetText ("{1}{0}{0}Exception rethrown at [{2}]: {0}");
323                         string tmp = String.Format (message, Environment.NewLine, StackTrace, remote_stack_index);
324
325                         remote_stack_trace = tmp;
326                         remote_stack_index++;
327
328                         stack_trace = null;
329
330                         return this;
331                 }
332
333                 internal void GetFullNameForStackTrace (StringBuilder sb, MethodBase mi)
334                 {
335                         ParameterInfo[] p = mi.GetParameters ();
336                         sb.Append (mi.DeclaringType.ToString ());
337                         sb.Append (".");
338                         sb.Append (mi.Name);
339
340 #if NET_2_0 || BOOTSTRAP_NET_2_0
341                         if (mi.IsGenericMethod) {
342                                 Type[] gen_params = mi.GetGenericArguments ();
343                                 sb.Append ("[");
344                                 for (int j = 0; j < gen_params.Length; j++) {
345                                         if (j > 0)
346                                                 sb.Append (",");
347                                         sb.Append (gen_params [j].Name);
348                                 }
349                                 sb.Append ("]");
350                         }
351 #endif
352                         sb.Append (" (");
353                         for (int i = 0; i < p.Length; ++i) {
354                                 if (i > 0)
355                                         sb.Append (", ");
356                                 Type pt = p[i].ParameterType;
357                                 if (pt.IsClass && pt.Namespace != String.Empty) {
358                                         sb.Append (pt.Namespace);
359                                         sb.Append (".");
360                                 }
361                                 sb.Append (pt.Name);
362                                 if (p [i].Name != null) {
363                                         sb.Append (" ");
364                                         sb.Append (p [i].Name);
365                                 }
366                         }
367                         sb.Append (")");
368                 }
369
370 #if NET_2_0
371                 //
372                 // The documentation states that this is available in 1.x,
373                 // but it was not available (MemberRefing this would fail)
374                 // and it states the signature is `override sealed', but the
375                 // correct value is `newslot' 
376                 //
377                 public new Type GetType ()
378                 {
379                         return base.GetType ();
380                 }
381 #endif
382         }
383 }