Merge pull request #2024 from BogdanovKirill/webrequesttest
[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                 internal StackTrace[] captured_traces;
71                 IntPtr[] native_trace_ips;
72                 object dynamic_methods;
73                 #endregion
74 #pragma warning restore 169, 649
75
76                 /* Don't add fields here, the runtime depends on the layout of subclasses */
77
78                 public Exception ()
79                 {
80                 }
81
82                 public Exception (string message)
83                 {
84                         this._message = message;
85                 }
86
87                 protected Exception (SerializationInfo info, StreamingContext context)
88                 {
89                         if (info == null)
90                                 throw new ArgumentNullException ("info");
91
92                         class_name          = info.GetString ("ClassName");
93                         _message             = info.GetString ("Message");
94                         help_link           = info.GetString ("HelpURL");
95                         stack_trace         = info.GetString ("StackTraceString");
96                         _remoteStackTraceString  = info.GetString ("RemoteStackTraceString");
97                         remote_stack_index  = info.GetInt32  ("RemoteStackIndex");
98                         hresult             = info.GetInt32  ("HResult");
99                         source              = info.GetString ("Source");
100                         inner_exception     = (Exception) info.GetValue ("InnerException", typeof (Exception));
101
102                         try {
103                                 _data = (IDictionary) info.GetValue ("Data", typeof (IDictionary));
104                         } catch (SerializationException) {
105                                 // member did not exist in .NET 1.x
106                         }
107                 }
108
109                 public Exception (string message, Exception innerException)
110                 {
111                         inner_exception = innerException;
112                         this._message = message;
113                 }
114
115                 public Exception InnerException {
116                         get { return inner_exception; }
117                 }
118
119                 public virtual string HelpLink {
120                         get { return help_link; }
121                         set { help_link = value; }
122                 }
123
124                 public int HResult {
125                         get { return hresult; }
126                         protected set { hresult = value; }
127                 }
128                 
129                 internal void SetErrorCode(int hr)
130                 {
131                         HResult = hr;
132                 }
133
134                 internal void SetMessage (string s)
135                 {
136                         _message = s;
137                 }
138
139                 internal void SetStackTrace (string s)
140                 {
141                         stack_trace = s;
142                 }
143
144                 string ClassName {
145                         get {
146                                 if (class_name == null)
147                                         class_name = GetType ().ToString ();
148                                 return class_name;
149                         }
150                 }
151
152                 public virtual string Message {
153                         get {
154                                 if (_message == null)
155                                         _message = string.Format (Locale.GetText ("Exception of type '{0}' was thrown."),
156                                                 ClassName);
157
158                                 return _message;
159                         }
160                 }
161                 
162                 [MonoTODO]
163                 protected event EventHandler<SafeSerializationEventArgs> SerializeObjectState {
164                         add {
165                         }
166                         remove {
167                         }
168                 }
169
170                 public virtual string Source {
171                         get {
172                                 if (source == null) {
173                                         StackTrace st = new StackTrace (this, true);
174                                         if (st.FrameCount > 0) {
175                                                 StackFrame sf = st.GetFrame (0);
176                                                 if (st != null) {
177                                                         MethodBase method = sf.GetMethod ();
178                                                         if (method != null) {
179                                                                 source = method.DeclaringType.Assembly.UnprotectedGetName ().Name;
180                                                         }
181                                                 }
182                                         }
183                                 }
184
185                                 // source can be null
186                                 return source;
187                         }
188
189                         set {
190                                 source = value;
191                         }
192                 }
193
194                 public virtual string StackTrace {
195                         get {
196                                 if (stack_trace != null)
197                                         return stack_trace;
198
199                                 if (trace_ips == null)
200                                         /* Not thrown yet */
201                                         return null;
202
203                                 StackTrace st = new StackTrace (this, 0, true);
204                                 return stack_trace = st.ToString ();
205                         }
206                 }
207
208                 public MethodBase TargetSite {
209                         get {
210                                 StackTrace st = new StackTrace (this, true);
211                                 if (st.FrameCount > 0)
212                                         return st.GetFrame (0).GetMethod ();
213                                 
214                                 return null;
215                         }
216                 }
217
218                 public virtual IDictionary Data {
219                         get {
220                                 if (_data == null) {
221                                         // default to empty dictionary
222                                         _data = new Dictionary<object, object> ();
223                                 }
224                                 return _data;
225                         }
226                 }
227
228                 public virtual Exception GetBaseException ()
229                 {
230                         Exception inner = inner_exception;
231                                 
232                         while (inner != null)
233                         {
234                                 if (inner.InnerException != null)
235                                         inner = inner.InnerException;
236                                 else
237                                         return inner;
238                         }
239
240                         return this;
241                 }
242
243                 [SecurityPermission (SecurityAction.LinkDemand, SerializationFormatter = true)]
244                 public virtual void GetObjectData (SerializationInfo info, StreamingContext context)
245                 {
246                         if (info == null)
247                                 throw new ArgumentNullException ("info");
248
249                         info.AddValue ("ClassName", ClassName);
250                         info.AddValue ("Message", _message);
251                         info.AddValue ("InnerException", inner_exception);
252                         info.AddValue ("HelpURL", help_link);
253                         info.AddValue ("StackTraceString", StackTrace);
254                         info.AddValue ("RemoteStackTraceString", _remoteStackTraceString);
255                         info.AddValue ("RemoteStackIndex", remote_stack_index);
256                         info.AddValue ("HResult", hresult);
257                         info.AddValue ("Source", Source);
258                         info.AddValue ("ExceptionMethod", null);
259                         info.AddValue ("Data", _data, typeof (IDictionary));
260                 }
261
262                 public override string ToString ()
263                 {
264                         System.Text.StringBuilder result = new System.Text.StringBuilder (ClassName);
265                         result.Append (": ").Append (Message);
266
267                         if (null != _remoteStackTraceString)
268                                 result.Append (_remoteStackTraceString);
269                                 
270                         if (inner_exception != null) 
271                         {
272                                 result.Append (" ---> ").Append (inner_exception.ToString ());
273                                 result.Append (Environment.NewLine);
274                                 result.Append (Locale.GetText ("  --- End of inner exception stack trace ---"));
275                         }
276
277                         if (StackTrace != null)
278                                 result.Append (Environment.NewLine).Append (StackTrace);
279                         return result.ToString();
280                 }
281
282                 internal Exception FixRemotingException ()
283                 {
284                         string message = (0 == remote_stack_index) ?
285                                 Locale.GetText ("{0}{0}Server stack trace: {0}{1}{0}{0}Exception rethrown at [{2}]: {0}") :
286                                 Locale.GetText ("{1}{0}{0}Exception rethrown at [{2}]: {0}");
287                         string tmp = String.Format (message, Environment.NewLine, StackTrace, remote_stack_index);
288
289                         _remoteStackTraceString = tmp;
290                         remote_stack_index++;
291
292                         stack_trace = null;
293
294                         return this;
295                 }
296
297                 // For ExceptionDispatchInfo
298                 internal void RestoreExceptionDispatchInfo (System.Runtime.ExceptionServices.ExceptionDispatchInfo exceptionDispatchInfo)
299                 {
300                         captured_traces = (StackTrace[]) exceptionDispatchInfo.BinaryStackTraceArray;
301                         trace_ips = null;
302                         stack_trace = null;
303                 }
304
305                 //
306                 // The documentation states that this is available in 1.x,
307                 // but it was not available (MemberRefing this would fail)
308                 // and it states the signature is `override sealed', but the
309                 // correct value is `newslot' 
310                 //
311                 public new Type GetType ()
312                 {
313                         return base.GetType ();
314                 }
315
316                 internal enum ExceptionMessageKind
317                 {
318                         ThreadAbort = 1,
319                         ThreadInterrupted = 2,
320                         OutOfMemory = 3
321                 }
322
323                 internal static String GetMessageFromNativeResources (ExceptionMessageKind kind)
324                 {
325                         switch (kind) {
326                         case ExceptionMessageKind.ThreadAbort:
327                                 return "";
328                         case ExceptionMessageKind.ThreadInterrupted:
329                                 return "";
330                         case ExceptionMessageKind.OutOfMemory:
331                                 return "Out of memory";
332                         }
333                         return "";
334                 }
335         }
336 }