You've already forked linux-packaging-mono
Rewrite with hard-coded offsets into the PE file format to discern if a binary is PE32 or PE32+, and then to determine if it contains a "CLR Data Directory" entry that looks valid. Tested with PE32 and PE32+ compiled Mono binaries, PE32 and PE32+ native binaries, and a random assortment of garbage files. Former-commit-id: 9e7ac86ec84f653a2f79b87183efd5b0ebda001b
2503 lines
112 KiB
C#
2503 lines
112 KiB
C#
//-----------------------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//-----------------------------------------------------------------------------
|
|
namespace System.ServiceModel.Description
|
|
{
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Globalization;
|
|
using System.Runtime;
|
|
using System.Security;
|
|
using System.ServiceModel;
|
|
using System.ServiceModel.Channels;
|
|
using System.Text;
|
|
using System.Xml;
|
|
using System.Xml.Schema;
|
|
using ConfigNS = System.ServiceModel.Configuration;
|
|
using WsdlConfigNS = System.Web.Services.Configuration;
|
|
using WsdlNS = System.Web.Services.Description;
|
|
|
|
public class WsdlImporter : MetadataImporter
|
|
{
|
|
readonly Dictionary<WsdlNS.NamedItem, WsdlImportException> importErrors = new Dictionary<WsdlNS.NamedItem, WsdlImportException>();
|
|
bool isFaulted = false;
|
|
|
|
readonly Dictionary<XmlQualifiedName, WsdlContractConversionContext> importedPortTypes = new Dictionary<XmlQualifiedName, WsdlContractConversionContext>();
|
|
readonly Dictionary<XmlQualifiedName, WsdlEndpointConversionContext> importedBindings = new Dictionary<XmlQualifiedName, WsdlEndpointConversionContext>();
|
|
readonly Dictionary<WsdlNS.Port, ServiceEndpoint> importedPorts = new Dictionary<WsdlNS.Port, ServiceEndpoint>();
|
|
|
|
readonly KeyedByTypeCollection<IWsdlImportExtension> wsdlExtensions;
|
|
|
|
readonly WsdlNS.ServiceDescriptionCollection wsdlDocuments = new WsdlNS.ServiceDescriptionCollection();
|
|
readonly XmlSchemaSet xmlSchemas = WsdlExporter.GetEmptySchemaSet();
|
|
readonly Dictionary<string, XmlElement> policyDocuments = new Dictionary<string, XmlElement>();
|
|
readonly Dictionary<string, string> warnings = new Dictionary<string, string>();
|
|
WsdlPolicyReader wsdlPolicyReader;
|
|
|
|
bool beforeImportCalled = false;
|
|
|
|
public WsdlImporter(MetadataSet metadata)
|
|
: this(metadata, null, null, MetadataImporterQuotas.Defaults)
|
|
{
|
|
}
|
|
|
|
public WsdlImporter(MetadataSet metadata, IEnumerable<IPolicyImportExtension> policyImportExtensions,
|
|
IEnumerable<IWsdlImportExtension> wsdlImportExtensions)
|
|
: this(metadata, policyImportExtensions, wsdlImportExtensions, MetadataImporterQuotas.Defaults)
|
|
{
|
|
}
|
|
|
|
public WsdlImporter(MetadataSet metadata, IEnumerable<IPolicyImportExtension> policyImportExtensions,
|
|
IEnumerable<IWsdlImportExtension> wsdlImportExtensions, MetadataImporterQuotas quotas)
|
|
: base(policyImportExtensions, quotas)
|
|
{
|
|
// process wsdl extensions first for consistency with policy extensions (which are processed in base ctor)
|
|
if (wsdlImportExtensions == null)
|
|
{
|
|
wsdlImportExtensions = LoadWsdlExtensionsFromConfig();
|
|
}
|
|
|
|
this.wsdlExtensions = new KeyedByTypeCollection<IWsdlImportExtension>(wsdlImportExtensions);
|
|
|
|
// then look at metadata
|
|
if (metadata == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("metadata");
|
|
|
|
this.ProcessMetadataDocuments(metadata.MetadataSections);
|
|
}
|
|
|
|
public KeyedByTypeCollection<IWsdlImportExtension> WsdlImportExtensions
|
|
{
|
|
get { return this.wsdlExtensions; }
|
|
}
|
|
|
|
public WsdlNS.ServiceDescriptionCollection WsdlDocuments
|
|
{
|
|
get { return this.wsdlDocuments; }
|
|
}
|
|
|
|
public XmlSchemaSet XmlSchemas
|
|
{
|
|
get { return this.xmlSchemas; }
|
|
}
|
|
|
|
WsdlPolicyReader PolicyReader
|
|
{
|
|
get
|
|
{
|
|
if (this.wsdlPolicyReader == null)
|
|
{
|
|
this.wsdlPolicyReader = new WsdlPolicyReader(this);
|
|
}
|
|
return wsdlPolicyReader;
|
|
}
|
|
}
|
|
|
|
//Consider this should be made public
|
|
internal override XmlElement ResolvePolicyReference(string policyReference, XmlElement contextAssertion)
|
|
{
|
|
return this.PolicyReader.ResolvePolicyReference(policyReference, contextAssertion);
|
|
}
|
|
|
|
public override Collection<ContractDescription> ImportAllContracts()
|
|
{
|
|
if (this.isFaulted)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
|
|
|
|
EnsureBeforeImportCalled();
|
|
Collection<ContractDescription> contracts = new Collection<ContractDescription>();
|
|
foreach (WsdlNS.ServiceDescription wsdl in this.wsdlDocuments)
|
|
foreach (WsdlNS.PortType wsdlPortType in wsdl.PortTypes)
|
|
{
|
|
if (IsBlackListed(wsdlPortType))
|
|
continue;
|
|
|
|
ContractDescription contract = ImportWsdlPortType(wsdlPortType, WsdlPortTypeImportOptions.ReuseExistingContracts, ErrorBehavior.DoNotThrowExceptions);
|
|
if (contract != null)
|
|
contracts.Add(contract);
|
|
}
|
|
return contracts;
|
|
}
|
|
|
|
public override ServiceEndpointCollection ImportAllEndpoints()
|
|
{
|
|
if (this.isFaulted)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
|
|
|
|
EnsureBeforeImportCalled();
|
|
ServiceEndpointCollection endpoints = new ServiceEndpointCollection();
|
|
foreach (WsdlNS.Port wsdlPort in this.GetAllPorts())
|
|
{
|
|
if (IsBlackListed(wsdlPort))
|
|
continue;
|
|
|
|
ServiceEndpoint endpoint = ImportWsdlPort(wsdlPort, ErrorBehavior.DoNotThrowExceptions);
|
|
if (endpoint != null)
|
|
endpoints.Add(endpoint);
|
|
}
|
|
return endpoints;
|
|
}
|
|
|
|
public Collection<Binding> ImportAllBindings()
|
|
{
|
|
if (this.isFaulted)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
|
|
|
|
EnsureBeforeImportCalled();
|
|
Collection<Binding> bindings = new Collection<Binding>();
|
|
foreach (WsdlNS.Binding wsdlBinding in this.GetAllBindings())
|
|
{
|
|
WsdlEndpointConversionContext importedBindingContext = null;
|
|
if (IsBlackListed(wsdlBinding))
|
|
continue;
|
|
|
|
importedBindingContext = ImportWsdlBinding(wsdlBinding, ErrorBehavior.DoNotThrowExceptions);
|
|
if (importedBindingContext != null)
|
|
bindings.Add(importedBindingContext.Endpoint.Binding);
|
|
}
|
|
return bindings;
|
|
}
|
|
|
|
// WSDL Specific methods
|
|
public ContractDescription ImportContract(WsdlNS.PortType wsdlPortType)
|
|
{
|
|
if (this.isFaulted)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
|
|
|
|
if (wsdlPortType == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlPortType");
|
|
|
|
return ImportWsdlPortType(wsdlPortType, WsdlPortTypeImportOptions.ReuseExistingContracts, ErrorBehavior.RethrowExceptions);
|
|
}
|
|
|
|
public Binding ImportBinding(WsdlNS.Binding wsdlBinding)
|
|
{
|
|
if (this.isFaulted)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
|
|
|
|
if (wsdlBinding == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlBinding");
|
|
|
|
return ImportWsdlBinding(wsdlBinding, ErrorBehavior.RethrowExceptions).Endpoint.Binding;
|
|
}
|
|
|
|
public ServiceEndpoint ImportEndpoint(WsdlNS.Port wsdlPort)
|
|
{
|
|
if (this.isFaulted)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
|
|
|
|
if (wsdlPort == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlPort");
|
|
|
|
return ImportWsdlPort(wsdlPort, ErrorBehavior.RethrowExceptions);
|
|
}
|
|
|
|
public ServiceEndpointCollection ImportEndpoints(WsdlNS.PortType wsdlPortType)
|
|
{
|
|
if (this.isFaulted)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
|
|
|
|
if (wsdlPortType == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlPortType");
|
|
|
|
if (IsBlackListed(wsdlPortType))
|
|
throw CreateAlreadyFaultedException(wsdlPortType);
|
|
else
|
|
ImportWsdlPortType(wsdlPortType, WsdlPortTypeImportOptions.ReuseExistingContracts, ErrorBehavior.RethrowExceptions);
|
|
|
|
ServiceEndpointCollection endpoints = new ServiceEndpointCollection();
|
|
|
|
foreach (WsdlNS.Binding wsdlBinding in FindBindingsForPortType(wsdlPortType))
|
|
if (!IsBlackListed(wsdlBinding))
|
|
foreach (ServiceEndpoint endpoint in ImportEndpoints(wsdlBinding))
|
|
endpoints.Add(endpoint);
|
|
|
|
return endpoints;
|
|
}
|
|
|
|
internal ServiceEndpointCollection ImportEndpoints(ContractDescription contract)
|
|
{
|
|
if (this.isFaulted)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
|
|
|
|
if (contract == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contract");
|
|
|
|
if (!this.KnownContracts.ContainsKey(WsdlExporter.WsdlNamingHelper.GetPortTypeQName(contract)))
|
|
{
|
|
Fx.Assert("WsdlImporter.ImportEndpoints(ContractDescription contract): !this.KnownContracts.ContainsKey(WsdlExporter.WsdlNamingHelper.GetPortTypeQName(contract))");
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.WsdlImporterContractMustBeInKnownContracts)));
|
|
}
|
|
|
|
EnsureBeforeImportCalled();
|
|
ServiceEndpointCollection endpoints = new ServiceEndpointCollection();
|
|
|
|
foreach (WsdlNS.Binding wsdlBinding in FindBindingsForContract(contract))
|
|
if (!IsBlackListed(wsdlBinding))
|
|
foreach (ServiceEndpoint endpoint in ImportEndpoints(wsdlBinding))
|
|
endpoints.Add(endpoint);
|
|
|
|
return endpoints;
|
|
}
|
|
|
|
public ServiceEndpointCollection ImportEndpoints(WsdlNS.Binding wsdlBinding)
|
|
{
|
|
if (this.isFaulted)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
|
|
|
|
if (wsdlBinding == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlBinding");
|
|
|
|
if (IsBlackListed(wsdlBinding))
|
|
throw CreateAlreadyFaultedException(wsdlBinding);
|
|
else
|
|
ImportWsdlBinding(wsdlBinding, ErrorBehavior.RethrowExceptions);
|
|
|
|
ServiceEndpointCollection endpoints = new ServiceEndpointCollection();
|
|
|
|
foreach (WsdlNS.Port wsdlPort in FindPortsForBinding(wsdlBinding))
|
|
if (!IsBlackListed(wsdlPort))
|
|
{
|
|
ServiceEndpoint endpoint = ImportWsdlPort(wsdlPort, ErrorBehavior.DoNotThrowExceptions);
|
|
if (endpoint != null)
|
|
endpoints.Add(endpoint);
|
|
}
|
|
|
|
return endpoints;
|
|
}
|
|
|
|
public ServiceEndpointCollection ImportEndpoints(WsdlNS.Service wsdlService)
|
|
{
|
|
if (this.isFaulted)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.WsdlImporterIsFaulted)));
|
|
|
|
if (wsdlService == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("wsdlService");
|
|
|
|
EnsureBeforeImportCalled();
|
|
ServiceEndpointCollection endpoints = new ServiceEndpointCollection();
|
|
|
|
foreach (WsdlNS.Port wsdlPort in wsdlService.Ports)
|
|
if (!IsBlackListed(wsdlPort))
|
|
{
|
|
ServiceEndpoint endpoint = ImportWsdlPort(wsdlPort, ErrorBehavior.DoNotThrowExceptions);
|
|
if (endpoint != null)
|
|
endpoints.Add(endpoint);
|
|
}
|
|
|
|
return endpoints;
|
|
}
|
|
|
|
bool IsBlackListed(WsdlNS.NamedItem item)
|
|
{
|
|
return importErrors.ContainsKey(item);
|
|
}
|
|
|
|
ContractDescription ImportWsdlPortType(WsdlNS.PortType wsdlPortType, WsdlPortTypeImportOptions importOptions, ErrorBehavior errorBehavior)
|
|
{
|
|
if (IsBlackListed(wsdlPortType))
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateAlreadyFaultedException(wsdlPortType));
|
|
|
|
|
|
XmlQualifiedName wsdlPortTypeQName = new XmlQualifiedName(wsdlPortType.Name, wsdlPortType.ServiceDescription.TargetNamespace);
|
|
ContractDescription contractDescription = null;
|
|
|
|
if (importOptions == WsdlPortTypeImportOptions.IgnoreExistingContracts || !TryFindExistingContract(wsdlPortTypeQName, out contractDescription))
|
|
{
|
|
EnsureBeforeImportCalled();
|
|
|
|
try
|
|
{
|
|
|
|
contractDescription = CreateContractDescription(wsdlPortType, wsdlPortTypeQName);
|
|
WsdlContractConversionContext contractContext = new WsdlContractConversionContext(contractDescription, wsdlPortType);
|
|
|
|
foreach (WsdlNS.Operation wsdlOperation in wsdlPortType.Operations)
|
|
{
|
|
|
|
OperationDescription operationDescription = CreateOperationDescription(wsdlPortType, wsdlOperation, contractDescription);
|
|
contractContext.AddOperation(operationDescription, wsdlOperation);
|
|
|
|
foreach (WsdlNS.OperationMessage wsdlOperationMessage in wsdlOperation.Messages)
|
|
{
|
|
MessageDescription messageDescription;
|
|
if (TryCreateMessageDescription(wsdlOperationMessage, operationDescription, out messageDescription))
|
|
contractContext.AddMessage(messageDescription, wsdlOperationMessage);
|
|
}
|
|
|
|
foreach (WsdlNS.OperationFault wsdlOperationFault in wsdlOperation.Faults)
|
|
{
|
|
FaultDescription faultDescription;
|
|
if (TryCreateFaultDescription(wsdlOperationFault, operationDescription, out faultDescription))
|
|
contractContext.AddFault(faultDescription, wsdlOperationFault);
|
|
}
|
|
}
|
|
|
|
CallImportContract(contractContext);
|
|
VerifyImportedWsdlPortType(wsdlPortType);
|
|
|
|
importedPortTypes.Add(wsdlPortTypeQName, contractContext);
|
|
}
|
|
#pragma warning suppress 56500 // covered by FxCOP
|
|
catch (Exception e)
|
|
{
|
|
if (Fx.IsFatal(e))
|
|
throw;
|
|
WsdlImportException wie = WsdlImportException.Create(wsdlPortType, e);
|
|
LogImportError(wsdlPortType, wie);
|
|
if (errorBehavior == ErrorBehavior.RethrowExceptions)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(wie);
|
|
else
|
|
return null;
|
|
}
|
|
}
|
|
|
|
return contractDescription;
|
|
}
|
|
|
|
WsdlEndpointConversionContext ImportWsdlBinding(WsdlNS.Binding wsdlBinding, ErrorBehavior errorBehavior)
|
|
{
|
|
//Check for exisiting exception
|
|
if (IsBlackListed(wsdlBinding))
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateAlreadyFaultedException(wsdlBinding));
|
|
|
|
XmlQualifiedName wsdlBindingQName = new XmlQualifiedName(wsdlBinding.Name, wsdlBinding.ServiceDescription.TargetNamespace);
|
|
WsdlEndpointConversionContext bindingEndpointContext = null;
|
|
|
|
|
|
|
|
|
|
if (!importedBindings.TryGetValue(wsdlBindingQName, out bindingEndpointContext))
|
|
{
|
|
EnsureBeforeImportCalled();
|
|
|
|
try
|
|
{
|
|
bool wasExistingContract;
|
|
ContractDescription contractDescription = GetOrImportContractDescription(wsdlBinding.Type, out wasExistingContract);
|
|
WsdlContractConversionContext contractContext = null;
|
|
importedPortTypes.TryGetValue(wsdlBinding.Type, out contractContext);
|
|
|
|
ServiceEndpoint newWsdlBindingEndpoint = new ServiceEndpoint(contractDescription);
|
|
bindingEndpointContext = new WsdlEndpointConversionContext(contractContext, newWsdlBindingEndpoint, wsdlBinding, null);
|
|
|
|
foreach (WsdlNS.OperationBinding wsdlOperationBinding in wsdlBinding.Operations)
|
|
try
|
|
{
|
|
OperationDescription operation = Binding2DescriptionHelper.FindOperationDescription(wsdlOperationBinding, wsdlDocuments, bindingEndpointContext);
|
|
bindingEndpointContext.AddOperationBinding(operation, wsdlOperationBinding);
|
|
|
|
for (int i = 0; i < operation.Messages.Count; i++)
|
|
{
|
|
MessageDescription message = operation.Messages[i];
|
|
WsdlNS.MessageBinding wsdlMessageBinding = Binding2DescriptionHelper.FindMessageBinding(wsdlOperationBinding, message);
|
|
|
|
bindingEndpointContext.AddMessageBinding(message, wsdlMessageBinding);
|
|
}
|
|
|
|
foreach (FaultDescription fault in operation.Faults)
|
|
{
|
|
WsdlNS.FaultBinding wsdlFaultBinding = Binding2DescriptionHelper.FindFaultBinding(wsdlOperationBinding, fault);
|
|
if (wsdlFaultBinding != null)
|
|
{
|
|
bindingEndpointContext.AddFaultBinding(fault, wsdlFaultBinding);
|
|
}
|
|
}
|
|
}
|
|
#pragma warning suppress 56500 // covered by FxCOP
|
|
catch (Exception e)
|
|
{
|
|
if (Fx.IsFatal(e))
|
|
throw;
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(wsdlOperationBinding, e));
|
|
}
|
|
|
|
XmlQualifiedName bindingQName = WsdlNamingHelper.GetBindingName(wsdlBinding);
|
|
newWsdlBindingEndpoint.Binding = CreateBinding(bindingEndpointContext, bindingQName);
|
|
|
|
CallImportEndpoint(bindingEndpointContext);
|
|
VerifyImportedWsdlBinding(wsdlBinding);
|
|
importedBindings.Add(wsdlBindingQName, bindingEndpointContext);
|
|
}
|
|
#pragma warning suppress 56500 // covered by FxCOP
|
|
catch (Exception e)
|
|
{
|
|
if (Fx.IsFatal(e))
|
|
throw;
|
|
WsdlImportException wie = WsdlImportException.Create(wsdlBinding, e);
|
|
LogImportError(wsdlBinding, wie);
|
|
if (errorBehavior == ErrorBehavior.RethrowExceptions)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(wie);
|
|
else
|
|
return null;
|
|
}
|
|
}
|
|
return bindingEndpointContext;
|
|
}
|
|
|
|
ServiceEndpoint ImportWsdlPort(WsdlNS.Port wsdlPort, ErrorBehavior errorBehavior)
|
|
{
|
|
if (IsBlackListed(wsdlPort))
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateAlreadyFaultedException(wsdlPort));
|
|
|
|
|
|
ServiceEndpoint endpoint = null;
|
|
if (!importedPorts.TryGetValue(wsdlPort, out endpoint))
|
|
{
|
|
EnsureBeforeImportCalled();
|
|
|
|
try
|
|
{
|
|
WsdlNS.Binding wsdlBinding = this.wsdlDocuments.GetBinding(wsdlPort.Binding);
|
|
|
|
WsdlEndpointConversionContext bindingEndpointContext = ImportWsdlBinding(wsdlBinding, ErrorBehavior.RethrowExceptions);
|
|
|
|
WsdlEndpointConversionContext endpointContext;
|
|
endpoint = new ServiceEndpoint(bindingEndpointContext.Endpoint.Contract);
|
|
endpoint.Name = WsdlNamingHelper.GetEndpointName(wsdlPort).EncodedName;
|
|
|
|
endpointContext = new WsdlEndpointConversionContext(bindingEndpointContext, endpoint, wsdlPort);
|
|
|
|
if (WsdlPolicyReader.HasPolicy(wsdlPort))
|
|
{
|
|
XmlQualifiedName bindingQName = WsdlNamingHelper.GetBindingName(wsdlPort);
|
|
endpoint.Binding = CreateBinding(endpointContext, bindingQName);
|
|
}
|
|
else
|
|
{
|
|
endpoint.Binding = bindingEndpointContext.Endpoint.Binding;
|
|
}
|
|
|
|
CallImportEndpoint(endpointContext);
|
|
VerifyImportedWsdlPort(wsdlPort);
|
|
importedPorts.Add(wsdlPort, endpoint);
|
|
|
|
}
|
|
#pragma warning suppress 56500 // covered by FxCOP
|
|
catch (Exception e)
|
|
{
|
|
if (Fx.IsFatal(e))
|
|
throw;
|
|
WsdlImportException wie = WsdlImportException.Create(wsdlPort, e);
|
|
LogImportError(wsdlPort, wie);
|
|
if (errorBehavior == ErrorBehavior.RethrowExceptions)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(wie);
|
|
else
|
|
return null;
|
|
}
|
|
}
|
|
|
|
return endpoint;
|
|
}
|
|
|
|
static bool TryCreateMessageDescription(WsdlNS.OperationMessage wsdlOperationMessage, OperationDescription operationDescription, out MessageDescription messageDescription)
|
|
{
|
|
string actionUri = WSAddressingHelper.GetWsaActionUri(wsdlOperationMessage);
|
|
MessageDirection direction;
|
|
|
|
if (wsdlOperationMessage is WsdlNS.OperationInput)
|
|
direction = MessageDirection.Input;
|
|
else if (wsdlOperationMessage is WsdlNS.OperationOutput)
|
|
direction = MessageDirection.Output;
|
|
else
|
|
{
|
|
messageDescription = null;
|
|
return false;
|
|
}
|
|
|
|
messageDescription = new MessageDescription(actionUri, direction);
|
|
messageDescription.MessageName = WsdlNamingHelper.GetOperationMessageName(wsdlOperationMessage);
|
|
messageDescription.XsdTypeName = wsdlOperationMessage.Message;
|
|
operationDescription.Messages.Add(messageDescription);
|
|
return true;
|
|
}
|
|
|
|
static bool TryCreateFaultDescription(WsdlNS.OperationFault wsdlOperationFault, OperationDescription operationDescription, out FaultDescription faultDescription)
|
|
{
|
|
|
|
if (string.IsNullOrEmpty(wsdlOperationFault.Name))
|
|
{
|
|
faultDescription = null;
|
|
return false;
|
|
}
|
|
|
|
string actionUri = WSAddressingHelper.GetWsaActionUri(wsdlOperationFault);
|
|
faultDescription = new FaultDescription(actionUri);
|
|
faultDescription.SetNameOnly(new XmlName(wsdlOperationFault.Name, true /*isEncoded*/));
|
|
operationDescription.Faults.Add(faultDescription);
|
|
return true;
|
|
}
|
|
|
|
ContractDescription CreateContractDescription(WsdlNS.PortType wsdlPortType, XmlQualifiedName wsdlPortTypeQName)
|
|
{
|
|
ContractDescription contractDescription;
|
|
XmlQualifiedName contractQName = WsdlNamingHelper.GetContractName(wsdlPortTypeQName);
|
|
contractDescription = new ContractDescription(contractQName.Name, contractQName.Namespace);
|
|
NetSessionHelper.SetSession(contractDescription, wsdlPortType);
|
|
return contractDescription;
|
|
}
|
|
|
|
OperationDescription CreateOperationDescription(WsdlNS.PortType wsdlPortType, WsdlNS.Operation wsdlOperation, ContractDescription contract)
|
|
{
|
|
string operationName = WsdlNamingHelper.GetOperationName(wsdlOperation);
|
|
OperationDescription operationDescription = new OperationDescription(operationName, contract);
|
|
NetSessionHelper.SetInitiatingTerminating(operationDescription, wsdlOperation);
|
|
contract.Operations.Add(operationDescription);
|
|
return operationDescription;
|
|
}
|
|
|
|
Binding CreateBinding(WsdlEndpointConversionContext endpointContext, XmlQualifiedName bindingQName)
|
|
{
|
|
try
|
|
{
|
|
// either the wsdl:binding has already been imported or the wsdl:port has policy
|
|
BindingElementCollection bindingElements = ImportPolicyFromWsdl(endpointContext);
|
|
CustomBinding binding = new CustomBinding(bindingElements);
|
|
// use decoded form to preserve the user-given friendly name
|
|
binding.Name = NamingHelper.CodeName(bindingQName.Name);
|
|
binding.Namespace = bindingQName.Namespace;
|
|
|
|
return binding;
|
|
|
|
}
|
|
#pragma warning suppress 56500 // covered by FxCOP
|
|
catch (Exception e)
|
|
{
|
|
if (Fx.IsFatal(e))
|
|
throw;
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(endpointContext.WsdlBinding, e));
|
|
}
|
|
}
|
|
|
|
ContractDescription GetOrImportContractDescription(XmlQualifiedName wsdlPortTypeQName, out bool wasExistingContractDescription)
|
|
{
|
|
ContractDescription contractDescription;
|
|
|
|
if (!TryFindExistingContract(wsdlPortTypeQName, out contractDescription))
|
|
{
|
|
WsdlNS.PortType wsdlPortType = wsdlDocuments.GetPortType(wsdlPortTypeQName);
|
|
|
|
contractDescription = ImportWsdlPortType(wsdlPortType, WsdlPortTypeImportOptions.IgnoreExistingContracts, ErrorBehavior.RethrowExceptions);
|
|
|
|
wasExistingContractDescription = false;
|
|
}
|
|
|
|
wasExistingContractDescription = true;
|
|
return contractDescription;
|
|
}
|
|
|
|
void ProcessMetadataDocuments(IEnumerable<MetadataSection> metadataSections)
|
|
{
|
|
|
|
foreach (MetadataSection doc in metadataSections)
|
|
{
|
|
try
|
|
{
|
|
if (doc.Metadata is MetadataReference || doc.Metadata is MetadataLocation)
|
|
continue;
|
|
|
|
if (doc.Dialect == MetadataSection.ServiceDescriptionDialect)
|
|
{
|
|
wsdlDocuments.Add(TryConvert<WsdlNS.ServiceDescription>(doc));
|
|
}
|
|
if (doc.Dialect == MetadataSection.XmlSchemaDialect)
|
|
{
|
|
xmlSchemas.Add(TryConvert<XmlSchema>(doc));
|
|
}
|
|
if (doc.Dialect == MetadataSection.PolicyDialect)
|
|
{
|
|
if (string.IsNullOrEmpty(doc.Identifier))
|
|
{
|
|
LogImportWarning(SR.GetString(SR.PolicyDocumentMustHaveIdentifier));
|
|
}
|
|
else
|
|
{
|
|
policyDocuments.Add(doc.Identifier, TryConvert<XmlElement>(doc));
|
|
}
|
|
}
|
|
}
|
|
#pragma warning suppress 56500 // covered by FxCOP
|
|
catch (Exception e)
|
|
{
|
|
if (Fx.IsFatal(e))
|
|
throw;
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(doc.Identifier, e));
|
|
}
|
|
}
|
|
}
|
|
|
|
T TryConvert<T>(MetadataSection doc)
|
|
{
|
|
try
|
|
{
|
|
return ((T)doc.Metadata);
|
|
}
|
|
catch (InvalidCastException)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(
|
|
SR.GetString(SR.SFxBadMetadataDialect, doc.Identifier, doc.Dialect, typeof(T).FullName, doc.GetType().FullName)));
|
|
}
|
|
}
|
|
|
|
bool TryFindExistingContract(XmlQualifiedName wsdlPortTypeQName, out ContractDescription existingContract)
|
|
{
|
|
XmlQualifiedName contractQName = WsdlNamingHelper.GetContractName(wsdlPortTypeQName);
|
|
|
|
// Scan Known Contracts first because wsdl:portType may not be available
|
|
if (this.KnownContracts.TryGetValue(contractQName, out existingContract))
|
|
return true;
|
|
|
|
WsdlContractConversionContext contractContext;
|
|
if (importedPortTypes.TryGetValue(wsdlPortTypeQName, out contractContext))
|
|
{
|
|
existingContract = contractContext.Contract;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void EnsureBeforeImportCalled()
|
|
{
|
|
if (!beforeImportCalled)
|
|
{
|
|
foreach (IWsdlImportExtension extension in this.wsdlExtensions)
|
|
{
|
|
try
|
|
{
|
|
extension.BeforeImport(this.wsdlDocuments, this.xmlSchemas, this.policyDocuments.Values);
|
|
}
|
|
#pragma warning suppress 56500 // covered by FxCOP
|
|
catch (Exception e)
|
|
{
|
|
this.isFaulted = true;
|
|
if (Fx.IsFatal(e))
|
|
throw;
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateBeforeImportExtensionException(extension, e));
|
|
}
|
|
}
|
|
beforeImportCalled = true;
|
|
}
|
|
}
|
|
|
|
void CallImportContract(WsdlContractConversionContext contractConversionContext)
|
|
{
|
|
foreach (IWsdlImportExtension extension in this.wsdlExtensions)
|
|
try
|
|
{
|
|
extension.ImportContract(this, contractConversionContext);
|
|
}
|
|
#pragma warning suppress 56500 // covered by FxCOP
|
|
catch (Exception e)
|
|
{
|
|
if (Fx.IsFatal(e))
|
|
throw;
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateExtensionException(extension, e));
|
|
}
|
|
}
|
|
|
|
void CallImportEndpoint(WsdlEndpointConversionContext endpointConversionContext)
|
|
{
|
|
foreach (IWsdlImportExtension extension in this.wsdlExtensions)
|
|
try
|
|
{
|
|
extension.ImportEndpoint(this, endpointConversionContext);
|
|
|
|
}
|
|
#pragma warning suppress 56500 // covered by FxCOP
|
|
catch (Exception e)
|
|
{
|
|
if (Fx.IsFatal(e))
|
|
throw;
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateExtensionException(extension, e));
|
|
}
|
|
}
|
|
|
|
void VerifyImportedWsdlPortType(WsdlNS.PortType wsdlPortType)
|
|
{
|
|
VerifyImportedExtensions(wsdlPortType);
|
|
foreach (WsdlNS.Operation wsdlOperation in wsdlPortType.Operations)
|
|
{
|
|
VerifyImportedExtensions(wsdlOperation);
|
|
|
|
foreach (WsdlNS.OperationMessage wsdlOperationMessage in wsdlOperation.Messages)
|
|
{
|
|
VerifyImportedExtensions(wsdlOperationMessage);
|
|
}
|
|
|
|
foreach (WsdlNS.OperationMessage wsdlOperationMessage in wsdlOperation.Faults)
|
|
{
|
|
VerifyImportedExtensions(wsdlOperationMessage);
|
|
}
|
|
}
|
|
}
|
|
|
|
void VerifyImportedWsdlBinding(WsdlNS.Binding wsdlBinding)
|
|
{
|
|
VerifyImportedExtensions(wsdlBinding);
|
|
foreach (WsdlNS.OperationBinding wsdlOperationBinding in wsdlBinding.Operations)
|
|
{
|
|
VerifyImportedExtensions(wsdlOperationBinding);
|
|
|
|
if (wsdlOperationBinding.Input != null)
|
|
{
|
|
VerifyImportedExtensions(wsdlOperationBinding.Input);
|
|
}
|
|
|
|
if (wsdlOperationBinding.Output != null)
|
|
{
|
|
VerifyImportedExtensions(wsdlOperationBinding.Output);
|
|
}
|
|
|
|
foreach (WsdlNS.MessageBinding wsdlMessageBinding in wsdlOperationBinding.Faults)
|
|
{
|
|
VerifyImportedExtensions(wsdlMessageBinding);
|
|
}
|
|
}
|
|
}
|
|
|
|
void VerifyImportedWsdlPort(WsdlNS.Port wsdlPort)
|
|
{
|
|
VerifyImportedExtensions(wsdlPort);
|
|
}
|
|
|
|
void VerifyImportedExtensions(WsdlNS.NamedItem item)
|
|
{
|
|
foreach (object ext in item.Extensions)
|
|
{
|
|
if (item.Extensions.IsHandled(ext))
|
|
continue;
|
|
|
|
XmlQualifiedName qName = GetUnhandledExtensionQName(ext, item);
|
|
|
|
if (item.Extensions.IsRequired(ext) || IsNonSoapWsdl11BindingExtension(ext))
|
|
{
|
|
string errorMsg = SR.GetString(SR.RequiredWSDLExtensionIgnored, qName.Name, qName.Namespace);
|
|
WsdlImportException wie = WsdlImportException.Create(item, new InvalidOperationException(errorMsg));
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(wie);
|
|
}
|
|
else
|
|
{
|
|
string xPath = CreateXPathString(item);
|
|
string errorMsg = SR.GetString(SR.OptionalWSDLExtensionIgnored, qName.Name, qName.Namespace, xPath);
|
|
this.Errors.Add(new MetadataConversionError(errorMsg, true));
|
|
}
|
|
}
|
|
}
|
|
|
|
static bool IsNonSoapWsdl11BindingExtension(object ext)
|
|
{
|
|
if (ext is WsdlNS.HttpAddressBinding
|
|
|| ext is WsdlNS.HttpBinding
|
|
|| ext is WsdlNS.HttpOperationBinding
|
|
|| ext is WsdlNS.HttpUrlEncodedBinding
|
|
|| ext is WsdlNS.HttpUrlReplacementBinding
|
|
|| ext is WsdlNS.MimeContentBinding
|
|
|| ext is WsdlNS.MimeMultipartRelatedBinding
|
|
|| ext is WsdlNS.MimePart
|
|
|| ext is WsdlNS.MimeTextBinding
|
|
|| ext is WsdlNS.MimeXmlBinding
|
|
)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
XmlQualifiedName GetUnhandledExtensionQName(object extension, WsdlNS.NamedItem item)
|
|
{
|
|
XmlElement element = extension as XmlElement;
|
|
if (element != null)
|
|
{
|
|
return new XmlQualifiedName(element.LocalName, element.NamespaceURI);
|
|
}
|
|
else if (extension is WsdlNS.ServiceDescriptionFormatExtension)
|
|
{
|
|
WsdlConfigNS.XmlFormatExtensionAttribute[] xfeAttributes
|
|
= (WsdlConfigNS.XmlFormatExtensionAttribute[])ServiceReflector.GetCustomAttributes(extension.GetType(),
|
|
typeof(WsdlConfigNS.XmlFormatExtensionAttribute), false);
|
|
|
|
if (xfeAttributes.Length > 0)
|
|
{
|
|
return new XmlQualifiedName(xfeAttributes[0].ElementName, xfeAttributes[0].Namespace);
|
|
}
|
|
}
|
|
WsdlImportException wie = WsdlImportException.Create(item, new InvalidOperationException(SR.GetString(SR.UnknownWSDLExtensionIgnored, extension.GetType().AssemblyQualifiedName)));
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(wie);
|
|
}
|
|
|
|
internal static class Binding2DescriptionHelper
|
|
{
|
|
internal static OperationDescription FindOperationDescription(WsdlNS.OperationBinding wsdlOperationBinding, WsdlNS.ServiceDescriptionCollection wsdlDocuments, WsdlEndpointConversionContext endpointContext)
|
|
{
|
|
|
|
OperationDescription operation;
|
|
if (endpointContext.ContractConversionContext != null)
|
|
{
|
|
WsdlNS.Operation wsdlOperation = FindWsdlOperation(wsdlOperationBinding, wsdlDocuments);
|
|
operation = endpointContext.ContractConversionContext.GetOperationDescription(wsdlOperation);
|
|
}
|
|
else
|
|
{
|
|
operation = FindOperationDescription(endpointContext.Endpoint.Contract, wsdlOperationBinding);
|
|
}
|
|
return operation;
|
|
}
|
|
|
|
internal static WsdlNS.MessageBinding FindMessageBinding(WsdlNS.OperationBinding wsdlOperationBinding, MessageDescription message)
|
|
{
|
|
WsdlNS.MessageBinding wsdlMessageBinding;
|
|
if (message.Direction == MessageDirection.Input)
|
|
{
|
|
wsdlMessageBinding = wsdlOperationBinding.Input;
|
|
}
|
|
else
|
|
{
|
|
wsdlMessageBinding = wsdlOperationBinding.Output;
|
|
}
|
|
return wsdlMessageBinding;
|
|
}
|
|
|
|
internal static WsdlNS.FaultBinding FindFaultBinding(WsdlNS.OperationBinding wsdlOperationBinding, FaultDescription fault)
|
|
{
|
|
foreach (WsdlNS.FaultBinding faultBinding in wsdlOperationBinding.Faults)
|
|
if (faultBinding.Name == fault.Name)
|
|
return faultBinding;
|
|
return null;
|
|
}
|
|
|
|
static WsdlNS.Operation FindWsdlOperation(WsdlNS.OperationBinding wsdlOperationBinding, WsdlNS.ServiceDescriptionCollection wsdlDocuments)
|
|
{
|
|
WsdlNS.PortType wsdlPortType = wsdlDocuments.GetPortType(wsdlOperationBinding.Binding.Type);
|
|
|
|
string wsdlOperationBindingName = wsdlOperationBinding.Name;
|
|
|
|
if (wsdlOperationBindingName == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInvalidWsdlBindingOpNoName, wsdlOperationBinding.Binding.Name)));
|
|
}
|
|
|
|
WsdlNS.Operation partialMatchResult = null;
|
|
|
|
foreach (WsdlNS.Operation wsdlOperation in wsdlPortType.Operations)
|
|
{
|
|
switch (Match(wsdlOperationBinding, wsdlOperation))
|
|
{
|
|
case MatchResult.None:
|
|
break;
|
|
case MatchResult.Partial:
|
|
partialMatchResult = wsdlOperation;
|
|
break;
|
|
case MatchResult.Exact:
|
|
return wsdlOperation;
|
|
default:
|
|
Fx.AssertAndFailFast("Unexpected MatchResult value.");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (partialMatchResult != null)
|
|
{
|
|
return partialMatchResult;
|
|
}
|
|
else
|
|
{
|
|
//unable to find wsdloperation for wsdlOperationBinding, invalid wsdl binding
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInvalidWsdlBindingOpMismatch2, wsdlOperationBinding.Binding.Name, wsdlOperationBinding.Name)));
|
|
}
|
|
}
|
|
|
|
internal enum MatchResult
|
|
{
|
|
None,
|
|
Partial,
|
|
Exact
|
|
}
|
|
|
|
internal static MatchResult Match(WsdlNS.OperationBinding wsdlOperationBinding, WsdlNS.Operation wsdlOperation)
|
|
{
|
|
// This method checks if there is a match based on Names, between the specified OperationBinding and Operation.
|
|
// When searching for the Operation associated with an OperationBinding, we need to return an exact match if possible,
|
|
// or a partial match otherwise (when some of the Names are null).
|
|
// Bug 16833 @ CSDMain requires that partial matches are allowed, while the TFS bug 477838 requires that exact matches are done (when possible).
|
|
if (wsdlOperationBinding.Name != wsdlOperation.Name)
|
|
{
|
|
return MatchResult.None;
|
|
}
|
|
|
|
MatchResult result = MatchResult.Exact;
|
|
|
|
foreach (WsdlNS.OperationMessage wsdlOperationMessage in wsdlOperation.Messages)
|
|
{
|
|
WsdlNS.MessageBinding wsdlMessageBinding;
|
|
if (wsdlOperationMessage is WsdlNS.OperationInput)
|
|
wsdlMessageBinding = wsdlOperationBinding.Input;
|
|
else
|
|
wsdlMessageBinding = wsdlOperationBinding.Output;
|
|
|
|
if (wsdlMessageBinding == null)
|
|
{
|
|
return MatchResult.None;
|
|
}
|
|
|
|
switch (MatchOperationParameterName(wsdlMessageBinding, wsdlOperationMessage))
|
|
{
|
|
case MatchResult.None:
|
|
return MatchResult.None;
|
|
case MatchResult.Partial:
|
|
result = MatchResult.Partial;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static MatchResult MatchOperationParameterName(WsdlNS.MessageBinding wsdlMessageBinding, WsdlNS.OperationMessage wsdlOperationMessage)
|
|
{
|
|
string wsdlOperationMessageName = wsdlOperationMessage.Name;
|
|
string wsdlMessageBindingName = wsdlMessageBinding.Name;
|
|
|
|
if (wsdlOperationMessageName == wsdlMessageBindingName)
|
|
{
|
|
return MatchResult.Exact;
|
|
}
|
|
|
|
string wsdlOperationMessageDecodedName = WsdlNamingHelper.GetOperationMessageName(wsdlOperationMessage).DecodedName;
|
|
if ((wsdlOperationMessageName == null) && (wsdlMessageBindingName == wsdlOperationMessageDecodedName))
|
|
{
|
|
return MatchResult.Partial;
|
|
}
|
|
else if ((wsdlMessageBindingName == null) && (wsdlOperationMessageName == wsdlOperationMessageDecodedName))
|
|
{
|
|
return MatchResult.Partial;
|
|
}
|
|
else
|
|
{
|
|
return MatchResult.None;
|
|
}
|
|
}
|
|
|
|
static OperationDescription FindOperationDescription(ContractDescription contract, WsdlNS.OperationBinding wsdlOperationBinding)
|
|
{
|
|
foreach (OperationDescription operationDescription in contract.Operations)
|
|
{
|
|
if (CompareOperations(operationDescription, contract, wsdlOperationBinding))
|
|
return operationDescription;
|
|
}
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnableToLocateOperation2, wsdlOperationBinding.Name, contract.Name)));
|
|
}
|
|
|
|
static bool CompareOperations(OperationDescription operationDescription, ContractDescription parentContractDescription, WsdlNS.OperationBinding wsdlOperationBinding)
|
|
{
|
|
string wsdlOperationName = WsdlExporter.WsdlNamingHelper.GetWsdlOperationName(operationDescription, parentContractDescription);
|
|
|
|
if (wsdlOperationName != wsdlOperationBinding.Name)
|
|
return false;
|
|
|
|
if (operationDescription.Messages.Count > 2)
|
|
return false;
|
|
|
|
// Either both have output message or neither have an output message;
|
|
if (FindMessage(operationDescription.Messages, MessageDirection.Output) != (wsdlOperationBinding.Output != null))
|
|
return false;
|
|
|
|
// Either both have output message or neither have an output message;
|
|
if (FindMessage(operationDescription.Messages, MessageDirection.Input) != (wsdlOperationBinding.Input != null))
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
private static bool FindMessage(MessageDescriptionCollection messageDescriptionCollection, MessageDirection transferDirection)
|
|
{
|
|
foreach (MessageDescription message in messageDescriptionCollection)
|
|
if (message.Direction == transferDirection)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
internal static class WSAddressingHelper
|
|
{
|
|
internal static string GetWsaActionUri(WsdlNS.OperationMessage wsdlOperationMessage)
|
|
{
|
|
string actionUri = FindWsaActionAttribute(wsdlOperationMessage);
|
|
return (actionUri == null) ? CreateDefaultWsaActionUri(wsdlOperationMessage) : actionUri;
|
|
}
|
|
|
|
internal static string FindWsaActionAttribute(WsdlNS.OperationMessage wsdlOperationMessage)
|
|
{
|
|
XmlAttribute[] attributes = wsdlOperationMessage.ExtensibleAttributes;
|
|
if (attributes != null && attributes.Length > 0)
|
|
{
|
|
foreach (XmlAttribute attribute in attributes)
|
|
{
|
|
if ((attribute.NamespaceURI == MetadataStrings.AddressingWsdl.NamespaceUri
|
|
|| attribute.NamespaceURI == MetadataStrings.AddressingMetadata.NamespaceUri)
|
|
&& attribute.LocalName == MetadataStrings.AddressingMetadata.Action)
|
|
{
|
|
return attribute.Value;
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
static string CreateDefaultWsaActionUri(WsdlNS.OperationMessage wsdlOperationMessage)
|
|
{
|
|
if (wsdlOperationMessage is WsdlNS.OperationFault)
|
|
return AddressingVersion.WSAddressing10.DefaultFaultAction;
|
|
|
|
// We figure out default action. All specifications' rules below are the same.
|
|
// Using [WSDL Binding W3C Working Draft 13 April 2005] Section 3.3
|
|
// Using [WSDL Binding W3C Candidate Recommendation 29 May 2006] Section 4.4.4
|
|
// Using [Metadata W3C Working Draft 13 16 May 2007] Section 4.4.4
|
|
|
|
string ns = wsdlOperationMessage.Operation.PortType.ServiceDescription.TargetNamespace ?? string.Empty;
|
|
string portTypeName = wsdlOperationMessage.Operation.PortType.Name;
|
|
XmlName operationMessageName = WsdlNamingHelper.GetOperationMessageName(wsdlOperationMessage);
|
|
|
|
string delimiter = ns.StartsWith("urn:", StringComparison.OrdinalIgnoreCase) ? ":" : "/";
|
|
|
|
string baseActionUri = ns.EndsWith(delimiter, StringComparison.OrdinalIgnoreCase) ? ns : ns + delimiter;
|
|
|
|
string actionUri = string.Format(CultureInfo.InvariantCulture, "{0}{1}{2}{3}", baseActionUri, portTypeName, delimiter, operationMessageName.EncodedName);
|
|
|
|
return actionUri;
|
|
}
|
|
|
|
internal static EndpointAddress ImportAddress(WsdlNS.Port wsdlPort)
|
|
{
|
|
//Try to read Endpoint Address from WsdlPort
|
|
if (wsdlPort != null)
|
|
{
|
|
XmlElement addressing10Element = wsdlPort.Extensions.Find(AddressingStrings.EndpointReference, Addressing10Strings.Namespace);
|
|
XmlElement addressing200408Element = wsdlPort.Extensions.Find(AddressingStrings.EndpointReference, Addressing200408Strings.Namespace);
|
|
WsdlNS.SoapAddressBinding soapAddressBinding = (WsdlNS.SoapAddressBinding)wsdlPort.Extensions.Find(typeof(WsdlNS.SoapAddressBinding));
|
|
|
|
//
|
|
if (addressing10Element != null)
|
|
{
|
|
return EndpointAddress.ReadFrom(AddressingVersion.WSAddressing10, new XmlNodeReader(addressing10Element));
|
|
}
|
|
if (addressing200408Element != null)
|
|
{
|
|
return EndpointAddress.ReadFrom(AddressingVersion.WSAddressingAugust2004, new XmlNodeReader(addressing200408Element));
|
|
}
|
|
else if (soapAddressBinding != null)
|
|
{
|
|
return new EndpointAddress(soapAddressBinding.Location);
|
|
}
|
|
|
|
}
|
|
return null;
|
|
}
|
|
|
|
internal static AddressingVersion FindAddressingVersion(PolicyConversionContext policyContext)
|
|
{
|
|
if (PolicyConversionContext.FindAssertion(policyContext.GetBindingAssertions(),
|
|
MetadataStrings.Addressing10.WsdlBindingPolicy.UsingAddressing,
|
|
MetadataStrings.Addressing10.WsdlBindingPolicy.NamespaceUri, true /*remove*/) != null)
|
|
{
|
|
return AddressingVersion.WSAddressing10;
|
|
}
|
|
else if (PolicyConversionContext.FindAssertion(policyContext.GetBindingAssertions(),
|
|
MetadataStrings.Addressing10.MetadataPolicy.Addressing,
|
|
MetadataStrings.Addressing10.MetadataPolicy.NamespaceUri, true /*remove*/) != null)
|
|
{
|
|
return AddressingVersion.WSAddressing10;
|
|
}
|
|
else if (PolicyConversionContext.FindAssertion(policyContext.GetBindingAssertions(),
|
|
MetadataStrings.Addressing200408.Policy.UsingAddressing,
|
|
MetadataStrings.Addressing200408.Policy.NamespaceUri, true /*remove*/) != null)
|
|
{
|
|
return AddressingVersion.WSAddressingAugust2004;
|
|
}
|
|
else
|
|
{
|
|
return AddressingVersion.None;
|
|
}
|
|
}
|
|
|
|
internal static SupportedAddressingMode DetermineSupportedAddressingMode(MetadataImporter importer, PolicyConversionContext context)
|
|
{
|
|
// Do not remove this assertion - the message encoding binding element importer owns it.
|
|
XmlElement addressingAssertion = PolicyConversionContext.FindAssertion(context.GetBindingAssertions(),
|
|
MetadataStrings.Addressing10.MetadataPolicy.Addressing, MetadataStrings.Addressing10.MetadataPolicy.NamespaceUri, false);
|
|
|
|
if (addressingAssertion != null)
|
|
{
|
|
XmlElement policyElement = null;
|
|
foreach (XmlNode node in addressingAssertion.ChildNodes)
|
|
{
|
|
if (node is XmlElement && MetadataSection.IsPolicyElement((XmlElement)node))
|
|
{
|
|
policyElement = (XmlElement)node;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (policyElement == null)
|
|
{
|
|
string message = SR.GetString(SR.ElementRequired, MetadataStrings.Addressing10.MetadataPolicy.Prefix,
|
|
MetadataStrings.Addressing10.MetadataPolicy.Addressing, MetadataStrings.WSPolicy.Prefix,
|
|
MetadataStrings.WSPolicy.Elements.Policy);
|
|
|
|
importer.Errors.Add(new MetadataConversionError(message, false));
|
|
return SupportedAddressingMode.Anonymous;
|
|
}
|
|
|
|
IEnumerable<IEnumerable<XmlElement>> alternatives = importer.NormalizePolicy(new XmlElement[] { policyElement });
|
|
foreach (IEnumerable<XmlElement> alternative in alternatives)
|
|
{
|
|
foreach (XmlElement element in alternative)
|
|
{
|
|
if (element.NamespaceURI == MetadataStrings.Addressing10.MetadataPolicy.NamespaceUri)
|
|
{
|
|
if (element.LocalName == MetadataStrings.Addressing10.MetadataPolicy.NonAnonymousResponses)
|
|
{
|
|
return SupportedAddressingMode.NonAnonymous;
|
|
}
|
|
else if (element.LocalName == MetadataStrings.Addressing10.MetadataPolicy.AnonymousResponses)
|
|
{
|
|
return SupportedAddressingMode.Anonymous;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return SupportedAddressingMode.Anonymous;
|
|
}
|
|
}
|
|
|
|
static class WsdlNamingHelper
|
|
{
|
|
internal static XmlQualifiedName GetBindingName(WsdlNS.Binding wsdlBinding)
|
|
{
|
|
XmlName xmlName = new XmlName(wsdlBinding.Name, true /*isEncoded*/);
|
|
return new XmlQualifiedName(xmlName.EncodedName, wsdlBinding.ServiceDescription.TargetNamespace);
|
|
}
|
|
|
|
internal static XmlQualifiedName GetBindingName(WsdlNS.Port wsdlPort)
|
|
{
|
|
// Microsoft: composing names have potential problem of generating name that looks like an encoded name, consider avoiding '_'
|
|
XmlName xmlName = new XmlName(string.Format(CultureInfo.InvariantCulture, "{0}_{1}", wsdlPort.Service.Name, wsdlPort.Name), true /*isEncoded*/);
|
|
return new XmlQualifiedName(xmlName.EncodedName, wsdlPort.Service.ServiceDescription.TargetNamespace);
|
|
}
|
|
|
|
internal static XmlName GetEndpointName(WsdlNS.Port wsdlPort)
|
|
{
|
|
return new XmlName(wsdlPort.Name, true /*isEncoded*/);
|
|
}
|
|
|
|
internal static XmlQualifiedName GetContractName(XmlQualifiedName wsdlPortTypeQName)
|
|
{
|
|
return wsdlPortTypeQName;
|
|
}
|
|
|
|
internal static string GetOperationName(WsdlNS.Operation wsdlOperation)
|
|
{
|
|
return wsdlOperation.Name;
|
|
}
|
|
|
|
internal static XmlName GetOperationMessageName(WsdlNS.OperationMessage wsdlOperationMessage)
|
|
{
|
|
string messageName = null;
|
|
if (!string.IsNullOrEmpty(wsdlOperationMessage.Name))
|
|
{
|
|
messageName = wsdlOperationMessage.Name;
|
|
}
|
|
else if (wsdlOperationMessage.Operation.Messages.Count == 1)
|
|
{
|
|
messageName = wsdlOperationMessage.Operation.Name;
|
|
}
|
|
else if (wsdlOperationMessage.Operation.Messages.IndexOf(wsdlOperationMessage) == 0)
|
|
{
|
|
if (wsdlOperationMessage is WsdlNS.OperationInput)
|
|
messageName = wsdlOperationMessage.Operation.Name + "Request";
|
|
else if (wsdlOperationMessage is WsdlNS.OperationOutput)
|
|
messageName = wsdlOperationMessage.Operation.Name + "Solicit";
|
|
}
|
|
else if (wsdlOperationMessage.Operation.Messages.IndexOf(wsdlOperationMessage) == 1)
|
|
{
|
|
messageName = wsdlOperationMessage.Operation.Name + "Response";
|
|
}
|
|
else
|
|
{
|
|
// Microsoft: why this is an Assert, and not an exception?
|
|
Fx.Assert("Unsupported WSDL OM (More than 2 OperationMessages encountered in an Operation or WsdlOM is invalid)");
|
|
}
|
|
// names the come from service description documents have to be valid NCNames; XmlName.ctor will validate.
|
|
return new XmlName(messageName, true /*isEncoded*/);
|
|
}
|
|
}
|
|
|
|
internal static class NetSessionHelper
|
|
{
|
|
internal static void SetInitiatingTerminating(OperationDescription operationDescription, WsdlNS.Operation wsdlOperation)
|
|
{
|
|
XmlAttribute isInitiating = FindAttribute(wsdlOperation.ExtensibleAttributes, WsdlExporter.NetSessionHelper.IsInitiating,
|
|
WsdlExporter.NetSessionHelper.NamespaceUri);
|
|
|
|
if (isInitiating != null)
|
|
{
|
|
if (isInitiating.Value == WsdlExporter.NetSessionHelper.True)
|
|
{
|
|
operationDescription.IsInitiating = true;
|
|
}
|
|
if (isInitiating.Value == WsdlExporter.NetSessionHelper.False)
|
|
{
|
|
operationDescription.IsInitiating = false;
|
|
}
|
|
}
|
|
|
|
XmlAttribute isTerminating = FindAttribute(wsdlOperation.ExtensibleAttributes, WsdlExporter.NetSessionHelper.IsTerminating,
|
|
WsdlExporter.NetSessionHelper.NamespaceUri);
|
|
|
|
if (isTerminating != null)
|
|
{
|
|
if (isTerminating.Value == WsdlExporter.NetSessionHelper.True)
|
|
{
|
|
operationDescription.IsTerminating = true;
|
|
}
|
|
if (isTerminating.Value == WsdlExporter.NetSessionHelper.False)
|
|
{
|
|
operationDescription.IsTerminating = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal static void SetSession(ContractDescription contractDescription, WsdlNS.PortType wsdlPortType)
|
|
{
|
|
XmlAttribute usingSession = FindAttribute(wsdlPortType.ExtensibleAttributes, WsdlExporter.NetSessionHelper.UsingSession,
|
|
WsdlExporter.NetSessionHelper.NamespaceUri);
|
|
|
|
if (usingSession != null)
|
|
{
|
|
if (usingSession.Value == WsdlExporter.NetSessionHelper.True)
|
|
{
|
|
contractDescription.SessionMode = SessionMode.Required;
|
|
}
|
|
if (usingSession.Value == WsdlExporter.NetSessionHelper.False)
|
|
{
|
|
contractDescription.SessionMode = SessionMode.NotAllowed;
|
|
}
|
|
}
|
|
}
|
|
|
|
static XmlAttribute FindAttribute(XmlAttribute[] attributes, string localName, string ns)
|
|
{
|
|
if (attributes != null)
|
|
{
|
|
foreach (XmlAttribute attribute in attributes)
|
|
{
|
|
if (attribute.LocalName == localName && attribute.NamespaceURI == ns)
|
|
{
|
|
return attribute;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
internal static class SoapInPolicyWorkaroundHelper
|
|
{
|
|
public const string soapTransportUriKey = "TransportBindingElementImporter.TransportUri";
|
|
const string workaroundNS = NamingHelper.DefaultNamespace + "temporaryworkaround";
|
|
const string bindingAttrName = "bindingName";
|
|
const string bindingAttrNamespace = "bindingNamespace";
|
|
static XmlDocument xmlDocument;
|
|
|
|
static public void InsertAdHocPolicy(WsdlNS.Binding wsdlBinding, string value, string key)
|
|
{
|
|
XmlQualifiedName wsdlBindingQName = new XmlQualifiedName(wsdlBinding.Name, wsdlBinding.ServiceDescription.TargetNamespace);
|
|
string id = AddPolicyUri(wsdlBinding, key);
|
|
InsertPolicy(key, id, wsdlBinding.ServiceDescription, value, wsdlBindingQName);
|
|
}
|
|
|
|
static public string FindAdHocTransportPolicy(PolicyConversionContext policyContext, out XmlQualifiedName wsdlBindingQName)
|
|
{
|
|
return FindAdHocPolicy(policyContext, soapTransportUriKey, out wsdlBindingQName);
|
|
}
|
|
|
|
static public string FindAdHocPolicy(PolicyConversionContext policyContext, string key, out XmlQualifiedName wsdlBindingQName)
|
|
{
|
|
if (policyContext == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("policyContext");
|
|
|
|
XmlElement policy = PolicyConversionContext.FindAssertion(policyContext.GetBindingAssertions(), key, workaroundNS, true);
|
|
if (policy != null)
|
|
{
|
|
wsdlBindingQName = new XmlQualifiedName(policy.Attributes[bindingAttrName].Value, policy.Attributes[bindingAttrNamespace].Value);
|
|
return policy.InnerText;
|
|
}
|
|
else
|
|
{
|
|
wsdlBindingQName = null;
|
|
return null;
|
|
}
|
|
}
|
|
|
|
static string AddPolicyUri(WsdlNS.Binding wsdlBinding, string name)
|
|
{
|
|
string policyUris = ReadPolicyUris(wsdlBinding);
|
|
string id = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}_{1}_BindingAdHocPolicy", wsdlBinding.Name, name);
|
|
string newPolicyUris = string.Format(System.Globalization.CultureInfo.InvariantCulture, "#{0} {1}", id, policyUris).Trim();
|
|
WritePolicyUris(wsdlBinding, newPolicyUris);
|
|
return id;
|
|
}
|
|
|
|
static XmlDocument XmlDoc
|
|
{
|
|
get
|
|
{
|
|
if (xmlDocument == null)
|
|
{
|
|
NameTable nameTable = new NameTable();
|
|
nameTable.Add(MetadataStrings.WSPolicy.Elements.Policy);
|
|
nameTable.Add(MetadataStrings.WSPolicy.Elements.All);
|
|
nameTable.Add(MetadataStrings.WSPolicy.Elements.ExactlyOne);
|
|
nameTable.Add(MetadataStrings.WSPolicy.Attributes.PolicyURIs);
|
|
nameTable.Add(MetadataStrings.Wsu.Attributes.Id);
|
|
xmlDocument = new XmlDocument(nameTable);
|
|
}
|
|
return xmlDocument;
|
|
}
|
|
}
|
|
|
|
static void WritePolicyUris(WsdlNS.DocumentableItem item, string newValue)
|
|
{
|
|
|
|
int i;
|
|
XmlAttribute[] attributes = item.ExtensibleAttributes;
|
|
if (attributes != null && attributes.Length > 0)
|
|
{
|
|
foreach (XmlAttribute attribute in attributes)
|
|
if (MetadataImporter.PolicyHelper.IsPolicyURIs(attribute))
|
|
{
|
|
attribute.Value = newValue;
|
|
return;
|
|
}
|
|
// Need to extend
|
|
i = attributes.Length;
|
|
Array.Resize<XmlAttribute>(ref attributes, i + 1);
|
|
|
|
}
|
|
else
|
|
{
|
|
//Need to create
|
|
i = 0;
|
|
attributes = new XmlAttribute[1];
|
|
}
|
|
|
|
attributes[i] = CreatePolicyURIsAttribute(newValue);
|
|
item.ExtensibleAttributes = attributes;
|
|
}
|
|
|
|
static XmlAttribute CreatePolicyURIsAttribute(string value)
|
|
{
|
|
XmlAttribute attribute = XmlDoc.CreateAttribute(MetadataStrings.WSPolicy.Prefix,
|
|
MetadataStrings.WSPolicy.Attributes.PolicyURIs,
|
|
MetadataStrings.WSPolicy.NamespaceUri);
|
|
|
|
attribute.Value = value;
|
|
return attribute;
|
|
}
|
|
|
|
static string ReadPolicyUris(WsdlNS.DocumentableItem item)
|
|
{
|
|
|
|
XmlAttribute[] attributes = item.ExtensibleAttributes;
|
|
if (attributes != null && attributes.Length > 0)
|
|
{
|
|
foreach (XmlAttribute attribute in attributes)
|
|
{
|
|
if (MetadataImporter.PolicyHelper.IsPolicyURIs(attribute))
|
|
{
|
|
return attribute.Value;
|
|
}
|
|
}
|
|
}
|
|
|
|
return string.Empty;
|
|
}
|
|
|
|
static void InsertPolicy(string key, string id, WsdlNS.ServiceDescription policyWsdl, string value, XmlQualifiedName wsdlBindingQName)
|
|
{
|
|
|
|
// Create [wsp:Policy]
|
|
XmlElement policyElement = CreatePolicyElement(key, value, wsdlBindingQName);
|
|
|
|
//Create [wsp:Policy/@wsu:Id]
|
|
XmlAttribute idAttribute = XmlDoc.CreateAttribute(MetadataStrings.Wsu.Prefix,
|
|
MetadataStrings.Wsu.Attributes.Id,
|
|
MetadataStrings.Wsu.NamespaceUri);
|
|
idAttribute.Value = id;
|
|
policyElement.SetAttributeNode(idAttribute);
|
|
|
|
// Add wsp:Policy To WSDL
|
|
policyWsdl.Extensions.Add(policyElement);
|
|
|
|
}
|
|
|
|
static XmlElement CreatePolicyElement(string elementName, string value, XmlQualifiedName wsdlBindingQName)
|
|
{
|
|
|
|
// Create [wsp:Policy]
|
|
XmlElement policyElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix,
|
|
MetadataStrings.WSPolicy.Elements.Policy,
|
|
MetadataStrings.WSPolicy.NamespaceUri);
|
|
|
|
// Create [wsp:Policy/wsp:ExactlyOne]
|
|
XmlElement exactlyOneElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix,
|
|
MetadataStrings.WSPolicy.Elements.ExactlyOne,
|
|
MetadataStrings.WSPolicy.NamespaceUri);
|
|
policyElement.AppendChild(exactlyOneElement);
|
|
|
|
// Create [wsp:Policy/wsp:ExactlyOne/wsp:All]
|
|
XmlElement allElement = XmlDoc.CreateElement(MetadataStrings.WSPolicy.Prefix,
|
|
MetadataStrings.WSPolicy.Elements.All,
|
|
MetadataStrings.WSPolicy.NamespaceUri);
|
|
exactlyOneElement.AppendChild(allElement);
|
|
|
|
// Add [wsp:Policy/wsp:ExactlyOne/wsp:All/*]
|
|
XmlElement workaroundElement = xmlDocument.CreateElement(elementName, workaroundNS);
|
|
workaroundElement.InnerText = value;
|
|
|
|
XmlAttribute bindingName = xmlDocument.CreateAttribute(bindingAttrName);
|
|
bindingName.Value = wsdlBindingQName.Name;
|
|
workaroundElement.Attributes.Append(bindingName);
|
|
|
|
XmlAttribute bindingNamespace = xmlDocument.CreateAttribute(bindingAttrNamespace);
|
|
bindingNamespace.Value = wsdlBindingQName.Namespace;
|
|
workaroundElement.Attributes.Append(bindingNamespace);
|
|
|
|
workaroundElement.Attributes.Append(bindingNamespace);
|
|
|
|
|
|
allElement.AppendChild(workaroundElement);
|
|
|
|
return policyElement;
|
|
}
|
|
|
|
internal static void InsertAdHocTransportPolicy(WsdlNS.ServiceDescriptionCollection wsdlDocuments)
|
|
{
|
|
foreach (WsdlNS.ServiceDescription wsdl in wsdlDocuments)
|
|
if (wsdl != null)
|
|
{
|
|
foreach (WsdlNS.Binding wsdlBinding in wsdl.Bindings)
|
|
{
|
|
if (WsdlImporter.WsdlPolicyReader.ContainsPolicy(wsdlBinding))
|
|
{
|
|
WsdlNS.SoapBinding soapBinding = (WsdlNS.SoapBinding)wsdlBinding.Extensions.Find(typeof(WsdlNS.SoapBinding));
|
|
if (soapBinding != null)
|
|
WsdlImporter
|
|
.SoapInPolicyWorkaroundHelper
|
|
.InsertAdHocPolicy(wsdlBinding, soapBinding.Transport, soapTransportUriKey);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
IEnumerable<WsdlNS.Binding> FindBindingsForPortType(WsdlNS.PortType wsdlPortType)
|
|
{
|
|
foreach (WsdlNS.Binding wsdlBinding in GetAllBindings())
|
|
{
|
|
if (wsdlBinding.Type.Name == wsdlPortType.Name
|
|
&& wsdlBinding.Type.Namespace == wsdlPortType.ServiceDescription.TargetNamespace)
|
|
yield return wsdlBinding;
|
|
}
|
|
}
|
|
|
|
IEnumerable<WsdlNS.Binding> FindBindingsForContract(ContractDescription contract)
|
|
{
|
|
XmlQualifiedName qName = WsdlExporter.WsdlNamingHelper.GetPortTypeQName(contract);
|
|
foreach (WsdlNS.Binding wsdlBinding in GetAllBindings())
|
|
{
|
|
if (wsdlBinding.Type.Name == qName.Name
|
|
&& wsdlBinding.Type.Namespace == qName.Namespace)
|
|
yield return wsdlBinding;
|
|
}
|
|
}
|
|
|
|
IEnumerable<WsdlNS.Port> FindPortsForBinding(WsdlNS.Binding binding)
|
|
{
|
|
foreach (WsdlNS.Port wsdlPort in GetAllPorts())
|
|
{
|
|
if (wsdlPort.Binding.Name == binding.Name && wsdlPort.Binding.Namespace == binding.ServiceDescription.TargetNamespace)
|
|
yield return wsdlPort;
|
|
}
|
|
}
|
|
|
|
IEnumerable<WsdlNS.Binding> GetAllBindings()
|
|
{
|
|
foreach (WsdlNS.ServiceDescription wsdl in this.WsdlDocuments)
|
|
{
|
|
foreach (WsdlNS.Binding wsdlBinding in wsdl.Bindings)
|
|
{
|
|
yield return wsdlBinding;
|
|
}
|
|
}
|
|
}
|
|
|
|
IEnumerable<WsdlNS.Port> GetAllPorts()
|
|
{
|
|
foreach (WsdlNS.ServiceDescription wsdl in this.WsdlDocuments)
|
|
{
|
|
foreach (WsdlNS.Service wsdlService in wsdl.Services)
|
|
{
|
|
foreach (WsdlNS.Port wsdlPort in wsdlService.Ports)
|
|
{
|
|
yield return wsdlPort;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[Fx.Tag.SecurityNote(Critical = "Uses ClientSection.UnsafeGetSection to get config in PT.",
|
|
Safe = "Does not leak config object, just picks up extensions.")]
|
|
[SecuritySafeCritical]
|
|
static Collection<IWsdlImportExtension> LoadWsdlExtensionsFromConfig()
|
|
{
|
|
return ConfigNS.ClientSection.UnsafeGetSection().Metadata.LoadWsdlImportExtensions();
|
|
}
|
|
|
|
internal static IEnumerable<MetadataSection> CreateMetadataDocuments(WsdlNS.ServiceDescriptionCollection wsdlDocuments, XmlSchemaSet xmlSchemas, IEnumerable<XmlElement> policyDocuments)
|
|
{
|
|
|
|
if (wsdlDocuments != null)
|
|
foreach (WsdlNS.ServiceDescription wsdl in wsdlDocuments)
|
|
yield return MetadataSection.CreateFromServiceDescription(wsdl);
|
|
|
|
if (xmlSchemas != null)
|
|
foreach (XmlSchema schema in xmlSchemas.Schemas())
|
|
yield return MetadataSection.CreateFromSchema(schema);
|
|
|
|
if (policyDocuments != null)
|
|
foreach (XmlElement policyDocument in policyDocuments)
|
|
yield return MetadataSection.CreateFromPolicy(policyDocument, null);
|
|
}
|
|
|
|
BindingElementCollection ImportPolicyFromWsdl(WsdlEndpointConversionContext endpointContext)
|
|
{
|
|
PolicyAlternatives policyAlternatives = this.PolicyReader.GetPolicyAlternatives(endpointContext);
|
|
IEnumerable<PolicyConversionContext> policyContexts = GetPolicyConversionContextEnumerator(endpointContext.Endpoint, policyAlternatives, this.Quotas);
|
|
PolicyConversionContext firstContext = null;
|
|
|
|
StringBuilder unImportedPolicyMessage = null;
|
|
int policyConversionContextsSeen = 0; //limit on the number of alternatives that we'll evaluate
|
|
foreach (PolicyConversionContext policyConversionContext in policyContexts)
|
|
{
|
|
if (firstContext == null)
|
|
firstContext = policyConversionContext;
|
|
if (this.TryImportPolicy(policyConversionContext))
|
|
{
|
|
return policyConversionContext.BindingElements;
|
|
}
|
|
else
|
|
{
|
|
AppendUnImportedPolicyErrorMessage(ref unImportedPolicyMessage, endpointContext, policyConversionContext);
|
|
}
|
|
|
|
if (++policyConversionContextsSeen >= this.Quotas.MaxPolicyConversionContexts)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// we failed to import policy for all PolicyConversionContexts, lets pick one context (the first one)
|
|
// and wrap all unprocessed assertion in UnrecognizedAssertionsBindingElement
|
|
if (firstContext != null)
|
|
{
|
|
#pragma warning suppress 56506
|
|
firstContext.BindingElements.Insert(0, CollectUnrecognizedAssertions(firstContext, endpointContext));
|
|
LogImportWarning(unImportedPolicyMessage.ToString());
|
|
return firstContext.BindingElements;
|
|
}
|
|
// Consider: a /verbose option for svcutil...
|
|
if (endpointContext.WsdlPort != null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(endpointContext.WsdlPort, new InvalidOperationException(SR.GetString(SR.NoUsablePolicyAssertions))));
|
|
}
|
|
else
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(endpointContext.WsdlBinding, new InvalidOperationException(SR.GetString(SR.NoUsablePolicyAssertions))));
|
|
}
|
|
}
|
|
|
|
static UnrecognizedAssertionsBindingElement CollectUnrecognizedAssertions(PolicyConversionContext policyContext, WsdlEndpointConversionContext endpointContext)
|
|
{
|
|
XmlQualifiedName bindingQName = new XmlQualifiedName(endpointContext.WsdlBinding.Name, endpointContext.WsdlBinding.ServiceDescription.TargetNamespace);
|
|
UnrecognizedAssertionsBindingElement unknownBindingElement = new UnrecognizedAssertionsBindingElement(bindingQName, policyContext.GetBindingAssertions());
|
|
foreach (OperationDescription operation in policyContext.Contract.Operations)
|
|
{
|
|
if (policyContext.GetOperationBindingAssertions(operation).Count != 0)
|
|
{
|
|
unknownBindingElement.Add(operation, policyContext.GetOperationBindingAssertions(operation));
|
|
}
|
|
|
|
foreach (MessageDescription message in operation.Messages)
|
|
{
|
|
if (policyContext.GetMessageBindingAssertions(message).Count != 0)
|
|
{
|
|
unknownBindingElement.Add(message, policyContext.GetMessageBindingAssertions(message));
|
|
}
|
|
}
|
|
}
|
|
return unknownBindingElement;
|
|
}
|
|
|
|
static void AppendUnImportedPolicyErrorMessage(ref StringBuilder unImportedPolicyMessage, WsdlEndpointConversionContext endpointContext, PolicyConversionContext policyContext)
|
|
{
|
|
if (unImportedPolicyMessage == null)
|
|
{
|
|
unImportedPolicyMessage = new StringBuilder(SR.GetString(SR.UnabletoImportPolicy));
|
|
}
|
|
else
|
|
{
|
|
unImportedPolicyMessage.AppendLine();
|
|
}
|
|
|
|
if (policyContext.GetBindingAssertions().Count != 0)
|
|
AddUnImportedPolicyString(unImportedPolicyMessage, endpointContext.WsdlBinding, policyContext.GetBindingAssertions());
|
|
|
|
foreach (OperationDescription operation in policyContext.Contract.Operations)
|
|
{
|
|
if (policyContext.GetOperationBindingAssertions(operation).Count != 0)
|
|
{
|
|
AddUnImportedPolicyString(unImportedPolicyMessage,
|
|
endpointContext.GetOperationBinding(operation),
|
|
policyContext.GetOperationBindingAssertions(operation));
|
|
}
|
|
|
|
foreach (MessageDescription message in operation.Messages)
|
|
{
|
|
if (policyContext.GetMessageBindingAssertions(message).Count != 0)
|
|
{
|
|
AddUnImportedPolicyString(unImportedPolicyMessage,
|
|
endpointContext.GetMessageBinding(message),
|
|
policyContext.GetMessageBindingAssertions(message));
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
static void AddUnImportedPolicyString(StringBuilder stringBuilder, WsdlNS.NamedItem item, IEnumerable<XmlElement> unimportdPolicy)
|
|
{
|
|
stringBuilder.AppendLine(SR.GetString(SR.UnImportedAssertionList, CreateXPathString(item)));
|
|
// do not putput duplicated assetions
|
|
Dictionary<XmlElement, XmlElement> unique = new Dictionary<XmlElement, XmlElement>();
|
|
int uniqueAsserions = 0;
|
|
foreach (XmlElement element in unimportdPolicy)
|
|
{
|
|
if (unique.ContainsKey(element))
|
|
continue;
|
|
unique.Add(element, element);
|
|
uniqueAsserions++;
|
|
if (uniqueAsserions > 128)
|
|
{
|
|
stringBuilder.Append("..");
|
|
stringBuilder.AppendLine();
|
|
break;
|
|
}
|
|
WriteElement(element, stringBuilder);
|
|
}
|
|
}
|
|
|
|
static void WriteElement(XmlElement element, StringBuilder stringBuilder)
|
|
{
|
|
stringBuilder.Append(" <");
|
|
stringBuilder.Append(element.Name);
|
|
if (!string.IsNullOrEmpty(element.NamespaceURI))
|
|
{
|
|
stringBuilder.Append(' ');
|
|
stringBuilder.Append("xmlns");
|
|
if (!string.IsNullOrEmpty(element.Prefix))
|
|
{
|
|
stringBuilder.Append(':');
|
|
stringBuilder.Append(element.Prefix);
|
|
}
|
|
stringBuilder.Append('=');
|
|
stringBuilder.Append('\'');
|
|
stringBuilder.Append(element.NamespaceURI);
|
|
stringBuilder.Append('\'');
|
|
}
|
|
stringBuilder.Append(">..</");
|
|
stringBuilder.Append(element.Name);
|
|
stringBuilder.Append('>');
|
|
stringBuilder.AppendLine();
|
|
}
|
|
|
|
const string xPathDocumentFormatString = "//wsdl:definitions[@targetNamespace='{0}']";
|
|
const string xPathItemSubFormatString = "/wsdl:{0}";
|
|
const string xPathNamedItemSubFormatString = xPathItemSubFormatString + "[@name='{1}']";
|
|
|
|
static string GetElementName(WsdlNS.NamedItem item)
|
|
{
|
|
if (item is WsdlNS.PortType)
|
|
return "wsdl:portType";
|
|
else if (item is WsdlNS.Binding)
|
|
return "wsdl:binding";
|
|
else if (item is WsdlNS.ServiceDescription)
|
|
return "wsdl:definitions";
|
|
else if (item is WsdlNS.Service)
|
|
return "wsdl:service";
|
|
else if (item is WsdlNS.Message)
|
|
return "wsdl:message";
|
|
else if (item is WsdlNS.Operation)
|
|
return "wsdl:operation";
|
|
else if (item is WsdlNS.Port)
|
|
return "wsdl:port";
|
|
else
|
|
{
|
|
Fx.Assert("GetElementName Method should be updated to support " + item.GetType());
|
|
return null;
|
|
}
|
|
}
|
|
|
|
static string CreateXPathString(WsdlNS.NamedItem item)
|
|
{
|
|
if (item == null)
|
|
return SR.GetString(SR.XPathUnavailable);
|
|
string nameValue = item.Name;
|
|
string localName;
|
|
string wsdlNs;
|
|
string rest = string.Empty;
|
|
string itemPath = string.Empty;
|
|
|
|
GetXPathParameters(item, out wsdlNs, out localName, ref nameValue, ref rest);
|
|
string documentPath = string.Format(CultureInfo.InvariantCulture, xPathDocumentFormatString, wsdlNs);
|
|
|
|
if (localName != null)
|
|
{
|
|
itemPath = string.Format(CultureInfo.InvariantCulture, xPathNamedItemSubFormatString, localName, nameValue);
|
|
}
|
|
Fx.Assert(rest != null, "GetXPathParameters Method should never set rest to null. this happened for: " + item.GetType());
|
|
return documentPath + itemPath + rest;
|
|
}
|
|
|
|
static void GetXPathParameters(WsdlNS.NamedItem item, out string wsdlNs, out string localName, ref string nameValue, ref string rest)
|
|
{
|
|
if (item is WsdlNS.ServiceDescription)
|
|
{
|
|
localName = null;
|
|
wsdlNs = ((WsdlNS.ServiceDescription)item).TargetNamespace ?? String.Empty;
|
|
}
|
|
if (item is WsdlNS.PortType)
|
|
{
|
|
localName = "portType";
|
|
wsdlNs = ((WsdlNS.PortType)item).ServiceDescription.TargetNamespace ?? String.Empty;
|
|
}
|
|
else if (item is WsdlNS.Binding)
|
|
{
|
|
localName = "binding";
|
|
wsdlNs = ((WsdlNS.Binding)item).ServiceDescription.TargetNamespace ?? String.Empty;
|
|
}
|
|
else if (item is WsdlNS.ServiceDescription)
|
|
{
|
|
localName = "definitions";
|
|
wsdlNs = ((WsdlNS.ServiceDescription)item).TargetNamespace ?? String.Empty;
|
|
}
|
|
else if (item is WsdlNS.Service)
|
|
{
|
|
localName = "service";
|
|
wsdlNs = ((WsdlNS.Service)item).ServiceDescription.TargetNamespace ?? String.Empty;
|
|
}
|
|
else if (item is WsdlNS.Message)
|
|
{
|
|
localName = "message";
|
|
wsdlNs = ((WsdlNS.Message)item).ServiceDescription.TargetNamespace ?? String.Empty;
|
|
}
|
|
else if (item is WsdlNS.Port)
|
|
{
|
|
WsdlNS.Service wsdlService = ((WsdlNS.Port)item).Service;
|
|
localName = "service";
|
|
nameValue = wsdlService.Name;
|
|
wsdlNs = wsdlService.ServiceDescription.TargetNamespace ?? String.Empty;
|
|
rest = string.Format(CultureInfo.InvariantCulture, xPathNamedItemSubFormatString, "port", item.Name);
|
|
}
|
|
else if (item is WsdlNS.Operation)
|
|
{
|
|
WsdlNS.PortType wsdlPortType = ((WsdlNS.Operation)item).PortType;
|
|
localName = "portType";
|
|
nameValue = wsdlPortType.Name;
|
|
wsdlNs = wsdlPortType.ServiceDescription.TargetNamespace ?? String.Empty;
|
|
rest = string.Format(CultureInfo.InvariantCulture, xPathNamedItemSubFormatString, "operation", item.Name);
|
|
}
|
|
else if (item is WsdlNS.OperationBinding)
|
|
{
|
|
WsdlNS.OperationBinding wsdlOperationBinding = ((WsdlNS.OperationBinding)item);
|
|
localName = "binding";
|
|
nameValue = wsdlOperationBinding.Binding.Name;
|
|
wsdlNs = wsdlOperationBinding.Binding.ServiceDescription.TargetNamespace ?? String.Empty;
|
|
rest = string.Format(CultureInfo.InvariantCulture, xPathNamedItemSubFormatString, "operation", item.Name);
|
|
}
|
|
else if (item is WsdlNS.MessageBinding)
|
|
{
|
|
localName = "binding";
|
|
WsdlNS.OperationBinding wsdlOperationBinding = ((WsdlNS.MessageBinding)item).OperationBinding;
|
|
wsdlNs = wsdlOperationBinding.Binding.ServiceDescription.TargetNamespace ?? String.Empty;
|
|
nameValue = wsdlOperationBinding.Binding.Name;
|
|
string messageName = item.Name;
|
|
|
|
string messageTag = string.Empty;
|
|
if (item is WsdlNS.InputBinding)
|
|
messageTag = "input";
|
|
else if (item is WsdlNS.OutputBinding)
|
|
messageTag = "output";
|
|
else if (item is WsdlNS.FaultBinding)
|
|
messageTag = "fault";
|
|
else
|
|
Fx.Assert("Unsupported WSDL OM: unknown WsdlNS.MessageBinding: " + item.GetType());
|
|
|
|
rest = string.Format(CultureInfo.InvariantCulture, xPathNamedItemSubFormatString, "operation", wsdlOperationBinding.Name);
|
|
if (string.IsNullOrEmpty(messageName))
|
|
rest += string.Format(CultureInfo.InvariantCulture, xPathItemSubFormatString, messageTag);
|
|
else
|
|
rest += string.Format(CultureInfo.InvariantCulture, xPathNamedItemSubFormatString, messageTag, messageName);
|
|
}
|
|
else
|
|
{
|
|
Fx.Assert("GetXPathParameters Method should be updated to support " + item.GetType());
|
|
localName = null;
|
|
wsdlNs = null;
|
|
}
|
|
}
|
|
|
|
void LogImportWarning(string warningMessage)
|
|
{
|
|
if (warnings.ContainsKey(warningMessage))
|
|
return;
|
|
if (warnings.Count >= 1024)
|
|
warnings.Clear();
|
|
warnings.Add(warningMessage, warningMessage);
|
|
this.Errors.Add(new MetadataConversionError(warningMessage, true));
|
|
}
|
|
|
|
void LogImportError(WsdlNS.NamedItem item, WsdlImportException wie)
|
|
{
|
|
string errormessage;
|
|
if (wie.InnerException != null && (wie.InnerException is WsdlImportException))
|
|
{
|
|
WsdlImportException wieInner = wie.InnerException as WsdlImportException;
|
|
string dependencyMessage = SR.GetString(SR.WsdlImportErrorDependencyDetail, GetElementName(wieInner.SourceItem), GetElementName(item), CreateXPathString(wieInner.SourceItem));
|
|
errormessage = SR.GetString(SR.WsdlImportErrorMessageDetail, GetElementName(item), CreateXPathString(wie.SourceItem), dependencyMessage);
|
|
}
|
|
else
|
|
{
|
|
errormessage = SR.GetString(SR.WsdlImportErrorMessageDetail, GetElementName(item), CreateXPathString(wie.SourceItem), wie.Message);
|
|
}
|
|
|
|
importErrors.Add(item, wie);
|
|
this.Errors.Add(new MetadataConversionError(errormessage, false));
|
|
}
|
|
|
|
static Exception CreateBeforeImportExtensionException(IWsdlImportExtension importer, Exception e)
|
|
{
|
|
string errorMessage = SR.GetString(SR.WsdlExtensionBeforeImportError, importer.GetType().AssemblyQualifiedName, e.Message);
|
|
return new InvalidOperationException(errorMessage, e);
|
|
}
|
|
|
|
Exception CreateAlreadyFaultedException(WsdlNS.NamedItem item)
|
|
{
|
|
WsdlImportException innerException = importErrors[item];
|
|
string warningMsg = SR.GetString(SR.WsdlItemAlreadyFaulted, GetElementName(item));
|
|
return new AlreadyFaultedException(warningMsg, innerException);
|
|
}
|
|
|
|
static Exception CreateExtensionException(IWsdlImportExtension importer, Exception e)
|
|
{
|
|
string errorMessage = SR.GetString(SR.WsdlExtensionImportError, importer.GetType().FullName, e.Message);
|
|
//consider Microsoft, allow internal exceptions to throw WsdlImportException and handle it in some special way?
|
|
return new InvalidOperationException(errorMessage, e);
|
|
}
|
|
|
|
class AlreadyFaultedException : InvalidOperationException
|
|
{
|
|
internal AlreadyFaultedException(string message, WsdlImportException innerException)
|
|
: base(message, innerException) { }
|
|
}
|
|
|
|
class WsdlImportException : Exception
|
|
{
|
|
WsdlNS.NamedItem sourceItem;
|
|
readonly string xPath = null;
|
|
|
|
WsdlImportException(WsdlNS.NamedItem item, Exception innerException)
|
|
: base(string.Empty, innerException)
|
|
{
|
|
this.xPath = CreateXPathString(item);
|
|
this.sourceItem = item;
|
|
}
|
|
|
|
internal static WsdlImportException Create(WsdlNS.NamedItem item, Exception innerException)
|
|
{
|
|
WsdlImportException wie = innerException as WsdlImportException;
|
|
if (wie != null && wie.IsChildNodeOf(item))
|
|
{
|
|
wie.sourceItem = item;
|
|
return wie;
|
|
}
|
|
else
|
|
{
|
|
AlreadyFaultedException afe = innerException as AlreadyFaultedException;
|
|
if (afe != null)
|
|
return new WsdlImportException(item, afe.InnerException);
|
|
else
|
|
return new WsdlImportException(item, innerException);
|
|
}
|
|
}
|
|
|
|
internal bool IsChildNodeOf(WsdlNS.NamedItem item)
|
|
{
|
|
return this.XPath.StartsWith(CreateXPathString(item), StringComparison.Ordinal);
|
|
}
|
|
|
|
internal string XPath { get { return xPath; } }
|
|
|
|
internal WsdlNS.NamedItem SourceItem { get { return sourceItem; } }
|
|
|
|
public override string Message
|
|
{
|
|
get
|
|
{
|
|
Exception messageException = this.InnerException;
|
|
|
|
while (messageException is WsdlImportException)
|
|
messageException = messageException.InnerException;
|
|
|
|
if (messageException == null)
|
|
return string.Empty;
|
|
|
|
return messageException.Message;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class WsdlPolicyReader
|
|
{
|
|
WsdlImporter importer;
|
|
WsdlPolicyDictionary policyDictionary;
|
|
|
|
static readonly string[] EmptyStringArray = new string[0];
|
|
|
|
internal WsdlPolicyReader(WsdlImporter importer)
|
|
{
|
|
this.importer = importer;
|
|
this.policyDictionary = new WsdlPolicyDictionary(importer);
|
|
importer.PolicyWarningOccured += this.LogPolicyNormalizationWarning;
|
|
}
|
|
|
|
IEnumerable<IEnumerable<XmlElement>> GetPolicyAlternatives(WsdlNS.NamedItem item, WsdlNS.ServiceDescription wsdl)
|
|
{
|
|
Collection<XmlElement> policyElements = new Collection<XmlElement>();
|
|
|
|
foreach (XmlElement element in GetReferencedPolicy(item, wsdl))
|
|
{
|
|
policyElements.Add(element);
|
|
}
|
|
|
|
foreach (XmlElement element in GetEmbeddedPolicy(item))
|
|
{
|
|
policyElements.Add(element);
|
|
if (!policyDictionary.PolicySourceTable.ContainsKey(element))
|
|
policyDictionary.PolicySourceTable.Add(element, wsdl);
|
|
}
|
|
|
|
return importer.NormalizePolicy(policyElements);
|
|
}
|
|
|
|
void LogPolicyNormalizationWarning(XmlElement contextAssertion, string warningMessage)
|
|
{
|
|
string xPath = null;
|
|
if (contextAssertion != null)
|
|
xPath = this.policyDictionary.CreateIdXPath(contextAssertion);
|
|
|
|
StringBuilder warningMsg = new StringBuilder();
|
|
warningMsg.AppendLine(warningMessage);
|
|
|
|
if (!string.IsNullOrEmpty(xPath))
|
|
{
|
|
warningMsg.AppendLine(SR.GetString(SR.XPathPointer, xPath));
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We were given a context assertion that we couldn't get an XPath for
|
|
//
|
|
warningMsg.AppendLine(SR.GetString(SR.XPathPointer, SR.GetString(SR.XPathUnavailable)));
|
|
}
|
|
importer.LogImportWarning(warningMsg.ToString());
|
|
}
|
|
|
|
internal static bool ContainsPolicy(WsdlNS.Binding wsdlBinding)
|
|
{
|
|
if (HasPolicyAttached(wsdlBinding))
|
|
return true;
|
|
|
|
foreach (WsdlNS.OperationBinding wsdlOperationBinding in wsdlBinding.Operations)
|
|
{
|
|
if (HasPolicyAttached(wsdlOperationBinding))
|
|
{
|
|
return true;
|
|
}
|
|
if (wsdlOperationBinding.Input != null && HasPolicyAttached(wsdlOperationBinding.Input))
|
|
{
|
|
return true;
|
|
}
|
|
if (wsdlOperationBinding.Output != null && HasPolicyAttached(wsdlOperationBinding.Output))
|
|
{
|
|
return true;
|
|
}
|
|
foreach (WsdlNS.FaultBinding faultBinding in wsdlOperationBinding.Faults)
|
|
{
|
|
if (HasPolicyAttached(faultBinding))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
internal static bool HasPolicy(WsdlNS.Port wsdlPort)
|
|
{
|
|
return HasPolicyAttached(wsdlPort);
|
|
}
|
|
|
|
internal static IEnumerable<XmlElement> GetEmbeddedPolicy(WsdlNS.NamedItem item)
|
|
{
|
|
List<XmlElement> embeddedPolicies = new List<XmlElement>();
|
|
embeddedPolicies.AddRange(item.Extensions.FindAll(MetadataStrings.WSPolicy.Elements.Policy,
|
|
MetadataStrings.WSPolicy.NamespaceUri));
|
|
embeddedPolicies.AddRange(item.Extensions.FindAll(MetadataStrings.WSPolicy.Elements.Policy,
|
|
MetadataStrings.WSPolicy.NamespaceUri15));
|
|
return embeddedPolicies;
|
|
}
|
|
|
|
IEnumerable<XmlElement> GetReferencedPolicy(WsdlNS.NamedItem item, WsdlNS.ServiceDescription wsdl)
|
|
{
|
|
string xPath = CreateXPathString(item);
|
|
|
|
foreach (string policyRef in GetPolicyReferenceUris(item, xPath))
|
|
{
|
|
XmlElement policy = policyDictionary.ResolvePolicyReference(policyRef, wsdl);
|
|
if (policy == null)
|
|
{
|
|
StringBuilder warningMsg = new StringBuilder();
|
|
warningMsg.AppendLine(SR.GetString(SR.UnableToFindPolicyWithId, policyRef));
|
|
warningMsg.AppendLine(SR.GetString(SR.XPathPointer, xPath));
|
|
importer.LogImportWarning(warningMsg.ToString());
|
|
continue;
|
|
}
|
|
yield return policy;
|
|
}
|
|
}
|
|
|
|
IEnumerable<string> GetPolicyReferenceUris(WsdlNS.NamedItem item, string xPath)
|
|
{
|
|
//
|
|
// get policy from wsp:PolicyUris attribute
|
|
//
|
|
foreach (string policyUri in ReadPolicyUrisAttribute(item))
|
|
yield return policyUri;
|
|
|
|
//
|
|
// get policy from <wsp:PolicyReference> Elements
|
|
//
|
|
foreach (string policyUri in ReadPolicyReferenceElements(item, xPath))
|
|
yield return policyUri;
|
|
}
|
|
|
|
IEnumerable<string> ReadPolicyReferenceElements(WsdlNS.NamedItem item, string xPath)
|
|
{
|
|
List<XmlElement> policyReferences = new List<XmlElement>();
|
|
policyReferences.AddRange(item.Extensions.FindAll(MetadataStrings.WSPolicy.Elements.PolicyReference,
|
|
MetadataStrings.WSPolicy.NamespaceUri));
|
|
policyReferences.AddRange(item.Extensions.FindAll(MetadataStrings.WSPolicy.Elements.PolicyReference,
|
|
MetadataStrings.WSPolicy.NamespaceUri15));
|
|
|
|
foreach (XmlElement element in policyReferences)
|
|
{
|
|
string idRef = element.GetAttribute(MetadataStrings.WSPolicy.Attributes.URI);
|
|
|
|
if (idRef == null)
|
|
{
|
|
string warningMsg = SR.GetString(SR.PolicyReferenceMissingURI, MetadataStrings.WSPolicy.Attributes.URI);
|
|
importer.LogImportWarning(warningMsg);
|
|
}
|
|
else if (idRef == string.Empty)
|
|
{
|
|
string warningMsg = SR.GetString(SR.PolicyReferenceInvalidId);
|
|
importer.LogImportWarning(warningMsg);
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
yield return idRef;
|
|
}
|
|
}
|
|
}
|
|
|
|
static string[] ReadPolicyUrisAttribute(WsdlNS.NamedItem item)
|
|
{
|
|
|
|
XmlAttribute[] attributes = item.ExtensibleAttributes;
|
|
if (attributes != null && attributes.Length > 0)
|
|
{
|
|
foreach (XmlAttribute attribute in attributes)
|
|
{
|
|
if (PolicyHelper.IsPolicyURIs(attribute))
|
|
{
|
|
return attribute.Value.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
|
|
}
|
|
}
|
|
}
|
|
|
|
return EmptyStringArray;
|
|
}
|
|
|
|
static bool HasPolicyAttached(WsdlNS.NamedItem item)
|
|
{
|
|
XmlAttribute[] attributes = item.ExtensibleAttributes;
|
|
if (attributes != null && Array.Exists(attributes, PolicyHelper.IsPolicyURIs))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (item.Extensions.Find(MetadataStrings.WSPolicy.Elements.PolicyReference, MetadataStrings.WSPolicy.NamespaceUri) != null
|
|
|| item.Extensions.Find(MetadataStrings.WSPolicy.Elements.PolicyReference, MetadataStrings.WSPolicy.NamespaceUri15) != null)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (item.Extensions.Find(MetadataStrings.WSPolicy.Elements.Policy, MetadataStrings.WSPolicy.NamespaceUri) != null
|
|
|| item.Extensions.Find(MetadataStrings.WSPolicy.Elements.Policy, MetadataStrings.WSPolicy.NamespaceUri15) != null)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
internal PolicyAlternatives GetPolicyAlternatives(WsdlEndpointConversionContext endpointContext)
|
|
{
|
|
PolicyAlternatives policyAlternatives = new PolicyAlternatives();
|
|
|
|
//
|
|
// Create EndpointAlternatives either from wsd:binding or from CrossProduct of wsd:binding and wsdl:port policy
|
|
//
|
|
WsdlNS.ServiceDescription bindingWsdl = endpointContext.WsdlBinding.ServiceDescription;
|
|
IEnumerable<IEnumerable<XmlElement>> wsdlBindingAlternatives = this.GetPolicyAlternatives(endpointContext.WsdlBinding, bindingWsdl);
|
|
if (endpointContext.WsdlPort != null)
|
|
{
|
|
IEnumerable<IEnumerable<XmlElement>> wsdlPortAlternatives = this.GetPolicyAlternatives(endpointContext.WsdlPort, endpointContext.WsdlPort.Service.ServiceDescription);
|
|
policyAlternatives.EndpointAlternatives = PolicyHelper.CrossProduct<XmlElement>(wsdlBindingAlternatives, wsdlPortAlternatives, new YieldLimiter(this.importer.Quotas.MaxYields, this.importer));
|
|
}
|
|
else
|
|
{
|
|
policyAlternatives.EndpointAlternatives = wsdlBindingAlternatives;
|
|
}
|
|
|
|
//
|
|
// Create operation and message policy
|
|
//
|
|
policyAlternatives.OperationBindingAlternatives = new Dictionary<OperationDescription, IEnumerable<IEnumerable<XmlElement>>>(endpointContext.Endpoint.Contract.Operations.Count);
|
|
policyAlternatives.MessageBindingAlternatives = new Dictionary<MessageDescription, IEnumerable<IEnumerable<XmlElement>>>();
|
|
policyAlternatives.FaultBindingAlternatives = new Dictionary<FaultDescription, IEnumerable<IEnumerable<XmlElement>>>();
|
|
|
|
foreach (OperationDescription operation in endpointContext.Endpoint.Contract.Operations)
|
|
{
|
|
// Skip operations that have Action/ReplyAction = "*"
|
|
if (!WsdlExporter.OperationIsExportable(operation))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
WsdlNS.OperationBinding wsdlOperationBinding = endpointContext.GetOperationBinding(operation);
|
|
try
|
|
{
|
|
IEnumerable<IEnumerable<XmlElement>> operationAlternatives = this.GetPolicyAlternatives(wsdlOperationBinding, bindingWsdl);
|
|
policyAlternatives.OperationBindingAlternatives.Add(operation, operationAlternatives);
|
|
|
|
foreach (MessageDescription message in operation.Messages)
|
|
{
|
|
WsdlNS.MessageBinding wsdlMessageBinding = endpointContext.GetMessageBinding(message);
|
|
CreateMessageBindingAlternatives(policyAlternatives, bindingWsdl, message, wsdlMessageBinding);
|
|
}
|
|
|
|
foreach (FaultDescription fault in operation.Faults)
|
|
{
|
|
WsdlNS.FaultBinding wsdlFaultBinding = endpointContext.GetFaultBinding(fault);
|
|
CreateFaultBindingAlternatives(policyAlternatives, bindingWsdl, fault, wsdlFaultBinding);
|
|
}
|
|
}
|
|
#pragma warning suppress 56500 // covered by FxCOP
|
|
catch (Exception e)
|
|
{
|
|
if (Fx.IsFatal(e))
|
|
throw;
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(wsdlOperationBinding, e));
|
|
}
|
|
}
|
|
|
|
return policyAlternatives;
|
|
}
|
|
|
|
void CreateMessageBindingAlternatives(PolicyAlternatives policyAlternatives, WsdlNS.ServiceDescription bindingWsdl, MessageDescription message, WsdlNS.MessageBinding wsdlMessageBinding)
|
|
{
|
|
try
|
|
{
|
|
IEnumerable<IEnumerable<XmlElement>> messageAlternatives = this.GetPolicyAlternatives(wsdlMessageBinding, bindingWsdl);
|
|
policyAlternatives.MessageBindingAlternatives.Add(message, messageAlternatives);
|
|
}
|
|
#pragma warning suppress 56500 // covered by FxCOP
|
|
catch (Exception e)
|
|
{
|
|
if (Fx.IsFatal(e))
|
|
throw;
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(wsdlMessageBinding, e));
|
|
}
|
|
}
|
|
|
|
void CreateFaultBindingAlternatives(PolicyAlternatives policyAlternatives, WsdlNS.ServiceDescription bindingWsdl, FaultDescription fault, WsdlNS.FaultBinding wsdlFaultBinding)
|
|
{
|
|
try
|
|
{
|
|
IEnumerable<IEnumerable<XmlElement>> faultAlternatives = this.GetPolicyAlternatives(wsdlFaultBinding, bindingWsdl);
|
|
policyAlternatives.FaultBindingAlternatives.Add(fault, faultAlternatives);
|
|
}
|
|
#pragma warning suppress 56500 // covered by FxCOP
|
|
catch (Exception e)
|
|
{
|
|
if (Fx.IsFatal(e))
|
|
throw;
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsdlImportException.Create(wsdlFaultBinding, e));
|
|
}
|
|
}
|
|
|
|
internal XmlElement ResolvePolicyReference(string policyReference, XmlElement contextPolicyAssertion)
|
|
{
|
|
return this.policyDictionary.ResolvePolicyReference(policyReference, contextPolicyAssertion);
|
|
}
|
|
|
|
class WsdlPolicyDictionary
|
|
{
|
|
readonly MetadataImporter importer;
|
|
readonly Dictionary<WsdlNS.ServiceDescription, Dictionary<string, XmlElement>> embeddedPolicyDictionary = new Dictionary<WsdlNS.ServiceDescription, Dictionary<string, XmlElement>>();
|
|
readonly Dictionary<string, XmlElement> externalPolicyDictionary = new Dictionary<string, XmlElement>();
|
|
readonly Dictionary<XmlElement, WsdlNS.ServiceDescription> policySourceTable = new Dictionary<XmlElement, WsdlNS.ServiceDescription>();
|
|
|
|
internal Dictionary<XmlElement, WsdlNS.ServiceDescription> PolicySourceTable
|
|
{
|
|
get { return policySourceTable; }
|
|
}
|
|
|
|
internal WsdlPolicyDictionary(WsdlImporter importer)
|
|
{
|
|
this.importer = importer;
|
|
|
|
//
|
|
// Embedded Policy documents
|
|
//
|
|
foreach (WsdlNS.ServiceDescription wsdl in importer.wsdlDocuments)
|
|
{
|
|
foreach (XmlElement element in WsdlPolicyReader.GetEmbeddedPolicy(wsdl))
|
|
{
|
|
AddEmbeddedPolicy(importer, wsdl, element);
|
|
}
|
|
}
|
|
|
|
//
|
|
// External Policy documents
|
|
//
|
|
foreach (KeyValuePair<string, XmlElement> policyDocument in importer.policyDocuments)
|
|
{
|
|
AddExternalPolicy(importer, policyDocument);
|
|
}
|
|
|
|
}
|
|
|
|
void AddEmbeddedPolicy(WsdlImporter importer, WsdlNS.ServiceDescription wsdl, XmlElement element)
|
|
{
|
|
string key = GetFragmentIdentifier(element);
|
|
if (String.IsNullOrEmpty(key))
|
|
{
|
|
string xPath = CreateXPathString(wsdl);
|
|
string warningMsg = SR.GetString(SR.PolicyInWsdlMustHaveFragmentId, xPath);
|
|
importer.LogImportWarning(warningMsg);
|
|
return;
|
|
}
|
|
|
|
Dictionary<string, XmlElement> wsdlPolicyDictionary;
|
|
if (!this.embeddedPolicyDictionary.TryGetValue(wsdl, out wsdlPolicyDictionary))
|
|
{
|
|
wsdlPolicyDictionary = new Dictionary<string, XmlElement>();
|
|
this.embeddedPolicyDictionary.Add(wsdl, wsdlPolicyDictionary);
|
|
}
|
|
else if (wsdlPolicyDictionary.ContainsKey(key))
|
|
{
|
|
string xPath = CreateIdXPath(wsdl, element, key);
|
|
string warningMsg = SR.GetString(SR.DuplicatePolicyInWsdlSkipped, xPath);
|
|
importer.LogImportWarning(warningMsg);
|
|
return;
|
|
}
|
|
|
|
wsdlPolicyDictionary.Add(key, element);
|
|
policySourceTable.Add(element, wsdl);
|
|
}
|
|
|
|
void AddExternalPolicy(WsdlImporter importer, KeyValuePair<string, XmlElement> policyDocument)
|
|
{
|
|
if (policyDocument.Value.NamespaceURI != MetadataStrings.WSPolicy.NamespaceUri
|
|
&& policyDocument.Value.NamespaceURI != MetadataStrings.WSPolicy.NamespaceUri15)
|
|
{
|
|
string warningMsg = SR.GetString(SR.UnrecognizedPolicyDocumentNamespace, policyDocument.Value.NamespaceURI);
|
|
importer.LogImportWarning(warningMsg);
|
|
return;
|
|
}
|
|
|
|
if (PolicyHelper.GetNodeType(policyDocument.Value) != PolicyHelper.NodeType.Policy)
|
|
{
|
|
string warningMsg = SR.GetString(SR.UnsupportedPolicyDocumentRoot, policyDocument.Value.Name);
|
|
importer.LogImportWarning(warningMsg);
|
|
return;
|
|
}
|
|
|
|
string key = CreateKeyFromPolicy(policyDocument.Key, policyDocument.Value);
|
|
if (externalPolicyDictionary.ContainsKey(key))
|
|
{
|
|
string warningMsg = SR.GetString(SR.DuplicatePolicyDocumentSkipped, key);
|
|
importer.LogImportWarning(warningMsg);
|
|
return;
|
|
}
|
|
|
|
this.externalPolicyDictionary.Add(key, policyDocument.Value);
|
|
}
|
|
|
|
internal XmlElement ResolvePolicyReference(string policyReference, XmlElement contextPolicyAssertion)
|
|
{
|
|
XmlElement policy;
|
|
|
|
if (policyReference[0] != '#')
|
|
{
|
|
externalPolicyDictionary.TryGetValue(policyReference, out policy);
|
|
return policy;
|
|
}
|
|
|
|
if (contextPolicyAssertion == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
WsdlNS.ServiceDescription sourceWsdl;
|
|
if (!policySourceTable.TryGetValue(contextPolicyAssertion, out sourceWsdl))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return ResolvePolicyReference(policyReference, sourceWsdl);
|
|
}
|
|
|
|
internal XmlElement ResolvePolicyReference(string policyReference, WsdlNS.ServiceDescription wsdlDocument)
|
|
{
|
|
XmlElement policy;
|
|
if (policyReference[0] != '#')
|
|
{
|
|
externalPolicyDictionary.TryGetValue(policyReference, out policy);
|
|
return policy;
|
|
}
|
|
|
|
Dictionary<string, XmlElement> wsdlPolicyDictionary;
|
|
if (!this.embeddedPolicyDictionary.TryGetValue(wsdlDocument, out wsdlPolicyDictionary))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
wsdlPolicyDictionary.TryGetValue(policyReference, out policy);
|
|
return policy;
|
|
}
|
|
|
|
static string CreateKeyFromPolicy(string identifier, XmlElement policyElement)
|
|
{
|
|
string policyId = GetFragmentIdentifier(policyElement);
|
|
string policyUri = string.Format(CultureInfo.InvariantCulture, "{0}{1}", identifier, policyId);
|
|
return policyUri;
|
|
}
|
|
|
|
static string GetFragmentIdentifier(XmlElement element)
|
|
{
|
|
return PolicyHelper.GetFragmentIdentifier(element);
|
|
}
|
|
|
|
static readonly string wspPolicy = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", MetadataStrings.WSPolicy.Prefix, MetadataStrings.WSPolicy.Elements.Policy);
|
|
static readonly string xmlId = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", MetadataStrings.Xml.Prefix, MetadataStrings.Xml.Attributes.Id);
|
|
static readonly string wsuId = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", MetadataStrings.Wsu.Prefix, MetadataStrings.Wsu.Attributes.Id);
|
|
|
|
internal string CreateIdXPath(XmlElement policyAssertion)
|
|
{
|
|
WsdlNS.ServiceDescription sourceWsdl;
|
|
if (!policySourceTable.TryGetValue(policyAssertion, out sourceWsdl))
|
|
{
|
|
return null;
|
|
}
|
|
string key = GetFragmentIdentifier(policyAssertion);
|
|
if (string.IsNullOrEmpty(key))
|
|
{
|
|
return null;
|
|
}
|
|
return CreateIdXPath(sourceWsdl, policyAssertion, key);
|
|
}
|
|
|
|
internal static string CreateIdXPath(WsdlNS.ServiceDescription wsdl, XmlElement element, string key)
|
|
{
|
|
string xPath = CreateXPathString(wsdl);
|
|
|
|
string idAttrib;
|
|
if (element.HasAttribute(MetadataStrings.Wsu.Attributes.Id, MetadataStrings.Wsu.NamespaceUri))
|
|
{
|
|
idAttrib = wsuId;
|
|
}
|
|
else if (element.HasAttribute(MetadataStrings.Xml.Attributes.Id, MetadataStrings.Xml.NamespaceUri))
|
|
{
|
|
idAttrib = xmlId;
|
|
}
|
|
else
|
|
{
|
|
Fx.Assert("CreateIdXPath always called with a valid key");
|
|
return null;
|
|
}
|
|
return string.Format(CultureInfo.InvariantCulture, "{0}/{1}/[@{2}='{3}']", xPath, wspPolicy, idAttrib, key);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
enum ErrorBehavior
|
|
{
|
|
RethrowExceptions,
|
|
DoNotThrowExceptions,
|
|
}
|
|
|
|
enum WsdlPortTypeImportOptions
|
|
{
|
|
ReuseExistingContracts,
|
|
IgnoreExistingContracts,
|
|
}
|
|
}
|
|
}
|