//
// MessageEncodingBindingElementImporter.cs
//
-// Author: Atsushi Enomoto (atsushi@ximian.com)
+// Author:
+// Martin Baulig <martin.baulig@xamarin.com>
//
-// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
public class MessageEncodingBindingElementImporter
: IWsdlImportExtension, IPolicyImportExtension
{
- [MonoTODO]
void IWsdlImportExtension.BeforeImport (
ServiceDescriptionCollection wsdlDocuments,
XmlSchemaSet xmlSchemas,
{
}
- [MonoTODO]
void IWsdlImportExtension.ImportContract (WsdlImporter importer,
WsdlContractConversionContext context)
{
}
- [MonoTODO]
void IWsdlImportExtension.ImportEndpoint (WsdlImporter importer,
WsdlEndpointConversionContext context)
{
}
- [MonoTODO]
void IPolicyImportExtension.ImportPolicy (MetadataImporter importer,
PolicyConversionContext context)
{
+ var assertions = context.GetBindingAssertions ();
+
+ var mtom = PolicyImportHelper.GetMtomMessageEncodingPolicy (assertions);
+ if (mtom != null) {
+ // http://www.w3.org/Submission/WS-MTOMPolicy/
+ context.BindingElements.Add (new MtomMessageEncodingBindingElement ());
+ return;
+ }
+
+ var binary = PolicyImportHelper.GetBinaryMessageEncodingPolicy (assertions);
+ if (binary != null) {
+ context.BindingElements.Add (new BinaryMessageEncodingBindingElement ());
+ return;
+ }
+
+ context.BindingElements.Add (new TextMessageEncodingBindingElement ());
}
}
}
--- /dev/null
+//
+// PolicyImportHelper.cs
+//
+// Author:
+// Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Xml;
+using System.Collections.Generic;
+using System.ServiceModel.Description;
+
+using QName = System.Xml.XmlQualifiedName;
+
+namespace System.ServiceModel.Channels {
+
+ internal static class PolicyImportHelper {
+
+ internal const string SecurityPolicyNS = "http://schemas.xmlsoap.org/ws/2005/07/securitypolicy";
+ internal const string PolicyNS = "http://schemas.xmlsoap.org/ws/2004/09/policy";
+ internal const string MimeSerializationNS = "http://schemas.xmlsoap.org/ws/2004/09/policy/optimizedmimeserialization";
+ internal const string HttpAuthNS = "http://schemas.microsoft.com/ws/06/2004/policy/http";
+
+ internal const string FramingPolicyNS = "http://schemas.microsoft.com/ws/2006/05/framing/policy";
+ internal const string NetBinaryEncodingNS = "http://schemas.microsoft.com/ws/06/2004/mspolicy/netbinary1";
+
+ internal static XmlElement GetTransportBindingPolicy (PolicyAssertionCollection collection)
+ {
+ return FindAndRemove (collection, "TransportBinding", SecurityPolicyNS);
+ }
+
+ internal static XmlElement GetStreamedMessageFramingPolicy (PolicyAssertionCollection collection)
+ {
+ return FindAndRemove (collection, "Streamed", FramingPolicyNS);
+ }
+
+ internal static XmlElement GetBinaryMessageEncodingPolicy (PolicyAssertionCollection collection)
+ {
+ return FindAndRemove (collection, "BinaryEncoding", NetBinaryEncodingNS);
+ }
+
+ internal static XmlElement GetMtomMessageEncodingPolicy (PolicyAssertionCollection collection)
+ {
+ return FindAndRemove (collection, "OptimizedMimeSerialization", MimeSerializationNS);
+ }
+
+ static XmlElement FindAndRemove (PolicyAssertionCollection collection, string name, string ns)
+ {
+ var element = collection.Find (name, ns);
+ if (element != null)
+ collection.Remove (element);
+ return element;
+ }
+
+ internal static List<XmlElement> FindAssertionByNS (
+ PolicyAssertionCollection collection, string ns)
+ {
+ var list = new List<XmlElement> ();
+ foreach (var assertion in collection) {
+ if (assertion.NamespaceURI.Equals (ns))
+ list.Add (assertion);
+ }
+ return list;
+ }
+
+ internal static List<XmlElement> GetPolicyElements (XmlElement root, out bool error)
+ {
+ XmlElement policy = null;
+ var list = new List<XmlElement> ();
+
+ foreach (var node in root.ChildNodes) {
+ var e = node as XmlElement;
+ if (e == null)
+ continue;
+ if (!PolicyNS.Equals (e.NamespaceURI) || !e.LocalName.Equals ("Policy")) {
+ error = true;
+ return list;
+ }
+ if (policy != null) {
+ error = true;
+ return list;
+ }
+ policy = e;
+ }
+
+ if (policy == null) {
+ error = true;
+ return list;
+ }
+
+ foreach (var node in policy.ChildNodes) {
+ var e = node as XmlElement;
+ if (e != null)
+ list.Add (e);
+ }
+
+ error = false;
+ return list;
+ }
+
+ internal static bool FindPolicyElement (MetadataImporter importer, XmlElement root,
+ QName name, bool required, bool removeWhenFound,
+ out XmlElement element)
+ {
+ if (!FindPolicyElement (root, name, removeWhenFound, out element)) {
+ importer.AddWarning ("Invalid policy element: {0}", root.OuterXml);
+ return false;
+ }
+ if (required && (element == null)) {
+ importer.AddWarning ("Did not find policy element `{0}'.", name);
+ return false;
+ }
+ return true;
+ }
+
+ internal static bool FindPolicyElement (XmlElement root, QName name,
+ bool removeWhenFound, out XmlElement element)
+ {
+ XmlElement policy = null;
+ foreach (var node in root.ChildNodes) {
+ var e = node as XmlElement;
+ if (e == null)
+ continue;
+ if (!PolicyNS.Equals (e.NamespaceURI) || !e.LocalName.Equals ("Policy")) {
+ element = null;
+ return false;
+ }
+ if (policy != null) {
+ element = null;
+ return false;
+ }
+ policy = e;
+ }
+
+ if (policy == null) {
+ element = null;
+ return true;
+ }
+
+ element = null;
+ foreach (var node in policy.ChildNodes) {
+ var e = node as XmlElement;
+ if (e == null)
+ continue;
+ if (!name.Namespace.Equals (e.NamespaceURI) || !name.Name.Equals (e.LocalName))
+ continue;
+
+ element = e;
+ break;
+ }
+
+ if (!removeWhenFound || (element == null))
+ return true;
+
+ policy.RemoveChild (element);
+
+ bool foundAnother = false;
+ foreach (var node in policy.ChildNodes) {
+ var e = node as XmlElement;
+ if (e != null) {
+ foundAnother = true;
+ break;
+ }
+ }
+
+ if (!foundAnother)
+ root.RemoveChild (policy);
+ return true;
+ }
+
+ internal static XmlElement GetElement (MetadataImporter importer,
+ XmlElement root, string name, string ns)
+ {
+ return GetElement (importer, root, name, ns, false);
+ }
+
+ internal static XmlElement GetElement (MetadataImporter importer,
+ XmlElement root, string name, string ns,
+ bool required)
+ {
+ return GetElement (importer, root, new QName (name, ns), required);
+ }
+
+ internal static XmlElement GetElement (MetadataImporter importer,
+ XmlElement root, QName name, bool required)
+ {
+ var list = root.GetElementsByTagName (name.Name, name.Namespace);
+ if (list.Count < 1) {
+ if (required)
+ importer.AddWarning ("Did not find required policy element `{0}'", name);
+ return null;
+ }
+
+ if (list.Count > 1) {
+ importer.AddWarning ("Found duplicate policy element `{0}'", name);
+ return null;
+ }
+
+ var element = list [0] as XmlElement;
+ if (required && (element == null))
+ importer.AddWarning ("Did not find required policy element `{0}'", name);
+ return element;
+ }
+ }
+}
+
// StandardBindingImporter.cs
//
// Author:
-// Atsushi Enomoto <atsushi@ximian.com>
+// Martin Baulig <martin.baulig@xamarin.com>
//
-// Copyright (C) 2005 Novell, Inc. http://www.novell.com
+// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
using System;
-using System.Collections.Generic;
-using System.ServiceModel.Description;
-using System.Web.Services.Description;
+using System.Net;
using System.Xml;
using System.Xml.Schema;
+using System.Collections.Generic;
+using System.ServiceModel;
+using System.ServiceModel.Channels;
+using System.ServiceModel.Description;
+
+using WS = System.Web.Services.Description;
+using QName = System.Xml.XmlQualifiedName;
+
+namespace System.ServiceModel.Channels {
+
+ public class StandardBindingImporter : IWsdlImportExtension {
+ #region IWsdlImportExtension implementation
+
+ public void BeforeImport (WS.ServiceDescriptionCollection wsdlDocuments, XmlSchemaSet xmlSchemas,
+ ICollection<XmlElement> policy)
+ {
+ }
+
+ public void ImportContract (WsdlImporter importer, WsdlContractConversionContext contractContext)
+ {
+ }
+
+ WS.Port LookupPort (WsdlImporter importer, QName name)
+ {
+ foreach (WS.ServiceDescription doc in importer.WsdlDocuments) {
+ foreach (WS.Service service in doc.Services) {
+ foreach (WS.Port port in service.Ports) {
+ if (!name.Namespace.Equals (port.Binding.Namespace))
+ continue;
+ if (!name.Name.Equals (port.Binding.Name))
+ continue;
+ return port;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public void ImportEndpoint (WsdlImporter importer, WsdlEndpointConversionContext context)
+ {
+ var custom = context.Endpoint.Binding as CustomBinding;
+ if (custom == null)
+ return;
+
+ var soapHttp = GetHttpSoapBinding (context.WsdlBinding);
+ if (soapHttp != null) {
+ ImportBasicHttpBinding (importer, context, custom, soapHttp);
+ return;
+ }
+
+ var soapTcp = GetTcpSoapBinding (context.WsdlBinding);
+ if (soapTcp != null) {
+ ImportNetTcpBinding (importer, context, custom, soapTcp);
+ return;
+ }
+ }
-namespace System.ServiceModel.Channels
-{
- [MonoTODO]
- public class StandardBindingImporter : IWsdlImportExtension
- {
- [MonoTODO]
- void IWsdlImportExtension.BeforeImport (
- ServiceDescriptionCollection wsdlDocuments,
- XmlSchemaSet xmlSchemas,
- ICollection<XmlElement> policy)
+ internal static WS.SoapBinding GetHttpSoapBinding (WS.Binding binding)
{
+ WS.SoapBinding soap = null;
+ foreach (var extension in binding.Extensions) {
+ var check = extension as WS.SoapBinding;
+ if (check != null) {
+ soap = check;
+ break;
+ }
+ }
+
+ if (soap == null)
+ return null;
+ if (soap.Transport != WS.SoapBinding.HttpTransport)
+ return null;
+ if (soap.Style != WS.SoapBindingStyle.Document)
+ return null;
+ return soap;
}
- [MonoTODO]
- void IWsdlImportExtension.ImportContract (WsdlImporter importer,
- WsdlContractConversionContext context)
+ const string TcpTransport = "http://schemas.microsoft.com/soap/tcp";
+
+ internal static WS.Soap12Binding GetTcpSoapBinding (WS.Binding binding)
{
+ WS.Soap12Binding soap = null;
+ foreach (var extension in binding.Extensions) {
+ var check = extension as WS.Soap12Binding;
+ if (check != null) {
+ soap = check;
+ break;
+ }
+ }
+
+ if (soap == null)
+ return null;
+ if (soap.Transport != TcpTransport)
+ return null;
+ if (soap.Style != WS.SoapBindingStyle.Document)
+ return null;
+ return soap;
}
- [MonoTODO]
- void IWsdlImportExtension.ImportEndpoint (WsdlImporter importer,
- WsdlEndpointConversionContext context)
+ bool ImportBasicHttpBinding (
+ WsdlImporter importer, WsdlEndpointConversionContext context,
+ CustomBinding custom, WS.SoapBinding soap)
{
+ TransportBindingElement transportElement = null;
+ MtomMessageEncodingBindingElement mtomElement = null;
+ TextMessageEncodingBindingElement textElement = null;
+ bool foundUnknownElement = false;
+
+ foreach (var element in custom.Elements) {
+ if (element is TransportBindingElement)
+ transportElement = (TransportBindingElement)element;
+ else if (element is MtomMessageEncodingBindingElement)
+ mtomElement = (MtomMessageEncodingBindingElement)element;
+ else if (element is TextMessageEncodingBindingElement)
+ textElement = (TextMessageEncodingBindingElement)element;
+ else {
+ importer.AddWarning (
+ "Found unknown binding element `{0}' while attempting " +
+ "to import binding `{0}'.", element.GetType (),
+ custom.Name);
+ foundUnknownElement = true;
+ }
+ }
+
+ if (foundUnknownElement)
+ return false;
+
+ if ((mtomElement != null) && (textElement != null)) {
+ // FIXME: Should never happen
+ importer.AddWarning (
+ "Found both MtomMessageEncodingBindingElement and " +
+ "TextMessageEncodingBindingElement while attempting to " +
+ "import binding `{0}'.", custom.Name);
+ return false;
+ }
+
+ BasicHttpBinding httpBinding;
+ AuthenticationSchemes authScheme;
+
+ /*
+ * FIXME: Maybe make the BasicHttpBinding use the transport element
+ * that we created with the TransportBindingElementImporter ?
+ *
+ * There seems to be no public API to do that, so maybe add a private .ctor ?
+ *
+ */
+
+ var httpsTransport = transportElement as HttpsTransportBindingElement;
+ var httpTransport = transportElement as HttpTransportBindingElement;
+
+ if (httpsTransport != null) {
+ httpBinding = new BasicHttpBinding (BasicHttpSecurityMode.Transport);
+ authScheme = httpsTransport.AuthenticationScheme;
+ } else if (httpTransport != null) {
+ authScheme = httpTransport.AuthenticationScheme;
+ if ((authScheme != AuthenticationSchemes.None) &&
+ (authScheme != AuthenticationSchemes.Anonymous))
+ httpBinding = new BasicHttpBinding (
+ BasicHttpSecurityMode.TransportCredentialOnly);
+ else
+ httpBinding = new BasicHttpBinding ();
+ } else {
+ httpBinding = new BasicHttpBinding ();
+ authScheme = AuthenticationSchemes.Anonymous;
+ }
+
+ if (mtomElement != null)
+ httpBinding.MessageEncoding = WSMessageEncoding.Mtom;
+ else if (textElement != null)
+ httpBinding.MessageEncoding = WSMessageEncoding.Text;
+ else {
+ importer.AddWarning (
+ "Found neither MtomMessageEncodingBindingElement nor " +
+ "TextMessageEncodingBindingElement while attempting to " +
+ "import binding `{0}'.", custom.Name);
+ return false;
+ }
+
+ httpBinding.Name = context.Endpoint.Binding.Name;
+ httpBinding.Namespace = context.Endpoint.Binding.Namespace;
+
+ switch (authScheme) {
+ case AuthenticationSchemes.None:
+ case AuthenticationSchemes.Anonymous:
+ httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
+ break;
+ case AuthenticationSchemes.Basic:
+ httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
+ break;
+ case AuthenticationSchemes.Digest:
+ httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Digest;
+ break;
+ case AuthenticationSchemes.Ntlm:
+ httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
+ break;
+ case AuthenticationSchemes.Negotiate:
+ httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
+ break;
+ default:
+ importer.AddWarning ("Invalid auth scheme: {0}", authScheme);
+ return false;
+ }
+
+ if ((httpsTransport != null) && httpsTransport.RequireClientCertificate) {
+ if (httpBinding.Security.Transport.ClientCredentialType != HttpClientCredentialType.None) {
+ importer.AddWarning ("Cannot use both client certificate and explicit auth type.");
+ return false;
+ }
+ httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
+ }
+
+ context.Endpoint.Binding = httpBinding;
+ return true;
}
+
+ bool ImportNetTcpBinding (
+ WsdlImporter importer, WsdlEndpointConversionContext context,
+ CustomBinding custom, WS.Soap12Binding soap)
+ {
+ TcpTransportBindingElement transportElement = null;
+ BinaryMessageEncodingBindingElement binaryElement = null;
+ TransactionFlowBindingElement transactionFlowElement = null;
+ WindowsStreamSecurityBindingElement windowsStreamElement = null;
+ SslStreamSecurityBindingElement sslStreamElement = null;
+ bool foundUnknownElement = false;
+
+ foreach (var element in custom.Elements) {
+ if (element is TcpTransportBindingElement)
+ transportElement = (TcpTransportBindingElement)element;
+ else if (element is BinaryMessageEncodingBindingElement)
+ binaryElement = (BinaryMessageEncodingBindingElement)element;
+ else if (element is TransactionFlowBindingElement)
+ transactionFlowElement = (TransactionFlowBindingElement)element;
+ else if (element is WindowsStreamSecurityBindingElement)
+ windowsStreamElement = (WindowsStreamSecurityBindingElement)element;
+ else if (element is SslStreamSecurityBindingElement)
+ sslStreamElement = (SslStreamSecurityBindingElement)element;
+ else {
+ importer.AddWarning (
+ "Found unknown binding element `{0}' while importing " +
+ "binding `{1}'.", element.GetType (), custom.Name);
+ foundUnknownElement = true;
+ }
+ }
+
+ if (foundUnknownElement)
+ return false;
+
+ if (transportElement == null) {
+ importer.AddWarning (
+ "Missing TcpTransportBindingElement while importing " +
+ "binding `{0}'.", custom.Name);
+ return false;
+ }
+ if (binaryElement == null) {
+ importer.AddWarning (
+ "Missing BinaryMessageEncodingBindingElement while importing " +
+ "binding `{0}'.", custom.Name);
+ return false;
+ }
+
+ if ((windowsStreamElement != null) && (sslStreamElement != null)) {
+ importer.AddWarning (
+ "Found both WindowsStreamSecurityBindingElement and " +
+ "SslStreamSecurityBindingElement while importing binding `{0}.",
+ custom.Name);
+ return false;
+ }
+
+ NetTcpSecurity security;
+ if (windowsStreamElement != null) {
+ security = new NetTcpSecurity (SecurityMode.Transport);
+ security.Transport.ProtectionLevel = windowsStreamElement.ProtectionLevel;
+ } else if (sslStreamElement != null) {
+ security = new NetTcpSecurity (SecurityMode.TransportWithMessageCredential);
+ } else {
+ security = new NetTcpSecurity (SecurityMode.None);
+ }
+
+ var netTcp = new NetTcpBinding (transportElement, security, false);
+
+ netTcp.Name = context.Endpoint.Binding.Name;
+ netTcp.Namespace = context.Endpoint.Binding.Namespace;
+
+ context.Endpoint.Binding = netTcp;
+ return true;
+ }
+
+ #endregion
}
}
+
// TransportBindingElementImporter.cs
//
// Author:
-// Atsushi Enomoto <atsushi@ximian.com>
+// Martin Baulig <martin.baulig@xamarin.com>
//
-// Copyright (C) 2005 Novell, Inc. http://www.novell.com
+// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
using System;
+using System.Net;
+using System.Net.Security;
+using System.Xml;
+using System.Xml.Schema;
using System.Collections.Generic;
-using System.Runtime.Serialization;
using System.ServiceModel;
-using System.ServiceModel.Configuration;
+using System.ServiceModel.Channels;
using System.ServiceModel.Description;
-using System.Web.Services.Description;
-using System.Xml;
-using System.Xml.Schema;
-namespace System.ServiceModel.Channels
-{
- [MonoTODO]
- public class TransportBindingElementImporter
- : IWsdlImportExtension, IPolicyImportExtension
- {
- public TransportBindingElementImporter ()
+using WS = System.Web.Services.Description;
+using QName = System.Xml.XmlQualifiedName;
+
+namespace System.ServiceModel.Channels {
+
+ public class TransportBindingElementImporter : IWsdlImportExtension, IPolicyImportExtension {
+ #region IWsdlImportExtension implementation
+
+ public void BeforeImport (WS.ServiceDescriptionCollection wsdlDocuments, XmlSchemaSet xmlSchemas,
+ ICollection<XmlElement> policy)
+ {
+ }
+
+ public void ImportContract (WsdlImporter importer, WsdlContractConversionContext contractContext)
+ {
+ }
+
+ public void ImportEndpoint (WsdlImporter importer, WsdlEndpointConversionContext context)
{
+ // Only import the binding, not the endpoint.
+ if (context.WsdlPort == null)
+ return;
+
+ DoImportEndpoint (context);
}
- void IWsdlImportExtension.BeforeImport (ServiceDescriptionCollection wsdlDocuments,
- XmlSchemaSet xmlSchemas, ICollection<XmlElement> policy)
+ bool DoImportEndpoint (WsdlEndpointConversionContext context)
{
+ if (ImportBasicHttpEndpoint (context))
+ return true;
+ if (ImportNetTcpEndpoint (context))
+ return true;
+ return false;
}
- void IWsdlImportExtension.ImportContract (WsdlImporter importer,
- WsdlContractConversionContext context)
+ bool ImportBasicHttpEndpoint (WsdlEndpointConversionContext context)
{
+ var http = context.Endpoint.Binding as BasicHttpBinding;
+ if (http == null)
+ return false;
+
+ WS.SoapAddressBinding address = null;
+ foreach (var extension in context.WsdlPort.Extensions) {
+ var check = extension as WS.SoapAddressBinding;
+ if (check != null) {
+ address = check;
+ break;
+ }
+ }
+
+ if (address == null)
+ return false;
+
+ context.Endpoint.Address = new EndpointAddress (address.Location);
+ context.Endpoint.ListenUri = new Uri (address.Location);
+ context.Endpoint.ListenUriMode = ListenUriMode.Explicit;
+ return true;
+ }
+
+ bool ImportNetTcpEndpoint (WsdlEndpointConversionContext context)
+ {
+ var tcp = context.Endpoint.Binding as NetTcpBinding;
+ if (tcp == null)
+ return false;
+
+ WS.Soap12AddressBinding address = null;
+ foreach (var extension in context.WsdlPort.Extensions) {
+ var check = extension as WS.Soap12AddressBinding;
+ if (check != null) {
+ address = check;
+ break;
+ }
+ }
+
+ if (address == null)
+ return false;
+
+ context.Endpoint.Address = new EndpointAddress (address.Location);
+ context.Endpoint.ListenUri = new Uri (address.Location);
+ context.Endpoint.ListenUriMode = ListenUriMode.Explicit;
+ return true;
}
- void IWsdlImportExtension.ImportEndpoint(WsdlImporter importer,
- WsdlEndpointConversionContext context)
+ #endregion
+
+ #region IPolicyImportExtension implementation
+
+ public void ImportPolicy (MetadataImporter importer, PolicyConversionContext context)
{
- for (int i = 0; i < context.WsdlBinding.Extensions.Count; i ++) {
- if (context.WsdlBinding.Extensions [i] is SoapBinding) {
- SoapBinding transport = context.WsdlBinding.Extensions [i] as SoapBinding;
- if (transport.Transport != SoapBinding.HttpTransport)
- //FIXME: not http
- return;
+ var customCtx = context as CustomPolicyConversionContext;
+ var customBinding = context.Endpoint.Binding as CustomBinding;
+ if ((customCtx == null) || (customBinding == null))
+ // FIXME: Should we allow this ?
+ throw new InvalidOperationException ();
+
+ var soapHttp = StandardBindingImporter.GetHttpSoapBinding (customCtx.WsdlBinding);
+ if (soapHttp != null) {
+ if (!ImportHttpPolicy (importer, customCtx, soapHttp))
+ context.BindingElements.Add (new HttpTransportBindingElement ());
+ return;
+ }
+
+ var soapTcp = StandardBindingImporter.GetTcpSoapBinding (customCtx.WsdlBinding);
+ if (soapTcp != null) {
+ if (!ImportTcpPolicy (importer, customCtx, soapTcp))
+ context.BindingElements.Add (new TcpTransportBindingElement ());
+ return;
+ }
+ }
+
+ #endregion
- if (! (context.Endpoint.Binding is CustomBinding))
- //FIXME:
- throw new Exception ();
+ bool ImportHttpAuthScheme (MetadataImporter importer,
+ HttpTransportBindingElement bindingElement,
+ PolicyConversionContext context)
+ {
+ var assertions = context.GetBindingAssertions ();
+ var authSchemes = AuthenticationSchemes.None;
- ((CustomBinding) context.Endpoint.Binding).Elements.Add (new HttpTransportBindingElement ());
- //((CustomBinding) context.Endpoint.Binding).Scheme = "http";
+ var httpsTransport = bindingElement as HttpsTransportBindingElement;
+ bool certificate = httpsTransport != null ?
+ httpsTransport.RequireClientCertificate : false;
- for (int j = 0; j < context.WsdlPort.Extensions.Count; j ++) {
- SoapAddressBinding address = context.WsdlPort.Extensions [j] as SoapAddressBinding;
- if (address == null)
- continue;
+ var authElements = PolicyImportHelper.FindAssertionByNS (
+ assertions, PolicyImportHelper.HttpAuthNS);
+ foreach (XmlElement authElement in authElements) {
+ assertions.Remove (authElement);
- context.Endpoint.Address = new EndpointAddress (address.Location);
- context.Endpoint.ListenUri = new Uri (address.Location);
- }
+ if (certificate) {
+ importer.AddWarning (
+ "Invalid authentication assertion while " +
+ "using client certificate: {0}", authElement.OuterXml);
+ return false;
+ }
+ switch (authElement.LocalName) {
+ case "BasicAuthentication":
+ authSchemes |= AuthenticationSchemes.Basic;
+ break;
+ case "NtlmAuthentication":
+ authSchemes |= AuthenticationSchemes.Ntlm;
break;
+ case "DigestAuthentication":
+ authSchemes |= AuthenticationSchemes.Digest;
+ break;
+ case "NegotiateAuthentication":
+ authSchemes |= AuthenticationSchemes.Negotiate;
+ break;
+ default:
+ importer.AddWarning (
+ "Invalid policy assertion: {0}", authElement.OuterXml);
+ return false;
}
}
+
+ bindingElement.AuthenticationScheme = authSchemes;
+ return true;
+ }
+
+ bool ImportWindowsTransportSecurity (MetadataImporter importer,
+ PolicyConversionContext context,
+ XmlElement policyElement)
+ {
+ var protectionLevel = PolicyImportHelper.GetElement (
+ importer, policyElement, "ProtectionLevel",
+ PolicyImportHelper.FramingPolicyNS, true);
+ if (protectionLevel == null) {
+ importer.AddWarning (
+ "Invalid policy assertion: {0}", policyElement.OuterXml);
+ return false;
+ }
+
+ var element = new WindowsStreamSecurityBindingElement ();
+
+ switch (protectionLevel.InnerText.ToLowerInvariant ()) {
+ case "none":
+ element.ProtectionLevel = ProtectionLevel.None;
+ break;
+ case "sign":
+ element.ProtectionLevel = ProtectionLevel.Sign;
+ break;
+ case "encryptandsign":
+ element.ProtectionLevel = ProtectionLevel.EncryptAndSign;
+ break;
+ default:
+ importer.AddWarning (
+ "Invalid policy assertion: {0}", protectionLevel.OuterXml);
+ return false;
+ }
+
+ context.BindingElements.Add (element);
+ return true;
+ }
+
+ bool ImportTransport (MetadataImporter importer, TransportBindingElement bindingElement,
+ XmlElement transportPolicy)
+ {
+ XmlElement algorithmSuite, layout;
+ if (!PolicyImportHelper.FindPolicyElement (
+ importer, transportPolicy,
+ new QName ("AlgorithmSuite", PolicyImportHelper.SecurityPolicyNS),
+ false, true, out algorithmSuite) ||
+ !PolicyImportHelper.FindPolicyElement (
+ importer, transportPolicy,
+ new QName ("Layout", PolicyImportHelper.SecurityPolicyNS),
+ false, true, out layout))
+ return false;
+
+ bool foundUnknown = false;
+ foreach (var node in transportPolicy.ChildNodes) {
+ var e = node as XmlElement;
+ if (e == null)
+ continue;
+ importer.AddWarning ("Unknown policy assertion: {0}", e.OuterXml);
+ foundUnknown = true;
+ }
+
+ return !foundUnknown;
+ }
+
+ bool GetTransportToken (MetadataImporter importer, XmlElement transportPolicy,
+ out XmlElement transportToken)
+ {
+ return PolicyImportHelper.FindPolicyElement (
+ importer, transportPolicy,
+ new QName ("TransportToken", PolicyImportHelper.SecurityPolicyNS),
+ false, true, out transportToken);
+ }
+
+ bool ImportHttpTransport (MetadataImporter importer, PolicyConversionContext context,
+ XmlElement transportPolicy,
+ out HttpTransportBindingElement bindingElement)
+ {
+ XmlElement transportToken;
+ if (!GetTransportToken (importer, transportPolicy, out transportToken)) {
+ bindingElement = null;
+ return false;
+ }
+
+ if (transportToken == null) {
+ bindingElement = new HttpTransportBindingElement ();
+ return true;
+ }
+
+ bool error;
+ var tokenElementList = PolicyImportHelper.GetPolicyElements (transportToken, out error);
+ if (error || (tokenElementList.Count != 1)) {
+ importer.AddWarning ("Invalid policy assertion: {0}", transportToken.OuterXml);
+ bindingElement = null;
+ return false;
+ }
+
+ var tokenElement = tokenElementList [0];
+ if (!PolicyImportHelper.SecurityPolicyNS.Equals (tokenElement.NamespaceURI) ||
+ !tokenElement.LocalName.Equals ("HttpsToken")) {
+ importer.AddWarning ("Invalid policy assertion: {0}", tokenElement.OuterXml);
+ bindingElement = null;
+ return false;
+ }
+
+ var httpsTransport = new HttpsTransportBindingElement ();
+ bindingElement = httpsTransport;
+
+ var certAttr = tokenElement.GetAttribute ("RequireClientCertificate");
+ if (!String.IsNullOrEmpty (certAttr))
+ httpsTransport.RequireClientCertificate = Boolean.Parse (certAttr);
+ return true;
+ }
+
+ bool ImportTcpTransport (MetadataImporter importer, PolicyConversionContext context,
+ XmlElement transportPolicy)
+ {
+ XmlElement transportToken;
+ if (!GetTransportToken (importer, transportPolicy, out transportToken))
+ return false;
+
+ if (transportToken == null)
+ return true;
+
+ bool error;
+ var tokenElementList = PolicyImportHelper.GetPolicyElements (transportToken, out error);
+ if (error || (tokenElementList.Count != 1)) {
+ importer.AddWarning ("Invalid policy assertion: {0}", transportToken.OuterXml);
+ return false;
+ }
+
+ var tokenElement = tokenElementList [0];
+ if (!PolicyImportHelper.FramingPolicyNS.Equals (tokenElement.NamespaceURI)) {
+ importer.AddWarning ("Invalid policy assertion: {0}", tokenElement.OuterXml);
+ return false;
+ }
+
+ if (tokenElement.LocalName.Equals ("WindowsTransportSecurity")) {
+ if (!ImportWindowsTransportSecurity (importer, context, tokenElement))
+ return false;
+ } else if (tokenElement.LocalName.Equals ("SslTransportSecurity")) {
+ context.BindingElements.Add (new SslStreamSecurityBindingElement ());
+ }
+
+ return true;
}
- void IPolicyImportExtension.ImportPolicy (MetadataImporter importer,
- PolicyConversionContext context)
+ bool ImportHttpPolicy (MetadataImporter importer, PolicyConversionContext context,
+ WS.SoapBinding soap)
{
- throw new NotImplementedException ();
+ HttpTransportBindingElement httpTransport;
+ var assertions = context.GetBindingAssertions ();
+ var transportPolicy = PolicyImportHelper.GetTransportBindingPolicy (assertions);
+ if (transportPolicy != null) {
+ if (!ImportHttpTransport (importer, context, transportPolicy, out httpTransport))
+ return false;
+ if (!ImportTransport (importer, httpTransport, transportPolicy))
+ return false;
+ } else {
+ httpTransport = new HttpTransportBindingElement ();
+ }
+
+ if (!ImportHttpAuthScheme (importer, httpTransport, context))
+ return false;
+
+ context.BindingElements.Add (httpTransport);
+ return true;
+ }
+
+ bool ImportTcpPolicy (MetadataImporter importer, PolicyConversionContext context,
+ WS.Soap12Binding soap)
+ {
+ var assertions = context.GetBindingAssertions ();
+
+ var tcpTransport = new TcpTransportBindingElement ();
+
+ var transportPolicy = PolicyImportHelper.GetTransportBindingPolicy (assertions);
+ if (transportPolicy != null) {
+ if (!ImportTcpTransport (importer, context, transportPolicy))
+ return false;
+ if (!ImportTransport (importer, tcpTransport, transportPolicy))
+ return false;
+ }
+
+ var streamed = PolicyImportHelper.GetStreamedMessageFramingPolicy (assertions);
+ if (streamed != null)
+ tcpTransport.TransferMode = TransferMode.Streamed;
+
+ context.BindingElements.Add (tcpTransport);
+ return true;
}
}
}
--- /dev/null
+//
+// CustomPolicyConversionContext.cs
+//
+// Author:
+// Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Xml;
+using System.ServiceModel.Channels;
+using WS = System.Web.Services.Description;
+
+namespace System.ServiceModel.Description {
+
+ internal class CustomPolicyConversionContext : PolicyConversionContext {
+ WS.Binding binding;
+ PolicyAssertionCollection assertions;
+ BindingElementCollection binding_elements;
+
+ internal WS.Binding WsdlBinding {
+ get { return binding; }
+ }
+
+ #region implemented abstract members of PolicyConversionContext
+
+ public override PolicyAssertionCollection GetBindingAssertions ()
+ {
+ return assertions;
+ }
+
+ public override PolicyAssertionCollection GetFaultBindingAssertions (FaultDescription fault)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override PolicyAssertionCollection GetMessageBindingAssertions (MessageDescription message)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override PolicyAssertionCollection GetOperationBindingAssertions (OperationDescription operation)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override BindingElementCollection BindingElements {
+ get {
+ return binding_elements;
+ }
+ }
+
+ #endregion
+
+ public CustomPolicyConversionContext (WS.Binding binding, ServiceEndpoint endpoint)
+ : base (endpoint)
+ {
+ this.binding = binding;
+ assertions = new PolicyAssertionCollection ();
+ binding_elements = ((CustomBinding)endpoint.Binding).Elements;
+ }
+
+ public void AddPolicyAssertion (XmlElement element)
+ {
+ /*
+ * http://www.w3.org/Submission/WS-Policy/#Policy_Assertion:
+ *
+ * <wsp:Policy … >
+ * <wsp:ExactlyOne>
+ * ( <wsp:All> ( <Assertion …> … </Assertion> )* </wsp:All> )*
+ * </wsp:ExactlyOne>
+ * </wsp:Policy>
+ *
+ */
+
+ var exactlyOne = element.FirstChild as XmlElement;
+ if (exactlyOne == null) {
+ // OOPS
+ return;
+ }
+
+ if (!exactlyOne.NamespaceURI.Equals (Constants.WspNamespace) ||
+ !exactlyOne.LocalName.Equals ("ExactlyOne")) {
+ // FIXME: What to do with this ... ?
+ return;
+ }
+
+ foreach (var node in exactlyOne.ChildNodes) {
+ var child = node as XmlElement;
+ if (child == null)
+ continue;
+
+ if (!child.NamespaceURI.Equals (Constants.WspNamespace) ||
+ !child.LocalName.Equals ("All")) {
+ // FIXME: Can assertions go here ... ?
+ continue;
+ }
+
+ foreach (var node2 in child.ChildNodes) {
+ var assertion = node2 as XmlElement;
+ if (assertion == null)
+ continue;
+
+ assertions.Add (assertion);
+ }
+ }
+ }
+ }
+}
+
policy_extensions.Add (new MessageEncodingBindingElementImporter ());
}
- [MonoTODO ("Not in use yet")]
public Collection<MetadataConversionError> Errors {
get { return errors; }
}
}
return (T) value;
}
+
+ internal MetadataConversionError AddError (string message, params object[] args)
+ {
+ var error = new MetadataConversionError (string.Format (message, args));
+ Errors.Add (error);
+ return error;
+ }
+
+ internal MetadataConversionError AddWarning (string message, params object[] args)
+ {
+ var error = new MetadataConversionError (string.Format (message, args), true);
+ Errors.Add (error);
+ return error;
+ }
+
+ internal class MetadataImportException : Exception
+ {
+ public MetadataConversionError Error {
+ get;
+ private set;
+ }
+
+ public MetadataImportException (MetadataConversionError error)
+ : base (error.Message)
+ {
+ this.Error = error;
+ }
+
+ public MetadataImportException (MetadataConversionError error, Exception inner)
+ : base (error.Message, inner)
+ {
+ this.Error = error;
+ }
+ }
+
}
}
{
public abstract class PolicyConversionContext
{
+ ServiceEndpoint endpoint;
+
protected PolicyConversionContext (ServiceEndpoint endpoint)
{
+ this.endpoint = endpoint;
+ }
+
+ internal ServiceEndpoint Endpoint {
+ get { return endpoint; }
}
public abstract BindingElementCollection BindingElements { get; }
public ContractDescription Contract {
- get { throw new NotImplementedException (); }
+ get { return endpoint.Contract; }
}
public abstract PolicyAssertionCollection GetBindingAssertions ();
//
// WsdlImporter.cs
//
-// Author:
+// Authors:
// Atsushi Enomoto <atsushi@ximian.com>
// Ankit Jain <jankit@novell.com>
+// Martin Baulig <martin.baulig@xamarin.com>
//
// Copyright (C) 2005 Novell, Inc. http://www.novell.com
+// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
using System.Xml.Schema;
using SMBinding = System.ServiceModel.Channels.Binding;
+using WS = System.Web.Services.Description;
using WSServiceDescription = System.Web.Services.Description.ServiceDescription;
using WSBinding = System.Web.Services.Description.Binding;
using WSMessage = System.Web.Services.Description.Message;
XmlSchemaSet xmlschemas;
List<XmlElement> policies; /* ?? */
MetadataSet metadata;
+ bool beforeImportCalled;
KeyedByTypeCollection<IWsdlImportExtension> wsdl_extensions;
Collection<ContractDescription> contracts = null;
ServiceEndpointCollection endpoint_colln = null;
+ // Contract by PortType
+ Dictionary<PortType, ContractDescription> contractHash = null;
+ // ServiceEndpoint by WSBinding
+ Dictionary<WSBinding, ServiceEndpoint> bindingHash = null;
+ // ServiceEndpoint by Port
+ Dictionary<Port, ServiceEndpoint> endpointHash = null;
+
public WsdlImporter (
MetadataSet metadata,
IEnumerable<IPolicyImportExtension> policyImportExtensions,
wsdl_extensions.Add (new DataContractSerializerMessageContractImporter ());
wsdl_extensions.Add (new XmlSerializerMessageContractImporter ());
- //wsdl_extensions.Add (new MessageEncodingBindingElementImporter ());
+ wsdl_extensions.Add (new MessageEncodingBindingElementImporter ());
wsdl_extensions.Add (new TransportBindingElementImporter ());
wsdl_extensions.Add (new StandardBindingImporter ());
} else {
this.wsdl_documents = new ServiceDescriptionCollection ();
this.xmlschemas = new XmlSchemaSet ();
this.policies = new List<XmlElement> ();
+ this.contractHash = new Dictionary<PortType, ContractDescription> ();
+ this.bindingHash = new Dictionary<WSBinding, ServiceEndpoint> ();
+ this.endpointHash = new Dictionary<Port, ServiceEndpoint> ();
foreach (MetadataSection ms in metadata.MetadataSections) {
if (ms.Dialect == MetadataSection.ServiceDescriptionDialect &&
{
Collection<SMBinding> bindings = new Collection<SMBinding> ();
- foreach (WSServiceDescription sd in wsdl_documents)
- foreach (WSBinding binding in sd.Bindings)
- bindings.Add (ImportBinding (binding));
+ foreach (WSServiceDescription sd in wsdl_documents) {
+ foreach (WSBinding binding in sd.Bindings) {
+ var endpoint = ImportBinding (binding, false);
+ if (endpoint != null)
+ bindings.Add (endpoint.Binding);
+ }
+ }
return bindings;
}
- public SMBinding ImportBinding (WSBinding binding)
+ void BeforeImport ()
{
- /* Default, CustomBinding.. */
- CustomBinding smbinding = new CustomBinding ();
+ if (beforeImportCalled)
+ return;
foreach (IWsdlImportExtension extension in wsdl_extensions)
extension.BeforeImport (wsdl_documents, xmlschemas, policies);
+
+ beforeImportCalled = true;
+ }
- smbinding.Name = binding.Name;
- smbinding.Namespace = binding.ServiceDescription.TargetNamespace;
+ public SMBinding ImportBinding (WSBinding binding)
+ {
+ return ImportBinding (binding, true).Binding;
+ }
- //FIXME: Added by MessageEncodingBindingElementConverter.ImportPolicy
- smbinding.Elements.Add (new TextMessageEncodingBindingElement ());
+ ServiceEndpoint ImportBinding (WSBinding binding, bool throwOnError)
+ {
+ if (bindingHash.ContainsKey (binding)) {
+ var sep = bindingHash [binding];
+ if (sep != null)
+ return sep;
+
+ if (!throwOnError)
+ return null;
+
+ throw new InvalidOperationException (String.Format (
+ "Failed to import binding {0}, an error has " +
+ "already been reported before.", binding.Name));
+ }
- /*ImportContract
- PortType portType = null;
- foreach (WSServiceDescription sd in wsdl_documents) {
- portType = sd.PortTypes [binding.Type.Name];
- if (portType != null)
- break;
+ try {
+ var port_type = GetPortTypeFromBinding (binding);
+ var contract = ImportContract (port_type);
+ var contract_context = new WsdlContractConversionContext (contract, port_type);
+
+ var sep = ImportBinding (binding, contract_context);
+ bindingHash.Add (binding, sep);
+ return sep;
+ } catch (MetadataImportException) {
+ bindingHash.Add (binding, null);
+ if (throwOnError)
+ throw;
+ return null;
+ } catch (Exception ex) {
+ bindingHash.Add (binding, null);
+ var error = AddError (
+ "Failed to import binding `{0}': {1}", binding.Name, ex.Message);
+ if (throwOnError)
+ throw new MetadataImportException (error, ex);
+ return null;
}
+ }
+
+ ServiceEndpoint ImportBinding (WSBinding binding,
+ WsdlContractConversionContext contract_context)
+ {
+ BeforeImport ();
- //FIXME: if portType == null
- */
+ var sep = new ServiceEndpoint (contract_context.Contract);
+
+ var custom = new CustomBinding ();
+ custom.Name = binding.Name;
+ custom.Namespace = binding.ServiceDescription.TargetNamespace;
+
+ sep.Binding = custom;
+
+ try {
+ ImportPolicy (binding, sep);
+ } catch (Exception ex) {
+ // FIXME: Policy import is still experimental.
+ AddWarning ("Exception while trying to import policy for " +
+ "binding `{0}': {1}", binding.Name, ex.Message);
+ }
+
+ var endpoint_context = new WsdlEndpointConversionContext (
+ contract_context, sep, null, binding);
+
+ foreach (IWsdlImportExtension extension in wsdl_extensions)
+ extension.ImportEndpoint (this, endpoint_context);
- // FIXME: ImportContract here..
+ return sep;
+ }
+
+ void ImportPolicy (WSBinding binding, ServiceEndpoint endpoint)
+ {
+ var context = new Description.CustomPolicyConversionContext (binding, endpoint);
+ var assertions = context.GetBindingAssertions ();
+
+ foreach (var ext in binding.Extensions) {
+ var xml = ext as XmlElement;
+ if (xml == null)
+ continue;
+ if (!xml.NamespaceURI.Equals (Constants.WspNamespace))
+ continue;
+ if (!xml.LocalName.Equals ("PolicyReference"))
+ continue;
+ var uri = xml.GetAttribute ("URI");
+
+ if (!uri.StartsWith ("#")) {
+ // FIXME
+ AddWarning (
+ "Failed to resolve unknown policy reference `{0}' for " +
+ "binding `{1}'.", uri, binding.Name);
+ continue;
+ }
+
+ foreach (var sext in binding.ServiceDescription.Extensions) {
+ var sxml = sext as XmlElement;
+ if (sxml == null)
+ continue;
+ if (!sxml.NamespaceURI.Equals (Constants.WspNamespace))
+ continue;
+ if (!sxml.LocalName.Equals ("Policy"))
+ continue;
+ var id = sxml.GetAttribute ("Id", Constants.WsuNamespace);
+ if (!uri.Substring (1).Equals (id))
+ continue;
+ context.AddPolicyAssertion (sxml);
+ }
+ }
- return smbinding;
+ foreach (IPolicyImportExtension extension in PolicyImportExtensions) {
+ try {
+ extension.ImportPolicy (this, context);
+ } catch (Exception ex) {
+ AddWarning (
+ "PolicyImportException `{0}' threw an exception while " +
+ "trying to import policy references for endpoint `{1}': {2}",
+ extension.GetType ().Name, endpoint.Name, ex.Message);
+ }
+ }
}
+ PortType GetPortTypeFromBinding (WSBinding binding)
+ {
+ foreach (WSServiceDescription sd in wsdl_documents) {
+ var port_type = sd.PortTypes [binding.Type.Name];
+ if (port_type != null)
+ return port_type;
+ }
+
+ throw new MetadataImportException (AddError (
+ "PortType named {0} not found in namespace {1}.",
+ binding.Type.Name, binding.Type.Namespace));
+ }
+
public override Collection<ContractDescription> ImportAllContracts ()
{
if (contracts != null)
contracts = new Collection<ContractDescription> ();
foreach (WSServiceDescription sd in wsdl_documents) {
- foreach (PortType pt in sd.PortTypes)
- contracts.Add (ImportContract (pt));
+ foreach (PortType pt in sd.PortTypes) {
+ var cd = ImportContract (pt, false);
+ if (cd != null)
+ contracts.Add (cd);
+ }
}
return contracts;
endpoint_colln = new ServiceEndpointCollection ();
- foreach (IWsdlImportExtension extension in wsdl_extensions) {
- extension.BeforeImport (wsdl_documents, xmlschemas, policies);
+ foreach (WSServiceDescription wsd in wsdl_documents) {
+ foreach (Service service in wsd.Services) {
+ foreach (Port port in service.Ports) {
+ var sep = ImportEndpoint (port, false);
+ if (sep != null)
+ endpoint_colln.Add (sep);
+ }
+ }
}
- foreach (WSServiceDescription wsd in wsdl_documents)
- foreach (Service service in wsd.Services)
- foreach (Port port in service.Ports)
- endpoint_colln.Add (ImportEndpoint (port));
-
return endpoint_colln;
}
public ContractDescription ImportContract (PortType wsdlPortType)
{
- foreach (IWsdlImportExtension extension in wsdl_extensions) {
- extension.BeforeImport (wsdl_documents, xmlschemas, policies);
+ return ImportContract (wsdlPortType, true);
+ }
+
+ ContractDescription ImportContract (PortType portType, bool throwOnError)
+ {
+ if (contractHash.ContainsKey (portType)) {
+ var cd = contractHash [portType];
+ if (cd != null)
+ return cd;
+
+ if (!throwOnError)
+ return null;
+
+ throw new InvalidOperationException (String.Format (
+ "Failed to import contract for port type `{0}', " +
+ "an error has already been reported.", portType.Name));
}
+ try {
+ var cd = DoImportContract (portType);
+ contractHash.Add (portType, cd);
+ return cd;
+ } catch (MetadataImportException) {
+ contractHash.Add (portType, null);
+ if (throwOnError)
+ throw;
+ return null;
+ } catch (Exception ex) {
+ contractHash.Add (portType, null);
+ var error = AddError (
+ "Failed to import contract for port type `{0}': {1}",
+ portType.Name, ex.Message);
+ if (throwOnError)
+ throw new MetadataImportException (error, ex);
+ return null;
+ }
+ }
+
+ ContractDescription DoImportContract (PortType wsdlPortType)
+ {
+ BeforeImport ();
+
ContractDescription cd = new ContractDescription (wsdlPortType.Name, wsdlPortType.ServiceDescription.TargetNamespace);
foreach (Operation op in wsdlPortType.Operations) {
public ServiceEndpoint ImportEndpoint (Port wsdlPort)
{
- foreach (IWsdlImportExtension extension in wsdl_extensions) {
- extension.BeforeImport (wsdl_documents, xmlschemas, policies);
+ return ImportEndpoint (wsdlPort, true);
+ }
+
+ ServiceEndpoint ImportEndpoint (Port port, bool throwOnError)
+ {
+ ServiceEndpoint endpoint;
+ if (endpointHash.ContainsKey (port)) {
+ endpoint = endpointHash [port];
+ if (endpoint != null)
+ return endpoint;
+
+ if (!throwOnError)
+ return null;
+
+ throw new InvalidOperationException (String.Format (
+ "Failed to import port `{0}', an error has " +
+ "already been reported before.", port.Name));
}
- //Get the corresponding contract
- //via the PortType
- WSBinding wsb = wsdlPort.Service.ServiceDescription.Bindings [wsdlPort.Binding.Name];
- if (wsb == null)
- //FIXME
- throw new Exception (String.Format ("Binding named {0} not found.", wsdlPort.Binding.Name));
+ var binding = port.Service.ServiceDescription.Bindings [port.Binding.Name];
+ if (binding == null) {
+ endpointHash.Add (port, null);
+ var error = AddError (
+ "Failed to import port `{0}': cannot find binding `{1}' that " +
+ "this port depends on.", port.Name, port.Binding.Name);
+ if (throwOnError)
+ throw new MetadataImportException (error);
+ return null;
+ }
- SMBinding binding = ImportBinding (wsb);
+ try {
+ endpoint = ImportBinding (binding, throwOnError);
+ } catch (Exception ex) {
+ endpointHash.Add (port, null);
+ var error = AddError (
+ "Failed to import port `{0}': error while trying to import " +
+ "binding `{1}' that this port depends on: {2}",
+ port.Name, port.Binding.Name, ex.Message);
+ if (throwOnError)
+ throw new MetadataImportException (error, ex);
+ return null;
+ }
- PortType port_type = null;
- foreach (WSServiceDescription sd in wsdl_documents) {
- port_type = sd.PortTypes [wsb.Type.Name];
- if (port_type != null)
- break;
+ if (endpoint == null) {
+ endpointHash.Add (port, null);
+ AddError (
+ "Failed to import port `{0}': error while trying to import " +
+ "binding `{1}' that this port depends on.",
+ port.Name, port.Binding.Name);
+ return null;
}
- if (port_type == null)
- //FIXME
- throw new Exception (String.Format ("PortType named {0} not found.", wsb.Type.Name));
+ try {
+ ImportEndpoint (port, binding, endpoint, throwOnError);
+ endpointHash.Add (port, endpoint);
+ return endpoint;
+ } catch (MetadataImportException) {
+ endpointHash.Add (port, null);
+ if (throwOnError)
+ throw;
+ return null;
+ } catch (Exception ex) {
+ endpointHash.Add (port, null);
+ var error = AddError (
+ "Failed to import port `{0}': {1}", port.Name, ex.Message);
+ if (throwOnError)
+ throw new MetadataImportException (error, ex);
+ return null;
+ }
+ }
- ContractDescription contract = ImportContract (port_type);
- ServiceEndpoint sep = new ServiceEndpoint (contract);
+ void ImportEndpoint (Port port, WSBinding wsb, ServiceEndpoint sep, bool throwOnError)
+ {
+ BeforeImport ();
- sep.Binding = binding;
+ var port_type = GetPortTypeFromBinding (wsb);
- WsdlContractConversionContext contract_context = new WsdlContractConversionContext (contract, port_type);
+ var contract_context = new WsdlContractConversionContext (sep.Contract, port_type);
WsdlEndpointConversionContext endpoint_context = new WsdlEndpointConversionContext (
- contract_context, sep, wsdlPort, wsb);
+ contract_context, sep, port, wsb);
foreach (IWsdlImportExtension extension in wsdl_extensions)
extension.ImportEndpoint (this, endpoint_context);
+ }
- return sep;
+ void ImportEndpoints (ServiceEndpointCollection coll, WSBinding binding)
+ {
+ foreach (WSServiceDescription wsd in wsdl_documents) {
+ foreach (WS.Service service in wsd.Services) {
+ foreach (WS.Port port in service.Ports) {
+ if (!binding.Name.Equals (port.Binding.Name))
+ continue;
+ var sep = ImportEndpoint (port, false);
+ if (sep != null)
+ coll.Add (sep);
+ }
+ }
+ }
}
- public ServiceEndpointCollection ImportEndpoints (
- WSBinding binding)
+ public ServiceEndpointCollection ImportEndpoints (WSBinding binding)
{
- throw new NotImplementedException ();
+ var coll = new ServiceEndpointCollection ();
+ ImportEndpoints (coll, binding);
+ return coll;
}
- public ServiceEndpointCollection ImportEndpoints (
- PortType portType)
+ public ServiceEndpointCollection ImportEndpoints (PortType portType)
{
- throw new NotImplementedException ();
+ var coll = new ServiceEndpointCollection ();
+
+ foreach (WSServiceDescription wsd in wsdl_documents) {
+ foreach (WS.Binding binding in wsd.Bindings) {
+ if (!binding.Type.Name.Equals (portType.Name))
+ continue;
+
+ ImportEndpoints (coll, binding);
+ }
+ }
+
+ return coll;
}
- public ServiceEndpointCollection ImportEndpoints (
- Service service)
+ public ServiceEndpointCollection ImportEndpoints (Service service)
{
- throw new NotImplementedException ();
+ var coll = new ServiceEndpointCollection ();
+
+ foreach (Port port in service.Ports) {
+ var sep = ImportEndpoint (port, false);
+ if (sep != null)
+ coll.Add (sep);
+ }
+
+ return coll;
}
}
}
System.ServiceModel.Channels/PeerOutputChannel.cs
System.ServiceModel.Channels/PeerTransportBindingElement.cs
System.ServiceModel.Channels/PnrpPeerResolverBindingElement.cs
+System.ServiceModel.Channels/PolicyImportHelper.cs
System.ServiceModel.Channels/PrivacyNoticeBindingElement.cs
System.ServiceModel.Channels/ReliableSessionBindingElement.cs
System.ServiceModel.Channels/ReliableSessionBindingElementImporter.cs
System.ServiceModel.Description/ClientViaBehavior.cs
System.ServiceModel.Description/ContractDescription.cs
System.ServiceModel.Description/ContractDescriptionGenerator.cs
+System.ServiceModel.Description/CustomPolicyConversionContext.cs
System.ServiceModel.Description/DataContractSerializerMessageContractImporter.cs
System.ServiceModel.Description/DataContractSerializerOperationBehavior.cs
System.ServiceModel.Description/FaultDescription.cs
XmlDictionaryReaderQuotas reader_quotas;
bool transaction_flow;
TransactionProtocol transaction_protocol;
- TcpTransportBindingElement transport = new TcpTransportBindingElement ();
+ TcpTransportBindingElement transport;
public NetTcpBinding ()
: this (SecurityMode.Transport)
bool reliableSessionEnabled)
{
security = new NetTcpSecurity (securityMode);
+ transport = new TcpTransportBindingElement ();
+ }
+
+ internal NetTcpBinding (TcpTransportBindingElement transport,
+ NetTcpSecurity security,
+ bool reliableSessionEnabled)
+ {
+ this.transport = transport;
+ this.security = security;
}
public HostNameComparisonMode HostNameComparisonMode {
BindingElement CreateTransportSecurity ()
{
switch (Security.Mode) {
- case SecurityMode.None:
- case SecurityMode.Message:
+ case SecurityMode.Transport:
+ return new WindowsStreamSecurityBindingElement () {
+ ProtectionLevel = Security.Transport.ProtectionLevel };
+
+ case SecurityMode.TransportWithMessageCredential:
+ return new SslStreamSecurityBindingElement ();
+
+ default:
return null;
}
namespace MonoTests.System.ServiceModel.MetadataTests {
[TestFixture]
- [Category ("NotWorking")]
[Category ("MetadataTests")]
public partial class ImportTests {
Assert.AreEqual (name, ((XmlElement) o).Name);
}
- [Test]
- public void BindingsTest ()
- {
- NoExtensionsSetup ();
- IEnumerable<SMBinding> bindings = wi.ImportAllBindings ();
-
- int count = 0;
- foreach (SMBinding b in bindings) {
- Assert.AreEqual (typeof (CustomBinding), b.GetType (), "#B1");
- Assert.AreEqual ("BasicHttpBinding_IEchoService", b.Name, "#B2");
- Assert.AreEqual ("http://tempuri.org/", b.Namespace, "#B3");
- Assert.AreEqual ("", b.Scheme, "#B4");
-
- //FIXME: Test BindingElements
-
- count++;
- }
- Assert.AreEqual (1, count);
- }
-
[Test]
[Category ("NotWorking")]
public void ContractsTest ()
var mset = new MetadataSet ();
WSServiceDescription sd = null;
- sd = WSServiceDescription.Read (XmlReader.Create ("670945.wsdl"));
+ sd = WSServiceDescription.Read (XmlReader.Create ("Test/XmlFiles/670945.wsdl"));
mset.MetadataSections.Add (new MetadataSection () {
Dialect = MetadataSection.ServiceDescriptionDialect,
Metadata = sd });