2010-04-07 Jb Evain <jbevain@novell.com>
[mcs.git] / class / corlib / System.Runtime.Remoting / SoapServices.cs
blob4efa68a1599b4ba5c594dfadcd97e0fb83b953bd
1 //
2 // System.Runtime.Remoting.SoapServices.cs
3 //
4 // Author: Jaime Anguiano Olarra (jaime@gnome.org)
5 // Lluis Sanchez Gual (lluis@ximian.com)
6 //
7 // (c) 2002, Jaime Anguiano Olarra
8 //
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System;
35 using System.Collections;
36 using System.Runtime.Remoting;
37 using System.Runtime.Remoting.Metadata;
38 using System.Reflection;
39 using System.Runtime.InteropServices;
41 namespace System.Runtime.Remoting {
43 [System.Runtime.InteropServices.ComVisible (true)]
44 public class SoapServices
46 static Hashtable _xmlTypes = new Hashtable ();
47 static Hashtable _xmlElements = new Hashtable ();
48 static Hashtable _soapActions = new Hashtable ();
49 static Hashtable _soapActionsMethods = new Hashtable ();
50 static Hashtable _typeInfos = new Hashtable ();
52 class TypeInfo
54 public Hashtable Attributes;
55 public Hashtable Elements;
58 // Private constructor: nobody instantiates this class
59 private SoapServices () {}
61 // properties
63 public static string XmlNsForClrType
65 get { return "http://schemas.microsoft.com/clr/"; }
68 public static string XmlNsForClrTypeWithAssembly
70 get { return "http://schemas.microsoft.com/clr/assem/"; }
73 public static string XmlNsForClrTypeWithNs
75 get { return "http://schemas.microsoft.com/clr/ns/"; }
78 public static string XmlNsForClrTypeWithNsAndAssembly
80 get { return "http://schemas.microsoft.com/clr/nsassem/"; }
84 // public methods
86 public static string CodeXmlNamespaceForClrTypeNamespace (string typeNamespace,
87 string assemblyName)
89 // If assemblyName is empty, then use the corlib namespace
91 if (assemblyName == string.Empty)
92 return XmlNsForClrTypeWithNs + typeNamespace;
93 else if (typeNamespace == string.Empty)
94 return EncodeNs (XmlNsForClrTypeWithAssembly + assemblyName);
95 else
96 return EncodeNs (XmlNsForClrTypeWithNsAndAssembly + typeNamespace + "/" + assemblyName);
99 public static bool DecodeXmlNamespaceForClrTypeNamespace (string inNamespace,
100 out string typeNamespace,
101 out string assemblyName) {
103 if (inNamespace == null) throw new ArgumentNullException ("inNamespace");
105 inNamespace = DecodeNs (inNamespace);
106 typeNamespace = null;
107 assemblyName = null;
109 if (inNamespace.StartsWith(XmlNsForClrTypeWithNsAndAssembly))
111 int typePos = XmlNsForClrTypeWithNsAndAssembly.Length;
112 if (typePos >= inNamespace.Length) return false;
113 int assemPos = inNamespace.IndexOf ('/', typePos+1);
114 if (assemPos == -1) return false;
115 typeNamespace = inNamespace.Substring (typePos, assemPos - typePos);
116 assemblyName = inNamespace.Substring (assemPos+1);
117 return true;
119 else if (inNamespace.StartsWith(XmlNsForClrTypeWithNs))
121 int typePos = XmlNsForClrTypeWithNs.Length;
122 typeNamespace = inNamespace.Substring (typePos);
123 return true;
125 else if (inNamespace.StartsWith(XmlNsForClrTypeWithAssembly))
127 int typePos = XmlNsForClrTypeWithAssembly.Length;
128 assemblyName = inNamespace.Substring (typePos);
129 return true;
131 else
132 return false;
135 public static void GetInteropFieldTypeAndNameFromXmlAttribute (Type containingType,
136 string xmlAttribute, string xmlNamespace,
137 out Type type, out string name)
139 TypeInfo tf = (TypeInfo) _typeInfos [containingType];
140 Hashtable ht = tf != null ? tf.Attributes : null;
141 GetInteropFieldInfo (ht, xmlAttribute, xmlNamespace, out type, out name);
144 public static void GetInteropFieldTypeAndNameFromXmlElement (Type containingType,
145 string xmlElement, string xmlNamespace,
146 out Type type, out string name)
148 TypeInfo tf = (TypeInfo) _typeInfos [containingType];
149 Hashtable ht = tf != null ? tf.Elements : null;
150 GetInteropFieldInfo (ht, xmlElement, xmlNamespace, out type, out name);
153 static void GetInteropFieldInfo (Hashtable fields,
154 string xmlName, string xmlNamespace,
155 out Type type, out string name)
157 if (fields != null)
159 FieldInfo field = (FieldInfo) fields [GetNameKey (xmlName, xmlNamespace)];
160 if (field != null)
162 type = field.FieldType;
163 name = field.Name;
164 return;
167 type = null;
168 name = null;
171 static string GetNameKey (string name, string namspace)
173 if (namspace == null) return name;
174 else return name + " " + namspace;
177 public static Type GetInteropTypeFromXmlElement (string xmlElement, string xmlNamespace)
179 lock (_xmlElements.SyncRoot)
181 return (Type) _xmlElements [xmlElement + " " + xmlNamespace];
185 public static Type GetInteropTypeFromXmlType (string xmlType, string xmlTypeNamespace)
187 lock (_xmlTypes.SyncRoot)
189 return (Type) _xmlTypes [xmlType + " " + xmlTypeNamespace];
193 private static string GetAssemblyName(MethodBase mb)
195 if (mb.DeclaringType.Assembly == typeof (object).Assembly)
196 return string.Empty;
197 else
198 return mb.DeclaringType.Assembly.GetName().Name;
201 public static string GetSoapActionFromMethodBase (MethodBase mb)
203 return InternalGetSoapAction (mb);
206 public static bool GetTypeAndMethodNameFromSoapAction (string soapAction,
207 out string typeName,
208 out string methodName)
210 lock (_soapActions.SyncRoot)
212 MethodBase mb = (MethodBase) _soapActionsMethods [soapAction];
213 if (mb != null)
215 typeName = mb.DeclaringType.AssemblyQualifiedName;
216 methodName = mb.Name;
217 return true;
221 string type;
222 string assembly;
224 typeName = null;
225 methodName = null;
227 int i = soapAction.LastIndexOf ('#');
228 if (i == -1) return false;
230 methodName = soapAction.Substring (i+1);
232 if (!DecodeXmlNamespaceForClrTypeNamespace (soapAction.Substring (0,i), out type, out assembly) )
233 return false;
235 if (assembly == null)
236 typeName = type + ", " + typeof (object).Assembly.GetName().Name;
237 else
238 typeName = type + ", " + assembly;
240 return true;
243 public static bool GetXmlElementForInteropType (Type type, out string xmlElement, out string xmlNamespace)
245 SoapTypeAttribute att = (SoapTypeAttribute) InternalRemotingServices.GetCachedSoapAttribute (type);
246 if (!att.IsInteropXmlElement)
248 xmlElement = null;
249 xmlNamespace = null;
250 return false;
253 xmlElement = att.XmlElementName;
254 xmlNamespace = att.XmlNamespace;
255 return true;
258 public static string GetXmlNamespaceForMethodCall (MethodBase mb)
260 return CodeXmlNamespaceForClrTypeNamespace (mb.DeclaringType.FullName, GetAssemblyName(mb));
263 public static string GetXmlNamespaceForMethodResponse (MethodBase mb)
265 return CodeXmlNamespaceForClrTypeNamespace (mb.DeclaringType.FullName, GetAssemblyName(mb));
268 public static bool GetXmlTypeForInteropType (Type type, out string xmlType, out string xmlTypeNamespace)
270 SoapTypeAttribute att = (SoapTypeAttribute) InternalRemotingServices.GetCachedSoapAttribute (type);
272 if (!att.IsInteropXmlType)
274 xmlType = null;
275 xmlTypeNamespace = null;
276 return false;
279 xmlType = att.XmlTypeName;
280 xmlTypeNamespace = att.XmlTypeNamespace;
281 return true;
284 public static bool IsClrTypeNamespace (string namespaceString)
286 return namespaceString.StartsWith (XmlNsForClrType);
289 public static bool IsSoapActionValidForMethodBase (string soapAction, MethodBase mb)
291 string typeName;
292 string methodName;
293 GetTypeAndMethodNameFromSoapAction (soapAction, out typeName, out methodName);
295 if (methodName != mb.Name) return false;
297 string methodClassType = mb.DeclaringType.AssemblyQualifiedName;
298 return typeName == methodClassType;
301 public static void PreLoad (Assembly assembly)
303 foreach (Type t in assembly.GetTypes ())
304 PreLoad (t);
307 public static void PreLoad (Type type)
309 string name, namspace;
310 TypeInfo tf = _typeInfos [type] as TypeInfo;
311 if (tf != null) return;
313 if (GetXmlTypeForInteropType (type, out name, out namspace))
314 RegisterInteropXmlType (name, namspace, type);
316 if (GetXmlElementForInteropType (type, out name, out namspace))
317 RegisterInteropXmlElement (name, namspace, type);
319 lock (_typeInfos.SyncRoot)
321 tf = new TypeInfo ();
322 FieldInfo[] fields = type.GetFields (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
324 foreach (FieldInfo field in fields)
326 SoapFieldAttribute att = (SoapFieldAttribute) InternalRemotingServices.GetCachedSoapAttribute (field);
327 if (!att.IsInteropXmlElement ()) continue;
329 string key = GetNameKey (att.XmlElementName, att.XmlNamespace);
330 if (att.UseAttribute)
332 if (tf.Attributes == null) tf.Attributes = new Hashtable ();
333 tf.Attributes [key] = field;
335 else
337 if (tf.Elements == null) tf.Elements = new Hashtable ();
338 tf.Elements [key] = field;
341 _typeInfos [type] = tf;
345 public static void RegisterInteropXmlElement (string xmlElement, string xmlNamespace, Type type)
347 lock (_xmlElements.SyncRoot)
349 _xmlElements [xmlElement + " " + xmlNamespace] = type;
353 public static void RegisterInteropXmlType (string xmlType, string xmlTypeNamespace, Type type)
355 lock (_xmlTypes.SyncRoot)
357 _xmlTypes [xmlType + " " + xmlTypeNamespace] = type;
361 public static void RegisterSoapActionForMethodBase (MethodBase mb)
363 InternalGetSoapAction (mb);
366 static string InternalGetSoapAction (MethodBase mb)
368 lock (_soapActions.SyncRoot)
370 string action = (string) _soapActions [mb];
371 if (action == null)
373 SoapMethodAttribute att = (SoapMethodAttribute) InternalRemotingServices.GetCachedSoapAttribute (mb);
374 action = att.SoapAction;
375 _soapActions [mb] = action;
376 _soapActionsMethods [action] = mb;
378 return action;
382 public static void RegisterSoapActionForMethodBase (MethodBase mb, string soapAction)
384 lock (_soapActions.SyncRoot)
386 _soapActions [mb] = soapAction;
387 _soapActionsMethods [soapAction] = mb;
391 static string EncodeNs (string ns)
393 // Simple url encoding for namespaces
395 ns = ns.Replace (",","%2C");
396 ns = ns.Replace (" ","%20");
397 return ns.Replace ("=","%3D");
400 static string DecodeNs (string ns)
402 ns = ns.Replace ("%2C",",");
403 ns = ns.Replace ("%20"," ");
404 return ns.Replace ("%3D","=");