Add licensing info
[mono.git] / mcs / class / System.Runtime.Remoting / System.Runtime.Remoting.MetadataServices / MetaDataExporter.cs
index a531af6e53ab0980092a4895a4302338f5ff532b..0c8c4785a19a04a1e7caf0e3d01e6e2770e60f64 100644 (file)
@@ -7,15 +7,36 @@
 // (C) 2003 Novell, Inc
 //
 
+//
+// 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.Collections;
 using System.IO;
 using System.Text;
 using System.Xml;
 using System.Reflection;
 using System.Net;
-using System.Web.Services.Description;
 using System.Runtime.Remoting;
 using System.Runtime.Remoting.Metadata;
+using System.Runtime.Serialization;
 
 namespace System.Runtime.Remoting.MetadataServices
 {
@@ -29,7 +50,10 @@ namespace System.Runtime.Remoting.MetadataServices
                        if (servicetypes.Length == 0) return;
                        Type maint = servicetypes [0].ObjectType;
                        
-                       ArrayList services = FindServices (servicetypes);
+                       Hashtable dataTypes = new Hashtable (); 
+                       ArrayList services = new ArrayList ();
+                       FindTypes (servicetypes, dataTypes, services);
+                       
                        if (services.Count > 0)
                                maint = ((ServiceType) services[0]).ObjectType;
                        
@@ -49,7 +73,6 @@ namespace System.Runtime.Remoting.MetadataServices
                        tw.WriteAttributeString ("xmlns", "soap", MetaData.XmlnsNamespace, MetaData.SoapNamespace);
                        
                        int nums = 0;
-                       Hashtable dataTypes = FindDataTypes (servicetypes);
                        foreach (DictionaryEntry entry in dataTypes)
                        {
                                string ns = (string) entry.Key;
@@ -95,7 +118,7 @@ namespace System.Runtime.Remoting.MetadataServices
                                WriteServiceBinding (tw, st);
 */
                        foreach (ServiceType st in services)
-                               WriteServiceBinding (tw, st);
+                               WriteServiceBinding (tw, st, dataTypes);
 
                        // Service element
                        
@@ -107,7 +130,6 @@ namespace System.Runtime.Remoting.MetadataServices
 
                        foreach (ServiceType st in services)
                        {
-//                             if (st.Url == null) continue;
                                WriteServiceType (tw, st);
                        }
                        tw.WriteEndElement ();
@@ -123,13 +145,18 @@ namespace System.Runtime.Remoting.MetadataServices
                        tw.WriteStartElement ("port", MetaData.WsdlNamespace);
                        tw.WriteAttributeString ("name", GetPortName (st.ObjectType));
                        tw.WriteAttributeString ("binding", "tns:" + GetBindingName (st.ObjectType));
-                       tw.WriteStartElement ("soap","address", MetaData.SoapNamespace);
-                       tw.WriteAttributeString ("location", st.Url);
-                       tw.WriteEndElement ();
+                       
+                       if (st.Url != null)
+                       {
+                               tw.WriteStartElement ("soap","address", MetaData.SoapNamespace);
+                               tw.WriteAttributeString ("location", st.Url);
+                               tw.WriteEndElement ();
+                       }
+                       
                        tw.WriteEndElement ();
                }
                
-               void WriteServiceBinding  (XmlTextWriter tw, ServiceType st)
+               void WriteServiceBinding  (XmlTextWriter tw, ServiceType st, Hashtable dataTypes)
                {
                        Type type = st.ObjectType;
                        string typeName = type.Name;
@@ -190,7 +217,7 @@ namespace System.Runtime.Remoting.MetadataServices
                                                if (sb.Length != 0) sb.Append (" ");
                                                sb.Append (par.Name);
                                        }
-                                       tw.WriteAttributeString ("parameterOreder", sb.ToString ());
+                                       tw.WriteAttributeString ("parameterOrder", sb.ToString ());
                                        
                                        tw.WriteStartElement ("input", MetaData.WsdlNamespace);
                                        tw.WriteAttributeString ("name", met.Name + "Request");
@@ -218,32 +245,15 @@ namespace System.Runtime.Remoting.MetadataServices
                        tw.WriteAttributeString ("transport", "http://schemas.xmlsoap.org/soap/http");
                        tw.WriteEndElement ();
                        
-                       if (type.IsInterface)
-                       {
-                               tw.WriteStartElement ("suds", "interface", MetaData.SudsNamespace);
-                               tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, type, null));
-                               if (type.BaseType != null && type.BaseType != typeof(object))
-                                       tw.WriteAttributeString ("extends", GetQualifiedXmlType (tw, type.BaseType, null));
-                       }
-                       else
+                       WriteTypeSuds (tw, type);
+                       
+                       SchemaInfo sinfo = (SchemaInfo) dataTypes [GetXmlNamespace (type,null)];
+                       if (sinfo != null && !sinfo.SudsGenerated)
                        {
-                               tw.WriteStartElement ("suds", "class", MetaData.SudsNamespace);
-                               tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, type, null));
-                               
-                               if (isService)
-                               {
-                                       if (type.IsMarshalByRef) {
-                                               tw.WriteAttributeString ("rootType", "MarshalByRefObject");
-                                       }
-                                       else {
-                                               tw.WriteAttributeString ("rootType", "Delegate");
-                                       }
-                                       
-                                       if (type.BaseType != typeof(MarshalByRefObject))
-                                               tw.WriteAttributeString ("extends", GetQualifiedXmlType (tw, type.BaseType, null));
-                               }
+                               foreach (Type dt in sinfo.Types)
+                                       WriteTypeSuds (tw, dt);
+                               sinfo.SudsGenerated = true;
                        }
-                       tw.WriteEndElement ();
                        
                        if (isService)
                        {
@@ -278,6 +288,59 @@ namespace System.Runtime.Remoting.MetadataServices
                        tw.WriteEndElement ();  // binding
                }
                
+               void WriteTypeSuds (XmlTextWriter tw, Type type)
+               {
+                       if (type.IsArray || type.IsEnum)
+                       {
+                               return;
+                       }
+                       else if (type.IsInterface)
+                       {
+                               tw.WriteStartElement ("suds", "interface", MetaData.SudsNamespace);
+                               tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, type, null));
+                               foreach (Type interf in type.GetInterfaces ()) {
+                                       tw.WriteStartElement ("suds","extends", MetaData.SudsNamespace);
+                                       tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, interf, null));
+                                       tw.WriteEndElement ();
+                               }
+                       }
+                       else if (type.IsValueType)
+                       {
+                               tw.WriteStartElement ("suds", "struct", MetaData.SudsNamespace);
+                               tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, type, null));
+                               if (type.BaseType != typeof(ValueType))
+                                       tw.WriteAttributeString ("extends", GetQualifiedXmlType (tw, type.BaseType, null));
+                       }
+                       else
+                       {
+                               tw.WriteStartElement ("suds", "class", MetaData.SudsNamespace);
+                               tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, type, null));
+                               
+                               if (IsService (type))
+                               {
+                                       if (type.IsMarshalByRef)
+                                               tw.WriteAttributeString ("rootType", "MarshalByRefObject");
+                                       else
+                                               tw.WriteAttributeString ("rootType", "Delegate");
+                                       
+                                       if (type.BaseType != typeof(MarshalByRefObject))
+                                               tw.WriteAttributeString ("extends", GetQualifiedXmlType (tw, type.BaseType, null));
+                                               
+                                       if (type.IsMarshalByRef) {
+                                               foreach (Type interf in type.GetInterfaces ()) {
+                                                       tw.WriteStartElement ("suds","implements", MetaData.SudsNamespace);
+                                                       tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, interf, null));
+                                                       tw.WriteEndElement ();
+                                               }
+                                       }
+                               }
+                               else if (typeof(ISerializable).IsAssignableFrom (type))
+                                       tw.WriteAttributeString ("rootType", "ISerializable");
+                                       
+                       }
+                       tw.WriteEndElement ();  // suds
+               }
+               
                void WriteMessageBindingBody (XmlTextWriter tw, Type t)
                {
                        tw.WriteStartElement ("soap", "body", MetaData.SoapNamespace);
@@ -358,7 +421,7 @@ namespace System.Runtime.Remoting.MetadataServices
                        
                        tw.WriteStartElement ("complexType", MetaData.SchemaNamespace);
                        tw.WriteAttributeString ("name", GetXmlType (type));
-                       if (type.BaseType != null && type.BaseType != typeof(object))
+                       if (type.BaseType != null && type.BaseType != typeof(object) && type.BaseType != typeof(ValueType))
                                tw.WriteAttributeString ("base", GetQualifiedXmlType (tw, type.BaseType, null));
                        
                        FieldInfo[] fields = type.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
@@ -441,7 +504,7 @@ namespace System.Runtime.Remoting.MetadataServices
                        }
                        else
                        {
-                               name = GetXsdType (type);
+                               name = GetXsdType (type);                                       
                                if (name != null) return "xsd:" + name;
                                
                                if (!SoapServices.GetXmlTypeForInteropType (type, out name, out ns))
@@ -468,9 +531,7 @@ namespace System.Runtime.Remoting.MetadataServices
                        {
                                string name = null, ns;
                                
-                               if (!type.IsEnum)
-                                       name = GetXsdType (type);
-                                       
+                               name = GetXsdType (type);
                                if (name != null) return name;
                                
                                if (SoapServices.GetXmlTypeForInteropType (type, out name, out ns))
@@ -496,15 +557,26 @@ namespace System.Runtime.Remoting.MetadataServices
                        return t.Name + "Binding";
                }
                
-               Hashtable FindDataTypes (ServiceType[] servicetypes)
+               void FindTypes (ServiceType[] servicetypes, Hashtable dataTypes, ArrayList services)
                {
                        Hashtable types = new Hashtable ();
+                       ArrayList mbrTypes = new ArrayList();
+                       
                        foreach (ServiceType st in servicetypes)
-                               FindDataTypes (st.ObjectType, null, types);
-                       return types;
+                               FindDataTypes (st.ObjectType, null, dataTypes, mbrTypes);
+                               
+                       foreach (Type mbrType in mbrTypes)
+                       {
+                               ServiceType stFound = null;
+                               foreach (ServiceType st in servicetypes)
+                                       if (mbrType == st.ObjectType) stFound = st;
+                                       
+                               if (stFound != null) services.Add (stFound);
+                               else services.Add (new ServiceType (mbrType));
+                       }
                }
                
-               void FindDataTypes (Type t, Type containerType, Hashtable types)
+               void FindDataTypes (Type t, Type containerType, Hashtable types, ArrayList services)
                {
                        if (IsSystemType (t))
                        {
@@ -515,6 +587,8 @@ namespace System.Runtime.Remoting.MetadataServices
                        
                        if (!IsService (t))
                        {
+                               if (!t.IsSerializable) return;
+                               
                                string ns = GetXmlNamespace (t, containerType);
                                SchemaInfo sinfo = (SchemaInfo) types [ns];
                                if (sinfo == null)
@@ -533,20 +607,21 @@ namespace System.Runtime.Remoting.MetadataServices
                                {
                                        string fns = GetXmlNamespace (fi.FieldType, t);
                                        if (!sinfo.Imports.Contains (fns)) sinfo.Imports.Add (fns);
-                                       FindDataTypes (fi.FieldType, t, types);
+                                       FindDataTypes (fi.FieldType, t, types, services);
                                }
                        }
                        else
                        {
+                               if (services.Contains (t)) return;
+                               services.Add (t);
+                               
                                foreach (MethodInfo met in t.GetMethods (BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
                                {
                                        ParameterInfo[] pars = met.GetParameters ();
                                        foreach (ParameterInfo par in pars)
-                                               if (!par.ParameterType.IsMarshalByRef)
-                                                       FindDataTypes (par.ParameterType, t, types);
+                                               FindDataTypes (par.ParameterType, t, types, services);
                                                        
-                                       if (!met.ReturnType.IsMarshalByRef)
-                                               FindDataTypes (met.ReturnType, t, types);
+                                       FindDataTypes (met.ReturnType, t, types, services);
                                }
                        }
                }
@@ -563,6 +638,8 @@ namespace System.Runtime.Remoting.MetadataServices
                
                static string GetXsdType (Type type)
                {
+                       if (type.IsEnum) return null;
+                       
                        switch (Type.GetTypeCode (type))
                        {
                                case TypeCode.Boolean: return "boolean";
@@ -595,5 +672,6 @@ namespace System.Runtime.Remoting.MetadataServices
        {
                public ArrayList Types = new ArrayList ();
                public ArrayList Imports = new ArrayList ();
+               public bool SudsGenerated;
        }
 }