[MSBuild] Fix minor assembly resolution issue
[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                 public virtual string StackTrace {
194                         get {
195                                 if (stack_trace != null)
196                                         return stack_trace;
197
198                                 if (trace_ips == null)
199                                         /* Not thrown yet */
200                                         return null;
201
202                                 StringBuilder sb = new StringBuilder ();
203
204                                 // Add traces captured using ExceptionDispatchInfo
205                                 if (captured_traces != null) {
206                                         foreach (var t in captured_traces) {
207                                                 if (!t.AddFrames (sb, true))
208                                                         continue;
209
210                                                 sb.Append (Environment.NewLine);
211                                                 sb.Append ("--- End of stack trace from previous location where exception was thrown ---");
212                                                 sb.Append (Environment.NewLine);
213                                         }
214                                 }
215
216                                 StackTrace st = new StackTrace (this, 0, true, true);
217                                 st.AddFrames (sb, true);
218
219                                 stack_trace = sb.ToString ();
220
221                                 return stack_trace;
222                         }
223                 }
224
225                 public MethodBase TargetSite {
226                         get {
227                                 StackTrace st = new StackTrace (this, true);
228                                 if (st.FrameCount > 0)
229                                         return st.GetFrame (0).GetMethod ();
230                                 
231                                 return null;
232                         }
233                 }
234
235                 public virtual IDictionary Data {
236                         get {
237                                 if (_data == null) {
238                                         // default to empty dictionary
239                                         _data = new Dictionary<object, object> ();
240                                 }
241                                 return _data;
242                         }
243                 }
244
245                 public virtual Exception GetBaseException ()
246                 {
247                         Exception inner = inner_exception;
248                                 
249                         while (inner != null)
250                         {
251                                 if (inner.InnerException != null)
252                                         inner = inner.InnerException;
253                                 else
254                                         return inner;
255                         }
256
257                         return this;
258                 }
259
260                 [SecurityPermission (SecurityAction.LinkDemand, SerializationFormatter = true)]
261                 public virtual void GetObjectData (SerializationInfo info, StreamingContext context)
262                 {
263                         if (info == null)
264                                 throw new ArgumentNullException ("info");
265
266                         info.AddValue ("ClassName", ClassName);
267                         info.AddValue ("Message", _message);
268                         info.AddValue ("InnerException", inner_exception);
269                         info.AddValue ("HelpURL", help_link);
270                         info.AddValue ("StackTraceString", StackTrace);
271                         info.AddValue ("RemoteStackTraceString", _remoteStackTraceString);
272                         info.AddValue ("RemoteStackIndex", remote_stack_index);
273                         info.AddValue ("HResult", hresult);
274                         info.AddValue ("Source", Source);
275                         info.AddValue ("ExceptionMethod", null);
276                         info.AddValue ("Data", _data, typeof (IDictionary));
277                 }
278
279                 public override string ToString ()
280                 {
281                         System.Text.StringBuilder result = new System.Text.StringBuilder (ClassName);
282                         result.Append (": ").Append (Message);
283
284                         if (null != _remoteStackTraceString)
285                                 result.Append (_remoteStackTraceString);
286                                 
287                         if (inner_exception != null) 
288                         {
289                                 result.Append (" ---> ").Append (inner_exception.ToString ());
290                                 result.Append (Environment.NewLine);
291                                 result.Append (Locale.GetText ("  --- End of inner exception stack trace ---"));
292                         }
293
294                         if (StackTrace != null)
295                                 result.Append (Environment.NewLine).Append (StackTrace);
296                         return result.ToString();
297                 }
298
299                 internal Exception FixRemotingException ()
300                 {
301                         string message = (0 == remote_stack_index) ?
302                                 Locale.GetText ("{0}{0}Server stack trace: {0}{1}{0}{0}Exception rethrown at [{2}]: {0}") :
303                                 Locale.GetText ("{1}{0}{0}Exception rethrown at [{2}]: {0}");
304                         string tmp = String.Format (message, Environment.NewLine, StackTrace, remote_stack_index);
305
306                         _remoteStackTraceString = tmp;
307                         remote_stack_index++;
308
309                         stack_trace = null;
310
311                         return this;
312                 }
313
314                 // For ExceptionDispatchInfo
315                 internal void RestoreExceptionDispatchInfo (System.Runtime.ExceptionServices.ExceptionDispatchInfo exceptionDispatchInfo)
316                 {
317                         captured_traces = (StackTrace[]) exceptionDispatchInfo.BinaryStackTraceArray;
318                         trace_ips = null;
319                 }
320
321                 //
322                 // The documentation states that this is available in 1.x,
323                 // but it was not available (MemberRefing this would fail)
324                 // and it states the signature is `override sealed', but the
325                 // correct value is `newslot' 
326                 //
327                 public new Type GetType ()
328                 {
329                         return base.GetType ();
330                 }
331
332                 internal enum ExceptionMessageKind
333                 {
334                         ThreadAbort = 1,
335                         ThreadInterrupted = 2,
336                         OutOfMemory = 3
337                 }
338
339                 internal static String GetMessageFromNativeResources (ExceptionMessageKind kind)
340                 {
341                         switch (kind) {
342                         case ExceptionMessageKind.ThreadAbort:
343                                 return "";
344                         case ExceptionMessageKind.ThreadInterrupted:
345                                 return "";
346                         case ExceptionMessageKind.OutOfMemory:
347                                 return "Out of memory";
348                         }
349                         return "";
350                 }
351         }
352 }