a23d2a0d725550cd5e8e1afdd18faa36d1920aba
[mono.git] / mcs / class / System.Runtime.Remoting / System.Runtime.Remoting.MetadataServices / MetaDataExporter.cs
1 //
2 // System.Runtime.Remoting.MetadataServices.MetaDataExporter
3 //
4 // Authors:
5 //              Lluis Sanchez Gual (lluis@ximian.com)
6 //
7 // (C) 2003 Novell, Inc
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System.Collections;
32 using System.IO;
33 using System.Text;
34 using System.Xml;
35 using System.Reflection;
36 using System.Net;
37 using System.Runtime.Remoting;
38 using System.Runtime.Remoting.Metadata;
39 using System.Runtime.Serialization;
40
41 namespace System.Runtime.Remoting.MetadataServices
42 {
43         internal class MetaDataExporter
44         {
45                 public void ExportTypes (ServiceType[] servicetypes, SdlType sdltype, XmlTextWriter tw)
46                 {
47                         if (sdltype == SdlType.Sdl)     // Obsolete, we don't support this
48                                 throw new NotSupportedException ();
49
50                         if (servicetypes.Length == 0) return;
51                         Type maint = servicetypes [0].ObjectType;
52                         
53                         Hashtable dataTypes = new Hashtable (); 
54                         ArrayList services = new ArrayList ();
55                         FindTypes (servicetypes, dataTypes, services);
56                         
57                         if (services.Count > 0)
58                                 maint = ((ServiceType) services[0]).ObjectType;
59                         
60                         string serviceNs = GetXmlNamespace (maint, null);
61                         
62                         tw.Formatting = Formatting.Indented;
63                         tw.WriteStartElement ("definitions", MetaData.WsdlNamespace);
64                         tw.WriteAttributeString ("name", maint.Name);
65                         tw.WriteAttributeString ("targetNamespace", serviceNs);
66                         tw.WriteAttributeString ("xmlns", MetaData.XmlnsNamespace, MetaData.WsdlNamespace);
67                         tw.WriteAttributeString ("xmlns", "tns", MetaData.XmlnsNamespace, serviceNs);
68                         tw.WriteAttributeString ("xmlns", "xsd", MetaData.XmlnsNamespace, MetaData.SchemaNamespace);
69                         tw.WriteAttributeString ("xmlns", "xsi", MetaData.XmlnsNamespace, MetaData.SchemaInstanceNamespace);
70                         tw.WriteAttributeString ("xmlns", "suds", MetaData.XmlnsNamespace, MetaData.SudsNamespace);
71                         tw.WriteAttributeString ("xmlns", "wsdl", MetaData.XmlnsNamespace, MetaData.WsdlNamespace);
72                         tw.WriteAttributeString ("xmlns", "soapenc", MetaData.XmlnsNamespace, MetaData.SoapEncodingNamespace);
73                         tw.WriteAttributeString ("xmlns", "soap", MetaData.XmlnsNamespace, MetaData.SoapNamespace);
74                         
75                         int nums = 0;
76                         foreach (DictionaryEntry entry in dataTypes)
77                         {
78                                 string ns = (string) entry.Key;
79                                 if (tw.LookupPrefix (ns) != null) continue;
80                                 tw.WriteAttributeString ("xmlns", "ns"+nums, MetaData.XmlnsNamespace, ns);
81                                 nums++;
82                         }
83                         
84                         // Schema
85                         
86                         if (dataTypes.Count > 0)
87                         {
88                                 tw.WriteStartElement ("types", MetaData.WsdlNamespace);
89                                 foreach (DictionaryEntry entry in dataTypes)
90                                 {
91                                         SchemaInfo sinfo = (SchemaInfo) entry.Value;
92                                         if (sinfo == null || sinfo.Types.Count == 0) continue;
93                                         
94                                         tw.WriteStartElement ("s", "schema", MetaData.SchemaNamespace);
95                                         tw.WriteAttributeString ("targetNamespace", (string) entry.Key);
96                                         tw.WriteAttributeString ("elementFormDefault", "unqualified");
97                                         tw.WriteAttributeString ("attributeFormDefault", "unqualified");
98                                         
99                                         foreach (string ns in sinfo.Imports)
100                                         {
101                                                 if (ns == (string) entry.Key) continue;
102                                                 tw.WriteStartElement ("import", MetaData.SchemaNamespace);
103                                                 tw.WriteAttributeString ("namespace", ns);
104                                                 tw.WriteEndElement ();
105                                         }
106                                         
107                                         foreach (Type type in sinfo.Types)
108                                                 WriteDataTypeSchema (tw, type);
109                                                 
110                                         tw.WriteEndElement ();
111                                 }
112                                 tw.WriteEndElement ();
113                         }
114                         
115                         // Bindings
116                         
117 /*                      foreach (ServiceType st in servicetypes)
118                                 WriteServiceBinding (tw, st);
119 */
120                         foreach (ServiceType st in services)
121                                 WriteServiceBinding (tw, st, dataTypes);
122
123                         // Service element
124                         
125                         tw.WriteStartElement ("service", MetaData.WsdlNamespace);
126                         if (services.Count > 0)
127                                 tw.WriteAttributeString ("name", GetServiceName (maint));
128                         else
129                                 tw.WriteAttributeString ("name", "Service");
130
131                         foreach (ServiceType st in services)
132                         {
133                                 WriteServiceType (tw, st);
134                         }
135                         tw.WriteEndElement ();
136
137                         // Closing
138
139                         tw.WriteEndElement ();
140                         tw.Flush ();
141                 }
142                 
143                 void WriteServiceType (XmlTextWriter tw, ServiceType st)
144                 {
145                         tw.WriteStartElement ("port", MetaData.WsdlNamespace);
146                         tw.WriteAttributeString ("name", GetPortName (st.ObjectType));
147                         tw.WriteAttributeString ("binding", "tns:" + GetBindingName (st.ObjectType));
148                         
149                         if (st.Url != null)
150                         {
151                                 tw.WriteStartElement ("soap","address", MetaData.SoapNamespace);
152                                 tw.WriteAttributeString ("location", st.Url);
153                                 tw.WriteEndElement ();
154                         }
155                         
156                         tw.WriteEndElement ();
157                 }
158                 
159                 void WriteServiceBinding  (XmlTextWriter tw, ServiceType st, Hashtable dataTypes)
160                 {
161                         Type type = st.ObjectType;
162                         string typeName = type.Name;
163                         MethodInfo[] mets = type.GetMethods (BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
164                         bool isService = IsService (type);
165                         
166                         // Messages
167                         
168                         if (isService)
169                         {
170                                 foreach (MethodInfo met in mets)
171                                 {
172                                         if (met.DeclaringType.Assembly == typeof(object).Assembly) continue;
173                                         
174                                         ParameterInfo[] pars = met.GetParameters ();
175                                         tw.WriteStartElement ("message", MetaData.WsdlNamespace);
176                                         tw.WriteAttributeString ("name", typeName + "." + met.Name + "Input");
177                                         foreach (ParameterInfo par in pars)
178                                         {
179                                                 if (!par.ParameterType.IsByRef)
180                                                         WritePart (tw, par.Name, par.ParameterType, type);
181                                         }
182                                         tw.WriteEndElement ();  // message
183                                         
184                                         tw.WriteStartElement ("message", MetaData.WsdlNamespace);
185                                         tw.WriteAttributeString ("name", typeName + "." + met.Name + "Output");
186                                         
187                                         if (met.ReturnType != typeof(void))
188                                                 WritePart (tw, "return", met.ReturnType, type);
189                                         
190                                         foreach (ParameterInfo par in pars)
191                                         {
192                                                 if (par.ParameterType.IsByRef || par.IsOut)
193                                                         WritePart (tw, par.Name, par.ParameterType, type);
194                                         }
195                                         tw.WriteEndElement ();  // message
196                                 }
197                         }
198                         
199                         // Port type
200                         
201                         tw.WriteStartElement ("portType", MetaData.WsdlNamespace);
202                         tw.WriteAttributeString ("name", typeName + "PortType");
203                         
204                         if (isService)
205                         {
206                                 foreach (MethodInfo met in mets)
207                                 {
208                                         if (met.DeclaringType.Assembly == typeof(object).Assembly) continue;
209                                         
210                                         tw.WriteStartElement ("operation", MetaData.WsdlNamespace);
211                                         tw.WriteAttributeString ("name", met.Name);
212                                         
213                                         StringBuilder sb = new StringBuilder ();
214                                         ParameterInfo[] pars = met.GetParameters ();
215                                         foreach (ParameterInfo par in pars)
216                                         {
217                                                 if (sb.Length != 0) sb.Append (" ");
218                                                 sb.Append (par.Name);
219                                         }
220                                         tw.WriteAttributeString ("parameterOrder", sb.ToString ());
221                                         
222                                         tw.WriteStartElement ("input", MetaData.WsdlNamespace);
223                                         tw.WriteAttributeString ("name", met.Name + "Request");
224                                         tw.WriteAttributeString ("message", "tns:" + typeName + "." + met.Name + "Input");
225                                         tw.WriteEndElement ();
226                                         
227                                         tw.WriteStartElement ("output", MetaData.WsdlNamespace);
228                                         tw.WriteAttributeString ("name", met.Name + "Response");
229                                         tw.WriteAttributeString ("message", "tns:" + typeName + "." + met.Name + "Output");
230                                         tw.WriteEndElement ();
231                                         
232                                         tw.WriteEndElement ();  // operation
233                                 }
234                         }
235                         tw.WriteEndElement ();  // portType
236                         
237                         // Binding
238                         
239                         tw.WriteStartElement ("binding", MetaData.WsdlNamespace);
240                         tw.WriteAttributeString ("name", typeName + "Binding");
241                         tw.WriteAttributeString ("type", "tns:" + typeName + "PortType");
242
243                         tw.WriteStartElement ("soap", "binding", MetaData.SoapNamespace);
244                         tw.WriteAttributeString ("style", "rpc");
245                         tw.WriteAttributeString ("transport", "http://schemas.xmlsoap.org/soap/http");
246                         tw.WriteEndElement ();
247                         
248                         WriteTypeSuds (tw, type);
249                         
250                         SchemaInfo sinfo = (SchemaInfo) dataTypes [GetXmlNamespace (type,null)];
251                         if (sinfo != null && !sinfo.SudsGenerated)
252                         {
253                                 foreach (Type dt in sinfo.Types)
254                                         WriteTypeSuds (tw, dt);
255                                 sinfo.SudsGenerated = true;
256                         }
257                         
258                         if (isService)
259                         {
260                                 foreach (MethodInfo met in mets)
261                                 {
262                                         if (met.DeclaringType.Assembly == typeof(object).Assembly) continue;
263                                         
264                                         tw.WriteStartElement ("operation", MetaData.WsdlNamespace);
265                                         tw.WriteAttributeString ("name", met.Name);
266                                         
267                                         tw.WriteStartElement ("soap", "operation", MetaData.SoapNamespace);
268                                         tw.WriteAttributeString ("soapAction", GetSoapAction (met));
269                                         tw.WriteEndElement ();
270                                         
271                                         tw.WriteStartElement ("suds", "method", MetaData.SudsNamespace);
272                                         tw.WriteAttributeString ("attributes", "public");
273                                         tw.WriteEndElement ();
274                                         
275                                         tw.WriteStartElement ("input", MetaData.WsdlNamespace);
276                                         tw.WriteAttributeString ("name", met.Name + "Request");
277                                         WriteMessageBindingBody (tw, type);
278                                         tw.WriteEndElement ();
279                                         
280                                         tw.WriteStartElement ("output", MetaData.WsdlNamespace);
281                                         tw.WriteAttributeString ("name", met.Name + "Response");
282                                         WriteMessageBindingBody (tw, type);
283                                         tw.WriteEndElement ();
284                                         
285                                         tw.WriteEndElement ();  // operation
286                                 }
287                         }
288                         tw.WriteEndElement ();  // binding
289                 }
290                 
291                 void WriteTypeSuds (XmlTextWriter tw, Type type)
292                 {
293                         if (type.IsArray || type.IsEnum)
294                         {
295                                 return;
296                         }
297                         else if (type.IsInterface)
298                         {
299                                 tw.WriteStartElement ("suds", "interface", MetaData.SudsNamespace);
300                                 tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, type, null));
301                                 foreach (Type interf in type.GetInterfaces ()) {
302                                         tw.WriteStartElement ("suds","extends", MetaData.SudsNamespace);
303                                         tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, interf, null));
304                                         tw.WriteEndElement ();
305                                 }
306                         }
307                         else if (type.IsValueType)
308                         {
309                                 tw.WriteStartElement ("suds", "struct", MetaData.SudsNamespace);
310                                 tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, type, null));
311                                 if (type.BaseType != typeof(ValueType))
312                                         tw.WriteAttributeString ("extends", GetQualifiedXmlType (tw, type.BaseType, null));
313                         }
314                         else
315                         {
316                                 tw.WriteStartElement ("suds", "class", MetaData.SudsNamespace);
317                                 tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, type, null));
318                                 
319                                 if (IsService (type))
320                                 {
321                                         if (type.IsMarshalByRef)
322                                                 tw.WriteAttributeString ("rootType", "MarshalByRefObject");
323                                         else
324                                                 tw.WriteAttributeString ("rootType", "Delegate");
325                                         
326                                         if (type.BaseType != typeof(MarshalByRefObject))
327                                                 tw.WriteAttributeString ("extends", GetQualifiedXmlType (tw, type.BaseType, null));
328                                                 
329                                         if (type.IsMarshalByRef) {
330                                                 foreach (Type interf in type.GetInterfaces ()) {
331                                                         tw.WriteStartElement ("suds","implements", MetaData.SudsNamespace);
332                                                         tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, interf, null));
333                                                         tw.WriteEndElement ();
334                                                 }
335                                         }
336                                 }
337                                 else if (typeof(ISerializable).IsAssignableFrom (type))
338                                         tw.WriteAttributeString ("rootType", "ISerializable");
339                                         
340                         }
341                         tw.WriteEndElement ();  // suds
342                 }
343                 
344                 void WriteMessageBindingBody (XmlTextWriter tw, Type t)
345                 {
346                         tw.WriteStartElement ("soap", "body", MetaData.SoapNamespace);
347                         tw.WriteAttributeString ("use", "encoded");
348                         tw.WriteAttributeString ("encodingStyle", MetaData.SoapEncodingNamespace);
349                         tw.WriteAttributeString ("namespace", GetXmlNamespace (t, null));
350                         tw.WriteEndElement ();
351                 }
352                 
353                 void WritePart (XmlTextWriter tw, string name, Type t, Type containerType)
354                 {
355                         tw.WriteStartElement ("part", MetaData.WsdlNamespace);
356                         tw.WriteAttributeString ("name", name);
357                         tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, t, containerType));
358                         tw.WriteEndElement ();
359                 }
360                 
361                 void WriteDataTypeSchema (XmlTextWriter tw, Type type)
362                 {
363                         if (type.IsArray)
364                                 WriteArraySchema (tw, type);
365                         else if (type.IsEnum)
366                                 WriteEnumSchema (tw, type);
367                         else
368                                 WriteClassSchema (tw, type);
369                 }
370                 
371                 void WriteArraySchema (XmlTextWriter tw, Type type)
372                 {
373                         tw.WriteStartElement ("complexType", MetaData.SchemaNamespace);
374                         tw.WriteAttributeString ("name", GetXmlType (type));
375                         tw.WriteStartElement ("complexContent", MetaData.SchemaNamespace);
376                         tw.WriteStartElement ("restriction", MetaData.SchemaNamespace);
377                         tw.WriteAttributeString ("base", GetQualifiedName (tw, MetaData.SoapEncodingNamespace, "Array"));
378                         tw.WriteStartElement ("attribute", MetaData.SchemaNamespace);
379                         tw.WriteAttributeString ("ref", GetQualifiedName (tw, MetaData.SoapEncodingNamespace, "arrayType"));
380                         
381                         string arrayType = "";
382                         
383                         while (type.IsArray)
384                         {
385                                 arrayType = arrayType + "[" + new string (',', type.GetArrayRank()-1) + "]";
386                                 type = type.GetElementType ();
387                         }
388                         arrayType = GetQualifiedXmlType (tw, type, null) + arrayType;
389                         
390                         tw.WriteAttributeString ("wsdl", "arrayType", MetaData.WsdlNamespace, arrayType);
391                         tw.WriteEndElement ();  // attribute
392                         tw.WriteEndElement ();  // restriction
393                         tw.WriteEndElement ();  // complexContent
394                         tw.WriteEndElement ();  // complexType
395                 }
396                 
397                 void WriteEnumSchema (XmlTextWriter tw, Type type)
398                 {
399                         tw.WriteStartElement ("simpleType", MetaData.SchemaNamespace);
400                         tw.WriteAttributeString ("name", GetXmlType (type));
401                         tw.WriteAttributeString ("suds", "enumType", MetaData.SudsNamespace, GetQualifiedXmlType (tw, EnumToUnderlying (type), null));
402                         tw.WriteStartElement ("restriction", MetaData.SchemaNamespace);
403                         tw.WriteAttributeString ("base", "xsd:string");
404                         
405                         foreach (string name in Enum.GetNames (type))
406                         {
407                                 tw.WriteStartElement ("enumeration", MetaData.SchemaNamespace);
408                                 tw.WriteAttributeString ("value", name);
409                                 tw.WriteEndElement ();
410                         }
411                         tw.WriteEndElement ();  // restriction
412                         tw.WriteEndElement ();  // simpleType
413                 }
414                 
415                 void WriteClassSchema (XmlTextWriter tw, Type type)
416                 {
417                         tw.WriteStartElement ("element", MetaData.SchemaNamespace);
418                         tw.WriteAttributeString ("name", type.Name);
419                         tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, type, null));
420                         tw.WriteEndElement ();
421                         
422                         tw.WriteStartElement ("complexType", MetaData.SchemaNamespace);
423                         tw.WriteAttributeString ("name", GetXmlType (type));
424                         if (type.BaseType != null && type.BaseType != typeof(object) && type.BaseType != typeof(ValueType))
425                                 tw.WriteAttributeString ("base", GetQualifiedXmlType (tw, type.BaseType, null));
426                         
427                         FieldInfo[] fields = type.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
428                         
429                         // Element fields
430                         
431                         bool elemsStart = false;
432                         foreach (FieldInfo fi in fields)
433                         {
434                                 SoapFieldAttribute att = (SoapFieldAttribute) InternalRemotingServices.GetCachedSoapAttribute (fi);
435                                 if (att.UseAttribute) continue;
436                         
437                                 if (!elemsStart) { tw.WriteStartElement ("all", MetaData.SchemaNamespace); elemsStart = true; }
438                                 tw.WriteStartElement ("element", MetaData.SchemaNamespace);
439                                 tw.WriteAttributeString ("name", att.XmlElementName);
440                                 tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, fi.FieldType, type));
441                                 tw.WriteEndElement ();
442                         }
443                         if (elemsStart) tw.WriteEndElement ();  // all
444                         
445                         // Attribute fields
446                         
447                         foreach (FieldInfo fi in fields)
448                         {
449                                 SoapFieldAttribute att = (SoapFieldAttribute) InternalRemotingServices.GetCachedSoapAttribute (fi);
450                                 if (!att.UseAttribute) continue;
451                         
452                                 tw.WriteStartElement ("attribute", MetaData.SchemaNamespace);
453                                 tw.WriteAttributeString ("name", att.XmlElementName);
454                                 tw.WriteAttributeString ("type", GetQualifiedXmlType (tw, fi.FieldType, type));
455                                 tw.WriteEndElement ();
456                         }
457                         
458                         tw.WriteEndElement ();  // complexType
459                         
460                 }
461                 
462                 ArrayList FindServices (ServiceType[] servicetypes)
463                 {
464                         ArrayList list = new ArrayList ();
465                         foreach (ServiceType st in servicetypes)
466                                 if (IsService (st.ObjectType)) list.Add (st);
467                         return list;
468                 }
469                 
470                 string GetSoapAction (MethodInfo mb)
471                 {
472                         return SoapServices.GetSoapActionFromMethodBase (mb);
473                 }
474                 
475                 string GetXmlNamespace (Type t, Type containerType)
476                 {
477                         string name, ns;
478                         
479                         if (t.IsArray)
480                         {
481                                 return GetXmlNamespace (containerType, null);
482                         }
483
484                         if (SoapServices.GetXmlTypeForInteropType (t, out name, out ns))
485                                 return ns;
486                                 
487                         SoapTypeAttribute att = (SoapTypeAttribute) InternalRemotingServices.GetCachedSoapAttribute (t);
488                         return att.XmlNamespace;
489                 }
490                 
491                 string GetQualifiedName (XmlTextWriter tw, string namspace, string localName)
492                 {
493                         return tw.LookupPrefix (namspace) + ":" + localName;
494                 }
495                 
496                 string GetQualifiedXmlType (XmlTextWriter tw, Type type, Type containerType)
497                 {
498                         string name, ns;
499                         
500                         if (type.IsArray)
501                         {
502                                 name = GetXmlType (type);
503                                 ns = GetXmlNamespace (type, containerType);
504                         }
505                         else
506                         {
507                                 name = GetXsdType (type);                                       
508                                 if (name != null) return "xsd:" + name;
509                                 
510                                 if (!SoapServices.GetXmlTypeForInteropType (type, out name, out ns))
511                                 {
512                                         SoapTypeAttribute att = (SoapTypeAttribute) InternalRemotingServices.GetCachedSoapAttribute (type);
513                                         name = att.XmlTypeName;
514                                         ns = att.XmlNamespace;
515                                 }
516                         }
517                         
518                         return GetQualifiedName (tw, ns, name);
519                 }
520                 
521                 string GetXmlType (Type type)
522                 {
523                         if (type.IsArray)
524                         {
525                                 string itemType = GetXmlType (type.GetElementType ());
526                                 itemType = "ArrayOf" + char.ToUpper (itemType[0]) + itemType.Substring (1);
527                                 if (type.GetArrayRank () > 1) itemType += type.GetArrayRank ();
528                                 return itemType;
529                         }
530                         else
531                         {
532                                 string name = null, ns;
533                                 
534                                 name = GetXsdType (type);
535                                 if (name != null) return name;
536                                 
537                                 if (SoapServices.GetXmlTypeForInteropType (type, out name, out ns))
538                                         return name;
539                                         
540                                 SoapTypeAttribute att = (SoapTypeAttribute) InternalRemotingServices.GetCachedSoapAttribute (type);
541                                 return att.XmlTypeName;
542                         }
543                 }
544                 
545                 string GetServiceName (Type t)
546                 {
547                         return t.Name + "Service";
548                 }
549                 
550                 string GetPortName (Type t)
551                 {
552                         return t.Name + "Port";
553                 }
554                 
555                 string GetBindingName (Type t)
556                 {
557                         return t.Name + "Binding";
558                 }
559                 
560                 void FindTypes (ServiceType[] servicetypes, Hashtable dataTypes, ArrayList services)
561                 {
562                         ArrayList mbrTypes = new ArrayList();
563                         
564                         foreach (ServiceType st in servicetypes)
565                                 FindDataTypes (st.ObjectType, null, dataTypes, mbrTypes);
566                                 
567                         foreach (Type mbrType in mbrTypes)
568                         {
569                                 ServiceType stFound = null;
570                                 foreach (ServiceType st in servicetypes)
571                                         if (mbrType == st.ObjectType) stFound = st;
572                                         
573                                 if (stFound != null) services.Add (stFound);
574                                 else services.Add (new ServiceType (mbrType));
575                         }
576                 }
577                 
578                 void FindDataTypes (Type t, Type containerType, Hashtable types, ArrayList services)
579                 {
580                         if (IsSystemType (t))
581                         {
582                                 string ns = GetXmlNamespace (t, null);
583                                 types [ns] = null;
584                                 return;
585                         }
586                         
587                         if (!IsService (t))
588                         {
589                                 if (!t.IsSerializable) return;
590                                 
591                                 string ns = GetXmlNamespace (t, containerType);
592                                 SchemaInfo sinfo = (SchemaInfo) types [ns];
593                                 if (sinfo == null)
594                                 {
595                                         sinfo = new SchemaInfo ();
596                                         types [ns] = sinfo;
597                                 }
598                                 
599                                 if (sinfo.Types.Contains (t)) return;
600                                 
601                                 sinfo.Types.Add (t);
602                                 if (t.IsArray) return;
603                                 
604                                 FieldInfo[] fields = t.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
605                                 foreach (FieldInfo fi in fields)
606                                 {
607                                         string fns = GetXmlNamespace (fi.FieldType, t);
608                                         if (!sinfo.Imports.Contains (fns)) sinfo.Imports.Add (fns);
609                                         FindDataTypes (fi.FieldType, t, types, services);
610                                 }
611                         }
612                         else
613                         {
614                                 if (services.Contains (t)) return;
615                                 services.Add (t);
616                                 
617                                 foreach (MethodInfo met in t.GetMethods (BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
618                                 {
619                                         ParameterInfo[] pars = met.GetParameters ();
620                                         foreach (ParameterInfo par in pars)
621                                                 FindDataTypes (par.ParameterType, t, types, services);
622                                                         
623                                         FindDataTypes (met.ReturnType, t, types, services);
624                                 }
625                         }
626                 }
627                 
628                 bool IsService (Type t)
629                 {
630                         return t.IsMarshalByRef || t.IsInterface || typeof(Delegate).IsAssignableFrom (t);
631                 }
632                 
633                 bool IsSystemType (Type t)
634                 {
635                         return t.FullName.StartsWith ("System.") && !t.IsArray;
636                 }
637                 
638                 static string GetXsdType (Type type)
639                 {
640                         if (type.IsEnum) return null;
641                         
642                         switch (Type.GetTypeCode (type))
643                         {
644                                 case TypeCode.Boolean: return "boolean";
645                                 case TypeCode.Byte: return "unsignedByte";
646                                 case TypeCode.Char: return "char";
647                                 case TypeCode.DateTime: return "dateTime";
648                                 case TypeCode.Decimal: return "decimal";
649                                 case TypeCode.Double: return "double";
650                                 case TypeCode.Int16: return "short";
651                                 case TypeCode.Int32: return "int";
652                                 case TypeCode.Int64: return "long";
653                                 case TypeCode.SByte: return "byte";
654                                 case TypeCode.Single: return "float";
655                                 case TypeCode.UInt16: return "unsignedShort";
656                                 case TypeCode.UInt32: return "unsignedInt";
657                                 case TypeCode.UInt64: return "unsignedLong";
658                                 case TypeCode.String: return "string";
659                         }
660                         
661                         if (type == typeof (TimeSpan))
662                                 return "duration";
663                         if (type == typeof (object))
664                                 return "anyType";
665                                 
666                         return null;
667                 }
668                 
669                 //
670                 // This is needed, because enumerations from assemblies
671                 // do not report their underlyingtype, but they report
672                 // themselves
673                 //
674                 public static Type EnumToUnderlying (Type t)
675                 {
676                         TypeCode tc = Type.GetTypeCode (t);
677         
678                         switch (tc){
679                         case TypeCode.Boolean:
680                                 return typeof (bool);
681                         case TypeCode.Byte:
682                                 return typeof (byte);
683                         case TypeCode.SByte:
684                                 return typeof (sbyte);
685                         case TypeCode.Int16:
686                                 return typeof (short);
687                         case TypeCode.UInt16:
688                                 return typeof (ushort);
689                         case TypeCode.Int32:
690                                 return typeof (int);
691                         case TypeCode.UInt32:
692                                 return typeof (uint);
693                         case TypeCode.Int64:
694                                 return typeof (long);
695                         case TypeCode.UInt64:
696                                 return typeof (ulong);
697                         }
698                         throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
699                 }
700         }
701         
702         class SchemaInfo
703         {
704                 public ArrayList Types = new ArrayList ();
705                 public ArrayList Imports = new ArrayList ();
706                 public bool SudsGenerated;
707         }
708 }