Merge pull request #1412 from esdrubal/stackframe
[mono.git] / mcs / class / corlib / System / AggregateException.cs
1 //
2 // AggregateException.cs
3 //
4 // Authors:
5 //   Marek Safar (marek.safar@gmail.com)
6 //
7 // Copyright (c) 2008 Jérémie "Garuma" Laval
8 // Copyright (C) 2013 Xamarin Inc (http://www.xamarin.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a copy
11 // of this software and associated documentation files (the "Software"), to deal
12 // in the Software without restriction, including without limitation the rights
13 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 // copies of the Software, and to permit persons to whom the Software is
15 // furnished to do so, subject to the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be included in
18 // all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 // THE SOFTWARE.
27 //
28 //
29
30 #if NET_4_0
31 using System;
32 using System.Collections.ObjectModel;
33 using System.Collections.Generic;
34 using System.Runtime.Serialization;
35
36 namespace System
37 {
38         [System.SerializableAttribute]
39         [System.Diagnostics.DebuggerDisplay ("Count = {InnerExceptions.Count}")]
40         public class AggregateException : Exception
41         {
42                 List<Exception> innerExceptions = new List<Exception> ();
43                 const string defaultMessage = "One or more errors occurred";
44                 
45                 public AggregateException () : base (defaultMessage)
46                 {
47                 }
48                 
49                 public AggregateException (string message): base (message)
50                 {
51                 }
52                 
53                 public AggregateException (string message, Exception innerException): base (message, innerException)
54                 {
55                         if (innerException == null)
56                                 throw new ArgumentNullException ("innerException");
57                         innerExceptions.Add (innerException);
58                 }
59                 
60                 protected AggregateException (SerializationInfo info, StreamingContext context)
61                         : base (info, context)
62                 {
63                 }
64                 
65                 public AggregateException (params Exception[] innerExceptions)
66                         : this (defaultMessage, innerExceptions)
67                 {
68                 }
69                 
70                 public AggregateException (string message, params Exception[] innerExceptions)
71                         : base (message, innerExceptions == null || innerExceptions.Length == 0 ? null : innerExceptions[0])
72                 {
73                         if (innerExceptions == null)
74                                 throw new ArgumentNullException ("innerExceptions");
75                         foreach (var exception in innerExceptions)
76                                 if (exception == null)
77                                         throw new ArgumentException ("One of the inner exception is null", "innerExceptions");
78
79                         this.innerExceptions.AddRange (innerExceptions);
80                 }
81                 
82                 public AggregateException (IEnumerable<Exception> innerExceptions)
83                         : this (defaultMessage, innerExceptions)
84                 {
85                 }
86                 
87                 public AggregateException (string message, IEnumerable<Exception> innerExceptions)
88                         : this (message, new List<Exception> (innerExceptions).ToArray ())
89                 {
90                 }
91                 
92                 public AggregateException Flatten ()
93                 {
94                         List<Exception> inner = new List<Exception> ();
95                         
96                         foreach (Exception e in innerExceptions) {
97                                 AggregateException aggEx = e as AggregateException;
98                                 if (aggEx != null) {
99                                         inner.AddRange (aggEx.Flatten ().InnerExceptions);
100                                 } else {
101                                         inner.Add (e);
102                                 }                               
103                         }
104
105                         return new AggregateException (inner);
106                 }
107                 
108                 public void Handle (Func<Exception, bool> predicate)
109                 {
110                         if (predicate == null)
111                                 throw new ArgumentNullException ("predicate");
112
113                         List<Exception> failed = new List<Exception> ();
114                         foreach (var e in innerExceptions) {
115                                 if (!predicate (e))
116                                         failed.Add (e);
117                         }
118
119                         if (failed.Count > 0)
120                                 throw new AggregateException (failed);
121                 }
122                 
123                 public ReadOnlyCollection<Exception> InnerExceptions {
124                         get {
125                                 return innerExceptions.AsReadOnly ();
126                         }
127                 }
128
129                 public override string ToString ()
130                 {
131                         System.Text.StringBuilder finalMessage = new System.Text.StringBuilder (base.ToString ());
132
133                         int currentIndex = -1;
134                         foreach (Exception e in innerExceptions) {
135                                 finalMessage.Append (Environment.NewLine);
136                                 finalMessage.Append (" --> (Inner exception ");
137                                 finalMessage.Append (++currentIndex);
138                                 finalMessage.Append (") ");
139                                 finalMessage.Append (e.ToString ());
140                                 finalMessage.Append (Environment.NewLine);
141                         }
142                         return finalMessage.ToString ();
143                 }
144
145                 public override void GetObjectData (SerializationInfo info,     StreamingContext context)
146                 {
147                         if (info == null) {
148                                 throw new ArgumentNullException("info");
149                         }
150                         base.GetObjectData(info, context);
151                         info.AddValue ("InnerExceptions", innerExceptions.ToArray(), typeof (Exception[]));
152                 }
153
154                 public override Exception GetBaseException ()
155                 {
156                         Exception inner = this;
157                         for (var ae = this; ae.innerExceptions.Count == 1;) {
158                                 inner = ae.InnerExceptions [0];
159
160                                 var aei = inner as AggregateException;
161                                 if (aei == null)
162                                         break;
163
164                                 ae = aei;
165                         }
166
167                         return inner;
168                 }
169         }
170 }
171 #endif