[runtime] Updates comments.
[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.Collections.Generic;
33 using System.Diagnostics;
34 using System.Reflection;
35 using System.Text;
36 using System.Runtime.InteropServices;
37 using System.Runtime.CompilerServices;
38 using System.Runtime.Serialization;
39 using System.Security.Permissions;
40
41 namespace System
42 {
43         [Serializable]
44         [ComVisible(true)]
45         [ComDefaultInterface (typeof (_Exception))]
46         [ClassInterface (ClassInterfaceType.None)]
47         [StructLayout (LayoutKind.Sequential)]
48 #if MOBILE
49         public class Exception : ISerializable
50 #else
51         public class Exception : ISerializable, _Exception
52 #endif
53         {
54 #pragma warning disable 169, 649
55                 #region Sync with object-internals.h
56                 /* Stores the IPs and the generic sharing infos
57                    (vtable/MRGCTX) of the frames. */
58                 IntPtr [] trace_ips;
59                 Exception inner_exception;
60                 internal string message;
61                 string help_link;
62                 string class_name;
63                 string stack_trace;
64                 // formerly known as remote_stack_trace (see #425512):
65                 string _remoteStackTraceString;
66                 int remote_stack_index;
67                 internal int hresult = -2146233088;
68                 string source;
69                 IDictionary _data;
70                 StackTrace[] captured_traces;
71                 IntPtr[] native_trace_ips;
72                 #endregion
73 #pragma warning restore 169, 649
74
75                 /* Don't add fields here, the runtime depends on the layout of subclasses */
76
77                 public Exception ()
78                 {
79                 }
80
81                 public Exception (string message)
82                 {
83                         this.message = message;
84                 }
85
86                 protected Exception (SerializationInfo info, StreamingContext context)
87                 {
88                         if (info == null)
89                                 throw new ArgumentNullException ("info");
90
91                         class_name          = info.GetString ("ClassName");
92                         message             = info.GetString ("Message");
93                         help_link           = info.GetString ("HelpURL");
94                         stack_trace         = info.GetString ("StackTraceString");
95                         _remoteStackTraceString  = info.GetString ("RemoteStackTraceString");
96                         remote_stack_index  = info.GetInt32  ("RemoteStackIndex");
97                         hresult             = info.GetInt32  ("HResult");
98                         source              = info.GetString ("Source");
99                         inner_exception     = (Exception) info.GetValue ("InnerException", typeof (Exception));
100
101                         try {
102                                 _data = (IDictionary) info.GetValue ("Data", typeof (IDictionary));
103                         } catch (SerializationException) {
104                                 // member did not exist in .NET 1.x
105                         }
106                 }
107
108                 public Exception (string message, Exception innerException)
109                 {
110                         inner_exception = innerException;
111                         this.message = message;
112                 }
113
114                 public Exception InnerException {
115                         get { return inner_exception; }
116                 }
117
118                 public virtual string HelpLink {
119                         get { return help_link; }
120                         set { help_link = value; }
121                 }
122
123                 public int HResult {
124                         get { return hresult; }
125                         protected set { hresult = value; }
126                 }
127         
128                 internal void SetErrorCode(int hr)
129                 {
130                         HResult = hr;
131                 }
132
133                 internal void SetMessage (string s)
134                 {
135                         message = s;
136                 }
137
138                 internal void SetStackTrace (string s)
139                 {
140                         stack_trace = s;
141                 }
142
143                 string ClassName {
144                         get {
145                                 if (class_name == null)
146                                         class_name = GetType ().ToString ();
147                                 return class_name;
148                         }
149                 }
150
151                 public virtual string Message {
152                         get {
153                                 if (message == null)
154                                         message = string.Format (Locale.GetText ("Exception of type '{0}' was thrown."),
155                                                 ClassName);
156
157                                 return message;
158                         }
159                 }
160                 
161                 [MonoTODO]
162                 protected event EventHandler<SafeSerializationEventArgs> SerializeObjectState {
163                         add {
164                         }
165                         remove {
166                         }
167                 }
168
169                 public virtual string Source {
170                         get {
171                                 if (source == null) {
172                                         StackTrace st = new StackTrace (this, true);
173                                         if (st.FrameCount > 0) {
174                                                 StackFrame sf = st.GetFrame (0);
175                                                 if (st != null) {
176                                                         MethodBase method = sf.GetMethod ();
177                                                         if (method != null) {
178                                                                 source = method.DeclaringType.Assembly.UnprotectedGetName ().Name;
179                                                         }
180                                                 }
181                                         }
182                                 }
183
184                                 // source can be null
185                                 return source;
186                         }
187
188                         set {
189                                 source = value;
190                         }
191                 }
192
193                 bool AddFrames (StringBuilder sb, string newline, string unknown, StackTrace st)
194                 {
195                         int i;
196                         for (i = 0; i < st.FrameCount; i++) {
197                                 StackFrame frame = st.GetFrame (i);
198                                 if (i == 0)
199                                         sb.AppendFormat ("  {0} ", Locale.GetText ("at"));
200                                 else
201                                         sb.Append (newline);
202
203                                 if (frame.GetMethod () == null) {
204                                         string internal_name = frame.GetInternalMethodName ();
205                                         if (internal_name != null)
206                                                 sb.Append (internal_name);
207                                         else
208                                                 sb.AppendFormat ("<0x{0:x5} + 0x{1:x5}> {2}", frame.GetMethodAddress (), frame.GetNativeOffset (), unknown);
209                                 } else {
210                                         GetFullNameForStackTrace (sb, frame.GetMethod ());
211
212                                         if (frame.GetILOffset () == -1)
213                                                 sb.AppendFormat ("<0x{0:x5} + 0x{1:x5}> ", frame.GetMethodAddress (), frame.GetNativeOffset ());
214                                         else
215                                                 sb.AppendFormat (" [0x{0:x5}] ", frame.GetILOffset ());
216
217                                         sb.AppendFormat ("in {0}:{1} ", frame.GetSecureFileName (),
218                                                                          frame.GetFileLineNumber ());
219                                 }
220                         }
221
222                         return i != 0;
223                 }
224
225                 public virtual string StackTrace {
226                         get {
227                                 if (stack_trace != null)
228                                         return stack_trace;
229
230                                 if (trace_ips == null)
231                                         /* Not thrown yet */
232                                         return null;
233
234                                 StringBuilder sb = new StringBuilder ();
235
236                                 string newline = String.Format ("{0}  {1} ", Environment.NewLine, Locale.GetText ("at"));
237                                 string unknown = Locale.GetText ("<unknown method>");
238
239                                 // Add traces captured using ExceptionDispatchInfo
240                                 if (captured_traces != null) {
241                                         foreach (var t in captured_traces) {
242                                                 if (!AddFrames (sb, newline, unknown, t))
243                                                         continue;
244
245                                                 sb.Append (Environment.NewLine);
246                                                 sb.Append ("--- End of stack trace from previous location where exception was thrown ---");
247                                                 sb.Append (Environment.NewLine);
248                                         }
249                                 }
250
251                                 StackTrace st = new StackTrace (this, 0, true, true);
252                                 AddFrames (sb, newline, unknown, st);
253
254                                 stack_trace = sb.ToString ();
255
256                                 return stack_trace;
257                         }
258                 }
259
260                 public MethodBase TargetSite {
261                         get {
262                                 StackTrace st = new StackTrace (this, true);
263                                 if (st.FrameCount > 0)
264                                         return st.GetFrame (0).GetMethod ();
265                                 
266                                 return null;
267                         }
268                 }
269
270                 public virtual IDictionary Data {
271                         get {
272                                 if (_data == null) {
273                                         // default to empty dictionary
274                                         _data = new Dictionary<object, object> ();
275                                 }
276                                 return _data;
277                         }
278                 }
279
280                 public virtual Exception GetBaseException ()
281                 {
282                         Exception inner = inner_exception;
283                                 
284                         while (inner != null)
285                         {
286                                 if (inner.InnerException != null)
287                                         inner = inner.InnerException;
288                                 else
289                                         return inner;
290                         }
291
292                         return this;
293                 }
294
295                 [SecurityPermission (SecurityAction.LinkDemand, SerializationFormatter = true)]
296                 public virtual void GetObjectData (SerializationInfo info, StreamingContext context)
297                 {
298                         if (info == null)
299                                 throw new ArgumentNullException ("info");
300
301                         info.AddValue ("ClassName", ClassName);
302                         info.AddValue ("Message", message);
303                         info.AddValue ("InnerException", inner_exception);
304                         info.AddValue ("HelpURL", help_link);
305                         info.AddValue ("StackTraceString", StackTrace);
306                         info.AddValue ("RemoteStackTraceString", _remoteStackTraceString);
307                         info.AddValue ("RemoteStackIndex", remote_stack_index);
308                         info.AddValue ("HResult", hresult);
309                         info.AddValue ("Source", Source);
310                         info.AddValue ("ExceptionMethod", null);
311                         info.AddValue ("Data", _data, typeof (IDictionary));
312                 }
313
314                 public override string ToString ()
315                 {
316                         System.Text.StringBuilder result = new System.Text.StringBuilder (ClassName);
317                         result.Append (": ").Append (Message);
318
319                         if (null != _remoteStackTraceString)
320                                 result.Append (_remoteStackTraceString);
321                                 
322                         if (inner_exception != null) 
323                         {
324                                 result.Append (" ---> ").Append (inner_exception.ToString ());
325                                 result.Append (Environment.NewLine);
326                                 result.Append (Locale.GetText ("  --- End of inner exception stack trace ---"));
327                         }
328
329                         if (StackTrace != null)
330                                 result.Append (Environment.NewLine).Append (StackTrace);
331                         return result.ToString();
332                 }
333
334                 internal Exception FixRemotingException ()
335                 {
336                         string message = (0 == remote_stack_index) ?
337                                 Locale.GetText ("{0}{0}Server stack trace: {0}{1}{0}{0}Exception rethrown at [{2}]: {0}") :
338                                 Locale.GetText ("{1}{0}{0}Exception rethrown at [{2}]: {0}");
339                         string tmp = String.Format (message, Environment.NewLine, StackTrace, remote_stack_index);
340
341                         _remoteStackTraceString = tmp;
342                         remote_stack_index++;
343
344                         stack_trace = null;
345
346                         return this;
347                 }
348
349                 internal void GetFullNameForStackTrace (StringBuilder sb, MethodBase mi)
350                 {
351                         ParameterInfo[] p = mi.GetParametersInternal ();
352                         sb.Append (mi.DeclaringType.ToString ());
353                         sb.Append (".");
354                         sb.Append (mi.Name);
355
356                         if (mi.IsGenericMethod) {
357                                 Type[] gen_params = mi.GetGenericArguments ();
358                                 sb.Append ("[");
359                                 for (int j = 0; j < gen_params.Length; j++) {
360                                         if (j > 0)
361                                                 sb.Append (",");
362                                         sb.Append (gen_params [j].Name);
363                                 }
364                                 sb.Append ("]");
365                         }
366
367                         sb.Append (" (");
368                         for (int i = 0; i < p.Length; ++i) {
369                                 if (i > 0)
370                                         sb.Append (", ");
371                                 Type pt = p[i].ParameterType;
372                                 if (pt.IsClass && !String.IsNullOrEmpty (pt.Namespace)) {
373                                         sb.Append (pt.Namespace);
374                                         sb.Append (".");
375                                 }
376                                 sb.Append (pt.Name);
377                                 if (p [i].Name != null) {
378                                         sb.Append (" ");
379                                         sb.Append (p [i].Name);
380                                 }
381                         }
382                         sb.Append (")");
383                 }
384
385                 // For ExceptionDispatchInfo
386                 internal void CaptureTrace ()
387                 {
388                         if (captured_traces != null) {
389                                 Array.Resize (ref captured_traces, captured_traces.Length + 1);
390                         } else {
391                                 captured_traces = new StackTrace [1];
392                         }
393                         captured_traces [captured_traces.Length - 1] = new StackTrace (this, 0, true, true);
394
395                         trace_ips = null;
396                 }
397
398                 //
399                 // The documentation states that this is available in 1.x,
400                 // but it was not available (MemberRefing this would fail)
401                 // and it states the signature is `override sealed', but the
402                 // correct value is `newslot' 
403                 //
404                 public new Type GetType ()
405                 {
406                         return base.GetType ();
407                 }
408         }
409 }