2 // System.Runtime.Remoting.SoapServices.cs
4 // Author: Jaime Anguiano Olarra (jaime@gnome.org)
5 // Lluis Sanchez Gual (lluis@ximian.com)
7 // (c) 2002, Jaime Anguiano Olarra
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:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
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.
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 ();
54 public Hashtable Attributes
;
55 public Hashtable Elements
;
58 // Private constructor: nobody instantiates this class
59 private SoapServices () {}
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/"; }
86 public static string CodeXmlNamespaceForClrTypeNamespace (string typeNamespace
,
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
);
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;
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);
119 else if (inNamespace
.StartsWith(XmlNsForClrTypeWithNs
))
121 int typePos
= XmlNsForClrTypeWithNs
.Length
;
122 typeNamespace
= inNamespace
.Substring (typePos
);
125 else if (inNamespace
.StartsWith(XmlNsForClrTypeWithAssembly
))
127 int typePos
= XmlNsForClrTypeWithAssembly
.Length
;
128 assemblyName
= inNamespace
.Substring (typePos
);
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
)
159 FieldInfo field
= (FieldInfo
) fields
[GetNameKey (xmlName
, xmlNamespace
)];
162 type
= field
.FieldType
;
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
)
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
,
208 out string methodName
)
210 lock (_soapActions
.SyncRoot
)
212 MethodBase mb
= (MethodBase
) _soapActionsMethods
[soapAction
];
215 typeName
= mb
.DeclaringType
.AssemblyQualifiedName
;
216 methodName
= mb
.Name
;
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
) )
235 if (assembly
== null)
236 typeName
= type
+ ", " + typeof (object).Assembly
.GetName().Name
;
238 typeName
= type
+ ", " + assembly
;
243 public static bool GetXmlElementForInteropType (Type type
, out string xmlElement
, out string xmlNamespace
)
245 SoapTypeAttribute att
= (SoapTypeAttribute
) InternalRemotingServices
.GetCachedSoapAttribute (type
);
246 if (!att
.IsInteropXmlElement
)
253 xmlElement
= att
.XmlElementName
;
254 xmlNamespace
= att
.XmlNamespace
;
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
)
275 xmlTypeNamespace
= null;
279 xmlType
= att
.XmlTypeName
;
280 xmlTypeNamespace
= att
.XmlTypeNamespace
;
284 public static bool IsClrTypeNamespace (string namespaceString
)
286 return namespaceString
.StartsWith (XmlNsForClrType
);
289 public static bool IsSoapActionValidForMethodBase (string soapAction
, MethodBase mb
)
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 ())
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
;
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
];
373 SoapMethodAttribute att
= (SoapMethodAttribute
) InternalRemotingServices
.GetCachedSoapAttribute (mb
);
374 action
= att
.SoapAction
;
375 _soapActions
[mb
] = action
;
376 _soapActionsMethods
[action
] = mb
;
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","=");