Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.ServiceModel / System / ServiceModel / Description / WsdlImporter.cs
1 //-----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //-----------------------------------------------------------------------------
4 namespace System.ServiceModel.Description
5 {
6     using System.Collections;
7     using System.Collections.Generic;
8     using System.Collections.ObjectModel;
9     using System.Globalization;
10     using System.Runtime;
11     using System.Security;
12     using System.ServiceModel;
13     using System.ServiceModel.Channels;
14     using System.Text;
15     using System.Xml;
16     using System.Xml.Schema;
17     using ConfigNS = System.ServiceModel.Configuration;
18     using WsdlConfigNS = System.Web.Services.Configuration;
19     using WsdlNS = System.Web.Services.Description;
20
21     public class WsdlImporter : MetadataImporter
22     {
23         readonly Dictionary<WsdlNS.NamedItem, WsdlImportException> importErrors = new Dictionary<WsdlNS.NamedItem, WsdlImportException>();
24         bool isFaulted = false;
25
26         readonly Dictionary<XmlQualifiedName, WsdlContractConversionContext> importedPortTypes = new Dictionary<XmlQualifiedName, WsdlContractConversionContext>();
27         readonly Dictionary<XmlQualifiedName, WsdlEndpointConversionContext> importedBindings = new Dictionary<XmlQualifiedName, WsdlEndpointConversionContext>();
28         readonly Dictionary<WsdlNS.Port, ServiceEndpoint> importedPorts = new Dictionary<WsdlNS.Port, ServiceEndpoint>();
29
30         readonly KeyedByTypeCollection<IWsdlImportExtension> wsdlExtensions;
31
32         readonly WsdlNS.ServiceDescriptionCollection wsdlDocuments = new WsdlNS.ServiceDescriptionCollection();
33         readonly XmlSchemaSet xmlSchemas = WsdlExporter.GetEmptySchemaSet();
34         readonly Dictionary<string, XmlElement> policyDocuments = new Dictionary<string, XmlElement>();
35         readonly Dictionary<string, string> warnings = new Dictionary<string, string>();
36         WsdlPolicyReader wsdlPolicyReader;
37
38         bool beforeImportCalled = false;
39
40         public WsdlImporter(MetadataSet metadata)
41             : this(metadata, null, null, MetadataImporterQuotas.Defaults)
42         {
43         }
44
45         public WsdlImporter(MetadataSet metadata, IEnumerable<IPolicyImportExtension> policyImportExtensions,
46             IEnumerable<IWsdlImportExtension> wsdlImportExtensions)
47             : this(metadata, policyImportExtensions, wsdlImportExtensions, MetadataImporterQuotas.Defaults)
48         {
49         }
50
51         public WsdlImporter(MetadataSet metadata, IEnumerable<IPolicyImportExtension> policyImportExtensions,
52             IEnumerable<IWsdlImportExtension> wsdlImportExtensions, MetadataImporterQuotas quotas)
53             : base(policyImportExtensions, quotas)
54         {
55             // process wsdl extensions first for consistency with policy extensions (which are processed in base ctor)
56             if (wsdlImportExtensions == null)
57             {
58                 wsdlImportExtensions = LoadWsdlExtensionsFromConfig();
59             }
60
61             this.wsdlExtensions = new KeyedByTypeCollection<IWsdlImportExtension>(wsdlImportExtensions);
62
63             // then look at metadata
64             if (metadata == null)
65                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("metadata");
66
67             this.ProcessMetadataDocuments(metadata.MetadataSections);
68         }
69
70         public KeyedByTypeCollection<IWsdlImportExtension> WsdlImportExtensions
71         {
72             get { return this.wsdlExtensions; }
73         }
74
75         public WsdlNS.ServiceDescriptionCollection WsdlDocuments
76         {
77             get { return this.wsdlDocuments; }
78         }
79
80         public XmlSchemaSet XmlSchemas
81         {
82             get { return this.xmlSchemas; }
83         }
84
85         WsdlPolicyReader PolicyReader
86         {
87             get
88             {
89                 if (this.wsdlPolicyReader == null)
90                 {
91                     this.wsdlPolicyReader = new WsdlPolicyReader(this);
92                 }
93                 return wsdlPolicyReader;
94             }
95         }
96
97         //Consider this should be made public
98         internal override XmlElement ResolvePolicyReference(string policyReference, XmlElement contextAssertion)
99         {
100             return this.PolicyReader.ResolvePolicyReference(policyReference, contextAssertion);
101         }
102
103         public override Collection<ContractDescription> ImportAllContracts()
104         {
105             if (this.isFaulted)
106                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
107
108             EnsureBeforeImportCalled();
109             Collection<ContractDescription> contracts = new Collection<ContractDescription>();
110             foreach (WsdlNS.ServiceDescription wsdl in this.wsdlDocuments)
111                 foreach (WsdlNS.PortType wsdlPortType in wsdl.PortTypes)
112                 {
113                     if (IsBlackListed(wsdlPortType))
114                         continue;
115
116                     ContractDescription contract = ImportWsdlPortType(wsdlPortType, WsdlPortTypeImportOptions.ReuseExistingContracts, ErrorBehavior.DoNotThrowExceptions);
117                     if (contract != null)
118                         contracts.Add(contract);
119                 }
120             return contracts;
121         }
122
123         public override ServiceEndpointCollection ImportAllEndpoints()
124         {
125             if (this.isFaulted)
126                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
127
128             EnsureBeforeImportCalled();
129             ServiceEndpointCollection endpoints = new ServiceEndpointCollection();
130             foreach (WsdlNS.Port wsdlPort in this.GetAllPorts())
131             {
132                 if (IsBlackListed(wsdlPort))
133                     continue;
134
135                 ServiceEndpoint endpoint = ImportWsdlPort(wsdlPort, ErrorBehavior.DoNotThrowExceptions);
136                 if (endpoint != null)
137                     endpoints.Add(endpoint);
138             }
139             return endpoints;
140         }
141
142         public Collection<Binding> ImportAllBindings()
143         {
144             if (this.isFaulted)
145                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
146
147             EnsureBeforeImportCalled();
148             Collection<Binding> bindings = new Collection<Binding>();
149             foreach (WsdlNS.Binding wsdlBinding in this.GetAllBindings())
150             {
151                 WsdlEndpointConversionContext importedBindingContext = null;
152                 if (IsBlackListed(wsdlBinding))
153                     continue;
154
155                 importedBindingContext = ImportWsdlBinding(wsdlBinding, ErrorBehavior.DoNotThrowExceptions);
156                 if (importedBindingContext != null)
157                     bindings.Add(importedBindingContext.Endpoint.Binding);
158             }
159             return bindings;
160         }
161
162         // WSDL Specific methods
163         public ContractDescription ImportContract(WsdlNS.PortType wsdlPortType)
164         {
165             if (this.isFaulted)
166                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
167
168             if (wsdlPortType == null)
169                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlPortType");
170
171             return ImportWsdlPortType(wsdlPortType, WsdlPortTypeImportOptions.ReuseExistingContracts, ErrorBehavior.RethrowExceptions);
172         }
173
174         public Binding ImportBinding(WsdlNS.Binding wsdlBinding)
175         {
176             if (this.isFaulted)
177                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
178
179             if (wsdlBinding == null)
180                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlBinding");
181
182             return ImportWsdlBinding(wsdlBinding, ErrorBehavior.RethrowExceptions).Endpoint.Binding;
183         }
184
185         public ServiceEndpoint ImportEndpoint(WsdlNS.Port wsdlPort)
186         {
187             if (this.isFaulted)
188                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
189
190             if (wsdlPort == null)
191                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlPort");
192
193             return ImportWsdlPort(wsdlPort, ErrorBehavior.RethrowExceptions);
194         }
195
196         public ServiceEndpointCollection ImportEndpoints(WsdlNS.PortType wsdlPortType)
197         {
198             if (this.isFaulted)
199                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
200
201             if (wsdlPortType == null)
202                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlPortType");
203
204             if (IsBlackListed(wsdlPortType))
205                 throw CreateAlreadyFaultedException(wsdlPortType);
206             else
207                 ImportWsdlPortType(wsdlPortType, WsdlPortTypeImportOptions.ReuseExistingContracts, ErrorBehavior.RethrowExceptions);
208
209             ServiceEndpointCollection endpoints = new ServiceEndpointCollection();
210
211             foreach (WsdlNS.Binding wsdlBinding in FindBindingsForPortType(wsdlPortType))
212                 if (!IsBlackListed(wsdlBinding))
213                     foreach (ServiceEndpoint endpoint in ImportEndpoints(wsdlBinding))
214                         endpoints.Add(endpoint);
215
216             return endpoints;
217         }
218
219         internal ServiceEndpointCollection ImportEndpoints(ContractDescription contract)
220         {
221             if (this.isFaulted)
222                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
223
224             if (contract == null)
225                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contract");
226
227             if (!this.KnownContracts.ContainsKey(WsdlExporter.WsdlNamingHelper.GetPortTypeQName(contract)))
228             {
229                 Fx.Assert("WsdlImporter.ImportEndpoints(ContractDescription contract): !this.KnownContracts.ContainsKey(WsdlExporter.WsdlNamingHelper.GetPortTypeQName(contract))");
230                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.WsdlImporterContractMustBeInKnownContracts)));
231             }
232
233             EnsureBeforeImportCalled();
234             ServiceEndpointCollection endpoints = new ServiceEndpointCollection();
235
236             foreach (WsdlNS.Binding wsdlBinding in FindBindingsForContract(contract))
237                 if (!IsBlackListed(wsdlBinding))
238                     foreach (ServiceEndpoint endpoint in ImportEndpoints(wsdlBinding))
239                         endpoints.Add(endpoint);
240
241             return endpoints;
242         }
243
244         public ServiceEndpointCollection ImportEndpoints(WsdlNS.Binding wsdlBinding)
245         {
246             if (this.isFaulted)
247                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
248
249             if (wsdlBinding == null)
250                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlBinding");
251
252             if (IsBlackListed(wsdlBinding))
253                 throw CreateAlreadyFaultedException(wsdlBinding);
254             else
255                 ImportWsdlBinding(wsdlBinding, ErrorBehavior.RethrowExceptions);
256
257             ServiceEndpointCollection endpoints = new ServiceEndpointCollection();
258
259             foreach (WsdlNS.Port wsdlPort in FindPortsForBinding(wsdlBinding))
260                 if (!IsBlackListed(wsdlPort))
261                 {
262                     ServiceEndpoint endpoint = ImportWsdlPort(wsdlPort, ErrorBehavior.DoNotThrowExceptions);
263                     if (endpoint != null)
264                         endpoints.Add(endpoint);
265                 }
266
267             return endpoints;
268         }
269
270         public ServiceEndpointCollection ImportEndpoints(WsdlNS.Service wsdlService)
271         {
272             if (this.isFaulted)
273                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
274
275             if (wsdlService == null)
276                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlService");
277
278             EnsureBeforeImportCalled();
279             ServiceEndpointCollection endpoints = new ServiceEndpointCollection();
280
281             foreach (WsdlNS.Port wsdlPort in wsdlService.Ports)
282                 if (!IsBlackListed(wsdlPort))
283                 {
284                     ServiceEndpoint endpoint = ImportWsdlPort(wsdlPort, ErrorBehavior.DoNotThrowExceptions);
285                     if (endpoint != null)
286                         endpoints.Add(endpoint);
287                 }
288
289             return endpoints;
290         }
291
292         bool IsBlackListed(WsdlNS.NamedItem item)
293         {
294             return importErrors.ContainsKey(item);
295         }
296
297         ContractDescription ImportWsdlPortType(WsdlNS.PortType wsdlPortType, WsdlPortTypeImportOptions importOptions, ErrorBehavior errorBehavior)
298         {
299             if (IsBlackListed(wsdlPortType))
300                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateAlreadyFaultedException(wsdlPortType));
301
302
303             XmlQualifiedName wsdlPortTypeQName = new XmlQualifiedName(wsdlPortType.Name, wsdlPortType.ServiceDescription.TargetNamespace);
304             ContractDescription contractDescription = null;
305
306             if (importOptions == WsdlPortTypeImportOptions.IgnoreExistingContracts || !TryFindExistingContract(wsdlPortTypeQName, out contractDescription))
307             {
308                 EnsureBeforeImportCalled();
309
310                 try
311                 {
312
313                     contractDescription = CreateContractDescription(wsdlPortType, wsdlPortTypeQName);
314                     WsdlContractConversionContext contractContext = new WsdlContractConversionContext(contractDescription, wsdlPortType);
315
316                     foreach (WsdlNS.Operation wsdlOperation in wsdlPortType.Operations)
317                     {
318
319                         OperationDescription operationDescription = CreateOperationDescription(wsdlPortType, wsdlOperation, contractDescription);
320                         contractContext.AddOperation(operationDescription, wsdlOperation);
321
322                         foreach (WsdlNS.OperationMessage wsdlOperationMessage in wsdlOperation.Messages)
323                         {
324                             MessageDescription messageDescription;
325                             if (TryCreateMessageDescription(wsdlOperationMessage, operationDescription, out messageDescription))
326                                 contractContext.AddMessage(messageDescription, wsdlOperationMessage);
327                         }
328
329                         foreach (WsdlNS.OperationFault wsdlOperationFault in wsdlOperation.Faults)
330                         {
331                             FaultDescription faultDescription;
332                             if (TryCreateFaultDescription(wsdlOperationFault, operationDescription, out faultDescription))
333                                 contractContext.AddFault(faultDescription, wsdlOperationFault);
334                         }
335                     }
336
337                     CallImportContract(contractContext);
338                     VerifyImportedWsdlPortType(wsdlPortType);
339
340                     importedPortTypes.Add(wsdlPortTypeQName, contractContext);
341                 }
342 #pragma warning suppress 56500 // covered by FxCOP
343                 catch (Exception e)
344                 {
345                     if (Fx.IsFatal(e))
346                         throw;
347                     WsdlImportException wie = WsdlImportException.Create(wsdlPortType, e);
348                     LogImportError(wsdlPortType, wie);
349                     if (errorBehavior == ErrorBehavior.RethrowExceptions)
350                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(wie);
351                     else
352                         return null;
353                 }
354             }
355
356             return contractDescription;
357         }
358
359         WsdlEndpointConversionContext ImportWsdlBinding(WsdlNS.Binding wsdlBinding, ErrorBehavior errorBehavior)
360         {
361             //Check for exisiting exception
362             if (IsBlackListed(wsdlBinding))
363                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateAlreadyFaultedException(wsdlBinding));
364
365             XmlQualifiedName wsdlBindingQName = new XmlQualifiedName(wsdlBinding.Name, wsdlBinding.ServiceDescription.TargetNamespace);
366             WsdlEndpointConversionContext bindingEndpointContext = null;
367
368
369
370
371             if (!importedBindings.TryGetValue(wsdlBindingQName, out bindingEndpointContext))
372             {
373                 EnsureBeforeImportCalled();
374
375                 try
376                 {
377                     bool wasExistingContract;
378                     ContractDescription contractDescription = GetOrImportContractDescription(wsdlBinding.Type, out wasExistingContract);
379                     WsdlContractConversionContext contractContext = null;
380                     importedPortTypes.TryGetValue(wsdlBinding.Type, out contractContext);
381
382                     ServiceEndpoint newWsdlBindingEndpoint = new ServiceEndpoint(contractDescription);
383                     bindingEndpointContext = new WsdlEndpointConversionContext(contractContext, newWsdlBindingEndpoint, wsdlBinding, null);
384
385                     foreach (WsdlNS.OperationBinding wsdlOperationBinding in wsdlBinding.Operations)
386                         try
387                         {
388                             OperationDescription operation = Binding2DescriptionHelper.FindOperationDescription(wsdlOperationBinding, wsdlDocuments, bindingEndpointContext);
389                             bindingEndpointContext.AddOperationBinding(operation, wsdlOperationBinding);
390
391                             for (int i = 0; i < operation.Messages.Count; i++)
392                             {
393                                 MessageDescription message = operation.Messages[i];
394                                 WsdlNS.MessageBinding wsdlMessageBinding = Binding2DescriptionHelper.FindMessageBinding(wsdlOperationBinding, message);
395
396                                 bindingEndpointContext.AddMessageBinding(message, wsdlMessageBinding);
397                             }
398
399                             foreach (FaultDescription fault in operation.Faults)
400                             {
401                                 WsdlNS.FaultBinding wsdlFaultBinding = Binding2DescriptionHelper.FindFaultBinding(wsdlOperationBinding, fault);
402                                 if (wsdlFaultBinding != null)
403                                 {
404                                     bindingEndpointContext.AddFaultBinding(fault, wsdlFaultBinding);
405                                 }
406                             }
407                         }
408 #pragma warning suppress 56500 // covered by FxCOP
409                         catch (Exception e)
410                         {
411                             if (Fx.IsFatal(e))
412                                 throw;
413                             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(wsdlOperationBinding, e));
414                         }
415
416                     XmlQualifiedName bindingQName = WsdlNamingHelper.GetBindingName(wsdlBinding);
417                     newWsdlBindingEndpoint.Binding = CreateBinding(bindingEndpointContext, bindingQName);
418
419                     CallImportEndpoint(bindingEndpointContext);
420                     VerifyImportedWsdlBinding(wsdlBinding);
421                     importedBindings.Add(wsdlBindingQName, bindingEndpointContext);
422                 }
423 #pragma warning suppress 56500 // covered by FxCOP
424                 catch (Exception e)
425                 {
426                     if (Fx.IsFatal(e))
427                         throw;
428                     WsdlImportException wie = WsdlImportException.Create(wsdlBinding, e);
429                     LogImportError(wsdlBinding, wie);
430                     if (errorBehavior == ErrorBehavior.RethrowExceptions)
431                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(wie);
432                     else
433                         return null;
434                 }
435             }
436             return bindingEndpointContext;
437         }
438
439         ServiceEndpoint ImportWsdlPort(WsdlNS.Port wsdlPort, ErrorBehavior errorBehavior)
440         {
441             if (IsBlackListed(wsdlPort))
442                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateAlreadyFaultedException(wsdlPort));
443
444
445             ServiceEndpoint endpoint = null;
446             if (!importedPorts.TryGetValue(wsdlPort, out endpoint))
447             {
448                 EnsureBeforeImportCalled();
449
450                 try
451                 {
452                     WsdlNS.Binding wsdlBinding = this.wsdlDocuments.GetBinding(wsdlPort.Binding);
453
454                     WsdlEndpointConversionContext bindingEndpointContext = ImportWsdlBinding(wsdlBinding, ErrorBehavior.RethrowExceptions);
455
456                     WsdlEndpointConversionContext endpointContext;
457                     endpoint = new ServiceEndpoint(bindingEndpointContext.Endpoint.Contract);
458                     endpoint.Name = WsdlNamingHelper.GetEndpointName(wsdlPort).EncodedName;
459
460                     endpointContext = new WsdlEndpointConversionContext(bindingEndpointContext, endpoint, wsdlPort);
461
462                     if (WsdlPolicyReader.HasPolicy(wsdlPort))
463                     {
464                         XmlQualifiedName bindingQName = WsdlNamingHelper.GetBindingName(wsdlPort);
465                         endpoint.Binding = CreateBinding(endpointContext, bindingQName);
466                     }
467                     else
468                     {
469                         endpoint.Binding = bindingEndpointContext.Endpoint.Binding;
470                     }
471
472                     CallImportEndpoint(endpointContext);
473                     VerifyImportedWsdlPort(wsdlPort);
474                     importedPorts.Add(wsdlPort, endpoint);
475
476                 }
477 #pragma warning suppress 56500 // covered by FxCOP
478                 catch (Exception e)
479                 {
480                     if (Fx.IsFatal(e))
481                         throw;
482                     WsdlImportException wie = WsdlImportException.Create(wsdlPort, e);
483                     LogImportError(wsdlPort, wie);
484                     if (errorBehavior == ErrorBehavior.RethrowExceptions)
485                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(wie);
486                     else
487                         return null;
488                 }
489             }
490
491             return endpoint;
492         }
493
494         static bool TryCreateMessageDescription(WsdlNS.OperationMessage wsdlOperationMessage, OperationDescription operationDescription, out MessageDescription messageDescription)
495         {
496             string actionUri = WSAddressingHelper.GetWsaActionUri(wsdlOperationMessage);
497             MessageDirection direction;
498
499             if (wsdlOperationMessage is WsdlNS.OperationInput)
500                 direction = MessageDirection.Input;
501             else if (wsdlOperationMessage is WsdlNS.OperationOutput)
502                 direction = MessageDirection.Output;
503             else
504             {
505                 messageDescription = null;
506                 return false;
507             }
508
509             messageDescription = new MessageDescription(actionUri, direction);
510             messageDescription.MessageName = WsdlNamingHelper.GetOperationMessageName(wsdlOperationMessage);
511             messageDescription.XsdTypeName = wsdlOperationMessage.Message;
512             operationDescription.Messages.Add(messageDescription);
513             return true;
514         }
515
516         static bool TryCreateFaultDescription(WsdlNS.OperationFault wsdlOperationFault, OperationDescription operationDescription, out FaultDescription faultDescription)
517         {
518
519             if (string.IsNullOrEmpty(wsdlOperationFault.Name))
520             {
521                 faultDescription = null;
522                 return false;
523             }
524
525             string actionUri = WSAddressingHelper.GetWsaActionUri(wsdlOperationFault);
526             faultDescription = new FaultDescription(actionUri);
527             faultDescription.SetNameOnly(new XmlName(wsdlOperationFault.Name, true /*isEncoded*/));
528             operationDescription.Faults.Add(faultDescription);
529             return true;
530         }
531
532         ContractDescription CreateContractDescription(WsdlNS.PortType wsdlPortType, XmlQualifiedName wsdlPortTypeQName)
533         {
534             ContractDescription contractDescription;
535             XmlQualifiedName contractQName = WsdlNamingHelper.GetContractName(wsdlPortTypeQName);
536             contractDescription = new ContractDescription(contractQName.Name, contractQName.Namespace);
537             NetSessionHelper.SetSession(contractDescription, wsdlPortType);
538             return contractDescription;
539         }
540
541         OperationDescription CreateOperationDescription(WsdlNS.PortType wsdlPortType, WsdlNS.Operation wsdlOperation, ContractDescription contract)
542         {
543             string operationName = WsdlNamingHelper.GetOperationName(wsdlOperation);
544             OperationDescription operationDescription = new OperationDescription(operationName, contract);
545             NetSessionHelper.SetInitiatingTerminating(operationDescription, wsdlOperation);
546             contract.Operations.Add(operationDescription);
547             return operationDescription;
548         }
549
550         Binding CreateBinding(WsdlEndpointConversionContext endpointContext, XmlQualifiedName bindingQName)
551         {
552             try
553             {
554                 // either the wsdl:binding has already been imported or the wsdl:port has policy
555                 BindingElementCollection bindingElements = ImportPolicyFromWsdl(endpointContext);
556                 CustomBinding binding = new CustomBinding(bindingElements);
557                 // use decoded form to preserve the user-given friendly name  
558                 binding.Name = NamingHelper.CodeName(bindingQName.Name);
559                 binding.Namespace = bindingQName.Namespace;
560
561                 return binding;
562
563             }
564 #pragma warning suppress 56500 // covered by FxCOP
565             catch (Exception e)
566             {
567                 if (Fx.IsFatal(e))
568                     throw;
569                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(endpointContext.WsdlBinding, e));
570             }
571         }
572
573         ContractDescription GetOrImportContractDescription(XmlQualifiedName wsdlPortTypeQName, out bool wasExistingContractDescription)
574         {
575             ContractDescription contractDescription;
576
577             if (!TryFindExistingContract(wsdlPortTypeQName, out contractDescription))
578             {
579                 WsdlNS.PortType wsdlPortType = wsdlDocuments.GetPortType(wsdlPortTypeQName);
580
581                 contractDescription = ImportWsdlPortType(wsdlPortType, WsdlPortTypeImportOptions.IgnoreExistingContracts, ErrorBehavior.RethrowExceptions);
582
583                 wasExistingContractDescription = false;
584             }
585
586             wasExistingContractDescription = true;
587             return contractDescription;
588         }
589
590         void ProcessMetadataDocuments(IEnumerable<MetadataSection> metadataSections)
591         {
592
593             foreach (MetadataSection doc in metadataSections)
594             {
595                 try
596                 {
597                     if (doc.Metadata is MetadataReference || doc.Metadata is MetadataLocation)
598                         continue;
599
600                     if (doc.Dialect == MetadataSection.ServiceDescriptionDialect)
601                     {
602                         wsdlDocuments.Add(TryConvert<WsdlNS.ServiceDescription>(doc));
603                     }
604                     if (doc.Dialect == MetadataSection.XmlSchemaDialect)
605                     {
606                         xmlSchemas.Add(TryConvert<XmlSchema>(doc));
607                     }
608                     if (doc.Dialect == MetadataSection.PolicyDialect)
609                     {
610                         if (string.IsNullOrEmpty(doc.Identifier))
611                         {
612                             LogImportWarning(SR.GetString(SR.PolicyDocumentMustHaveIdentifier));
613                         }
614                         else
615                         {
616                             policyDocuments.Add(doc.Identifier, TryConvert<XmlElement>(doc));
617                         }
618                     }
619                 }
620 #pragma warning suppress 56500 // covered by FxCOP
621                 catch (Exception e)
622                 {
623                     if (Fx.IsFatal(e))
624                         throw;
625                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(doc.Identifier, e));
626                 }
627             }
628         }
629
630         T TryConvert<T>(MetadataSection doc)
631         {
632             try
633             {
634                 return ((T)doc.Metadata);
635             }
636             catch (InvalidCastException)
637             {
638                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(
639                     SR.GetString(SR.SFxBadMetadataDialect, doc.Identifier, doc.Dialect, typeof(T).FullName, doc.GetType().FullName)));
640             }
641         }
642
643         bool TryFindExistingContract(XmlQualifiedName wsdlPortTypeQName, out ContractDescription existingContract)
644         {
645             XmlQualifiedName contractQName = WsdlNamingHelper.GetContractName(wsdlPortTypeQName);
646
647             // Scan Known Contracts first because wsdl:portType may not be available
648             if (this.KnownContracts.TryGetValue(contractQName, out existingContract))
649                 return true;
650
651             WsdlContractConversionContext contractContext;
652             if (importedPortTypes.TryGetValue(wsdlPortTypeQName, out contractContext))
653             {
654                 existingContract = contractContext.Contract;
655                 return true;
656             }
657
658             return false;
659         }
660
661         void EnsureBeforeImportCalled()
662         {
663             if (!beforeImportCalled)
664             {
665                 foreach (IWsdlImportExtension extension in this.wsdlExtensions)
666                 {
667                     try
668                     {
669                         extension.BeforeImport(this.wsdlDocuments, this.xmlSchemas, this.policyDocuments.Values);
670                     }
671 #pragma warning suppress 56500 // covered by FxCOP
672                     catch (Exception e)
673                     {
674                         this.isFaulted = true;
675                         if (Fx.IsFatal(e))
676                             throw;
677                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateBeforeImportExtensionException(extension, e));
678                     }
679                 }
680                 beforeImportCalled = true;
681             }
682         }
683
684         void CallImportContract(WsdlContractConversionContext contractConversionContext)
685         {
686             foreach (IWsdlImportExtension extension in this.wsdlExtensions)
687                 try
688                 {
689                     extension.ImportContract(this, contractConversionContext);
690                 }
691 #pragma warning suppress 56500 // covered by FxCOP
692                 catch (Exception e)
693                 {
694                     if (Fx.IsFatal(e))
695                         throw;
696                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateExtensionException(extension, e));
697                 }
698         }
699
700         void CallImportEndpoint(WsdlEndpointConversionContext endpointConversionContext)
701         {
702             foreach (IWsdlImportExtension extension in this.wsdlExtensions)
703                 try
704                 {
705                     extension.ImportEndpoint(this, endpointConversionContext);
706
707                 }
708 #pragma warning suppress 56500 // covered by FxCOP
709                 catch (Exception e)
710                 {
711                     if (Fx.IsFatal(e))
712                         throw;
713                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateExtensionException(extension, e));
714                 }
715         }
716
717         void VerifyImportedWsdlPortType(WsdlNS.PortType wsdlPortType)
718         {
719             VerifyImportedExtensions(wsdlPortType);
720             foreach (WsdlNS.Operation wsdlOperation in wsdlPortType.Operations)
721             {
722                 VerifyImportedExtensions(wsdlOperation);
723
724                 foreach (WsdlNS.OperationMessage wsdlOperationMessage in wsdlOperation.Messages)
725                 {
726                     VerifyImportedExtensions(wsdlOperationMessage);
727                 }
728
729                 foreach (WsdlNS.OperationMessage wsdlOperationMessage in wsdlOperation.Faults)
730                 {
731                     VerifyImportedExtensions(wsdlOperationMessage);
732                 }
733             }
734         }
735
736         void VerifyImportedWsdlBinding(WsdlNS.Binding wsdlBinding)
737         {
738             VerifyImportedExtensions(wsdlBinding);
739             foreach (WsdlNS.OperationBinding wsdlOperationBinding in wsdlBinding.Operations)
740             {
741                 VerifyImportedExtensions(wsdlOperationBinding);
742
743                 if (wsdlOperationBinding.Input != null)
744                 {
745                     VerifyImportedExtensions(wsdlOperationBinding.Input);
746                 }
747
748                 if (wsdlOperationBinding.Output != null)
749                 {
750                     VerifyImportedExtensions(wsdlOperationBinding.Output);
751                 }
752
753                 foreach (WsdlNS.MessageBinding wsdlMessageBinding in wsdlOperationBinding.Faults)
754                 {
755                     VerifyImportedExtensions(wsdlMessageBinding);
756                 }
757             }
758         }
759
760         void VerifyImportedWsdlPort(WsdlNS.Port wsdlPort)
761         {
762             VerifyImportedExtensions(wsdlPort);
763         }
764
765         void VerifyImportedExtensions(WsdlNS.NamedItem item)
766         {
767             foreach (object ext in item.Extensions)
768             {
769                 if (item.Extensions.IsHandled(ext))
770                     continue;
771
772                 XmlQualifiedName qName = GetUnhandledExtensionQName(ext, item);
773
774                 if (item.Extensions.IsRequired(ext) || IsNonSoapWsdl11BindingExtension(ext))
775                 {
776                     string errorMsg = SR.GetString(SR.RequiredWSDLExtensionIgnored, qName.Name, qName.Namespace);
777                     WsdlImportException wie = WsdlImportException.Create(item, new InvalidOperationException(errorMsg));
778                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(wie);
779                 }
780                 else
781                 {
782                     string xPath = CreateXPathString(item);
783                     string errorMsg = SR.GetString(SR.OptionalWSDLExtensionIgnored, qName.Name, qName.Namespace, xPath);
784                     this.Errors.Add(new MetadataConversionError(errorMsg, true));
785                 }
786             }
787         }
788
789         static bool IsNonSoapWsdl11BindingExtension(object ext)
790         {
791             if (ext is WsdlNS.HttpAddressBinding
792                 || ext is WsdlNS.HttpBinding
793                 || ext is WsdlNS.HttpOperationBinding
794                 || ext is WsdlNS.HttpUrlEncodedBinding
795                 || ext is WsdlNS.HttpUrlReplacementBinding
796                 || ext is WsdlNS.MimeContentBinding
797                 || ext is WsdlNS.MimeMultipartRelatedBinding
798                 || ext is WsdlNS.MimePart
799                 || ext is WsdlNS.MimeTextBinding
800                 || ext is WsdlNS.MimeXmlBinding
801                 )
802             {
803                 return true;
804             }
805
806             return false;
807
808         }
809
810         XmlQualifiedName GetUnhandledExtensionQName(object extension, WsdlNS.NamedItem item)
811         {
812             XmlElement element = extension as XmlElement;
813             if (element != null)
814             {
815                 return new XmlQualifiedName(element.LocalName, element.NamespaceURI);
816             }
817             else if (extension is WsdlNS.ServiceDescriptionFormatExtension)
818             {
819                 WsdlConfigNS.XmlFormatExtensionAttribute[] xfeAttributes
820                     = (WsdlConfigNS.XmlFormatExtensionAttribute[])ServiceReflector.GetCustomAttributes(extension.GetType(),
821                     typeof(WsdlConfigNS.XmlFormatExtensionAttribute), false);
822
823                 if (xfeAttributes.Length > 0)
824                 {
825                     return new XmlQualifiedName(xfeAttributes[0].ElementName, xfeAttributes[0].Namespace);
826                 }
827             }
828             WsdlImportException wie = WsdlImportException.Create(item, new InvalidOperationException(SR.GetString(SR.UnknownWSDLExtensionIgnored, extension.GetType().AssemblyQualifiedName)));
829             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(wie);
830         }
831
832         internal static class Binding2DescriptionHelper
833         {
834             internal static OperationDescription FindOperationDescription(WsdlNS.OperationBinding wsdlOperationBinding, WsdlNS.ServiceDescriptionCollection wsdlDocuments, WsdlEndpointConversionContext endpointContext)
835             {
836
837                 OperationDescription operation;
838                 if (endpointContext.ContractConversionContext != null)
839                 {
840                     WsdlNS.Operation wsdlOperation = FindWsdlOperation(wsdlOperationBinding, wsdlDocuments);
841                     operation = endpointContext.ContractConversionContext.GetOperationDescription(wsdlOperation);
842                 }
843                 else
844                 {
845                     operation = FindOperationDescription(endpointContext.Endpoint.Contract, wsdlOperationBinding);
846                 }
847                 return operation;
848             }
849
850             internal static WsdlNS.MessageBinding FindMessageBinding(WsdlNS.OperationBinding wsdlOperationBinding, MessageDescription message)
851             {
852                 WsdlNS.MessageBinding wsdlMessageBinding;
853                 if (message.Direction == MessageDirection.Input)
854                 {
855                     wsdlMessageBinding = wsdlOperationBinding.Input;
856                 }
857                 else
858                 {
859                     wsdlMessageBinding = wsdlOperationBinding.Output;
860                 }
861                 return wsdlMessageBinding;
862             }
863
864             internal static WsdlNS.FaultBinding FindFaultBinding(WsdlNS.OperationBinding wsdlOperationBinding, FaultDescription fault)
865             {
866                 foreach (WsdlNS.FaultBinding faultBinding in wsdlOperationBinding.Faults)
867                     if (faultBinding.Name == fault.Name)
868                         return faultBinding;
869                 return null;
870             }
871
872             static WsdlNS.Operation FindWsdlOperation(WsdlNS.OperationBinding wsdlOperationBinding, WsdlNS.ServiceDescriptionCollection wsdlDocuments)
873             {
874                 WsdlNS.PortType wsdlPortType = wsdlDocuments.GetPortType(wsdlOperationBinding.Binding.Type);
875
876                 string wsdlOperationBindingName = wsdlOperationBinding.Name;
877
878                 if (wsdlOperationBindingName == null)
879                 {
880                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInvalidWsdlBindingOpNoName, wsdlOperationBinding.Binding.Name)));
881                 }
882
883                 WsdlNS.Operation partialMatchResult = null;
884
885                 foreach (WsdlNS.Operation wsdlOperation in wsdlPortType.Operations)
886                 {
887                     switch (Match(wsdlOperationBinding, wsdlOperation))
888                     {
889                         case MatchResult.None:
890                             break;
891                         case MatchResult.Partial:
892                             partialMatchResult = wsdlOperation;
893                             break;
894                         case MatchResult.Exact:
895                             return wsdlOperation;
896                         default:
897                             Fx.AssertAndFailFast("Unexpected MatchResult value.");
898                             break;
899                     }
900                 }
901
902                 if (partialMatchResult != null)
903                 {
904                     return partialMatchResult;
905                 }
906                 else
907                 {
908                     //unable to find wsdloperation for wsdlOperationBinding, invalid wsdl binding
909                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInvalidWsdlBindingOpMismatch2, wsdlOperationBinding.Binding.Name, wsdlOperationBinding.Name)));
910                 }
911             }
912
913             internal enum MatchResult
914             {
915                 None,
916                 Partial,
917                 Exact
918             }
919
920             internal static MatchResult Match(WsdlNS.OperationBinding wsdlOperationBinding, WsdlNS.Operation wsdlOperation)
921             {
922                 // This method checks if there is a match based on Names, between the specified OperationBinding and Operation.
923                 // When searching for the Operation associated with an OperationBinding, we need to return an exact match if possible,
924                 // or a partial match otherwise (when some of the Names are null).
925                 // Bug 16833 @ CSDMain requires that partial matches are allowed, while the TFS bug 477838 requires that exact matches are done (when possible).
926                 if (wsdlOperationBinding.Name != wsdlOperation.Name)
927                 {
928                     return MatchResult.None;
929                 }
930
931                 MatchResult result = MatchResult.Exact;
932
933                 foreach (WsdlNS.OperationMessage wsdlOperationMessage in wsdlOperation.Messages)
934                 {
935                     WsdlNS.MessageBinding wsdlMessageBinding;
936                     if (wsdlOperationMessage is WsdlNS.OperationInput)
937                         wsdlMessageBinding = wsdlOperationBinding.Input;
938                     else
939                         wsdlMessageBinding = wsdlOperationBinding.Output;
940
941                     if (wsdlMessageBinding == null)
942                     {
943                         return MatchResult.None;
944                     }
945
946                     switch (MatchOperationParameterName(wsdlMessageBinding, wsdlOperationMessage))
947                     {
948                         case MatchResult.None:
949                             return MatchResult.None;
950                         case MatchResult.Partial:
951                             result = MatchResult.Partial;
952                             break;
953                     }
954                 }
955                 
956                 return result;
957             }
958
959             static MatchResult MatchOperationParameterName(WsdlNS.MessageBinding wsdlMessageBinding, WsdlNS.OperationMessage wsdlOperationMessage)
960             {
961                 string wsdlOperationMessageName = wsdlOperationMessage.Name;
962                 string wsdlMessageBindingName = wsdlMessageBinding.Name;
963
964                 if (wsdlOperationMessageName == wsdlMessageBindingName)
965                 {
966                     return MatchResult.Exact;
967                 }
968
969                 string wsdlOperationMessageDecodedName = WsdlNamingHelper.GetOperationMessageName(wsdlOperationMessage).DecodedName;
970                 if ((wsdlOperationMessageName == null) && (wsdlMessageBindingName == wsdlOperationMessageDecodedName))
971                 {
972                     return MatchResult.Partial;
973                 }
974                 else if ((wsdlMessageBindingName == null) && (wsdlOperationMessageName == wsdlOperationMessageDecodedName))
975                 {
976                     return MatchResult.Partial;
977                 }
978                 else
979                 {
980                     return MatchResult.None;
981                 }
982             }
983
984             static OperationDescription FindOperationDescription(ContractDescription contract, WsdlNS.OperationBinding wsdlOperationBinding)
985             {
986                 foreach (OperationDescription operationDescription in contract.Operations)
987                 {
988                     if (CompareOperations(operationDescription, contract, wsdlOperationBinding))
989                         return operationDescription;
990                 }
991
992                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnableToLocateOperation2, wsdlOperationBinding.Name, contract.Name)));
993             }
994
995             static bool CompareOperations(OperationDescription operationDescription, ContractDescription parentContractDescription, WsdlNS.OperationBinding wsdlOperationBinding)
996             {
997                 string wsdlOperationName = WsdlExporter.WsdlNamingHelper.GetWsdlOperationName(operationDescription, parentContractDescription);
998
999                 if (wsdlOperationName != wsdlOperationBinding.Name)
1000                     return false;
1001
1002                 if (operationDescription.Messages.Count > 2)
1003                     return false;
1004
1005                 // Either both have output message or neither have an output message;
1006                 if (FindMessage(operationDescription.Messages, MessageDirection.Output) != (wsdlOperationBinding.Output != null))
1007                     return false;
1008
1009                 // Either both have output message or neither have an output message;
1010                 if (FindMessage(operationDescription.Messages, MessageDirection.Input) != (wsdlOperationBinding.Input != null))
1011                     return false;
1012
1013                 return true;
1014
1015             }
1016
1017             private static bool FindMessage(MessageDescriptionCollection messageDescriptionCollection, MessageDirection transferDirection)
1018             {
1019                 foreach (MessageDescription message in messageDescriptionCollection)
1020                     if (message.Direction == transferDirection)
1021                         return true;
1022                 return false;
1023             }
1024
1025         }
1026
1027         internal static class WSAddressingHelper
1028         {
1029             internal static string GetWsaActionUri(WsdlNS.OperationMessage wsdlOperationMessage)
1030             {
1031                 string actionUri = FindWsaActionAttribute(wsdlOperationMessage);
1032                 return (actionUri == null) ? CreateDefaultWsaActionUri(wsdlOperationMessage) : actionUri;
1033             }
1034
1035             internal static string FindWsaActionAttribute(WsdlNS.OperationMessage wsdlOperationMessage)
1036             {
1037                 XmlAttribute[] attributes = wsdlOperationMessage.ExtensibleAttributes;
1038                 if (attributes != null && attributes.Length > 0)
1039                 {
1040                     foreach (XmlAttribute attribute in attributes)
1041                     {
1042                         if ((attribute.NamespaceURI == MetadataStrings.AddressingWsdl.NamespaceUri
1043                              || attribute.NamespaceURI == MetadataStrings.AddressingMetadata.NamespaceUri)
1044                             && attribute.LocalName == MetadataStrings.AddressingMetadata.Action)
1045                         {
1046                             return attribute.Value;
1047                         }
1048                     }
1049                 }
1050
1051                 return null;
1052             }
1053
1054             static string CreateDefaultWsaActionUri(WsdlNS.OperationMessage wsdlOperationMessage)
1055             {
1056                 if (wsdlOperationMessage is WsdlNS.OperationFault)
1057                     return AddressingVersion.WSAddressing10.DefaultFaultAction;
1058
1059                 // We figure out default action. All specifications' rules below are the same.
1060                 // Using [WSDL Binding W3C Working Draft 13 April 2005] Section 3.3
1061                 // Using [WSDL Binding W3C Candidate Recommendation 29 May 2006] Section 4.4.4
1062                 // Using [Metadata W3C Working Draft 13 16 May 2007] Section 4.4.4
1063
1064                 string ns = wsdlOperationMessage.Operation.PortType.ServiceDescription.TargetNamespace ?? string.Empty;
1065                 string portTypeName = wsdlOperationMessage.Operation.PortType.Name;
1066                 XmlName operationMessageName = WsdlNamingHelper.GetOperationMessageName(wsdlOperationMessage);
1067
1068                 string delimiter = ns.StartsWith("urn:", StringComparison.OrdinalIgnoreCase) ? ":" : "/";
1069
1070                 string baseActionUri = ns.EndsWith(delimiter, StringComparison.OrdinalIgnoreCase) ? ns : ns + delimiter;
1071
1072                 string actionUri = string.Format(CultureInfo.InvariantCulture, "{0}{1}{2}{3}", baseActionUri, portTypeName, delimiter, operationMessageName.EncodedName);
1073
1074                 return actionUri;
1075             }
1076
1077             internal static EndpointAddress ImportAddress(WsdlNS.Port wsdlPort)
1078             {
1079                 //Try to read Endpoint Address from WsdlPort
1080                 if (wsdlPort != null)
1081                 {
1082                     XmlElement addressing10Element = wsdlPort.Extensions.Find(AddressingStrings.EndpointReference, Addressing10Strings.Namespace);
1083                     XmlElement addressing200408Element = wsdlPort.Extensions.Find(AddressingStrings.EndpointReference, Addressing200408Strings.Namespace);
1084                     WsdlNS.SoapAddressBinding soapAddressBinding = (WsdlNS.SoapAddressBinding)wsdlPort.Extensions.Find(typeof(WsdlNS.SoapAddressBinding));
1085
1086                     //
1087                     if (addressing10Element != null)
1088                     {
1089                         return EndpointAddress.ReadFrom(AddressingVersion.WSAddressing10, new XmlNodeReader(addressing10Element));
1090                     }
1091                     if (addressing200408Element != null)
1092                     {
1093                         return EndpointAddress.ReadFrom(AddressingVersion.WSAddressingAugust2004, new XmlNodeReader(addressing200408Element));
1094                     }
1095                     else if (soapAddressBinding != null)
1096                     {
1097                         return new EndpointAddress(soapAddressBinding.Location);
1098                     }
1099
1100                 }
1101                 return null;
1102             }
1103
1104             internal static AddressingVersion FindAddressingVersion(PolicyConversionContext policyContext)
1105             {
1106                 if (PolicyConversionContext.FindAssertion(policyContext.GetBindingAssertions(),
1107                             MetadataStrings.Addressing10.WsdlBindingPolicy.UsingAddressing,
1108                             MetadataStrings.Addressing10.WsdlBindingPolicy.NamespaceUri, true /*remove*/) != null)
1109                 {
1110                     return AddressingVersion.WSAddressing10;
1111                 }
1112                 else if (PolicyConversionContext.FindAssertion(policyContext.GetBindingAssertions(),
1113                             MetadataStrings.Addressing10.MetadataPolicy.Addressing,
1114                             MetadataStrings.Addressing10.MetadataPolicy.NamespaceUri, true /*remove*/) != null)
1115                 {
1116                     return AddressingVersion.WSAddressing10;
1117                 }
1118                 else if (PolicyConversionContext.FindAssertion(policyContext.GetBindingAssertions(),
1119                             MetadataStrings.Addressing200408.Policy.UsingAddressing,
1120                             MetadataStrings.Addressing200408.Policy.NamespaceUri, true /*remove*/) != null)
1121                 {
1122                     return AddressingVersion.WSAddressingAugust2004;
1123                 }
1124                 else
1125                 {
1126                     return AddressingVersion.None;
1127                 }
1128             }
1129
1130             internal static SupportedAddressingMode DetermineSupportedAddressingMode(MetadataImporter importer, PolicyConversionContext context)
1131             {
1132                 // Do not remove this assertion - the message encoding binding element importer owns it.
1133                 XmlElement addressingAssertion = PolicyConversionContext.FindAssertion(context.GetBindingAssertions(),
1134                     MetadataStrings.Addressing10.MetadataPolicy.Addressing, MetadataStrings.Addressing10.MetadataPolicy.NamespaceUri, false);
1135
1136                 if (addressingAssertion != null)
1137                 {
1138                     XmlElement policyElement = null;
1139                     foreach (XmlNode node in addressingAssertion.ChildNodes)
1140                     {
1141                         if (node is XmlElement && MetadataSection.IsPolicyElement((XmlElement)node))
1142                         {
1143                             policyElement = (XmlElement)node;
1144                             break;
1145                         }
1146                     }
1147
1148                     if (policyElement == null)
1149                     {
1150                         string message = SR.GetString(SR.ElementRequired, MetadataStrings.Addressing10.MetadataPolicy.Prefix,
1151                             MetadataStrings.Addressing10.MetadataPolicy.Addressing, MetadataStrings.WSPolicy.Prefix,
1152                             MetadataStrings.WSPolicy.Elements.Policy);
1153
1154                         importer.Errors.Add(new MetadataConversionError(message, false));
1155                         return SupportedAddressingMode.Anonymous;
1156                     }
1157
1158                     IEnumerable<IEnumerable<XmlElement>> alternatives = importer.NormalizePolicy(new XmlElement[] { policyElement });
1159                     foreach (IEnumerable<XmlElement> alternative in alternatives)
1160                     {
1161                         foreach (XmlElement element in alternative)
1162                         {
1163                             if (element.NamespaceURI == MetadataStrings.Addressing10.MetadataPolicy.NamespaceUri)
1164                             {
1165                                 if (element.LocalName == MetadataStrings.Addressing10.MetadataPolicy.NonAnonymousResponses)
1166                                 {
1167                                     return SupportedAddressingMode.NonAnonymous;
1168                                 }
1169                                 else if (element.LocalName == MetadataStrings.Addressing10.MetadataPolicy.AnonymousResponses)
1170                                 {
1171                                     return SupportedAddressingMode.Anonymous;
1172                                 }
1173                             }
1174                         }
1175                     }
1176                 }
1177
1178                 return SupportedAddressingMode.Anonymous;
1179             }
1180         }
1181
1182         static class WsdlNamingHelper
1183         {
1184             internal static XmlQualifiedName GetBindingName(WsdlNS.Binding wsdlBinding)
1185             {
1186                 XmlName xmlName = new XmlName(wsdlBinding.Name, true /*isEncoded*/);
1187                 return new XmlQualifiedName(xmlName.EncodedName, wsdlBinding.ServiceDescription.TargetNamespace);
1188             }
1189
1190             internal static XmlQualifiedName GetBindingName(WsdlNS.Port wsdlPort)
1191             {
1192                 // Microsoft: composing names have potential problem of generating name that looks like an encoded name, consider avoiding '_'
1193                 XmlName xmlName = new XmlName(string.Format(CultureInfo.InvariantCulture, "{0}_{1}", wsdlPort.Service.Name, wsdlPort.Name), true /*isEncoded*/);
1194                 return new XmlQualifiedName(xmlName.EncodedName, wsdlPort.Service.ServiceDescription.TargetNamespace);
1195             }
1196
1197             internal static XmlName GetEndpointName(WsdlNS.Port wsdlPort)
1198             {
1199                 return new XmlName(wsdlPort.Name, true /*isEncoded*/);
1200             }
1201
1202             internal static XmlQualifiedName GetContractName(XmlQualifiedName wsdlPortTypeQName)
1203             {
1204                 return wsdlPortTypeQName;
1205             }
1206
1207             internal static string GetOperationName(WsdlNS.Operation wsdlOperation)
1208             {
1209                 return wsdlOperation.Name;
1210             }
1211
1212             internal static XmlName GetOperationMessageName(WsdlNS.OperationMessage wsdlOperationMessage)
1213             {
1214                 string messageName = null;
1215                 if (!string.IsNullOrEmpty(wsdlOperationMessage.Name))
1216                 {
1217                     messageName = wsdlOperationMessage.Name;
1218                 }
1219                 else if (wsdlOperationMessage.Operation.Messages.Count == 1)
1220                 {
1221                     messageName = wsdlOperationMessage.Operation.Name;
1222                 }
1223                 else if (wsdlOperationMessage.Operation.Messages.IndexOf(wsdlOperationMessage) == 0)
1224                 {
1225                     if (wsdlOperationMessage is WsdlNS.OperationInput)
1226                         messageName = wsdlOperationMessage.Operation.Name + "Request";
1227                     else if (wsdlOperationMessage is WsdlNS.OperationOutput)
1228                         messageName = wsdlOperationMessage.Operation.Name + "Solicit";
1229                 }
1230                 else if (wsdlOperationMessage.Operation.Messages.IndexOf(wsdlOperationMessage) == 1)
1231                 {
1232                     messageName = wsdlOperationMessage.Operation.Name + "Response";
1233                 }
1234                 else
1235                 {
1236                     // Microsoft: why this is an Assert, and not an exception?
1237                     Fx.Assert("Unsupported WSDL OM (More than 2 OperationMessages encountered in an Operation or WsdlOM is invalid)");
1238                 }
1239                 // names the come from service description documents have to be valid NCNames; XmlName.ctor will validate.
1240                 return new XmlName(messageName, true /*isEncoded*/);
1241             }
1242         }
1243
1244         internal static class NetSessionHelper
1245         {
1246             internal static void SetInitiatingTerminating(OperationDescription operationDescription, WsdlNS.Operation wsdlOperation)
1247             {
1248                 XmlAttribute isInitiating = FindAttribute(wsdlOperation.ExtensibleAttributes, WsdlExporter.NetSessionHelper.IsInitiating,
1249                     WsdlExporter.NetSessionHelper.NamespaceUri);
1250
1251                 if (isInitiating != null)
1252                 {
1253                     if (isInitiating.Value == WsdlExporter.NetSessionHelper.True)
1254                     {
1255                         operationDescription.IsInitiating = true;
1256                     }
1257                     if (isInitiating.Value == WsdlExporter.NetSessionHelper.False)
1258                     {
1259                         operationDescription.IsInitiating = false;
1260                     }
1261                 }
1262
1263                 XmlAttribute isTerminating = FindAttribute(wsdlOperation.ExtensibleAttributes, WsdlExporter.NetSessionHelper.IsTerminating,
1264                     WsdlExporter.NetSessionHelper.NamespaceUri);
1265
1266                 if (isTerminating != null)
1267                 {
1268                     if (isTerminating.Value == WsdlExporter.NetSessionHelper.True)
1269                     {
1270                         operationDescription.IsTerminating = true;
1271                     }
1272                     if (isTerminating.Value == WsdlExporter.NetSessionHelper.False)
1273                     {
1274                         operationDescription.IsTerminating = false;
1275                     }
1276                 }
1277             }
1278
1279             internal static void SetSession(ContractDescription contractDescription, WsdlNS.PortType wsdlPortType)
1280             {
1281                 XmlAttribute usingSession = FindAttribute(wsdlPortType.ExtensibleAttributes, WsdlExporter.NetSessionHelper.UsingSession,
1282                     WsdlExporter.NetSessionHelper.NamespaceUri);
1283
1284                 if (usingSession != null)
1285                 {
1286                     if (usingSession.Value == WsdlExporter.NetSessionHelper.True)
1287                     {
1288                         contractDescription.SessionMode = SessionMode.Required;
1289                     }
1290                     if (usingSession.Value == WsdlExporter.NetSessionHelper.False)
1291                     {
1292                         contractDescription.SessionMode = SessionMode.NotAllowed;
1293                     }
1294                 }
1295             }
1296
1297             static XmlAttribute FindAttribute(XmlAttribute[] attributes, string localName, string ns)
1298             {
1299                 if (attributes != null)
1300                 {
1301                     foreach (XmlAttribute attribute in attributes)
1302                     {
1303                         if (attribute.LocalName == localName && attribute.NamespaceURI == ns)
1304                         {
1305                             return attribute;
1306                         }
1307                     }
1308                 }
1309                 return null;
1310             }
1311         }
1312
1313         internal static class SoapInPolicyWorkaroundHelper
1314         {
1315             public const string soapTransportUriKey = "TransportBindingElementImporter.TransportUri";
1316             const string workaroundNS = NamingHelper.DefaultNamespace + "temporaryworkaround";
1317             const string bindingAttrName = "bindingName";
1318             const string bindingAttrNamespace = "bindingNamespace";
1319             static XmlDocument xmlDocument;
1320
1321             static public void InsertAdHocPolicy(WsdlNS.Binding wsdlBinding, string value, string key)
1322             {
1323                 XmlQualifiedName wsdlBindingQName = new XmlQualifiedName(wsdlBinding.Name, wsdlBinding.ServiceDescription.TargetNamespace);
1324                 string id = AddPolicyUri(wsdlBinding, key);
1325                 InsertPolicy(key, id, wsdlBinding.ServiceDescription, value, wsdlBindingQName);
1326             }
1327
1328             static public string FindAdHocTransportPolicy(PolicyConversionContext policyContext, out XmlQualifiedName wsdlBindingQName)
1329             {
1330                 return FindAdHocPolicy(policyContext, soapTransportUriKey, out wsdlBindingQName);
1331             }
1332
1333             static public string FindAdHocPolicy(PolicyConversionContext policyContext, string key, out XmlQualifiedName wsdlBindingQName)
1334             {
1335                 if (policyContext == null)
1336                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("policyContext");
1337
1338                 XmlElement policy = PolicyConversionContext.FindAssertion(policyContext.GetBindingAssertions(), key, workaroundNS, true);
1339                 if (policy != null)
1340                 {
1341                     wsdlBindingQName = new XmlQualifiedName(policy.Attributes[bindingAttrName].Value, policy.Attributes[bindingAttrNamespace].Value);
1342                     return policy.InnerText;
1343                 }
1344                 else
1345                 {
1346                     wsdlBindingQName = null;
1347                     return null;
1348                 }
1349             }
1350
1351             static string AddPolicyUri(WsdlNS.Binding wsdlBinding, string name)
1352             {
1353                 string policyUris = ReadPolicyUris(wsdlBinding);
1354                 string id = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}_{1}_BindingAdHocPolicy", wsdlBinding.Name, name);
1355                 string newPolicyUris = string.Format(System.Globalization.CultureInfo.InvariantCulture, "#{0} {1}", id, policyUris).Trim();
1356                 WritePolicyUris(wsdlBinding, newPolicyUris);
1357                 return id;
1358             }
1359
1360             static XmlDocument XmlDoc
1361             {
1362                 get
1363                 {
1364                     if (xmlDocument == null)
1365                     {
1366                         NameTable nameTable = new NameTable();
1367                         nameTable.Add(MetadataStrings.WSPolicy.Elements.Policy);
1368                         nameTable.Add(MetadataStrings.WSPolicy.Elements.All);
1369                         nameTable.Add(MetadataStrings.WSPolicy.Elements.ExactlyOne);
1370                         nameTable.Add(MetadataStrings.WSPolicy.Attributes.PolicyURIs);
1371                         nameTable.Add(MetadataStrings.Wsu.Attributes.Id);
1372                         xmlDocument = new XmlDocument(nameTable);
1373                     }
1374                     return xmlDocument;
1375                 }
1376             }
1377
1378             static void WritePolicyUris(WsdlNS.DocumentableItem item, string newValue)
1379             {
1380
1381                 int i;
1382                 XmlAttribute[] attributes = item.ExtensibleAttributes;
1383                 if (attributes != null && attributes.Length > 0)
1384                 {
1385                     foreach (XmlAttribute attribute in attributes)
1386                         if (MetadataImporter.PolicyHelper.IsPolicyURIs(attribute))
1387                         {
1388                             attribute.Value = newValue;
1389                             return;
1390                         }
1391                     // Need to extend
1392                     i = attributes.Length;
1393                     Array.Resize<XmlAttribute>(ref attributes, i + 1);
1394
1395                 }
1396                 else
1397                 {
1398                     //Need to create
1399                     i = 0;
1400                     attributes = new XmlAttribute[1];
1401                 }
1402
1403                 attributes[i] = CreatePolicyURIsAttribute(newValue);
1404                 item.ExtensibleAttributes = attributes;
1405             }
1406
1407             static XmlAttribute CreatePolicyURIsAttribute(string value)
1408             {
1409                 XmlAttribute attribute = XmlDoc.CreateAttribute(MetadataStrings.WSPolicy.Prefix,
1410                                                             MetadataStrings.WSPolicy.Attributes.PolicyURIs,
1411                                                             MetadataStrings.WSPolicy.NamespaceUri);
1412
1413                 attribute.Value = value;
1414                 return attribute;
1415             }
1416
1417             static string ReadPolicyUris(WsdlNS.DocumentableItem item)
1418             {
1419
1420                 XmlAttribute[] attributes = item.ExtensibleAttributes;
1421                 if (attributes != null && attributes.Length > 0)
1422                 {
1423                     foreach (XmlAttribute attribute in attributes)
1424                     {
1425                         if (MetadataImporter.PolicyHelper.IsPolicyURIs(attribute))
1426                         {
1427                             return attribute.Value;
1428                         }
1429                     }
1430                 }
1431
1432                 return string.Empty;
1433             }
1434
1435             static void InsertPolicy(string key, string id, WsdlNS.ServiceDescription policyWsdl, string value, XmlQualifiedName wsdlBindingQName)
1436             {
1437
1438                 // Create [wsp:Policy]
1439                 XmlElement policyElement = CreatePolicyElement(key, value, wsdlBindingQName);
1440
1441                 //Create [wsp:Policy/@wsu:Id]
1442                 XmlAttribute idAttribute = XmlDoc.CreateAttribute(MetadataStrings.Wsu.Prefix,
1443                                                             MetadataStrings.Wsu.Attributes.Id,
1444                                                             MetadataStrings.Wsu.NamespaceUri);
1445                 idAttribute.Value = id;
1446                 policyElement.SetAttributeNode(idAttribute);
1447
1448                 // Add wsp:Policy To WSDL
1449                 policyWsdl.Extensions.Add(policyElement);
1450
1451             }
1452
1453             static XmlElement CreatePolicyElement(string elementName, string value, XmlQualifiedName wsdlBindingQName)
1454             {
1455
1456                 // Create [wsp:Policy]
1457                 XmlElement policyElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix,
1458                                                             MetadataStrings.WSPolicy.Elements.Policy,
1459                                                             MetadataStrings.WSPolicy.NamespaceUri);
1460
1461                 // Create [wsp:Policy/wsp:ExactlyOne]
1462                 XmlElement exactlyOneElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix,
1463                                                             MetadataStrings.WSPolicy.Elements.ExactlyOne,
1464                                                             MetadataStrings.WSPolicy.NamespaceUri);
1465                 policyElement.AppendChild(exactlyOneElement);
1466
1467                 // Create [wsp:Policy/wsp:ExactlyOne/wsp:All]
1468                 XmlElement allElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix,
1469                                                             MetadataStrings.WSPolicy.Elements.All,
1470                                                             MetadataStrings.WSPolicy.NamespaceUri);
1471                 exactlyOneElement.AppendChild(allElement);
1472
1473                 // Add [wsp:Policy/wsp:ExactlyOne/wsp:All/*]
1474                 XmlElement workaroundElement = xmlDocument.CreateElement(elementName, workaroundNS);
1475                 workaroundElement.InnerText = value;
1476
1477                 XmlAttribute bindingName = xmlDocument.CreateAttribute(bindingAttrName);
1478                 bindingName.Value = wsdlBindingQName.Name;
1479                 workaroundElement.Attributes.Append(bindingName);
1480
1481                 XmlAttribute bindingNamespace = xmlDocument.CreateAttribute(bindingAttrNamespace);
1482                 bindingNamespace.Value = wsdlBindingQName.Namespace;
1483                 workaroundElement.Attributes.Append(bindingNamespace);
1484
1485                 workaroundElement.Attributes.Append(bindingNamespace);
1486
1487
1488                 allElement.AppendChild(workaroundElement);
1489
1490                 return policyElement;
1491             }
1492
1493             internal static void InsertAdHocTransportPolicy(WsdlNS.ServiceDescriptionCollection wsdlDocuments)
1494             {
1495                 foreach (WsdlNS.ServiceDescription wsdl in wsdlDocuments)
1496                     if (wsdl != null)
1497                     {
1498                         foreach (WsdlNS.Binding wsdlBinding in wsdl.Bindings)
1499                         {
1500                             if (WsdlImporter.WsdlPolicyReader.ContainsPolicy(wsdlBinding))
1501                             {
1502                                 WsdlNS.SoapBinding soapBinding = (WsdlNS.SoapBinding)wsdlBinding.Extensions.Find(typeof(WsdlNS.SoapBinding));
1503                                 if (soapBinding != null)
1504                                     WsdlImporter
1505                                         .SoapInPolicyWorkaroundHelper
1506                                         .InsertAdHocPolicy(wsdlBinding, soapBinding.Transport, soapTransportUriKey);
1507                             }
1508                         }
1509                     }
1510             }
1511         }
1512
1513         IEnumerable<WsdlNS.Binding> FindBindingsForPortType(WsdlNS.PortType wsdlPortType)
1514         {
1515             foreach (WsdlNS.Binding wsdlBinding in GetAllBindings())
1516             {
1517                 if (wsdlBinding.Type.Name == wsdlPortType.Name
1518                     && wsdlBinding.Type.Namespace == wsdlPortType.ServiceDescription.TargetNamespace)
1519                     yield return wsdlBinding;
1520             }
1521         }
1522
1523         IEnumerable<WsdlNS.Binding> FindBindingsForContract(ContractDescription contract)
1524         {
1525             XmlQualifiedName qName = WsdlExporter.WsdlNamingHelper.GetPortTypeQName(contract);
1526             foreach (WsdlNS.Binding wsdlBinding in GetAllBindings())
1527             {
1528                 if (wsdlBinding.Type.Name == qName.Name
1529                     && wsdlBinding.Type.Namespace == qName.Namespace)
1530                     yield return wsdlBinding;
1531             }
1532         }
1533
1534         IEnumerable<WsdlNS.Port> FindPortsForBinding(WsdlNS.Binding binding)
1535         {
1536             foreach (WsdlNS.Port wsdlPort in GetAllPorts())
1537             {
1538                 if (wsdlPort.Binding.Name == binding.Name && wsdlPort.Binding.Namespace == binding.ServiceDescription.TargetNamespace)
1539                     yield return wsdlPort;
1540             }
1541         }
1542
1543         IEnumerable<WsdlNS.Binding> GetAllBindings()
1544         {
1545             foreach (WsdlNS.ServiceDescription wsdl in this.WsdlDocuments)
1546             {
1547                 foreach (WsdlNS.Binding wsdlBinding in wsdl.Bindings)
1548                 {
1549                     yield return wsdlBinding;
1550                 }
1551             }
1552         }
1553
1554         IEnumerable<WsdlNS.Port> GetAllPorts()
1555         {
1556             foreach (WsdlNS.ServiceDescription wsdl in this.WsdlDocuments)
1557             {
1558                 foreach (WsdlNS.Service wsdlService in wsdl.Services)
1559                 {
1560                     foreach (WsdlNS.Port wsdlPort in wsdlService.Ports)
1561                     {
1562                         yield return wsdlPort;
1563                     }
1564                 }
1565             }
1566         }
1567
1568         [Fx.Tag.SecurityNote(Critical = "Uses ClientSection.UnsafeGetSection to get config in PT.",
1569             Safe = "Does not leak config object, just picks up extensions.")]
1570         [SecuritySafeCritical]
1571         static Collection<IWsdlImportExtension> LoadWsdlExtensionsFromConfig()
1572         {
1573             return ConfigNS.ClientSection.UnsafeGetSection().Metadata.LoadWsdlImportExtensions();
1574         }
1575
1576         internal static IEnumerable<MetadataSection> CreateMetadataDocuments(WsdlNS.ServiceDescriptionCollection wsdlDocuments, XmlSchemaSet xmlSchemas, IEnumerable<XmlElement> policyDocuments)
1577         {
1578
1579             if (wsdlDocuments != null)
1580                 foreach (WsdlNS.ServiceDescription wsdl in wsdlDocuments)
1581                     yield return MetadataSection.CreateFromServiceDescription(wsdl);
1582
1583             if (xmlSchemas != null)
1584                 foreach (XmlSchema schema in xmlSchemas.Schemas())
1585                     yield return MetadataSection.CreateFromSchema(schema);
1586
1587             if (policyDocuments != null)
1588                 foreach (XmlElement policyDocument in policyDocuments)
1589                     yield return MetadataSection.CreateFromPolicy(policyDocument, null);
1590         }
1591
1592         BindingElementCollection ImportPolicyFromWsdl(WsdlEndpointConversionContext endpointContext)
1593         {
1594             PolicyAlternatives policyAlternatives = this.PolicyReader.GetPolicyAlternatives(endpointContext);
1595             IEnumerable<PolicyConversionContext> policyContexts = GetPolicyConversionContextEnumerator(endpointContext.Endpoint, policyAlternatives, this.Quotas);
1596             PolicyConversionContext firstContext = null;
1597
1598             StringBuilder unImportedPolicyMessage = null;
1599             int policyConversionContextsSeen = 0; //limit on the number of alternatives that we'll evaluate
1600             foreach (PolicyConversionContext policyConversionContext in policyContexts)
1601             {
1602                 if (firstContext == null)
1603                     firstContext = policyConversionContext;
1604                 if (this.TryImportPolicy(policyConversionContext))
1605                 {
1606                     return policyConversionContext.BindingElements;
1607                 }
1608                 else
1609                 {
1610                     AppendUnImportedPolicyErrorMessage(ref unImportedPolicyMessage, endpointContext, policyConversionContext);
1611                 }
1612
1613                 if (++policyConversionContextsSeen >= this.Quotas.MaxPolicyConversionContexts)
1614                 {
1615                     break;
1616                 }
1617             }
1618
1619             // we failed to import policy for all PolicyConversionContexts, lets pick one context (the first one)
1620             // and wrap all unprocessed assertion in UnrecognizedAssertionsBindingElement
1621             if (firstContext != null)
1622             {
1623 #pragma warning suppress 56506
1624                 firstContext.BindingElements.Insert(0, CollectUnrecognizedAssertions(firstContext, endpointContext));
1625                 LogImportWarning(unImportedPolicyMessage.ToString());
1626                 return firstContext.BindingElements;
1627             }
1628             // Consider: a /verbose option for svcutil...
1629             if (endpointContext.WsdlPort != null)
1630             {
1631                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(endpointContext.WsdlPort, new InvalidOperationException(SR.GetString(SR.NoUsablePolicyAssertions))));
1632             }
1633             else
1634             {
1635                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(endpointContext.WsdlBinding, new InvalidOperationException(SR.GetString(SR.NoUsablePolicyAssertions))));
1636             }
1637         }
1638
1639         static UnrecognizedAssertionsBindingElement CollectUnrecognizedAssertions(PolicyConversionContext policyContext, WsdlEndpointConversionContext endpointContext)
1640         {
1641             XmlQualifiedName bindingQName = new XmlQualifiedName(endpointContext.WsdlBinding.Name, endpointContext.WsdlBinding.ServiceDescription.TargetNamespace);
1642             UnrecognizedAssertionsBindingElement unknownBindingElement = new UnrecognizedAssertionsBindingElement(bindingQName, policyContext.GetBindingAssertions());
1643             foreach (OperationDescription operation in policyContext.Contract.Operations)
1644             {
1645                 if (policyContext.GetOperationBindingAssertions(operation).Count != 0)
1646                 {
1647                     unknownBindingElement.Add(operation, policyContext.GetOperationBindingAssertions(operation));
1648                 }
1649
1650                 foreach (MessageDescription message in operation.Messages)
1651                 {
1652                     if (policyContext.GetMessageBindingAssertions(message).Count != 0)
1653                     {
1654                         unknownBindingElement.Add(message, policyContext.GetMessageBindingAssertions(message));
1655                     }
1656                 }
1657             }
1658             return unknownBindingElement;
1659         }
1660
1661         static void AppendUnImportedPolicyErrorMessage(ref StringBuilder unImportedPolicyMessage, WsdlEndpointConversionContext endpointContext, PolicyConversionContext policyContext)
1662         {
1663             if (unImportedPolicyMessage == null)
1664             {
1665                 unImportedPolicyMessage = new StringBuilder(SR.GetString(SR.UnabletoImportPolicy));
1666             }
1667             else
1668             {
1669                 unImportedPolicyMessage.AppendLine();
1670             }
1671
1672             if (policyContext.GetBindingAssertions().Count != 0)
1673                 AddUnImportedPolicyString(unImportedPolicyMessage, endpointContext.WsdlBinding, policyContext.GetBindingAssertions());
1674
1675             foreach (OperationDescription operation in policyContext.Contract.Operations)
1676             {
1677                 if (policyContext.GetOperationBindingAssertions(operation).Count != 0)
1678                 {
1679                     AddUnImportedPolicyString(unImportedPolicyMessage,
1680                         endpointContext.GetOperationBinding(operation),
1681                         policyContext.GetOperationBindingAssertions(operation));
1682                 }
1683
1684                 foreach (MessageDescription message in operation.Messages)
1685                 {
1686                     if (policyContext.GetMessageBindingAssertions(message).Count != 0)
1687                     {
1688                         AddUnImportedPolicyString(unImportedPolicyMessage,
1689                             endpointContext.GetMessageBinding(message),
1690                             policyContext.GetMessageBindingAssertions(message));
1691                     }
1692                 }
1693             }
1694
1695         }
1696
1697         static void AddUnImportedPolicyString(StringBuilder stringBuilder, WsdlNS.NamedItem item, IEnumerable<XmlElement> unimportdPolicy)
1698         {
1699             stringBuilder.AppendLine(SR.GetString(SR.UnImportedAssertionList, CreateXPathString(item)));
1700             // do not putput duplicated assetions
1701             Dictionary<XmlElement, XmlElement> unique = new Dictionary<XmlElement, XmlElement>();
1702             int uniqueAsserions = 0;
1703             foreach (XmlElement element in unimportdPolicy)
1704             {
1705                 if (unique.ContainsKey(element))
1706                     continue;
1707                 unique.Add(element, element);
1708                 uniqueAsserions++;
1709                 if (uniqueAsserions > 128)
1710                 {
1711                     stringBuilder.Append("..");
1712                     stringBuilder.AppendLine();
1713                     break;
1714                 }
1715                 WriteElement(element, stringBuilder);
1716             }
1717         }
1718
1719         static void WriteElement(XmlElement element, StringBuilder stringBuilder)
1720         {
1721             stringBuilder.Append("    <");
1722             stringBuilder.Append(element.Name);
1723             if (!string.IsNullOrEmpty(element.NamespaceURI))
1724             {
1725                 stringBuilder.Append(' ');
1726                 stringBuilder.Append("xmlns");
1727                 if (!string.IsNullOrEmpty(element.Prefix))
1728                 {
1729                     stringBuilder.Append(':');
1730                     stringBuilder.Append(element.Prefix);
1731                 }
1732                 stringBuilder.Append('=');
1733                 stringBuilder.Append('\'');
1734                 stringBuilder.Append(element.NamespaceURI);
1735                 stringBuilder.Append('\'');
1736             }
1737             stringBuilder.Append(">..</");
1738             stringBuilder.Append(element.Name);
1739             stringBuilder.Append('>');
1740             stringBuilder.AppendLine();
1741         }
1742
1743         const string xPathDocumentFormatString = "//wsdl:definitions[@targetNamespace='{0}']";
1744         const string xPathItemSubFormatString = "/wsdl:{0}";
1745         const string xPathNamedItemSubFormatString = xPathItemSubFormatString + "[@name='{1}']";
1746
1747         static string GetElementName(WsdlNS.NamedItem item)
1748         {
1749             if (item is WsdlNS.PortType)
1750                 return "wsdl:portType";
1751             else if (item is WsdlNS.Binding)
1752                 return "wsdl:binding";
1753             else if (item is WsdlNS.ServiceDescription)
1754                 return "wsdl:definitions";
1755             else if (item is WsdlNS.Service)
1756                 return "wsdl:service";
1757             else if (item is WsdlNS.Message)
1758                 return "wsdl:message";
1759             else if (item is WsdlNS.Operation)
1760                 return "wsdl:operation";
1761             else if (item is WsdlNS.Port)
1762                 return "wsdl:port";
1763             else
1764             {
1765                 Fx.Assert("GetElementName Method should be updated to support " + item.GetType());
1766                 return null;
1767             }
1768         }
1769
1770         static string CreateXPathString(WsdlNS.NamedItem item)
1771         {
1772             if (item == null)
1773                 return SR.GetString(SR.XPathUnavailable);
1774             string nameValue = item.Name;
1775             string localName;
1776             string wsdlNs;
1777             string rest = string.Empty;
1778             string itemPath = string.Empty;
1779
1780             GetXPathParameters(item, out wsdlNs, out localName, ref nameValue, ref rest);
1781             string documentPath = string.Format(CultureInfo.InvariantCulture, xPathDocumentFormatString, wsdlNs);
1782
1783             if (localName != null)
1784             {
1785                 itemPath = string.Format(CultureInfo.InvariantCulture, xPathNamedItemSubFormatString, localName, nameValue);
1786             }
1787             Fx.Assert(rest != null, "GetXPathParameters Method should never set rest to null. this happened for: " + item.GetType());
1788             return documentPath + itemPath + rest;
1789         }
1790
1791         static void GetXPathParameters(WsdlNS.NamedItem item, out string wsdlNs, out string localName, ref string nameValue, ref string rest)
1792         {
1793             if (item is WsdlNS.ServiceDescription)
1794             {
1795                 localName = null;
1796                 wsdlNs = ((WsdlNS.ServiceDescription)item).TargetNamespace ?? String.Empty;
1797             }
1798             if (item is WsdlNS.PortType)
1799             {
1800                 localName = "portType";
1801                 wsdlNs = ((WsdlNS.PortType)item).ServiceDescription.TargetNamespace ?? String.Empty;
1802             }
1803             else if (item is WsdlNS.Binding)
1804             {
1805                 localName = "binding";
1806                 wsdlNs = ((WsdlNS.Binding)item).ServiceDescription.TargetNamespace ?? String.Empty;
1807             }
1808             else if (item is WsdlNS.ServiceDescription)
1809             {
1810                 localName = "definitions";
1811                 wsdlNs = ((WsdlNS.ServiceDescription)item).TargetNamespace ?? String.Empty;
1812             }
1813             else if (item is WsdlNS.Service)
1814             {
1815                 localName = "service";
1816                 wsdlNs = ((WsdlNS.Service)item).ServiceDescription.TargetNamespace ?? String.Empty;
1817             }
1818             else if (item is WsdlNS.Message)
1819             {
1820                 localName = "message";
1821                 wsdlNs = ((WsdlNS.Message)item).ServiceDescription.TargetNamespace ?? String.Empty;
1822             }
1823             else if (item is WsdlNS.Port)
1824             {
1825                 WsdlNS.Service wsdlService = ((WsdlNS.Port)item).Service;
1826                 localName = "service";
1827                 nameValue = wsdlService.Name;
1828                 wsdlNs = wsdlService.ServiceDescription.TargetNamespace ?? String.Empty;
1829                 rest = string.Format(CultureInfo.InvariantCulture, xPathNamedItemSubFormatString, "port", item.Name);
1830             }
1831             else if (item is WsdlNS.Operation)
1832             {
1833                 WsdlNS.PortType wsdlPortType = ((WsdlNS.Operation)item).PortType;
1834                 localName = "portType";
1835                 nameValue = wsdlPortType.Name;
1836                 wsdlNs = wsdlPortType.ServiceDescription.TargetNamespace ?? String.Empty;
1837                 rest = string.Format(CultureInfo.InvariantCulture, xPathNamedItemSubFormatString, "operation", item.Name);
1838             }
1839             else if (item is WsdlNS.OperationBinding)
1840             {
1841                 WsdlNS.OperationBinding wsdlOperationBinding = ((WsdlNS.OperationBinding)item);
1842                 localName = "binding";
1843                 nameValue = wsdlOperationBinding.Binding.Name;
1844                 wsdlNs = wsdlOperationBinding.Binding.ServiceDescription.TargetNamespace ?? String.Empty;
1845                 rest = string.Format(CultureInfo.InvariantCulture, xPathNamedItemSubFormatString, "operation", item.Name);
1846             }
1847             else if (item is WsdlNS.MessageBinding)
1848             {
1849                 localName = "binding";
1850                 WsdlNS.OperationBinding wsdlOperationBinding = ((WsdlNS.MessageBinding)item).OperationBinding;
1851                 wsdlNs = wsdlOperationBinding.Binding.ServiceDescription.TargetNamespace ?? String.Empty;
1852                 nameValue = wsdlOperationBinding.Binding.Name;
1853                 string messageName = item.Name;
1854
1855                 string messageTag = string.Empty;
1856                 if (item is WsdlNS.InputBinding)
1857                     messageTag = "input";
1858                 else if (item is WsdlNS.OutputBinding)
1859                     messageTag = "output";
1860                 else if (item is WsdlNS.FaultBinding)
1861                     messageTag = "fault";
1862                 else
1863                     Fx.Assert("Unsupported WSDL OM: unknown WsdlNS.MessageBinding: " + item.GetType());
1864
1865                 rest = string.Format(CultureInfo.InvariantCulture, xPathNamedItemSubFormatString, "operation", wsdlOperationBinding.Name);
1866                 if (string.IsNullOrEmpty(messageName))
1867                     rest += string.Format(CultureInfo.InvariantCulture, xPathItemSubFormatString, messageTag);
1868                 else
1869                     rest += string.Format(CultureInfo.InvariantCulture, xPathNamedItemSubFormatString, messageTag, messageName);
1870             }
1871             else
1872             {
1873                 Fx.Assert("GetXPathParameters Method should be updated to support " + item.GetType());
1874                 localName = null;
1875                 wsdlNs = null;
1876             }
1877         }
1878
1879         void LogImportWarning(string warningMessage)
1880         {
1881             if (warnings.ContainsKey(warningMessage))
1882                 return;
1883             if (warnings.Count >= 1024)
1884                 warnings.Clear();
1885             warnings.Add(warningMessage, warningMessage);
1886             this.Errors.Add(new MetadataConversionError(warningMessage, true));
1887         }
1888
1889         void LogImportError(WsdlNS.NamedItem item, WsdlImportException wie)
1890         {
1891             string errormessage;
1892             if (wie.InnerException != null && (wie.InnerException is WsdlImportException))
1893             {
1894                 WsdlImportException wieInner = wie.InnerException as WsdlImportException;
1895                 string dependencyMessage = SR.GetString(SR.WsdlImportErrorDependencyDetail, GetElementName(wieInner.SourceItem), GetElementName(item), CreateXPathString(wieInner.SourceItem));
1896                 errormessage = SR.GetString(SR.WsdlImportErrorMessageDetail, GetElementName(item), CreateXPathString(wie.SourceItem), dependencyMessage);
1897             }
1898             else
1899             {
1900                 errormessage = SR.GetString(SR.WsdlImportErrorMessageDetail, GetElementName(item), CreateXPathString(wie.SourceItem), wie.Message);
1901             }
1902
1903             importErrors.Add(item, wie);
1904             this.Errors.Add(new MetadataConversionError(errormessage, false));
1905         }
1906
1907         static Exception CreateBeforeImportExtensionException(IWsdlImportExtension importer, Exception e)
1908         {
1909             string errorMessage = SR.GetString(SR.WsdlExtensionBeforeImportError, importer.GetType().AssemblyQualifiedName, e.Message);
1910             return new InvalidOperationException(errorMessage, e);
1911         }
1912
1913         Exception CreateAlreadyFaultedException(WsdlNS.NamedItem item)
1914         {
1915             WsdlImportException innerException = importErrors[item];
1916             string warningMsg = SR.GetString(SR.WsdlItemAlreadyFaulted, GetElementName(item));
1917             return new AlreadyFaultedException(warningMsg, innerException);
1918         }
1919
1920         static Exception CreateExtensionException(IWsdlImportExtension importer, Exception e)
1921         {
1922             string errorMessage = SR.GetString(SR.WsdlExtensionImportError, importer.GetType().FullName, e.Message);
1923             //consider Microsoft, allow internal exceptions to throw WsdlImportException and handle it in some special way?
1924             return new InvalidOperationException(errorMessage, e);
1925         }
1926
1927         class AlreadyFaultedException : InvalidOperationException
1928         {
1929             internal AlreadyFaultedException(string message, WsdlImportException innerException)
1930                 : base(message, innerException) { }
1931         }
1932
1933         class WsdlImportException : Exception
1934         {
1935             WsdlNS.NamedItem sourceItem;
1936             readonly string xPath = null;
1937
1938             WsdlImportException(WsdlNS.NamedItem item, Exception innerException)
1939                 : base(string.Empty, innerException)
1940             {
1941                 this.xPath = CreateXPathString(item);
1942                 this.sourceItem = item;
1943             }
1944
1945             internal static WsdlImportException Create(WsdlNS.NamedItem item, Exception innerException)
1946             {
1947                 WsdlImportException wie = innerException as WsdlImportException;
1948                 if (wie != null && wie.IsChildNodeOf(item))
1949                 {
1950                     wie.sourceItem = item;
1951                     return wie;
1952                 }
1953                 else
1954                 {
1955                     AlreadyFaultedException afe = innerException as AlreadyFaultedException;
1956                     if (afe != null)
1957                         return new WsdlImportException(item, afe.InnerException);
1958                     else
1959                         return new WsdlImportException(item, innerException);
1960                 }
1961             }
1962
1963             internal bool IsChildNodeOf(WsdlNS.NamedItem item)
1964             {
1965                 return this.XPath.StartsWith(CreateXPathString(item), StringComparison.Ordinal);
1966             }
1967
1968             internal string XPath { get { return xPath; } }
1969
1970             internal WsdlNS.NamedItem SourceItem { get { return sourceItem; } }
1971
1972             public override string Message
1973             {
1974                 get
1975                 {
1976                     Exception messageException = this.InnerException;
1977
1978                     while (messageException is WsdlImportException)
1979                         messageException = messageException.InnerException;
1980
1981                     if (messageException == null)
1982                         return string.Empty;
1983
1984                     return messageException.Message;
1985                 }
1986             }
1987         }
1988
1989         internal class WsdlPolicyReader
1990         {
1991             WsdlImporter importer;
1992             WsdlPolicyDictionary policyDictionary;
1993
1994             static readonly string[] EmptyStringArray = new string[0];
1995
1996             internal WsdlPolicyReader(WsdlImporter importer)
1997             {
1998                 this.importer = importer;
1999                 this.policyDictionary = new WsdlPolicyDictionary(importer);
2000                 importer.PolicyWarningOccured += this.LogPolicyNormalizationWarning;
2001             }
2002
2003             IEnumerable<IEnumerable<XmlElement>> GetPolicyAlternatives(WsdlNS.NamedItem item, WsdlNS.ServiceDescription wsdl)
2004             {
2005                 Collection<XmlElement> policyElements = new Collection<XmlElement>();
2006
2007                 foreach (XmlElement element in GetReferencedPolicy(item, wsdl))
2008                 {
2009                     policyElements.Add(element);
2010                 }
2011
2012                 foreach (XmlElement element in GetEmbeddedPolicy(item))
2013                 {
2014                     policyElements.Add(element);
2015                     if (!policyDictionary.PolicySourceTable.ContainsKey(element))
2016                         policyDictionary.PolicySourceTable.Add(element, wsdl);
2017                 }
2018
2019                 return importer.NormalizePolicy(policyElements);
2020             }
2021
2022             void LogPolicyNormalizationWarning(XmlElement contextAssertion, string warningMessage)
2023             {
2024                 string xPath = null;
2025                 if (contextAssertion != null)
2026                     xPath = this.policyDictionary.CreateIdXPath(contextAssertion);
2027
2028                 StringBuilder warningMsg = new StringBuilder();
2029                 warningMsg.AppendLine(warningMessage);
2030
2031                 if (!string.IsNullOrEmpty(xPath))
2032                 {
2033                     warningMsg.AppendLine(SR.GetString(SR.XPathPointer, xPath));
2034                 }
2035                 else
2036                 {
2037                     //
2038                     // We were given a context assertion that we couldn't get an XPath for
2039                     //
2040                     warningMsg.AppendLine(SR.GetString(SR.XPathPointer, SR.GetString(SR.XPathUnavailable)));
2041                 }
2042                 importer.LogImportWarning(warningMsg.ToString());
2043             }
2044
2045             internal static bool ContainsPolicy(WsdlNS.Binding wsdlBinding)
2046             {
2047                 if (HasPolicyAttached(wsdlBinding))
2048                     return true;
2049
2050                 foreach (WsdlNS.OperationBinding wsdlOperationBinding in wsdlBinding.Operations)
2051                 {
2052                     if (HasPolicyAttached(wsdlOperationBinding))
2053                     {
2054                         return true;
2055                     }
2056                     if (wsdlOperationBinding.Input != null && HasPolicyAttached(wsdlOperationBinding.Input))
2057                     {
2058                         return true;
2059                     }
2060                     if (wsdlOperationBinding.Output != null && HasPolicyAttached(wsdlOperationBinding.Output))
2061                     {
2062                         return true;
2063                     }
2064                     foreach (WsdlNS.FaultBinding faultBinding in wsdlOperationBinding.Faults)
2065                     {
2066                         if (HasPolicyAttached(faultBinding))
2067                         {
2068                             return true;
2069                         }
2070                     }
2071                 }
2072
2073                 return false;
2074             }
2075
2076             internal static bool HasPolicy(WsdlNS.Port wsdlPort)
2077             {
2078                 return HasPolicyAttached(wsdlPort);
2079             }
2080
2081             internal static IEnumerable<XmlElement> GetEmbeddedPolicy(WsdlNS.NamedItem item)
2082             {
2083                 List<XmlElement> embeddedPolicies = new List<XmlElement>();
2084                 embeddedPolicies.AddRange(item.Extensions.FindAll(MetadataStrings.WSPolicy.Elements.Policy,
2085                     MetadataStrings.WSPolicy.NamespaceUri));
2086                 embeddedPolicies.AddRange(item.Extensions.FindAll(MetadataStrings.WSPolicy.Elements.Policy,
2087                     MetadataStrings.WSPolicy.NamespaceUri15));
2088                 return embeddedPolicies;
2089             }
2090
2091             IEnumerable<XmlElement> GetReferencedPolicy(WsdlNS.NamedItem item, WsdlNS.ServiceDescription wsdl)
2092             {
2093                 string xPath = CreateXPathString(item);
2094
2095                 foreach (string policyRef in GetPolicyReferenceUris(item, xPath))
2096                 {
2097                     XmlElement policy = policyDictionary.ResolvePolicyReference(policyRef, wsdl);
2098                     if (policy == null)
2099                     {
2100                         StringBuilder warningMsg = new StringBuilder();
2101                         warningMsg.AppendLine(SR.GetString(SR.UnableToFindPolicyWithId, policyRef));
2102                         warningMsg.AppendLine(SR.GetString(SR.XPathPointer, xPath));
2103                         importer.LogImportWarning(warningMsg.ToString());
2104                         continue;
2105                     }
2106                     yield return policy;
2107                 }
2108             }
2109
2110             IEnumerable<string> GetPolicyReferenceUris(WsdlNS.NamedItem item, string xPath)
2111             {
2112                 //
2113                 // get policy from wsp:PolicyUris attribute
2114                 //
2115                 foreach (string policyUri in ReadPolicyUrisAttribute(item))
2116                     yield return policyUri;
2117
2118                 //
2119                 // get policy from <wsp:PolicyReference> Elements
2120                 //
2121                 foreach (string policyUri in ReadPolicyReferenceElements(item, xPath))
2122                     yield return policyUri;
2123             }
2124
2125             IEnumerable<string> ReadPolicyReferenceElements(WsdlNS.NamedItem item, string xPath)
2126             {
2127                 List<XmlElement> policyReferences = new List<XmlElement>();
2128                 policyReferences.AddRange(item.Extensions.FindAll(MetadataStrings.WSPolicy.Elements.PolicyReference,
2129                     MetadataStrings.WSPolicy.NamespaceUri));
2130                 policyReferences.AddRange(item.Extensions.FindAll(MetadataStrings.WSPolicy.Elements.PolicyReference,
2131                     MetadataStrings.WSPolicy.NamespaceUri15));
2132
2133                 foreach (XmlElement element in policyReferences)
2134                 {
2135                     string idRef = element.GetAttribute(MetadataStrings.WSPolicy.Attributes.URI);
2136
2137                     if (idRef == null)
2138                     {
2139                         string warningMsg = SR.GetString(SR.PolicyReferenceMissingURI, MetadataStrings.WSPolicy.Attributes.URI);
2140                         importer.LogImportWarning(warningMsg);
2141                     }
2142                     else if (idRef == string.Empty)
2143                     {
2144                         string warningMsg = SR.GetString(SR.PolicyReferenceInvalidId);
2145                         importer.LogImportWarning(warningMsg);
2146                         continue;
2147                     }
2148                     else
2149                     {
2150                         yield return idRef;
2151                     }
2152                 }
2153             }
2154
2155             static string[] ReadPolicyUrisAttribute(WsdlNS.NamedItem item)
2156             {
2157
2158                 XmlAttribute[] attributes = item.ExtensibleAttributes;
2159                 if (attributes != null && attributes.Length > 0)
2160                 {
2161                     foreach (XmlAttribute attribute in attributes)
2162                     {
2163                         if (PolicyHelper.IsPolicyURIs(attribute))
2164                         {
2165                             return attribute.Value.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
2166                         }
2167                     }
2168                 }
2169
2170                 return EmptyStringArray;
2171             }
2172
2173             static bool HasPolicyAttached(WsdlNS.NamedItem item)
2174             {
2175                 XmlAttribute[] attributes = item.ExtensibleAttributes;
2176                 if (attributes != null && Array.Exists(attributes, PolicyHelper.IsPolicyURIs))
2177                 {
2178                     return true;
2179                 }
2180
2181                 if (item.Extensions.Find(MetadataStrings.WSPolicy.Elements.PolicyReference, MetadataStrings.WSPolicy.NamespaceUri) != null
2182                     || item.Extensions.Find(MetadataStrings.WSPolicy.Elements.PolicyReference, MetadataStrings.WSPolicy.NamespaceUri15) != null)
2183                 {
2184                     return true;
2185                 }
2186
2187                 if (item.Extensions.Find(MetadataStrings.WSPolicy.Elements.Policy, MetadataStrings.WSPolicy.NamespaceUri) != null
2188                     || item.Extensions.Find(MetadataStrings.WSPolicy.Elements.Policy, MetadataStrings.WSPolicy.NamespaceUri15) != null)
2189                 {
2190                     return true;
2191                 }
2192
2193                 return false;
2194             }
2195
2196             internal PolicyAlternatives GetPolicyAlternatives(WsdlEndpointConversionContext endpointContext)
2197             {
2198                 PolicyAlternatives policyAlternatives = new PolicyAlternatives();
2199
2200                 //
2201                 // Create EndpointAlternatives either from wsd:binding or from CrossProduct of wsd:binding and wsdl:port policy
2202                 //
2203                 WsdlNS.ServiceDescription bindingWsdl = endpointContext.WsdlBinding.ServiceDescription;
2204                 IEnumerable<IEnumerable<XmlElement>> wsdlBindingAlternatives = this.GetPolicyAlternatives(endpointContext.WsdlBinding, bindingWsdl);
2205                 if (endpointContext.WsdlPort != null)
2206                 {
2207                     IEnumerable<IEnumerable<XmlElement>> wsdlPortAlternatives = this.GetPolicyAlternatives(endpointContext.WsdlPort, endpointContext.WsdlPort.Service.ServiceDescription);
2208                     policyAlternatives.EndpointAlternatives = PolicyHelper.CrossProduct<XmlElement>(wsdlBindingAlternatives, wsdlPortAlternatives, new YieldLimiter(this.importer.Quotas.MaxYields, this.importer));
2209                 }
2210                 else
2211                 {
2212                     policyAlternatives.EndpointAlternatives = wsdlBindingAlternatives;
2213                 }
2214
2215                 //
2216                 // Create operation and message policy
2217                 //
2218                 policyAlternatives.OperationBindingAlternatives = new Dictionary<OperationDescription, IEnumerable<IEnumerable<XmlElement>>>(endpointContext.Endpoint.Contract.Operations.Count);
2219                 policyAlternatives.MessageBindingAlternatives = new Dictionary<MessageDescription, IEnumerable<IEnumerable<XmlElement>>>();
2220                 policyAlternatives.FaultBindingAlternatives = new Dictionary<FaultDescription, IEnumerable<IEnumerable<XmlElement>>>();
2221
2222                 foreach (OperationDescription operation in endpointContext.Endpoint.Contract.Operations)
2223                 {
2224                     // Skip operations that have Action/ReplyAction = "*" 
2225                     if (!WsdlExporter.OperationIsExportable(operation))
2226                     {
2227                         continue;
2228                     }
2229
2230                     WsdlNS.OperationBinding wsdlOperationBinding = endpointContext.GetOperationBinding(operation);
2231                     try
2232                     {
2233                         IEnumerable<IEnumerable<XmlElement>> operationAlternatives = this.GetPolicyAlternatives(wsdlOperationBinding, bindingWsdl);
2234                         policyAlternatives.OperationBindingAlternatives.Add(operation, operationAlternatives);
2235
2236                         foreach (MessageDescription message in operation.Messages)
2237                         {
2238                             WsdlNS.MessageBinding wsdlMessageBinding = endpointContext.GetMessageBinding(message);
2239                             CreateMessageBindingAlternatives(policyAlternatives, bindingWsdl, message, wsdlMessageBinding);
2240                         }
2241
2242                         foreach (FaultDescription fault in operation.Faults)
2243                         {
2244                             WsdlNS.FaultBinding wsdlFaultBinding = endpointContext.GetFaultBinding(fault);
2245                             CreateFaultBindingAlternatives(policyAlternatives, bindingWsdl, fault, wsdlFaultBinding);
2246                         }
2247                     }
2248 #pragma warning suppress 56500 // covered by FxCOP
2249                     catch (Exception e)
2250                     {
2251                         if (Fx.IsFatal(e))
2252                             throw;
2253                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(wsdlOperationBinding, e));
2254                     }
2255                 }
2256
2257                 return policyAlternatives;
2258             }
2259
2260             void CreateMessageBindingAlternatives(PolicyAlternatives policyAlternatives, WsdlNS.ServiceDescription bindingWsdl, MessageDescription message, WsdlNS.MessageBinding wsdlMessageBinding)
2261             {
2262                 try
2263                 {
2264                     IEnumerable<IEnumerable<XmlElement>> messageAlternatives = this.GetPolicyAlternatives(wsdlMessageBinding, bindingWsdl);
2265                     policyAlternatives.MessageBindingAlternatives.Add(message, messageAlternatives);
2266                 }
2267 #pragma warning suppress 56500 // covered by FxCOP
2268                 catch (Exception e)
2269                 {
2270                     if (Fx.IsFatal(e))
2271                         throw;
2272                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(wsdlMessageBinding, e));
2273                 }
2274             }
2275
2276             void CreateFaultBindingAlternatives(PolicyAlternatives policyAlternatives, WsdlNS.ServiceDescription bindingWsdl, FaultDescription fault, WsdlNS.FaultBinding wsdlFaultBinding)
2277             {
2278                 try
2279                 {
2280                     IEnumerable<IEnumerable<XmlElement>> faultAlternatives = this.GetPolicyAlternatives(wsdlFaultBinding, bindingWsdl);
2281                     policyAlternatives.FaultBindingAlternatives.Add(fault, faultAlternatives);
2282                 }
2283 #pragma warning suppress 56500 // covered by FxCOP
2284                 catch (Exception e)
2285                 {
2286                     if (Fx.IsFatal(e))
2287                         throw;
2288                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(wsdlFaultBinding, e));
2289                 }
2290             }
2291
2292             internal XmlElement ResolvePolicyReference(string policyReference, XmlElement contextPolicyAssertion)
2293             {
2294                 return this.policyDictionary.ResolvePolicyReference(policyReference, contextPolicyAssertion);
2295             }
2296
2297             class WsdlPolicyDictionary
2298             {
2299                 readonly MetadataImporter importer;
2300                 readonly Dictionary<WsdlNS.ServiceDescription, Dictionary<string, XmlElement>> embeddedPolicyDictionary = new Dictionary<WsdlNS.ServiceDescription, Dictionary<string, XmlElement>>();
2301                 readonly Dictionary<string, XmlElement> externalPolicyDictionary = new Dictionary<string, XmlElement>();
2302                 readonly Dictionary<XmlElement, WsdlNS.ServiceDescription> policySourceTable = new Dictionary<XmlElement, WsdlNS.ServiceDescription>();
2303
2304                 internal Dictionary<XmlElement, WsdlNS.ServiceDescription> PolicySourceTable
2305                 {
2306                     get { return policySourceTable; }
2307                 }
2308
2309                 internal WsdlPolicyDictionary(WsdlImporter importer)
2310                 {
2311                     this.importer = importer;
2312
2313                     //
2314                     // Embedded Policy documents
2315                     //
2316                     foreach (WsdlNS.ServiceDescription wsdl in importer.wsdlDocuments)
2317                     {
2318                         foreach (XmlElement element in WsdlPolicyReader.GetEmbeddedPolicy(wsdl))
2319                         {
2320                             AddEmbeddedPolicy(importer, wsdl, element);
2321                         }
2322                     }
2323
2324                     //
2325                     // External Policy documents
2326                     //
2327                     foreach (KeyValuePair<string, XmlElement> policyDocument in importer.policyDocuments)
2328                     {
2329                         AddExternalPolicy(importer, policyDocument);
2330                     }
2331
2332                 }
2333
2334                 void AddEmbeddedPolicy(WsdlImporter importer, WsdlNS.ServiceDescription wsdl, XmlElement element)
2335                 {
2336                     string key = GetFragmentIdentifier(element);
2337                     if (String.IsNullOrEmpty(key))
2338                     {
2339                         string xPath = CreateXPathString(wsdl);
2340                         string warningMsg = SR.GetString(SR.PolicyInWsdlMustHaveFragmentId, xPath);
2341                         importer.LogImportWarning(warningMsg);
2342                         return;
2343                     }
2344
2345                     Dictionary<string, XmlElement> wsdlPolicyDictionary;
2346                     if (!this.embeddedPolicyDictionary.TryGetValue(wsdl, out wsdlPolicyDictionary))
2347                     {
2348                         wsdlPolicyDictionary = new Dictionary<string, XmlElement>();
2349                         this.embeddedPolicyDictionary.Add(wsdl, wsdlPolicyDictionary);
2350                     }
2351                     else if (wsdlPolicyDictionary.ContainsKey(key))
2352                     {
2353                         string xPath = CreateIdXPath(wsdl, element, key);
2354                         string warningMsg = SR.GetString(SR.DuplicatePolicyInWsdlSkipped, xPath);
2355                         importer.LogImportWarning(warningMsg);
2356                         return;
2357                     }
2358
2359                     wsdlPolicyDictionary.Add(key, element);
2360                     policySourceTable.Add(element, wsdl);
2361                 }
2362
2363                 void AddExternalPolicy(WsdlImporter importer, KeyValuePair<string, XmlElement> policyDocument)
2364                 {
2365                     if (policyDocument.Value.NamespaceURI != MetadataStrings.WSPolicy.NamespaceUri
2366                         && policyDocument.Value.NamespaceURI != MetadataStrings.WSPolicy.NamespaceUri15)
2367                     {
2368                         string warningMsg = SR.GetString(SR.UnrecognizedPolicyDocumentNamespace, policyDocument.Value.NamespaceURI);
2369                         importer.LogImportWarning(warningMsg);
2370                         return;
2371                     }
2372
2373                     if (PolicyHelper.GetNodeType(policyDocument.Value) != PolicyHelper.NodeType.Policy)
2374                     {
2375                         string warningMsg = SR.GetString(SR.UnsupportedPolicyDocumentRoot, policyDocument.Value.Name);
2376                         importer.LogImportWarning(warningMsg);
2377                         return;
2378                     }
2379
2380                     string key = CreateKeyFromPolicy(policyDocument.Key, policyDocument.Value);
2381                     if (externalPolicyDictionary.ContainsKey(key))
2382                     {
2383                         string warningMsg = SR.GetString(SR.DuplicatePolicyDocumentSkipped, key);
2384                         importer.LogImportWarning(warningMsg);
2385                         return;
2386                     }
2387
2388                     this.externalPolicyDictionary.Add(key, policyDocument.Value);
2389                 }
2390
2391                 internal XmlElement ResolvePolicyReference(string policyReference, XmlElement contextPolicyAssertion)
2392                 {
2393                     XmlElement policy;
2394
2395                     if (policyReference[0] != '#')
2396                     {
2397                         externalPolicyDictionary.TryGetValue(policyReference, out policy);
2398                         return policy;
2399                     }
2400
2401                     if (contextPolicyAssertion == null)
2402                     {
2403                         return null;
2404                     }
2405
2406                     WsdlNS.ServiceDescription sourceWsdl;
2407                     if (!policySourceTable.TryGetValue(contextPolicyAssertion, out sourceWsdl))
2408                     {
2409                         return null;
2410                     }
2411
2412                     return ResolvePolicyReference(policyReference, sourceWsdl);
2413                 }
2414
2415                 internal XmlElement ResolvePolicyReference(string policyReference, WsdlNS.ServiceDescription wsdlDocument)
2416                 {
2417                     XmlElement policy;
2418                     if (policyReference[0] != '#')
2419                     {
2420                         externalPolicyDictionary.TryGetValue(policyReference, out policy);
2421                         return policy;
2422                     }
2423
2424                     Dictionary<string, XmlElement> wsdlPolicyDictionary;
2425                     if (!this.embeddedPolicyDictionary.TryGetValue(wsdlDocument, out wsdlPolicyDictionary))
2426                     {
2427                         return null;
2428                     }
2429
2430                     wsdlPolicyDictionary.TryGetValue(policyReference, out policy);
2431                     return policy;
2432                 }
2433
2434                 static string CreateKeyFromPolicy(string identifier, XmlElement policyElement)
2435                 {
2436                     string policyId = GetFragmentIdentifier(policyElement);
2437                     string policyUri = string.Format(CultureInfo.InvariantCulture, "{0}{1}", identifier, policyId);
2438                     return policyUri;
2439                 }
2440
2441                 static string GetFragmentIdentifier(XmlElement element)
2442                 {
2443                     return PolicyHelper.GetFragmentIdentifier(element);
2444                 }
2445
2446                 static readonly string wspPolicy = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", MetadataStrings.WSPolicy.Prefix, MetadataStrings.WSPolicy.Elements.Policy);
2447                 static readonly string xmlId = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", MetadataStrings.Xml.Prefix, MetadataStrings.Xml.Attributes.Id);
2448                 static readonly string wsuId = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", MetadataStrings.Wsu.Prefix, MetadataStrings.Wsu.Attributes.Id);
2449
2450                 internal string CreateIdXPath(XmlElement policyAssertion)
2451                 {
2452                     WsdlNS.ServiceDescription sourceWsdl;
2453                     if (!policySourceTable.TryGetValue(policyAssertion, out sourceWsdl))
2454                     {
2455                         return null;
2456                     }
2457                     string key = GetFragmentIdentifier(policyAssertion);
2458                     if (string.IsNullOrEmpty(key))
2459                     {
2460                         return null;
2461                     }
2462                     return CreateIdXPath(sourceWsdl, policyAssertion, key);
2463                 }
2464
2465                 internal static string CreateIdXPath(WsdlNS.ServiceDescription wsdl, XmlElement element, string key)
2466                 {
2467                     string xPath = CreateXPathString(wsdl);
2468
2469                     string idAttrib;
2470                     if (element.HasAttribute(MetadataStrings.Wsu.Attributes.Id, MetadataStrings.Wsu.NamespaceUri))
2471                     {
2472                         idAttrib = wsuId;
2473                     }
2474                     else if (element.HasAttribute(MetadataStrings.Xml.Attributes.Id, MetadataStrings.Xml.NamespaceUri))
2475                     {
2476                         idAttrib = xmlId;
2477                     }
2478                     else
2479                     {
2480                         Fx.Assert("CreateIdXPath always called with a valid key");
2481                         return null;
2482                     }
2483                     return string.Format(CultureInfo.InvariantCulture, "{0}/{1}/[@{2}='{3}']", xPath, wspPolicy, idAttrib, key);
2484                 }
2485
2486             }
2487
2488         }
2489
2490         enum ErrorBehavior
2491         {
2492             RethrowExceptions,
2493             DoNotThrowExceptions,
2494         }
2495
2496         enum WsdlPortTypeImportOptions
2497         {
2498             ReuseExistingContracts,
2499             IgnoreExistingContracts,
2500         }
2501     }
2502 }