Merge pull request #3528 from BrzVlad/fix-sgen-check-before-collections
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel.Channels / FaultConverter.cs
1 //
2 // FaultConverter.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2006 Novell, Inc.  http://www.novell.com
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 using System;
29 using System.Collections.Generic;
30 using System.ServiceModel;
31 using System.ServiceModel.Description;
32
33 namespace System.ServiceModel.Channels
34 {
35         public abstract class FaultConverter
36         {
37                 public static FaultConverter GetDefaultFaultConverter (MessageVersion version)
38                 {
39                         if (version == null)
40                                 throw new ArgumentNullException ("version");
41                         return new SimpleFaultConverter (version);
42                 }
43
44                 protected FaultConverter ()
45                 {
46                 }
47
48                 [MonoTODO]
49                 protected abstract bool OnTryCreateException (
50                         Message message, MessageFault fault, out Exception exception);
51
52                 [MonoTODO]
53                 protected abstract bool OnTryCreateFaultMessage (
54                         Exception exception, out Message message);
55
56                 public bool TryCreateException (Message message, MessageFault fault, out Exception exception)
57                 {
58                         return OnTryCreateException (message, fault, out exception);
59                 }
60
61                 public bool TryCreateFaultMessage (Exception exception, out Message message)
62                 {
63                         return OnTryCreateFaultMessage (exception, out message);
64                 }
65         }
66
67         class SimpleFaultConverter : FaultConverter
68         {
69                 static readonly Dictionary<Type,string> map;
70                 
71                 static SimpleFaultConverter ()
72                 {
73                         map = new Dictionary<Type,string> ();
74                         map [typeof (EndpointNotFoundException)] = "DestinationUnreachable";
75                         map [typeof (ActionNotSupportedException)] = "ActionNotSupported";
76                 }
77
78                 MessageVersion version;
79
80                 public SimpleFaultConverter (MessageVersion version)
81                 {
82                         this.version = version;
83                 }
84
85                 protected override bool OnTryCreateException (
86                         Message message, MessageFault fault, out Exception error)
87                 {
88                         if (message == null)
89                                 throw new ArgumentNullException ("message");
90                         if (fault == null)
91                                 throw new ArgumentNullException ("fault");
92
93                         error = null;
94
95                         FaultCode fc;
96                         if (version.Envelope.Equals (EnvelopeVersion.Soap11))
97                                 fc = fault.Code;
98                         else
99                                 fc = fault.Code.SubCode;
100
101                         if (fc == null)
102                                 return false;
103
104                         string msg = fault.Reason.GetMatchingTranslation ().Text;
105                         if (fc.Namespace == message.Version.Addressing.Namespace) {
106                                 switch (fc.Name) {
107                                 case "ActionNotSupported":
108                                         error = new ActionNotSupportedException (msg);
109                                         return true;
110                                 case "DestinationUnreachable":
111                                         error = new EndpointNotFoundException (msg);
112                                         return true;
113                                 }
114                         }
115
116                         return false;
117                 }
118
119                 protected override bool OnTryCreateFaultMessage (Exception error, out Message message)
120                 {
121                         if (version.Envelope.Equals (EnvelopeVersion.None)) {
122                                 message = null;
123                                 return false;
124                         }
125
126                         string action;
127                         if (!map.TryGetValue (error.GetType (), out action)) {
128                                 message = null;
129                                 return false;
130                         }
131
132                         FaultCode fc;
133                         if (version.Envelope.Equals (EnvelopeVersion.Soap12))
134                                 fc = new FaultCode ("Sender", version.Envelope.Namespace, new FaultCode (action, version.Addressing.Namespace));
135                         else
136                                 fc = new FaultCode (action, version.Addressing.Namespace);
137
138                         OperationContext ctx = OperationContext.Current;
139                         // FIXME: support more fault code depending on the exception type.
140 #if !MOBILE && !XAMMAC_4_5
141                         // FIXME: set correct fault reason.
142                         if (ctx != null && ctx.EndpointDispatcher.ChannelDispatcher.IncludeExceptionDetailInFaults) {
143                                 ExceptionDetail detail = new ExceptionDetail (error);
144                                 message = Message.CreateMessage (version, fc,
145                                         error.Message, detail, version.Addressing.FaultNamespace);
146                         }
147                         else
148 #endif
149                                 message = Message.CreateMessage (version, fc, error.Message, version.Addressing.FaultNamespace);
150
151                         return true;
152                 }
153         }
154 }