Mark tests as not working under TARGET_JVM
[mono.git] / mcs / class / System.Web.Services / System.Web.Services.Configuration / WebServicesConfigurationSectionHandler.cs
1 //
2 // System.Web.Services.Configuration.WebServicesConfigurationSectionHandler
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //
7 // (C) 2003 Ximian, Inc (http://www.ximian.com)
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;
32 using System.Collections;
33 using System.Configuration;
34 using System.Xml;
35
36 namespace System.Web.Services.Configuration
37 {
38         [Flags]
39         enum WSProtocol
40         {
41                 HttpSoap = 1,
42                 HttpPost = 1 << 1,
43                 HttpGet =  1 << 2,
44                 Documentation = 1 << 3,
45 #if NET_1_1
46                 HttpSoap12 = 1 << 4,
47                 HttpPostLocalhost = 1 << 5,
48                 AnyHttpSoap = HttpSoap | HttpSoap12,
49 #endif
50                 All = 0xFF
51         }
52         
53         class WSConfig
54         {
55 #if !TARGET_JVM
56                 volatile static WSConfig instance;
57 #else
58                 static WSConfig instance {
59                         get {
60                                 return (WSConfig)AppDomain.CurrentDomain.GetData("WSConfig.instance");
61                         }
62                         set {
63                                 AppDomain.CurrentDomain.SetData("WSConfig.instance", value);
64                         }
65                 }
66
67 #endif
68                 WSProtocol protocols;
69                 string wsdlHelpPage;
70                 string filePath;
71                 ArrayList extensionTypes = new ArrayList();
72                 ArrayList extensionImporterTypes = new ArrayList();
73                 ArrayList extensionReflectorTypes = new ArrayList();
74                 ArrayList formatExtensionTypes = new ArrayList();
75                 static readonly object lockobj = new object ();
76                 
77                 public WSConfig (WSConfig parent, object context)
78                 {
79                         if (parent == null)
80                                 return;
81                         
82                         protocols = parent.protocols;
83                         wsdlHelpPage = parent.wsdlHelpPage;
84                         if (wsdlHelpPage != null)
85                                 filePath = parent.filePath;
86                         else
87                                 filePath = context as string;
88                 }
89                 
90                 static WSProtocol ParseProtocol (string protoName, out string error)
91                 {
92                         WSProtocol proto;
93                         error = null;
94
95 #if ONLY_1_1
96                         switch (protoName) {
97                                 case "HttpSoap1.2":
98                                         protoName = "HttpSoap12";
99                                         break;
100                                 case "HttpSoap12":
101                                         protoName = null;
102                                         break;
103                         }
104 #endif
105                         try {
106                                 proto = (WSProtocol) Enum.Parse (typeof (WSProtocol), protoName);
107                         } catch {
108                                 error = "Invalid protocol name";
109                                 return 0;
110                         }
111
112                         return proto;
113                 }
114
115                 // Methods to modify configuration values
116                 public bool AddProtocol (string protoName, out string error)
117                 {
118                         if (protoName == "All") {
119                                 error = "Invalid protocol name";
120                                 return false;
121                         }
122
123                         WSProtocol proto = ParseProtocol (protoName, out error);
124                         if (error != null)
125                                 return false;
126
127                         protocols |= proto;
128                         return true;
129                 }
130
131                 public bool RemoveProtocol (string protoName, out string error)
132                 {
133                         if (protoName == "All") {
134                                 error = "Invalid protocol name";
135                                 return false;
136                         }
137
138                         WSProtocol proto = ParseProtocol (protoName, out error);
139                         if (error != null)
140                                 return false;
141
142                         protocols &= ~proto;
143                         return true;
144                 }
145
146                 public void ClearProtocol ()
147                 {
148                         protocols = 0;
149                 }
150
151                 // Methods to query/get configuration
152                 public static bool IsSupported (WSProtocol proto)
153                 {
154                         return ((Instance.protocols & proto) == proto && (proto != 0) && (proto != WSProtocol.All));
155                 }
156
157                 // Properties
158                 public string WsdlHelpPage {
159                         get { return wsdlHelpPage; }
160                         set { wsdlHelpPage = value; }
161                 }
162
163                 public string ConfigFilePath {
164                         get { return filePath; }
165                         set { filePath = value; }
166                 }
167
168                 static public WSConfig Instance {
169                         get {
170                                 //TODO: use HttpContext to get the configuration
171                                 if (instance != null)
172                                         return instance;
173
174                                 lock (lockobj) {
175                                         if (instance != null)
176                                                 return instance;
177
178                                         instance = (WSConfig) ConfigurationSettings.GetConfig ("system.web/webServices");
179                                 }
180
181                                 return instance;
182                         }
183                 }
184
185                 public ArrayList ExtensionTypes {
186                         get { return extensionTypes; }
187                 }
188
189                 public ArrayList ExtensionImporterTypes {
190                         get { return extensionImporterTypes; }
191                 }
192                 
193                 public ArrayList ExtensionReflectorTypes {
194                         get { return extensionReflectorTypes; }
195                 }
196                 
197                 public ArrayList FormatExtensionTypes {
198                         get { return formatExtensionTypes; }
199                 }
200                 
201         }
202         
203         enum WSExtensionGroup
204         {
205                 High,
206                 Low
207         }
208         
209         class WSExtensionConfig
210         {
211                 Type type;
212                 int priority;
213                 WSExtensionGroup group;
214
215                 public Exception SetType (string typeName)
216                 {
217                         Exception exc = null;
218                         
219                         try {
220                                 type = Type.GetType (typeName, true);
221                         } catch (Exception e) {
222                                 exc = e;
223                         }
224
225                         return exc;
226                 }
227                 
228                 public Exception SetPriority (string prio)
229                 {
230                         if (prio == null || prio == "")
231                                 return null;
232
233                         Exception exc = null;
234                         try {
235                                 priority = Int32.Parse (prio);
236                         } catch (Exception e) {
237                                 exc = e;
238                         }
239
240                         return exc;
241                 }
242                 
243                 public Exception SetGroup (string grp)
244                 {
245                         if (grp == null || grp == "")
246                                 return null;
247
248                         Exception exc = null;
249                         try {
250                                 group = (WSExtensionGroup) Int32.Parse (grp);
251                                 if (group < WSExtensionGroup.High || group > WSExtensionGroup.Low)
252                                         throw new ArgumentOutOfRangeException ("group", "Must be 0 or 1");
253                         } catch (Exception e) {
254                                 exc = e;
255                         }
256
257                         return exc;
258                 }
259                 
260                 // Getters
261                 public Type Type {
262                         get { return type; }
263                 }
264
265                 public int Priority {
266                         get { return priority; }
267                 }
268
269                 public WSExtensionGroup Group {
270                         get { return group; }
271                 }
272         }
273         
274         class WebServicesConfigurationSectionHandler : IConfigurationSectionHandler
275         {
276                 public object Create (object parent, object context, XmlNode section)
277                 {
278                         WSConfig config = new WSConfig (parent as WSConfig, context);
279
280                         if (section.Attributes != null && section.Attributes.Count != 0)
281                                 ThrowException ("Unrecognized attribute", section);
282
283                         XmlNodeList nodes = section.ChildNodes;
284                         foreach (XmlNode child in nodes) {
285                                 XmlNodeType ntype = child.NodeType;
286                                 if (ntype == XmlNodeType.Whitespace || ntype == XmlNodeType.Comment)
287                                         continue;
288
289                                 if (ntype != XmlNodeType.Element)
290                                         ThrowException ("Only elements allowed", child);
291                                 
292                                 string name = child.Name;
293                                 if (name == "protocols") {
294                                         ConfigProtocols (child, config);
295                                         continue;
296                                 }
297
298                                 if (name == "soapExtensionTypes") {
299                                         ConfigSoapExtensionTypes (child, config.ExtensionTypes);
300                                         continue;
301                                 }
302
303                                 if (name == "soapExtensionReflectorTypes") {
304                                         ConfigSoapExtensionTypes (child, config.ExtensionReflectorTypes);
305                                         continue;
306                                 }
307
308                                 if (name == "soapExtensionImporterTypes") {
309                                         ConfigSoapExtensionTypes (child, config.ExtensionImporterTypes);
310                                         continue;
311                                 }
312
313                                 if (name == "serviceDescriptionFormatExtensionTypes") {
314                                         ConfigFormatExtensionTypes (child, config);
315                                         continue;
316                                 }
317
318                                 if (name == "wsdlHelpGenerator") {
319                                         string href = AttValue ("href", child, false);
320                                         if (child.Attributes != null && child.Attributes.Count != 0)
321                                                 HandlersUtil.ThrowException ("Unrecognized attribute", child);
322
323                                         config.ConfigFilePath = context as string;
324                                         config.WsdlHelpPage = href;
325                                         continue;
326                                 }
327
328                                 ThrowException ("Unexpected element", child);
329                         }
330
331                         return config;
332                 }
333
334                 static void ConfigProtocols (XmlNode section, WSConfig config)
335                 {
336                         if (section.Attributes != null && section.Attributes.Count != 0)
337                                 ThrowException ("Unrecognized attribute", section);
338
339                         XmlNodeList nodes = section.ChildNodes;
340                         foreach (XmlNode child in nodes) {
341                                 XmlNodeType ntype = child.NodeType;
342                                 if (ntype == XmlNodeType.Whitespace || ntype == XmlNodeType.Comment)
343                                         continue;
344
345                                 if (ntype != XmlNodeType.Element)
346                                         ThrowException ("Only elements allowed", child);
347                                 
348                                 string name = child.Name;
349                                 string error;
350                                 if (name == "add") {
351                                         string protoName = AttValue ("name", child, false);
352                                         if (child.Attributes != null && child.Attributes.Count != 0)
353                                                 HandlersUtil.ThrowException ("Unrecognized attribute", child);
354
355                                         if (!config.AddProtocol (protoName, out error))
356                                                 ThrowException (error, child);
357                                         
358                                         continue;
359                                 }
360
361                                 if (name == "remove") {
362                                         string protoName = AttValue ("name", child, false);
363                                         if (child.Attributes != null && child.Attributes.Count != 0)
364                                                 HandlersUtil.ThrowException ("Unrecognized attribute", child);
365
366                                         if (!config.RemoveProtocol (protoName, out error))
367                                                 ThrowException (error, child);
368                                         
369                                         continue;
370                                 }
371
372                                 if (name == "clear") {
373                                         if (child.Attributes != null && child.Attributes.Count != 0)
374                                                 HandlersUtil.ThrowException ("Unrecognized attribute", child);
375
376                                         config.ClearProtocol ();
377                                         continue;
378                                 }
379
380                                 ThrowException ("Unexpected element", child);
381                         }
382                 }
383                 
384                 static void ConfigSoapExtensionTypes (XmlNode section, ArrayList extensions)
385                 {
386                         if (section.Attributes != null && section.Attributes.Count != 0)
387                                 ThrowException ("Unrecognized attribute", section);
388
389                         XmlNodeList nodes = section.ChildNodes;
390                         foreach (XmlNode child in nodes) {
391                                 XmlNodeType ntype = child.NodeType;
392                                 if (ntype == XmlNodeType.Whitespace || ntype == XmlNodeType.Comment)
393                                         continue;
394
395                                 if (ntype != XmlNodeType.Element)
396                                         ThrowException ("Only elements allowed", child);
397                                 
398                                 string name = child.Name;
399                                 if (name == "add") {
400                                         string seType = AttValue ("type", child, false);
401                                         string priority = AttValue ("priority", child);
402                                         string group = AttValue ("group", child);
403                                         if (child.Attributes != null && child.Attributes.Count != 0)
404                                                 HandlersUtil.ThrowException ("Unrecognized attribute", child);
405
406                                         WSExtensionConfig wse = new WSExtensionConfig ();
407                                         Exception e = wse.SetType (seType);
408                                         if (e != null)
409                                                 ThrowException (e.Message, child);
410
411                                         e = wse.SetPriority (priority);
412                                         if (e != null)
413                                                 ThrowException (e.Message, child);
414
415                                         e = wse.SetGroup (group);
416                                         if (e != null)
417                                                 ThrowException (e.Message, child);
418
419                                         extensions.Add (wse);
420                                         continue;
421                                 }
422
423                                 ThrowException ("Unexpected element", child);
424                         }
425                 }
426                 
427                 static void ConfigFormatExtensionTypes (XmlNode section, WSConfig config)
428                 {
429                         if (section.Attributes != null && section.Attributes.Count != 0)
430                                 ThrowException ("Unrecognized attribute", section);
431
432                         XmlNodeList nodes = section.ChildNodes;
433                         foreach (XmlNode child in nodes) {
434                                 XmlNodeType ntype = child.NodeType;
435                                 if (ntype == XmlNodeType.Whitespace || ntype == XmlNodeType.Comment)
436                                         continue;
437
438                                 if (ntype != XmlNodeType.Element)
439                                         ThrowException ("Only elements allowed", child);
440                                 
441                                 string name = child.Name;
442                                 if (name == "add") {
443                                         string typeName = AttValue ("name", child, false);
444                                         if (child.Attributes != null && child.Attributes.Count != 0)
445                                                 HandlersUtil.ThrowException ("Unrecognized attribute", child);
446
447                                         try {
448                                                 config.FormatExtensionTypes.Add (Type.GetType (typeName, true));
449                                         } catch (Exception e) {
450                                                 ThrowException (e.Message, child);
451                                         }
452                                         continue;
453                                 }
454
455                                 ThrowException ("Unexpected element", child);
456                         }
457                 }
458                 
459                 // To save some typing...
460                 static string AttValue (string name, XmlNode node, bool optional)
461                 {
462                         return HandlersUtil.ExtractAttributeValue (name, node, optional);
463                 }
464
465                 static string AttValue (string name, XmlNode node)
466                 {
467                         return HandlersUtil.ExtractAttributeValue (name, node, true);
468                 }
469
470                 static void ThrowException (string message, XmlNode node)
471                 {
472                         HandlersUtil.ThrowException (message, node);
473                 }
474                 //
475         }
476         
477         class HandlersUtil
478         {
479                 private HandlersUtil ()
480                 {
481                 }
482
483                 static internal string ExtractAttributeValue (string attKey, XmlNode node)
484                 {
485                         return ExtractAttributeValue (attKey, node, false);
486                 }
487                         
488                 static internal string ExtractAttributeValue (string attKey, XmlNode node, bool optional)
489                 {
490                         if (node.Attributes == null) {
491                                 if (optional)
492                                         return null;
493
494                                 ThrowException ("Required attribute not found: " + attKey, node);
495                         }
496
497                         XmlNode att = node.Attributes.RemoveNamedItem (attKey);
498                         if (att == null) {
499                                 if (optional)
500                                         return null;
501                                 ThrowException ("Required attribute not found: " + attKey, node);
502                         }
503
504                         string value = att.Value;
505                         if (value == String.Empty) {
506                                 string opt = optional ? "Optional" : "Required";
507                                 ThrowException (opt + " attribute is empty: " + attKey, node);
508                         }
509
510                         return value;
511                 }
512
513                 static internal void ThrowException (string msg, XmlNode node)
514                 {
515                         if (node != null && node.Name != String.Empty)
516                                 msg = msg + " (node name: " + node.Name + ") ";
517                         throw new ConfigurationException (msg, node);
518                 }
519         }
520
521 }