[LoongArch64] Part-5:add loongarch support in some files for LoongArch64. (#21769)
[mono-project.git] / mcs / class / System.Runtime.Remoting / System.Runtime.Remoting.MetadataServices / MetaDataCodeGenerator.cs
blob707f5087495aa3d73cfad94e3f4a4943ef6a282d
1 //
2 // System.Runtime.Remoting.MetadataServices.MetaDataCodeGenerator
3 //
4 // Authors:
5 // Lluis Sanchez Gual (lluis@ximian.com)
6 //
7 // (C) 2003 Novell, Inc
8 //
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.
31 using System.Collections;
32 using System.IO;
33 using System.Xml;
34 using System.Reflection;
35 using System.Runtime.Remoting;
36 using System.Runtime.Remoting.Metadata;
38 namespace System.Runtime.Remoting.MetadataServices
40 internal class MetaDataCodeGenerator
42 XmlDocument doc;
43 CodeFile currentFile;
44 XmlNamespaceManager nsManager;
45 Hashtable sudsTypes;
47 public void GenerateCode (bool clientProxy, string outputDirectory, Stream inputStream,
48 ArrayList outCodeStreamList, string proxyUrl, string proxyNamespace)
50 doc = new XmlDocument ();
51 doc.Load (inputStream);
53 nsManager = new XmlNamespaceManager (doc.NameTable);
54 nsManager.AddNamespace ("wsdl", MetaData.WsdlNamespace);
55 nsManager.AddNamespace ("s", MetaData.SchemaNamespace);
56 nsManager.AddNamespace ("suds", MetaData.SudsNamespace);
58 if (outputDirectory == null) outputDirectory = Directory.GetCurrentDirectory();
60 CodeFile mainFile = new CodeFile (outputDirectory);
62 currentFile = mainFile;
64 // Suds types
66 sudsTypes = new Hashtable ();
67 XmlNodeList nodes = doc.DocumentElement.SelectNodes ("wsdl:binding/suds:class|wsdl:binding/suds:interface|wsdl:binding/suds:struct", nsManager);
68 foreach (XmlElement node in nodes)
69 sudsTypes [GetTypeQualifiedName (node, node.GetAttribute ("type"))] = node;
71 // Data types
73 nodes = doc.SelectNodes ("wsdl:definitions/wsdl:types/s:schema", nsManager);
74 foreach (XmlElement schema in nodes)
75 GenerateSchemaCode (schema);
77 // Services
79 nodes = doc.SelectNodes ("wsdl:definitions/wsdl:service/wsdl:port", nsManager);
80 foreach (XmlElement port in nodes)
81 GeneratePortCode (port);
83 mainFile.Write ();
84 if (mainFile.FileName != null)
85 outCodeStreamList.Add (mainFile.FilePath);
88 void GeneratePortCode (XmlElement port)
90 XmlElement binding = GetBinding (port.GetAttribute ("binding"));
91 XmlElement type = null;
92 foreach (XmlNode node in binding)
93 if ((node is XmlElement) && ((XmlElement)node).NamespaceURI == MetaData.SudsNamespace)
94 { type = (XmlElement) node; break; }
96 string rootType = type.GetAttribute ("rootType");
97 if (rootType == "Delegate")
98 GenerateServiceDelegateCode (port, binding, type);
99 else
100 GenerateServiceClassCode (port, binding, type);
103 void GenerateServiceDelegateCode (XmlElement port, XmlElement binding, XmlElement type)
105 string typeName = (type != null) ? type.GetAttribute ("type") : port.GetAttribute ("name");
106 string portName = GetNameFromQn (binding.GetAttribute ("type"));
108 string name, ns;
109 GetTypeQualifiedName (port, typeName, out name, out ns);
110 currentFile.SetCurrentNamespace (ns);
112 XmlElement oper = (XmlElement) binding.SelectSingleNode ("wsdl:operation[@name='Invoke']", nsManager);
113 if (oper == null) throw new InvalidOperationException ("Invalid delegate schema");
115 string parsDec;
116 string returnType;
117 GetParameters (oper, portName, "Invoke", out parsDec, out returnType);
119 currentFile.WriteLine ("public delegate " + returnType + " " + name + " (" + parsDec + ");");
120 currentFile.WriteLine ("");
123 void GenerateServiceClassCode (XmlElement port, XmlElement binding, XmlElement type)
125 string typeName = (type != null) ? type.GetAttribute ("type") : port.GetAttribute ("name");
127 string name, ns;
128 GetTypeQualifiedName (port, typeName, out name, out ns);
129 currentFile.SetCurrentNamespace (ns);
131 string cls = "public " + type.LocalName + " " + name;
132 string baset = type.GetAttribute ("extends");
133 if (baset != "") cls += ": " + GetTypeQualifiedName (port, baset);
135 // Interfaces
137 XmlNodeList interfaces = type.SelectNodes ("suds:implements",nsManager);
138 if (interfaces.Count == 0) interfaces = type.SelectNodes ("suds:extends",nsManager);
140 foreach (XmlElement interf in interfaces)
142 string iname = GetTypeQualifiedName (interf, interf.GetAttribute ("type"));
143 if (cls.IndexOf (':') == -1) cls += ": " + iname;
144 else cls += ", " + iname;
147 currentFile.WriteLine (cls);
148 currentFile.WriteLineInd ("{");
150 string portName = GetNameFromQn (binding.GetAttribute ("type"));
151 bool isInterface = type.LocalName == "interface";
153 string vis = isInterface? "":"public ";
155 ArrayList mets = GetMethods (portName, binding);
156 foreach (MethodData met in mets)
158 if (met.IsProperty)
160 string prop = vis + met.ReturnType + " ";
161 if (met.Signature != "") prop += "this [" + met.Signature + "]";
162 else prop += met.Name;
164 if (isInterface)
166 prop += " { ";
167 if (met.HasGet) prop += "get; ";
168 if (met.HasSet) prop += "set; ";
169 prop += "}";
170 currentFile.WriteLine (prop);
172 else
174 currentFile.WriteLine (prop);
175 currentFile.WriteLineInd ("{");
176 if (met.HasGet) currentFile.WriteLine ("get { throw new NotImplementedException (); }");
177 if (met.HasSet) currentFile.WriteLine ("set { throw new NotImplementedException (); }");
178 currentFile.WriteLineUni ("}");
179 currentFile.WriteLine ("");
182 else
184 currentFile.WriteLine (vis + met.ReturnType + " " + met.Name + " (" + met.Signature + ")" + (isInterface?";":""));
185 if (!isInterface)
187 currentFile.WriteLineInd ("{");
188 currentFile.WriteLine ("throw new NotImplementedException ();");
189 currentFile.WriteLineUni ("}");
190 currentFile.WriteLine ("");
195 currentFile.WriteLineUni ("}");
196 currentFile.WriteLine ("");
199 class MethodData
201 public string ReturnType;
202 public string Signature;
203 public string Name;
204 public bool HasSet;
205 public bool HasGet;
207 public bool IsProperty { get { return HasGet || HasSet; } }
210 ArrayList GetMethods (string portName, XmlElement binding)
212 ArrayList mets = new ArrayList ();
214 XmlNodeList nodes = binding.SelectNodes ("wsdl:operation", nsManager);
215 foreach (XmlElement oper in nodes)
217 MethodData md = new MethodData ();
218 md.Name = oper.GetAttribute ("name");
220 GetParameters (oper, portName, md.Name, out md.Signature, out md.ReturnType);
222 if (md.Name.StartsWith ("set_") || md.Name.StartsWith ("get_"))
224 string tmp = ", " + md.Signature;
225 if (tmp.IndexOf (", out ") == -1 && tmp.IndexOf (", ref ") == -1)
227 bool isSet = md.Name[0]=='s';
228 md.Name = md.Name.Substring (4);
229 MethodData previousProp = null;
231 foreach (MethodData fmd in mets)
232 if (fmd.Name == md.Name && fmd.IsProperty)
233 previousProp = fmd;
235 if (previousProp != null) {
236 if (isSet) previousProp.HasSet = true;
237 else { previousProp.HasGet = true; previousProp.Signature = md.Signature; }
238 continue;
240 else {
241 if (isSet) { md.HasSet = true; md.Signature = ""; }
242 else md.HasGet = true;
247 mets.Add (md);
249 return mets;
252 void GetParameters (XmlElement oper, string portName, string operName, out string signature, out string returnType)
254 returnType = null;
256 XmlElement portType = (XmlElement) doc.SelectSingleNode ("wsdl:definitions/wsdl:portType[@name='" + portName + "']", nsManager);
257 XmlElement portOper = (XmlElement) portType.SelectSingleNode ("wsdl:operation[@name='" + operName + "']", nsManager);
258 string[] parNames = portOper.GetAttribute ("parameterOrder").Split (' ');
260 XmlElement inPortMsg = (XmlElement) portOper.SelectSingleNode ("wsdl:input", nsManager);
261 XmlElement inMsg = FindMessageFromPortMessage (inPortMsg);
263 XmlElement outPortMsg = (XmlElement) portOper.SelectSingleNode ("wsdl:output", nsManager);
264 XmlElement outMsg = FindMessageFromPortMessage (outPortMsg);
266 string[] parameters;
267 if (parNames [0] != "") parameters = new string [parNames.Length];
268 else parameters = new string [0];
270 foreach (XmlElement part in inMsg.SelectNodes ("wsdl:part",nsManager))
272 int i = Array.IndexOf (parNames, part.GetAttribute ("name"));
273 string type = GetTypeQualifiedName (part, part.GetAttribute ("type"));
274 parameters [i] = type + " " + parNames [i];
277 foreach (XmlElement part in outMsg.SelectNodes ("wsdl:part",nsManager))
279 string pn = part.GetAttribute ("name");
280 string type = GetTypeQualifiedName (part, part.GetAttribute ("type"));
282 if (pn == "return")
283 returnType = type;
284 else {
285 int i = Array.IndexOf (parNames, pn);
286 if (parameters [i] != null) parameters [i] = "ref " + parameters [i];
287 else parameters [i] = "out " + type + " " + pn;
291 signature = string.Join (", ", parameters);
292 if (returnType == null) returnType = "void";
295 XmlElement FindMessageFromPortMessage (XmlElement portMsg)
297 string msgName = portMsg.GetAttribute ("message");
298 msgName = GetNameFromQn (msgName);
299 return (XmlElement) doc.SelectSingleNode ("wsdl:definitions/wsdl:message[@name='" + msgName + "']", nsManager);
302 void GenerateSchemaCode (XmlElement schema)
304 string ns = schema.GetAttribute ("targetNamespace");
305 string clrNs = DecodeNamespace (ns);
306 currentFile.SetCurrentNamespace (clrNs);
308 foreach (XmlNode node in schema)
310 XmlElement elem = node as XmlElement;
311 if (elem == null) continue;
313 if (elem.LocalName == "complexType")
314 GenerateClassCode (ns, elem);
315 else if (elem.LocalName == "simpleType")
316 GenerateEnumCode (ns, elem);
320 void GenerateClassCode (string ns, XmlElement elem)
322 if (elem.SelectSingleNode ("s:complexContent/s:restriction", nsManager) != null) return;
323 string clrNs = DecodeNamespace (ns);
324 string typeName = GetTypeName (elem.GetAttribute ("name"), ns);
326 XmlElement sudsType = (XmlElement) sudsTypes [clrNs + "." + typeName];
328 string typetype = "class";
329 if (sudsType != null) typetype = sudsType.LocalName;
331 currentFile.WriteLine ("[Serializable, SoapType (XmlNamespace = @\"" + ns + "\", XmlTypeNamespace = @\"" + ns + "\")]");
333 string cls = "public " + typetype + " " + typeName;
334 string baseType = elem.GetAttribute ("base");
335 if (baseType != "") cls += ": " + GetTypeQualifiedName (elem, baseType);
337 bool isSerializable = (sudsType.GetAttribute ("rootType") == "ISerializable");
339 if (isSerializable)
341 if (cls.IndexOf (':') == -1) cls += ": ";
342 else cls += ", ";
343 cls += "System.Runtime.Serialization.ISerializable";
346 currentFile.WriteLine (cls);
347 currentFile.WriteLineInd ("{");
349 XmlNodeList elems = elem.GetElementsByTagName ("element", MetaData.SchemaNamespace);
350 foreach (XmlElement elemField in elems)
351 WriteField (elemField);
353 elems = elem.GetElementsByTagName ("attribute", MetaData.SchemaNamespace);
354 foreach (XmlElement elemField in elems)
355 WriteField (elemField);
357 if (isSerializable)
359 currentFile.WriteLine ("");
360 currentFile.WriteLine ("public " + typeName + " ()");
361 currentFile.WriteLineInd ("{");
362 currentFile.WriteLineUni ("}");
363 currentFile.WriteLine ("");
365 currentFile.WriteLine ("public " + typeName + " (System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)");
366 currentFile.WriteLineInd ("{");
367 currentFile.WriteLine ("throw new NotImplementedException ();");
368 currentFile.WriteLineUni ("}");
369 currentFile.WriteLine ("");
371 currentFile.WriteLine ("public void GetObjectData (System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)");
372 currentFile.WriteLineInd ("{");
373 currentFile.WriteLine ("throw new NotImplementedException ();");
374 currentFile.WriteLineUni ("}");
377 currentFile.WriteLineUni ("}");
378 currentFile.WriteLine ("");
381 void WriteField (XmlElement elemField)
383 bool isAttr = elemField.LocalName == "attribute";
385 string type = elemField.GetAttribute ("type");
387 if (isAttr)
388 currentFile.WriteLine ("[SoapField (UseAttribute = true)]");
389 else if (!IsPrimitive (elemField, type))
390 currentFile.WriteLine ("[SoapField (Embedded = true)]");
391 currentFile.WriteLine ("public " + GetTypeQualifiedName (elemField, type) + " " + elemField.GetAttribute ("name") + ";");
394 void GenerateEnumCode (string ns, XmlElement elem)
396 currentFile.WriteLine ("public enum " + GetTypeName (elem.GetAttribute ("name"), ns));
397 currentFile.WriteLineInd ("{");
399 XmlNodeList nodes = elem.SelectNodes ("s:restriction/s:enumeration/@value", nsManager);
400 foreach (XmlNode node in nodes)
401 currentFile.WriteLine (node.Value + ",");
403 currentFile.WriteLineUni ("}");
404 currentFile.WriteLine ("");
407 bool IsPrimitive (XmlNode node, string qname)
409 string name = GetTypeQualifiedName (node, qname);
410 return name.IndexOf ('.') == -1;
413 string GetTypeName (string localName, string ns)
415 return localName;
418 void GetTypeQualifiedName (XmlNode node, string qualifiedName, out string name, out string ns)
420 int i = qualifiedName.IndexOf (':');
421 if (i == -1)
423 name = qualifiedName;
424 ns = "";
425 return;
428 string prefix = qualifiedName.Substring (0,i);
429 name = qualifiedName.Substring (i+1);
430 ns = node.GetNamespaceOfPrefix (prefix);
432 string arrayType = GetArrayType (node, name, ns);
433 if (arrayType != null) {
434 name = arrayType;
435 ns = "";
437 else if (ns != MetaData.SchemaNamespace) {
438 ns = DecodeNamespace (ns);
440 else {
441 ns = "";
442 name = GetClrFromXsd (name);
446 string GetClrFromXsd (string type)
448 switch (type)
450 case "boolean": return "bool";
451 case "unsignedByte": return "byte";
452 case "char": return "char";
453 case "dateTime": return "DateTime";
454 case "decimal": return "decimal";
455 case "double": return "double";
456 case "short": return "short";
457 case "int": return "int";
458 case "long": return "long";
459 case "byte": return "sbyte";
460 case "float": return "float";
461 case "unsignedShort": return "ushort";
462 case "unsignedInt": return "uint";
463 case "unsignedLong": return "ulong";
464 case "string": return "string";
465 case "duration": return "TimeSpan";
466 case "anyType": return "object";
468 throw new InvalidOperationException ("Unknown schema type: " + type);
471 string GetTypeQualifiedName (XmlNode node, string qualifiedName)
473 string name, ns;
474 GetTypeQualifiedName (node, qualifiedName, out name, out ns);
475 if (ns != "") return ns + "." + name;
476 else return name;
479 string GetTypeNamespace (XmlNode node, string qualifiedName)
481 string name, ns;
482 GetTypeQualifiedName (node, qualifiedName, out name, out ns);
483 return ns;
486 string GetArrayType (XmlNode node, string name, string ns)
488 XmlNode anod = doc.SelectSingleNode ("wsdl:definitions/wsdl:types/s:schema[@targetNamespace='" + ns + "']/s:complexType[@name='" + name + "']/s:complexContent/s:restriction/s:attribute/@wsdl:arrayType", nsManager);
489 if (anod == null) return null;
491 string atype = anod.Value;
492 int i = atype.IndexOf ('[');
493 string itemType = GetTypeQualifiedName (node, atype.Substring (0,i));
495 return itemType + atype.Substring (i);
498 XmlElement GetBinding (string name)
500 int i = name.IndexOf (':');
501 name = name.Substring (i+1);
502 return doc.SelectSingleNode ("wsdl:definitions/wsdl:binding[@name='" + name + "']", nsManager) as XmlElement;
505 string DecodeNamespace (string xmlNamespace)
507 string tns, tasm;
509 if (!SoapServices.DecodeXmlNamespaceForClrTypeNamespace (xmlNamespace, out tns, out tasm))
510 tns = xmlNamespace;
512 return tns;
515 string GetLiteral (object ob)
517 if (ob == null) return "null";
518 if (ob is string) return "\"" + ob.ToString().Replace("\"","\"\"") + "\"";
519 if (ob is bool) return ((bool)ob) ? "true" : "false";
520 if (ob is XmlQualifiedName) {
521 XmlQualifiedName qn = (XmlQualifiedName)ob;
522 return "new XmlQualifiedName (" + GetLiteral(qn.Name) + "," + GetLiteral(qn.Namespace) + ")";
524 else return ob.ToString ();
527 string Params (params string[] pars)
529 string res = "";
530 foreach (string p in pars)
532 if (res != "") res += ", ";
533 res += p;
535 return res;
538 string GetNameFromQn (string qn)
540 int i = qn.IndexOf (':');
541 if (i == -1) return qn;
542 else return qn.Substring (i+1);
546 class CodeFile
548 public string FileName;
549 public string Directory;
550 public string FilePath;
551 Hashtable namespaces = new Hashtable ();
552 public StringWriter writer;
553 int indent;
555 public CodeFile (string directory)
557 Directory = directory;
560 public void SetCurrentNamespace (string ns)
562 writer = namespaces [ns] as StringWriter;
563 if (writer == null)
565 indent = 0;
566 writer = new StringWriter ();
567 namespaces [ns] = writer;
568 WriteLine ("namespace " + ns);
569 WriteLineInd ("{");
572 indent = 1;
574 if (FileName == null)
575 FileName = ns + ".cs";
578 public void WriteLineInd (string code)
580 WriteLine (code);
581 indent++;
584 public void WriteLineUni (string code)
586 if (indent > 0) indent--;
587 WriteLine (code);
590 public void WriteLine (string code)
592 if (code != "") writer.Write (new String ('\t',indent));
593 writer.WriteLine (code);
596 public void Write ()
598 if (FileName == null) return;
600 FilePath = Path.Combine (Directory, FileName);
601 StreamWriter sw = new StreamWriter (FilePath);
603 sw.WriteLine ("using System;");
604 sw.WriteLine ("using System.Runtime.Remoting.Metadata;");
605 sw.WriteLine ();
607 foreach (StringWriter nsWriter in namespaces.Values)
609 sw.Write (nsWriter.ToString ());
610 sw.WriteLine ("}");
611 sw.WriteLine ();
614 sw.Close ();