do not check order sequence if option /order was not used
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel.Description / WsdlImporter.cs
1 //
2 // WsdlImporter.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //      Ankit Jain <jankit@novell.com>  
7 //
8 // Copyright (C) 2005 Novell, Inc.  http://www.novell.com
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29 using System;
30 using System.Collections.Generic;
31 using System.Collections.ObjectModel;
32 using System.ServiceModel;
33 using System.ServiceModel.Channels;
34 using System.Web.Services.Description;
35 using System.Xml;
36 using System.Xml.Schema;
37
38 using SMBinding = System.ServiceModel.Channels.Binding;
39 using WSServiceDescription = System.Web.Services.Description.ServiceDescription;
40 using WSBinding = System.Web.Services.Description.Binding;
41 using WSMessage = System.Web.Services.Description.Message;
42 using QName = System.Xml.XmlQualifiedName;
43
44 namespace System.ServiceModel.Description
45 {
46         [MonoTODO]
47         public class WsdlImporter : MetadataImporter
48         {
49                 ServiceDescriptionCollection wsdl_documents;
50                 XmlSchemaSet xmlschemas;
51                 List<XmlElement> policies; /* ?? */
52                 MetadataSet metadata;
53
54                 KeyedByTypeCollection<IWsdlImportExtension> wsdl_extensions;
55                         
56                 //Imported
57                 Collection<ContractDescription> contracts = null;
58                 ServiceEndpointCollection endpoint_colln = null;
59
60                 public WsdlImporter (
61                         MetadataSet metadata,
62                         IEnumerable<IPolicyImportExtension> policyImportExtensions,
63                         IEnumerable<IWsdlImportExtension> wsdlImportExtensions)
64                         : base (policyImportExtensions)
65                 {
66                         if (metadata == null)
67                                 throw new ArgumentNullException ("metadata");
68                         
69                         if (wsdlImportExtensions == null) {
70                                 wsdl_extensions = new KeyedByTypeCollection<IWsdlImportExtension> ();
71
72                                 wsdl_extensions.Add (new DataContractSerializerMessageContractImporter ());
73                                 wsdl_extensions.Add (new XmlSerializerMessageContractImporter ());
74                                 //wsdl_extensions.Add (new MessageEncodingBindingElementImporter ());
75                                 wsdl_extensions.Add (new TransportBindingElementImporter ());
76                                 wsdl_extensions.Add (new StandardBindingImporter ());
77                         } else {
78                                 wsdl_extensions = new KeyedByTypeCollection<IWsdlImportExtension> (wsdlImportExtensions);
79                         }
80
81                         // It is okay to fill these members immediately when WsdlImporter.ctor() is invoked
82                         // i.e. after this .ctor(), those metadata docs are not considered anymore.
83                         this.metadata = metadata;
84                         this.wsdl_documents = new ServiceDescriptionCollection ();
85                         this.xmlschemas = new XmlSchemaSet ();
86                         this.policies = new List<XmlElement> ();
87
88                         foreach (MetadataSection ms in metadata.MetadataSections) {
89                                 if (ms.Dialect == MetadataSection.ServiceDescriptionDialect &&
90                                         ms.Metadata.GetType () == typeof (WSServiceDescription))
91                                         wsdl_documents.Add ((WSServiceDescription) ms.Metadata);
92                                 else
93                                 if (ms.Dialect == MetadataSection.XmlSchemaDialect &&
94                                         ms.Metadata.GetType () == typeof (XmlSchema))
95                                         xmlschemas.Add ((XmlSchema) ms.Metadata);
96                         }
97                 }
98
99                 public WsdlImporter (MetadataSet metadata)
100                         : this (metadata, null, null)
101                 {
102                 }
103
104                 public ServiceDescriptionCollection WsdlDocuments {
105                         get { return wsdl_documents; }
106                 }
107
108                 public KeyedByTypeCollection <IWsdlImportExtension> WsdlImportExtensions {
109                         get { return wsdl_extensions; }
110                 }
111
112                 public XmlSchemaSet XmlSchemas {
113                         get { return xmlschemas; }
114                 }
115
116                 public Collection<SMBinding> ImportAllBindings ()
117                 {
118                         Collection<SMBinding> bindings = new Collection<SMBinding> ();
119
120                         foreach (WSServiceDescription sd in wsdl_documents)
121                                 foreach (WSBinding binding in sd.Bindings)
122                                         bindings.Add (ImportBinding (binding));
123
124                         return bindings;
125                 }
126
127                 public SMBinding ImportBinding (WSBinding binding)
128                 {
129                         /* Default, CustomBinding.. */
130                         CustomBinding smbinding = new CustomBinding ();
131
132                         foreach (IWsdlImportExtension extension in wsdl_extensions)
133                                 extension.BeforeImport (wsdl_documents, xmlschemas, policies);
134
135                         smbinding.Name = binding.Name;
136                         smbinding.Namespace = binding.ServiceDescription.TargetNamespace;
137
138                         //FIXME: Added by MessageEncodingBindingElementConverter.ImportPolicy
139                         smbinding.Elements.Add (new TextMessageEncodingBindingElement ());
140
141                         /*ImportContract
142                         PortType portType = null;
143                         foreach (WSServiceDescription sd in wsdl_documents) {
144                                 portType = sd.PortTypes [binding.Type.Name];
145                                 if (portType != null)
146                                         break;
147                         }
148
149                         //FIXME: if portType == null
150                         */
151                         
152                         // FIXME: ImportContract here..
153
154                         return smbinding;
155                 }
156
157                 public override Collection<ContractDescription> ImportAllContracts ()
158                 {
159                         if (contracts != null)
160                                 return contracts;
161
162                         contracts = new Collection<ContractDescription> ();
163
164                         foreach (WSServiceDescription sd in wsdl_documents) {
165                                 foreach (PortType pt in sd.PortTypes)
166                                         contracts.Add (ImportContract (pt));
167                         }
168
169                         return contracts;
170                 }
171
172                 public override ServiceEndpointCollection ImportAllEndpoints ()
173                 {
174                         if (endpoint_colln != null)
175                                 return endpoint_colln;
176
177                         endpoint_colln = new ServiceEndpointCollection ();
178
179                         foreach (IWsdlImportExtension extension in wsdl_extensions) {
180                                 extension.BeforeImport (wsdl_documents, xmlschemas, policies);
181                         }
182
183                         foreach (WSServiceDescription wsd in wsdl_documents)
184                                 foreach (Service service in wsd.Services)
185                                         foreach (Port port in service.Ports)
186                                                 endpoint_colln.Add (ImportEndpoint (port));
187
188                         return endpoint_colln;
189                 }
190
191                 public ContractDescription ImportContract (PortType wsdlPortType)
192                 {
193                         foreach (IWsdlImportExtension extension in wsdl_extensions) {
194                                 extension.BeforeImport (wsdl_documents, xmlschemas, policies);
195                         }
196
197                         ContractDescription cd = new ContractDescription (wsdlPortType.Name, wsdlPortType.ServiceDescription.TargetNamespace);
198
199                         foreach (Operation op in wsdlPortType.Operations) {
200                                 OperationDescription op_descr = new OperationDescription (op.Name, cd);
201
202                                 foreach (OperationMessage opmsg in op.Messages) {
203                                         /* OperationMessageCollection */
204                                         MessageDescription msg_descr;
205                                         MessageDirection dir = MessageDirection.Input;
206                                         string action = "";
207
208                                         if (opmsg.GetType () == typeof (OperationInput))
209                                                 dir = MessageDirection.Input;
210                                         else if (opmsg.GetType () == typeof (OperationOutput))
211                                                 dir = MessageDirection.Output;
212                                         /* FIXME: OperationFault--> OperationDescription.Faults ? */
213
214                                         if (opmsg.ExtensibleAttributes != null) {
215                                                 for (int i = 0; i < opmsg.ExtensibleAttributes.Length; i++) {
216                                                         if (opmsg.ExtensibleAttributes [i].LocalName == "Action" &&
217                                                                 opmsg.ExtensibleAttributes [i].NamespaceURI == "http://www.w3.org/2006/05/addressing/wsdl")
218                                                                 /* addressing:Action */
219                                                                 action = opmsg.ExtensibleAttributes [i].Value;
220                                                         /* FIXME: other attributes ? */
221                                                 }
222                                         }
223
224                                         // fill Action from operation binding if required.
225                                         if (action == "") {
226                                                 if (dir != MessageDirection.Input)
227                                                         action = GetActionFromOperationBinding (wsdlPortType, op.Name);
228                                                 else
229                                                         action = "*";
230                                         }
231
232                                         msg_descr = new MessageDescription (action, dir);
233                                         /* FIXME: Headers ? */
234
235                                         op_descr.Messages.Add (msg_descr);
236                                 }
237
238                                 cd.Operations.Add (op_descr);
239                         }
240
241                         WsdlContractConversionContext context = new WsdlContractConversionContext (cd, wsdlPortType);
242                         foreach (IWsdlImportExtension extension in wsdl_extensions)
243                                 extension.ImportContract (this, context);
244
245                         return cd;
246                 }
247
248                 string GetActionFromOperationBinding (PortType pt, string opName)
249                 {
250                         foreach (WSBinding binding in pt.ServiceDescription.Bindings) {
251                                 foreach (OperationBinding ob in binding.Operations) {
252                                         if (ob.Name != opName)
253                                                 continue;
254                                         foreach (var ext in ob.Extensions) {
255                                                 var sob = ext as SoapOperationBinding;
256                                                 if (sob == null)
257                                                         continue;
258                                                 return sob.SoapAction;
259                                         }
260                                         return String.Empty;
261                                 }
262                         }
263                         return String.Empty;
264                 }
265
266                 public ServiceEndpoint ImportEndpoint (Port wsdlPort)
267                 {
268                         foreach (IWsdlImportExtension extension in wsdl_extensions) {
269                                 extension.BeforeImport (wsdl_documents, xmlschemas, policies);
270                         }
271
272                         //Get the corresponding contract
273                         //via the PortType
274                         WSBinding wsb = wsdlPort.Service.ServiceDescription.Bindings [wsdlPort.Binding.Name];
275                         if (wsb == null)
276                                 //FIXME
277                                 throw new Exception (String.Format ("Binding named {0} not found.", wsdlPort.Binding.Name));
278
279                         SMBinding binding = ImportBinding (wsb);
280
281                         PortType port_type = null;
282                         foreach (WSServiceDescription sd in wsdl_documents) {
283                                 port_type = sd.PortTypes [wsb.Type.Name];
284                                 if (port_type != null)
285                                         break;
286                         }
287
288                         if (port_type == null)
289                                 //FIXME
290                                 throw new Exception (String.Format ("PortType named {0} not found.", wsb.Type.Name));
291
292                         ContractDescription contract = ImportContract (port_type);
293                         ServiceEndpoint sep = new ServiceEndpoint (contract);
294
295                         sep.Binding = binding;
296
297                         WsdlContractConversionContext contract_context = new WsdlContractConversionContext (contract, port_type);
298                         WsdlEndpointConversionContext endpoint_context = new WsdlEndpointConversionContext (
299                                         contract_context, sep, wsdlPort, wsb);
300
301                         foreach (IWsdlImportExtension extension in wsdl_extensions)
302                                 extension.ImportEndpoint (this, endpoint_context);
303
304                         return sep;
305                 }
306
307                 public ServiceEndpointCollection ImportEndpoints (
308                         WSBinding binding)
309                 {
310                         throw new NotImplementedException ();
311                 }
312
313                 public ServiceEndpointCollection ImportEndpoints (
314                         PortType portType)
315                 {
316                         throw new NotImplementedException ();
317                 }
318
319                 public ServiceEndpointCollection ImportEndpoints (
320                         Service service)
321                 {
322                         throw new NotImplementedException ();
323                 }
324         }
325 }