1 //-----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //-----------------------------------------------------------------------------
4 
5 namespace System.ServiceModel.Channels
6 {
7     using System;
8     using System.Globalization;
9 
10     public abstract class FaultConverter
11     {
GetDefaultFaultConverter(MessageVersion version)12         public static FaultConverter GetDefaultFaultConverter(MessageVersion version)
13         {
14             return new DefaultFaultConverter(version);
15         }
16 
OnTryCreateException(Message message, MessageFault fault, out Exception exception)17         protected abstract bool OnTryCreateException(Message message, MessageFault fault, out Exception exception);
OnTryCreateFaultMessage(Exception exception, out Message message)18         protected abstract bool OnTryCreateFaultMessage(Exception exception, out Message message);
19 
TryCreateException(Message message, MessageFault fault, out Exception exception)20         public bool TryCreateException(Message message, MessageFault fault, out Exception exception)
21         {
22             if (message == null)
23             {
24                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
25             }
26             if (fault == null)
27             {
28                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("fault");
29             }
30 
31             bool created = this.OnTryCreateException(message, fault, out exception);
32 
33             if (created)
34             {
35                 if (exception == null)
36                 {
37                     string text = SR.GetString(SR.FaultConverterDidNotCreateException, this.GetType().Name);
38                     Exception error = new InvalidOperationException(text);
39                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(error);
40                 }
41             }
42             else
43             {
44                 if (exception != null)
45                 {
46                     string text = SR.GetString(SR.FaultConverterCreatedException, this.GetType().Name);
47                     Exception error = new InvalidOperationException(text, exception);
48                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(error);
49                 }
50             }
51 
52             return created;
53         }
54 
TryCreateFaultMessage(Exception exception, out Message message)55         public bool TryCreateFaultMessage(Exception exception, out Message message)
56         {
57             bool created = this.OnTryCreateFaultMessage(exception, out message);
58 
59             if (created)
60             {
61                 if (message == null)
62                 {
63                     string text = SR.GetString(SR.FaultConverterDidNotCreateFaultMessage, this.GetType().Name);
64                     Exception error = new InvalidOperationException(text);
65                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(error);
66                 }
67             }
68             else
69             {
70                 if (message != null)
71                 {
72                     string text = SR.GetString(SR.FaultConverterCreatedFaultMessage, this.GetType().Name);
73                     Exception error = new InvalidOperationException(text);
74                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(error);
75                 }
76             }
77 
78             return created;
79         }
80 
81         class DefaultFaultConverter : FaultConverter
82         {
83             MessageVersion version;
84 
DefaultFaultConverter(MessageVersion version)85             internal DefaultFaultConverter(MessageVersion version)
86             {
87                 this.version = version;
88             }
89 
OnTryCreateException(Message message, MessageFault fault, out Exception exception)90             protected override bool OnTryCreateException(Message message, MessageFault fault, out Exception exception)
91             {
92                 exception = null;
93 
94                 // SOAP MustUnderstand
95                 if (string.Compare(fault.Code.Namespace, version.Envelope.Namespace, StringComparison.Ordinal) == 0
96                     && string.Compare(fault.Code.Name, MessageStrings.MustUnderstandFault, StringComparison.Ordinal) == 0)
97                 {
98                     exception = new ProtocolException(fault.Reason.GetMatchingTranslation(CultureInfo.CurrentCulture).Text);
99                     return true;
100                 }
101 
102                 bool checkSender;
103                 bool checkReceiver;
104                 FaultCode code;
105 
106                 if (version.Envelope == EnvelopeVersion.Soap11)
107                 {
108                     checkSender = true;
109                     checkReceiver = true;
110                     code = fault.Code;
111                 }
112                 else
113                 {
114                     checkSender = fault.Code.IsSenderFault;
115                     checkReceiver = fault.Code.IsReceiverFault;
116                     code = fault.Code.SubCode;
117                 }
118 
119                 if (code == null)
120                 {
121                     return false;
122                 }
123 
124                 if (code.Namespace == null)
125                 {
126                     return false;
127                 }
128 
129                 if (checkSender)
130                 {
131                     // WS-Addressing
132                     if (string.Compare(code.Namespace, version.Addressing.Namespace, StringComparison.Ordinal) == 0)
133                     {
134                         if (string.Compare(code.Name, AddressingStrings.ActionNotSupported, StringComparison.Ordinal) == 0)
135                         {
136                             exception = new ActionNotSupportedException(fault.Reason.GetMatchingTranslation(CultureInfo.CurrentCulture).Text);
137                             return true;
138                         }
139                         else if (string.Compare(code.Name, AddressingStrings.DestinationUnreachable, StringComparison.Ordinal) == 0)
140                         {
141                             exception = new EndpointNotFoundException(fault.Reason.GetMatchingTranslation(CultureInfo.CurrentCulture).Text);
142                             return true;
143                         }
144                         else if (string.Compare(code.Name, Addressing10Strings.InvalidAddressingHeader, StringComparison.Ordinal) == 0)
145                         {
146                             if (code.SubCode != null && string.Compare(code.SubCode.Namespace, version.Addressing.Namespace, StringComparison.Ordinal) == 0 &&
147                                 string.Compare(code.SubCode.Name, Addressing10Strings.InvalidCardinality, StringComparison.Ordinal) == 0)
148                             {
149                                 exception = new MessageHeaderException(fault.Reason.GetMatchingTranslation(CultureInfo.CurrentCulture).Text, true);
150                                 return true;
151                             }
152                         }
153                         else if (version.Addressing == AddressingVersion.WSAddressing10)
154                         {
155                             if (string.Compare(code.Name, Addressing10Strings.MessageAddressingHeaderRequired, StringComparison.Ordinal) == 0)
156                             {
157                                 exception = new MessageHeaderException(fault.Reason.GetMatchingTranslation(CultureInfo.CurrentCulture).Text);
158                                 return true;
159                             }
160                             else if (string.Compare(code.Name, Addressing10Strings.InvalidAddressingHeader, StringComparison.Ordinal) == 0)
161                             {
162                                 exception = new ProtocolException(fault.Reason.GetMatchingTranslation(CultureInfo.CurrentCulture).Text);
163                                 return true;
164                             }
165                         }
166                         else
167                         {
168                             if (string.Compare(code.Name, Addressing200408Strings.MessageInformationHeaderRequired, StringComparison.Ordinal) == 0)
169                             {
170                                 exception = new ProtocolException(fault.Reason.GetMatchingTranslation(CultureInfo.CurrentCulture).Text);
171                                 return true;
172                             }
173                             else if (string.Compare(code.Name, Addressing200408Strings.InvalidMessageInformationHeader, StringComparison.Ordinal) == 0)
174                             {
175                                 exception = new ProtocolException(fault.Reason.GetMatchingTranslation(CultureInfo.CurrentCulture).Text);
176                                 return true;
177                             }
178                         }
179                     }
180                 }
181 
182                 if (checkReceiver)
183                 {
184                     // WS-Addressing
185                     if (string.Compare(code.Namespace, version.Addressing.Namespace, StringComparison.Ordinal) == 0)
186                     {
187                         if (string.Compare(code.Name, AddressingStrings.EndpointUnavailable, StringComparison.Ordinal) == 0)
188                         {
189                             exception = new ServerTooBusyException(fault.Reason.GetMatchingTranslation(CultureInfo.CurrentCulture).Text);
190                             return true;
191                         }
192                     }
193                 }
194 
195                 return false;
196             }
197 
OnTryCreateFaultMessage(Exception exception, out Message message)198             protected override bool OnTryCreateFaultMessage(Exception exception, out Message message)
199             {
200                 // WSA
201                 if (this.version.Addressing == AddressingVersion.WSAddressing10)
202                 {
203                     if (exception is MessageHeaderException)
204                     {
205                         MessageHeaderException mhe = exception as MessageHeaderException;
206                         if (mhe.HeaderNamespace == AddressingVersion.WSAddressing10.Namespace)
207                         {
208                             message = mhe.ProvideFault(this.version);
209                             return true;
210                         }
211                     }
212                     else if (exception is ActionMismatchAddressingException)
213                     {
214                         ActionMismatchAddressingException amae = exception as ActionMismatchAddressingException;
215                         message = amae.ProvideFault(this.version);
216                         return true;
217                     }
218                 }
219                 if (this.version.Addressing != AddressingVersion.None)
220                 {
221                     if (exception is ActionNotSupportedException)
222                     {
223                         ActionNotSupportedException anse = exception as ActionNotSupportedException;
224                         message = anse.ProvideFault(this.version);
225                         return true;
226                     }
227                 }
228 
229                 // SOAP
230                 if (exception is MustUnderstandSoapException)
231                 {
232                     MustUnderstandSoapException muse = exception as MustUnderstandSoapException;
233                     message = muse.ProvideFault(this.version);
234                     return true;
235                 }
236 
237                 message = null;
238                 return false;
239             }
240         }
241     }
242 }
243