treat DefaultWsdlHelpGenerator.jvm.aspx as DefaultWsdlHelpGenerator.aspx; correctly...
[mono.git] / mcs / class / System.Web.Services / System.Web.Services.Protocols / TypeStubManager.cs
1 //
2 // Methods.cs: Information about a method and its mapping to a SOAP web service.
3 //
4 // Author:
5 //   Miguel de Icaza
6 //   Lluis Sanchez Gual (lluis@ximian.com)
7 //
8 // (C) 2003 Ximian, Inc.
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Reflection;
33 using System.Collections;
34 using System.Xml;
35 using System.Xml.Serialization;
36 using System.Web.Services;
37 using System.Web.Services.Description;
38
39 namespace System.Web.Services.Protocols {
40
41         //
42         // This class represents all the information we extract from a MethodInfo
43         // in the WebClientProtocol derivative stub class
44         //
45         internal class MethodStubInfo 
46         {
47                 internal LogicalMethodInfo MethodInfo;
48                 internal TypeStubInfo TypeStub;
49
50                 // The name used by the stub class to reference this method.
51                 internal string Name;
52                 internal WebMethodAttribute MethodAttribute;
53                 
54                 internal string OperationName
55                 {
56                         get { return MethodInfo.Name; }
57                 }
58
59                 //
60                 // Constructor
61                 //
62                 public MethodStubInfo (TypeStubInfo parent, LogicalMethodInfo source)
63                 {
64                         TypeStub = parent;
65                         MethodInfo = source;
66
67                         object [] o = source.GetCustomAttributes (typeof (WebMethodAttribute));
68                         if (o.Length > 0)
69                         {
70                                 MethodAttribute = (WebMethodAttribute) o [0];
71                                 Name = MethodAttribute.MessageName;
72                                 if (Name == "") Name = source.Name;
73                         }
74                         else
75                                 Name = source.Name;
76                 }
77         }
78
79         //
80         // Holds the metadata loaded from the type stub, as well as
81         // the metadata for all the methods in the type
82         //
83         internal abstract class TypeStubInfo 
84         {
85                 Hashtable name_to_method = new Hashtable ();
86                 MethodStubInfo[] methods;
87                 ArrayList bindings = new ArrayList ();
88                 LogicalTypeInfo logicalType;
89                 string defaultBinding;
90                 ArrayList mappings;
91                 XmlSerializer[] serializers;
92
93                 public TypeStubInfo (LogicalTypeInfo logicalTypeInfo)
94                 {
95                         this.logicalType = logicalTypeInfo;
96
97                         object [] o = Type.GetCustomAttributes (typeof (WebServiceBindingAttribute), false);
98
99                         string defaultBindingName = logicalType.WebServiceName + ProtocolName;
100                         if (o.Length > 0)
101                                 foreach (WebServiceBindingAttribute at in o)
102                                         AddBinding (new BindingInfo (at, defaultBindingName, LogicalType.WebServiceNamespace));
103                         else 
104                                 AddBinding (new BindingInfo (null, defaultBindingName, logicalType.WebServiceNamespace));
105
106 #if NET_2_0
107                         foreach (Type ifaceType in Type.GetInterfaces ()) {
108                                 o = ifaceType.GetCustomAttributes (typeof (WebServiceBindingAttribute), false);
109                                 if (o.Length > 0) {
110                                         defaultBindingName = ifaceType.Name + ProtocolName;
111                                         foreach (WebServiceBindingAttribute at in o)
112                                                 AddBinding (new BindingInfo (at, defaultBindingName, LogicalType.WebServiceNamespace));
113                                 }
114                         }
115 #endif
116                 }
117                 
118 #if NET_2_0
119                 public WsiProfiles WsiClaims {
120                         get {
121                                 return (((BindingInfo) Bindings [0]).WebServiceBindingAttribute != null) ?
122                                         ((BindingInfo) Bindings [0]).WebServiceBindingAttribute.ConformsTo : WsiProfiles.None;
123                         }
124                 }
125 #endif
126                 
127                 public LogicalTypeInfo LogicalType
128                 {
129                         get { return logicalType; }
130                 }
131                 
132                 public Type Type
133                 {
134                         get { return logicalType.Type; }
135                 }
136                 
137                 public string DefaultBinding
138                 {
139                         get { return defaultBinding; }
140                 }
141                 
142                 public virtual XmlReflectionImporter XmlImporter 
143                 {
144                         get { return null; }
145                 }
146
147                 public virtual SoapReflectionImporter SoapImporter 
148                 {
149                         get { return null; }
150                 }
151                 
152                 public virtual string ProtocolName
153                 {
154                         get { return null; }
155                 }
156                 
157                 public XmlSerializer GetSerializer (int n)
158                 {
159                         return serializers [n];
160                 }
161                 
162                 public int RegisterSerializer (XmlMapping map)
163                 {
164                         if (mappings == null) mappings = new ArrayList ();
165                         return mappings.Add (map);
166                 }
167
168                 public void Initialize ()
169                 {
170                         BuildTypeMethods ();
171                         
172                         if (mappings != null)
173                         {
174                                 // Build all the serializers at once
175                                 XmlMapping[] maps = (XmlMapping[]) mappings.ToArray(typeof(XmlMapping));
176                                 serializers = XmlSerializer.FromMappings (maps);
177                         }
178                 }
179                 
180                 //
181                 // Extract all method information
182                 //
183                 protected virtual void BuildTypeMethods ()
184                 {
185                         bool isClientProxy = typeof(WebClientProtocol).IsAssignableFrom (Type);
186
187                         ArrayList metStubs = new ArrayList ();
188                         foreach (LogicalMethodInfo mi in logicalType.LogicalMethods)
189                         {
190                                 if (!isClientProxy && mi.CustomAttributeProvider.GetCustomAttributes (typeof(WebMethodAttribute), true).Length == 0)
191                                         continue;
192                                         
193                                 MethodStubInfo msi = CreateMethodStubInfo (this, mi, isClientProxy);
194
195                                 if (msi == null)
196                                         continue;
197
198                                 if (name_to_method.ContainsKey (msi.Name)) {
199                                         string msg = "Both " + msi.MethodInfo.ToString () + " and " + GetMethod (msi.Name).MethodInfo + " use the message name '" + msi.Name + "'. ";
200                                         msg += "Use the MessageName property of WebMethod custom attribute to specify unique message names for the methods";
201                                         throw new InvalidOperationException (msg);
202                                 }
203                                 
204                                 name_to_method [msi.Name] = msi;
205                                 metStubs.Add (msi);
206                         }
207                         methods = (MethodStubInfo[]) metStubs.ToArray (typeof (MethodStubInfo));
208                 }
209                 
210                 protected abstract MethodStubInfo CreateMethodStubInfo (TypeStubInfo typeInfo, LogicalMethodInfo methodInfo, bool isClientProxy);
211                 
212                 public MethodStubInfo GetMethod (string name)
213                 {
214                         return (MethodStubInfo) name_to_method [name];
215                 }
216
217                 public MethodStubInfo[] Methods
218                 {
219                         get { return methods; }
220                 }
221                 
222                 internal ArrayList Bindings
223                 {
224                         get { return bindings; }
225                 }
226                 
227                 internal void AddBinding (BindingInfo info)
228                 {
229                         bindings.Add (info);
230                 }
231                 
232                 internal BindingInfo GetBinding (string name)
233                 {
234                         if (name == null || name.Length == 0) return (BindingInfo) bindings[0];
235                         
236                         for (int n = 0; n < bindings.Count; n++)
237                                 if (((BindingInfo)bindings[n]).Name == name) return (BindingInfo)bindings[n];
238                         return null;
239                 }
240         }
241         
242         internal class BindingInfo
243         {
244                 public BindingInfo (WebServiceBindingAttribute at, string name, string ns)
245                 {
246                         if (at != null) {
247 #if NET_1_1
248                                 Name = at.Name;
249 #endif
250                                 Namespace = at.Namespace;
251                                 Location = at.Location;
252                                 WebServiceBindingAttribute = at;
253                         }
254
255                         if (Name == null || Name.Length == 0)
256                                 Name = name;
257
258                         if (Namespace == null || Namespace.Length == 0)
259                                 Namespace = ns;
260                 }
261                 
262                 public readonly string Name;
263                 public readonly string Namespace;
264                 public readonly string Location;
265                 public readonly WebServiceBindingAttribute WebServiceBindingAttribute;
266         }
267
268         //
269         // Manages type stubs
270         //
271         internal class TypeStubManager 
272         {
273 #if !TARGET_JVM
274                 static Hashtable type_to_manager;
275 #else
276                 const string type_to_manager_key = "TypeStubManager.type_to_manager";
277                 static Hashtable type_to_manager {
278                         get {
279                                 Hashtable hash = (Hashtable)AppDomain.CurrentDomain.GetData(type_to_manager_key);
280
281                                 if (hash != null)
282                                         return hash;
283
284                                 lock(type_to_manager_key) {
285                                         AppDomain.CurrentDomain.SetData(type_to_manager_key, new Hashtable());
286                                 }
287
288                                 return (Hashtable)AppDomain.CurrentDomain.GetData(type_to_manager_key);
289                         }
290                         set {
291                                 //do nothing: we manage our type_to_manager per domain
292                         }
293                 }
294 #endif
295                 
296                 static TypeStubManager ()
297                 {
298                         type_to_manager = new Hashtable ();
299                 }
300
301                 static internal TypeStubInfo GetTypeStub (Type t, string protocolName)
302                 {
303                         LogicalTypeInfo tm = GetLogicalTypeInfo (t);
304                         return tm.GetTypeStub (protocolName);
305                 }
306                 
307                 //
308                 // This needs to be thread safe
309                 //
310                 static internal LogicalTypeInfo GetLogicalTypeInfo (Type t)
311                 {
312                         lock (type_to_manager)
313                         {
314                                 LogicalTypeInfo tm = (LogicalTypeInfo) type_to_manager [t];
315         
316                                 if (tm != null)
317                                         return tm;
318
319                                 tm = new LogicalTypeInfo (t);
320                                 type_to_manager [t] = tm;
321
322                                 return tm;
323                         }
324                 }
325         }
326 }