Merge pull request #1218 from AndreyAkinshin/master
[mono.git] / mcs / class / System.Web.Services / System.Web.Services.Description / SoapProtocolReflector.cs
1 // 
2 // System.Web.Services.Description.SoapProtocolReflector.cs
3 //
4 // Author:
5 //   Tim Coleman (tim@timcoleman.com)
6 //   Lluis Sanchez Gual (lluis@ximian.com)
7 //
8 // Copyright (C) Tim Coleman, 2002
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Web.Services;
33 using System.Web.Services.Protocols;
34 using System.Xml.Serialization;
35 using System.Xml.Schema;
36 using System.Xml;
37
38 namespace System.Web.Services.Description {
39
40         internal abstract class SoapProtocolReflector : ProtocolReflector 
41         {
42                 #region Fields
43
44                 SoapBinding soapBinding;
45
46                 #endregion // Fields
47
48                 #region Constructors
49
50                 public SoapProtocolReflector ()
51                 {
52                 }
53                 
54                 #endregion // Constructors
55
56                 #region Properties
57
58                 public abstract SoapExtensionReflector ExtensionReflector { get; }
59
60                 #endregion
61
62                 #region Methods
63
64                 protected override void BeginClass ()
65                 {
66                         ExtensionReflector.ReflectDescription ();
67                 }
68
69                 protected override void EndClass ()
70                 {
71                 }
72
73                 protected override bool ReflectMethod ()
74                 {
75                         SoapMethodStubInfo method = (SoapMethodStubInfo) MethodStubInfo;
76                         bool existing = false;
77                         if (Parent != null) {
78                                 if (Parent.MappedMessagesIn.ContainsKey (method.MethodInfo))
79                                         existing = true;
80                                 else {
81                                         Parent.MappedMessagesIn [method.MethodInfo] = InputMessage;
82                                         Parent.MappedMessagesOut [method.MethodInfo] = OutputMessage;
83                                 }
84                         }
85                         if (!existing)
86                                 ImportMessageParts ();
87                         ExtensionReflector.ReflectMethod ();
88
89                         return !existing;
90                 }
91                 
92                 void ImportMessageParts ()
93                 {
94                         SoapMethodStubInfo method = (SoapMethodStubInfo) MethodStubInfo;
95                         ImportMessage (method.InputMembersMapping, InputMessage);
96                         ImportMessage (method.OutputMembersMapping, OutputMessage);
97                                 
98
99                         foreach (SoapHeaderMapping hf in method.Headers)
100                         {
101                                 if (hf.Custom) continue;
102                                 
103                                 Message msg = new Message ();
104                                 msg.Name = Operation.Name + hf.HeaderType.Name;
105                                 MessagePart part = new MessagePart ();
106                                 part.Name = hf.HeaderType.Name;
107                                 msg.Parts.Add (part);
108                                 ServiceDescription.Messages.Add (msg);
109
110                                 if (method.Use == SoapBindingUse.Literal)
111                                 {
112                                         // MS.NET reflects header classes in a weird way. The root element
113                                         // name is the CLR class name unless it is specified in an XmlRootAttribute.
114                                         // The usual is to use the xml type name by default, but not in this case.
115                                 
116                                         XmlRootAttribute root;
117                                         XmlAttributes ats = new XmlAttributes (hf.HeaderType);
118                                         if (ats.XmlRoot != null) root = ats.XmlRoot;
119                                         else root = new XmlRootAttribute (hf.HeaderType.Name);
120                                         
121                                         if (root.Namespace == null) root.Namespace = TypeInfo.LogicalType.GetWebServiceLiteralNamespace (ServiceDescription.TargetNamespace);
122                                         if (root.ElementName == null) root.ElementName = hf.HeaderType.Name;
123                                         
124                                         XmlTypeMapping mapping = ReflectionImporter.ImportTypeMapping (hf.HeaderType, root);
125                                         part.Element = new XmlQualifiedName (mapping.ElementName, mapping.Namespace);
126                                         SchemaExporter.ExportTypeMapping (mapping);
127                                 }
128                                 else
129                                 {
130                                         XmlTypeMapping mapping = SoapReflectionImporter.ImportTypeMapping (hf.HeaderType, TypeInfo.LogicalType.GetWebServiceEncodedNamespace (ServiceDescription.TargetNamespace));
131                                         part.Type = new XmlQualifiedName (mapping.ElementName, mapping.Namespace);
132                                         SoapSchemaExporter.ExportTypeMapping (mapping);
133                                 }
134                         }
135                 }
136                 
137                 void ImportMessage (XmlMembersMapping members, Message msg)
138                 {
139                         SoapMethodStubInfo method = (SoapMethodStubInfo) MethodStubInfo;
140                         bool needsEnclosingElement = (method.ParameterStyle == SoapParameterStyle.Wrapped && 
141                                                                                         method.SoapBindingStyle == SoapBindingStyle.Document);
142
143                         if (needsEnclosingElement)
144                         {
145                                 MessagePart part = new MessagePart ();
146                                 part.Name = "parameters";
147                                 XmlQualifiedName qname = new XmlQualifiedName (members.ElementName, members.Namespace);
148                                 if (method.Use == SoapBindingUse.Literal) part.Element = qname;
149                                 else part.Type = qname;
150                                 msg.Parts.Add (part);
151                         }
152                         else
153                         {
154                                 for (int n=0; n<members.Count; n++)
155                                 {
156                                         MessagePart part = new MessagePart ();
157                                         part.Name = members[n].MemberName;
158                                         
159                                         if (method.Use == SoapBindingUse.Literal) {
160                                                 if (members[n].Any)
161                                                         part.Type = new XmlQualifiedName ("any", members[n].Namespace);
162                                                 else
163                                                         part.Element = new XmlQualifiedName (members[n].ElementName, members[n].Namespace);
164                                         }
165                                         else {
166                                                 string namesp = members[n].TypeNamespace;
167                                                 if (namesp == "") namesp = members[n].Namespace;
168                                                 part.Name = members[n].ElementName;
169                                                 part.Type = new XmlQualifiedName (members[n].TypeName, namesp);
170                                         }
171                                         msg.Parts.Add (part);
172                                 }
173                         }
174                         
175                         
176                         if (method.Use == SoapBindingUse.Literal)
177                                 SchemaExporter.ExportMembersMapping (members);
178                         else
179                                 SoapSchemaExporter.ExportMembersMapping (members, needsEnclosingElement);
180                 }
181
182                 protected override string ReflectMethodBinding ()
183                 {
184                         return ((SoapMethodStubInfo)MethodStubInfo).Binding;
185                 }
186
187                 #endregion
188         }
189
190         internal class Soap11ProtocolReflector : SoapProtocolReflector
191         {
192                 SoapExtensionReflector reflector;
193                 
194                 public Soap11ProtocolReflector ()
195                 {
196                         reflector = new Soap11BindingExtensionReflector ();
197                         reflector.ReflectionContext = this;
198                 }
199
200                 public override string ProtocolName {
201                         get { return "Soap"; }
202                 }
203
204                 public override SoapExtensionReflector ExtensionReflector {
205                         get { return reflector; }
206                 }
207         }
208
209         internal class Soap12ProtocolReflector : SoapProtocolReflector
210         {
211                 SoapExtensionReflector reflector;
212                 
213                 public Soap12ProtocolReflector ()
214                 {
215                         reflector = new Soap12BindingExtensionReflector ();
216                         reflector.ReflectionContext = this;
217                 }
218
219                 public override string ProtocolName {
220                         get { return "Soap12"; }
221                 }
222
223                 public override SoapExtensionReflector ExtensionReflector {
224                         get { return reflector; }
225                 }
226         }
227 }