[WCF]: Implement missing WsdlImporter pieces.
authorMartin Baulig <martin.baulig@xamarin.com>
Tue, 27 Nov 2012 01:23:11 +0000 (02:23 +0100)
committerMartin Baulig <martin.baulig@xamarin.com>
Tue, 27 Nov 2012 01:30:54 +0000 (02:30 +0100)
The WsdlImporter can now import Bindings and Endpoints
from the WSDL, currently supporting BasicHttpBinding,
BasicHttpsBinding and NetTcpBinding.

There is also - limited and still experimental - support
for WS-Policy 1.5.  I only did the very basic pieces so
far, for instance things like TransportWithMessageCredentials
are not supported yet.

The policy importer will emit lots of warnings via
`MetadataImporter.Errors` (as warnings, not errors) whenever
it encounters something that it doesn't understand and
is also forgiving towards unknown and/or mal-formed
policy assertions.

This behavior is different from the MS runtime, which is
very strict, but there are simply too many missing pieces
to be more pedentic here.  Check whether Errors.Count == 0
to see whether all policy assertions have been correctly
imported.

There are also a few metadata samples, which are part of the
new nunit tests.  These are currently working:

  BasicHttp.xml, BasicHttp_Mtom.xml, BasicHttp_NtlmAuth.xml,
  BasicHttp_TransportSecurity.xml, BasicHttps.xml,
  BasicHttps_NtlmAuth.xml, NetTcp.xml, NetTcp_TransferMode.xml,
  NetTcp_TransportSecurity.xml

There are a few more in the Tests/MetadataTests/Resources/
directory which demonstrate missing pieces.

12 files changed:
mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageEncodingBindingElementImporter.cs
mcs/class/System.ServiceModel/System.ServiceModel.Channels/PolicyImportHelper.cs [new file with mode: 0644]
mcs/class/System.ServiceModel/System.ServiceModel.Channels/StandardBindingImporter.cs
mcs/class/System.ServiceModel/System.ServiceModel.Channels/TransportBindingElementImporter.cs
mcs/class/System.ServiceModel/System.ServiceModel.Description/CustomPolicyConversionContext.cs [new file with mode: 0644]
mcs/class/System.ServiceModel/System.ServiceModel.Description/MetadataImporter.cs
mcs/class/System.ServiceModel/System.ServiceModel.Description/PolicyConversionContext.cs
mcs/class/System.ServiceModel/System.ServiceModel.Description/WsdlImporter.cs
mcs/class/System.ServiceModel/System.ServiceModel.dll.sources
mcs/class/System.ServiceModel/System.ServiceModel/NetTcpBinding.cs
mcs/class/System.ServiceModel/Test/MetadataTests/ImportTests_Tests.cs
mcs/class/System.ServiceModel/Test/System.ServiceModel.Description/WsdlImporterTest.cs

index fe96d70eec9454f832008d2866b160b521da0621..27bfc263baefde14d1240473bf9836b1085d7f8d 100644 (file)
@@ -1,9 +1,10 @@
 //
 // 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
@@ -39,7 +40,6 @@ namespace System.ServiceModel.Channels
        public class MessageEncodingBindingElementImporter
                : IWsdlImportExtension, IPolicyImportExtension
        {
-               [MonoTODO]
                void IWsdlImportExtension.BeforeImport (
                        ServiceDescriptionCollection wsdlDocuments,
                        XmlSchemaSet xmlSchemas,
@@ -47,22 +47,35 @@ namespace System.ServiceModel.Channels
                {
                }
 
-               [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 ());
                }
        }
 }
diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/PolicyImportHelper.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/PolicyImportHelper.cs
new file mode 100644 (file)
index 0000000..517d5fe
--- /dev/null
@@ -0,0 +1,224 @@
+//
+// 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;
+               }
+       }
+}
+
index 2147439eea9bdf3f309a501275b0c9851b97b8b2..a555cf8781d4af04e842056f2105a13775021baf 100644 (file)
 // 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
        }
 }
+
index f323ccaba40db5dda825d01521570118406625df..b76f0e12edd6c312bc91ad20d0709eb7a873fe15 100644 (file)
 // 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;
                }
        }
 }
diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Description/CustomPolicyConversionContext.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Description/CustomPolicyConversionContext.cs
new file mode 100644 (file)
index 0000000..0d20e1b
--- /dev/null
@@ -0,0 +1,128 @@
+//
+// 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);
+                               }
+                       }
+               }
+       }
+}
+
index febc85272134b8af9a4b53a75a76294d0c19237f..2257936225f1b17a69dfd3e33df2fe51458a4593 100644 (file)
@@ -56,7 +56,6 @@ namespace System.ServiceModel.Description
                        policy_extensions.Add (new MessageEncodingBindingElementImporter ());
                }
 
-               [MonoTODO ("Not in use yet")]
                public Collection<MetadataConversionError> Errors {
                        get { return errors; }
                }
@@ -86,5 +85,40 @@ namespace System.ServiceModel.Description
                        }
                        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;
+                       }
+               }
+
        }
 }
index 368cab78063cb1ae24d9e9a5e46d8acae58f1a87..5595d01edfc8501127f9eafd61f9e276ce8c6255 100644 (file)
@@ -36,14 +36,21 @@ namespace System.ServiceModel.Description
 {
        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 ();
index 7cda8c5adf00bdfac1c60ec38b7799ea268e853a..c162422017791d2d73fc2182e20939f0755e00ec 100644 (file)
@@ -1,11 +1,13 @@
 //
 // 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
@@ -36,6 +38,7 @@ using System.Xml;
 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;
@@ -50,6 +53,7 @@ namespace System.ServiceModel.Description
                XmlSchemaSet xmlschemas;
                List<XmlElement> policies; /* ?? */
                MetadataSet metadata;
+               bool beforeImportCalled;
 
                KeyedByTypeCollection<IWsdlImportExtension> wsdl_extensions;
                        
@@ -57,6 +61,13 @@ namespace System.ServiceModel.Description
                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,
@@ -71,7 +82,7 @@ namespace System.ServiceModel.Description
 
                                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 {
@@ -84,6 +95,9 @@ namespace System.ServiceModel.Description
                        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 &&
@@ -117,43 +131,164 @@ namespace System.ServiceModel.Description
                {
                        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)
@@ -162,8 +297,11 @@ namespace System.ServiceModel.Description
                        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;
@@ -176,24 +314,63 @@ namespace System.ServiceModel.Description
 
                        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) {
@@ -265,61 +442,140 @@ namespace System.ServiceModel.Description
 
                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;
                }
        }
 }
index 36ce341867284718957a89edae8b690fef1f97e3..8baeb0a5ecd78d93bf64076f6ee7b9a560535503 100644 (file)
@@ -257,6 +257,7 @@ System.ServiceModel.Channels/PeerInputChannel.cs
 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
@@ -558,6 +559,7 @@ System.ServiceModel.Description/ClientCredentials.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
index c99b341052fc80d24cc665dc41207305b8d39cad..223faff637c7585e11ba417098edc929b3350c57 100644 (file)
@@ -45,7 +45,7 @@ namespace System.ServiceModel
                XmlDictionaryReaderQuotas reader_quotas;
                bool transaction_flow;
                TransactionProtocol transaction_protocol;
-               TcpTransportBindingElement transport = new TcpTransportBindingElement ();
+               TcpTransportBindingElement transport;
 
                public NetTcpBinding ()
                        : this (SecurityMode.Transport)
@@ -61,6 +61,15 @@ namespace System.ServiceModel
                        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 {
@@ -223,8 +232,14 @@ namespace System.ServiceModel
                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;
                        }
 
index 11a60b8a8bd5f0f9da9a8196fba5b0d6c9d55f3d..f41864106b1f742e40181e7a4bf347b0483bb261 100644 (file)
@@ -41,7 +41,6 @@ using WS = System.Web.Services.Description;
 namespace MonoTests.System.ServiceModel.MetadataTests {
 
        [TestFixture]
-       [Category ("NotWorking")]
        [Category ("MetadataTests")]
        public partial class ImportTests {
 
index 24630a2826307df14d71e7f7d7fce1debea457c7..cf2289e4d7d11a70bc3331cd41096437c1783776 100644 (file)
@@ -236,26 +236,6 @@ namespace MonoTests.System.ServiceModel.Description
                        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 ()
@@ -586,7 +566,7 @@ namespace MonoTests.System.ServiceModel.Description
                        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 });