WebServicesConfigurationSectionHandler.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. //
  2. // System.Web.Services.Configuration.WebServicesConfigurationSectionHandler
  3. //
  4. // Authors:
  5. // Gonzalo Paniagua Javier ([email protected])
  6. //
  7. // (C) 2003 Ximian, Inc (http://www.ximian.com)
  8. //
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining
  11. // a copy of this software and associated documentation files (the
  12. // "Software"), to deal in the Software without restriction, including
  13. // without limitation the rights to use, copy, modify, merge, publish,
  14. // distribute, sublicense, and/or sell copies of the Software, and to
  15. // permit persons to whom the Software is furnished to do so, subject to
  16. // the following conditions:
  17. //
  18. // The above copyright notice and this permission notice shall be
  19. // included in all copies or substantial portions of the Software.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. //
  29. using System;
  30. using System.Collections;
  31. using System.Configuration;
  32. using System.Xml;
  33. namespace System.Web.Services.Configuration
  34. {
  35. [Flags]
  36. enum WSProtocol
  37. {
  38. HttpSoap = 1,
  39. HttpPost = 1 << 1,
  40. HttpGet = 1 << 2,
  41. Documentation = 1 << 3,
  42. HttpSoap12 = 1 << 4,
  43. HttpPostLocalhost = 1 << 5,
  44. AnyHttpSoap = HttpSoap | HttpSoap12,
  45. All = 0xFF
  46. }
  47. class WSConfig
  48. {
  49. volatile static WSConfig instance;
  50. WSProtocol protocols;
  51. string wsdlHelpPage;
  52. string filePath;
  53. ArrayList extensionTypes = new ArrayList();
  54. ArrayList extensionImporterTypes = new ArrayList();
  55. ArrayList extensionReflectorTypes = new ArrayList();
  56. ArrayList formatExtensionTypes = new ArrayList();
  57. static readonly object lockobj = new object ();
  58. public WSConfig (WSConfig parent, object context)
  59. {
  60. if (parent == null)
  61. return;
  62. protocols = parent.protocols;
  63. wsdlHelpPage = parent.wsdlHelpPage;
  64. if (wsdlHelpPage != null)
  65. filePath = parent.filePath;
  66. else
  67. filePath = context as string;
  68. }
  69. static WSProtocol ParseProtocol (string protoName, out string error)
  70. {
  71. WSProtocol proto;
  72. error = null;
  73. try {
  74. proto = (WSProtocol) Enum.Parse (typeof (WSProtocol), protoName);
  75. } catch {
  76. error = "Invalid protocol name";
  77. return 0;
  78. }
  79. return proto;
  80. }
  81. // Methods to modify configuration values
  82. public bool AddProtocol (string protoName, out string error)
  83. {
  84. if (protoName == "All") {
  85. error = "Invalid protocol name";
  86. return false;
  87. }
  88. WSProtocol proto = ParseProtocol (protoName, out error);
  89. if (error != null)
  90. return false;
  91. protocols |= proto;
  92. return true;
  93. }
  94. public bool RemoveProtocol (string protoName, out string error)
  95. {
  96. if (protoName == "All") {
  97. error = "Invalid protocol name";
  98. return false;
  99. }
  100. WSProtocol proto = ParseProtocol (protoName, out error);
  101. if (error != null)
  102. return false;
  103. protocols &= ~proto;
  104. return true;
  105. }
  106. public void ClearProtocol ()
  107. {
  108. protocols = 0;
  109. }
  110. // Methods to query/get configuration
  111. public static bool IsSupported (WSProtocol proto)
  112. {
  113. return ((Instance.protocols & proto) == proto && (proto != 0) && (proto != WSProtocol.All));
  114. }
  115. // Properties
  116. public string WsdlHelpPage {
  117. get { return wsdlHelpPage; }
  118. set { wsdlHelpPage = value; }
  119. }
  120. public string ConfigFilePath {
  121. get { return filePath; }
  122. set { filePath = value; }
  123. }
  124. static public WSConfig Instance {
  125. get {
  126. //TODO: use HttpContext to get the configuration
  127. if (instance != null)
  128. return instance;
  129. lock (lockobj) {
  130. if (instance != null)
  131. return instance;
  132. instance = (WSConfig) ConfigurationSettings.GetConfig ("system.web/webServices");
  133. }
  134. return instance;
  135. }
  136. }
  137. public ArrayList ExtensionTypes {
  138. get { return extensionTypes; }
  139. }
  140. public ArrayList ExtensionImporterTypes {
  141. get { return extensionImporterTypes; }
  142. }
  143. public ArrayList ExtensionReflectorTypes {
  144. get { return extensionReflectorTypes; }
  145. }
  146. public ArrayList FormatExtensionTypes {
  147. get { return formatExtensionTypes; }
  148. }
  149. }
  150. enum WSExtensionGroup
  151. {
  152. High,
  153. Low
  154. }
  155. class WSExtensionConfig
  156. {
  157. Type type;
  158. int priority;
  159. WSExtensionGroup group;
  160. public Exception SetType (string typeName)
  161. {
  162. Exception exc = null;
  163. try {
  164. type = Type.GetType (typeName, true);
  165. } catch (Exception e) {
  166. exc = e;
  167. }
  168. return exc;
  169. }
  170. public Exception SetPriority (string prio)
  171. {
  172. if (prio == null || prio == "")
  173. return null;
  174. Exception exc = null;
  175. try {
  176. priority = Int32.Parse (prio);
  177. } catch (Exception e) {
  178. exc = e;
  179. }
  180. return exc;
  181. }
  182. public Exception SetGroup (string grp)
  183. {
  184. if (grp == null || grp == "")
  185. return null;
  186. Exception exc = null;
  187. try {
  188. group = (WSExtensionGroup) Int32.Parse (grp);
  189. if (group < WSExtensionGroup.High || group > WSExtensionGroup.Low)
  190. throw new ArgumentOutOfRangeException ("group", "Must be 0 or 1");
  191. } catch (Exception e) {
  192. exc = e;
  193. }
  194. return exc;
  195. }
  196. // Getters
  197. public Type Type {
  198. get { return type; }
  199. }
  200. public int Priority {
  201. get { return priority; }
  202. }
  203. public WSExtensionGroup Group {
  204. get { return group; }
  205. }
  206. }
  207. class WebServicesConfigurationSectionHandler : IConfigurationSectionHandler
  208. {
  209. public object Create (object parent, object context, XmlNode section)
  210. {
  211. WSConfig config = new WSConfig (parent as WSConfig, context);
  212. if (section.Attributes != null && section.Attributes.Count != 0)
  213. ThrowException ("Unrecognized attribute", section);
  214. XmlNodeList nodes = section.ChildNodes;
  215. foreach (XmlNode child in nodes) {
  216. XmlNodeType ntype = child.NodeType;
  217. if (ntype == XmlNodeType.Whitespace || ntype == XmlNodeType.Comment)
  218. continue;
  219. if (ntype != XmlNodeType.Element)
  220. ThrowException ("Only elements allowed", child);
  221. string name = child.Name;
  222. if (name == "protocols") {
  223. ConfigProtocols (child, config);
  224. continue;
  225. }
  226. if (name == "soapExtensionTypes") {
  227. ConfigSoapExtensionTypes (child, config.ExtensionTypes);
  228. continue;
  229. }
  230. if (name == "soapExtensionReflectorTypes") {
  231. ConfigSoapExtensionTypes (child, config.ExtensionReflectorTypes);
  232. continue;
  233. }
  234. if (name == "soapExtensionImporterTypes") {
  235. ConfigSoapExtensionTypes (child, config.ExtensionImporterTypes);
  236. continue;
  237. }
  238. if (name == "serviceDescriptionFormatExtensionTypes") {
  239. ConfigFormatExtensionTypes (child, config);
  240. continue;
  241. }
  242. if (name == "wsdlHelpGenerator") {
  243. string href = AttValue ("href", child, false);
  244. if (child.Attributes != null && child.Attributes.Count != 0)
  245. HandlersUtil.ThrowException ("Unrecognized attribute", child);
  246. config.ConfigFilePath = context as string;
  247. config.WsdlHelpPage = href;
  248. continue;
  249. }
  250. ThrowException ("Unexpected element", child);
  251. }
  252. return config;
  253. }
  254. static void ConfigProtocols (XmlNode section, WSConfig config)
  255. {
  256. if (section.Attributes != null && section.Attributes.Count != 0)
  257. ThrowException ("Unrecognized attribute", section);
  258. XmlNodeList nodes = section.ChildNodes;
  259. foreach (XmlNode child in nodes) {
  260. XmlNodeType ntype = child.NodeType;
  261. if (ntype == XmlNodeType.Whitespace || ntype == XmlNodeType.Comment)
  262. continue;
  263. if (ntype != XmlNodeType.Element)
  264. ThrowException ("Only elements allowed", child);
  265. string name = child.Name;
  266. string error;
  267. if (name == "add") {
  268. string protoName = AttValue ("name", child, false);
  269. if (child.Attributes != null && child.Attributes.Count != 0)
  270. HandlersUtil.ThrowException ("Unrecognized attribute", child);
  271. if (!config.AddProtocol (protoName, out error))
  272. ThrowException (error, child);
  273. continue;
  274. }
  275. if (name == "remove") {
  276. string protoName = AttValue ("name", child, false);
  277. if (child.Attributes != null && child.Attributes.Count != 0)
  278. HandlersUtil.ThrowException ("Unrecognized attribute", child);
  279. if (!config.RemoveProtocol (protoName, out error))
  280. ThrowException (error, child);
  281. continue;
  282. }
  283. if (name == "clear") {
  284. if (child.Attributes != null && child.Attributes.Count != 0)
  285. HandlersUtil.ThrowException ("Unrecognized attribute", child);
  286. config.ClearProtocol ();
  287. continue;
  288. }
  289. ThrowException ("Unexpected element", child);
  290. }
  291. }
  292. static void ConfigSoapExtensionTypes (XmlNode section, ArrayList extensions)
  293. {
  294. if (section.Attributes != null && section.Attributes.Count != 0)
  295. ThrowException ("Unrecognized attribute", section);
  296. XmlNodeList nodes = section.ChildNodes;
  297. foreach (XmlNode child in nodes) {
  298. XmlNodeType ntype = child.NodeType;
  299. if (ntype == XmlNodeType.Whitespace || ntype == XmlNodeType.Comment)
  300. continue;
  301. if (ntype != XmlNodeType.Element)
  302. ThrowException ("Only elements allowed", child);
  303. string name = child.Name;
  304. if (name == "add") {
  305. string seType = AttValue ("type", child, false);
  306. string priority = AttValue ("priority", child);
  307. string group = AttValue ("group", child);
  308. if (child.Attributes != null && child.Attributes.Count != 0)
  309. HandlersUtil.ThrowException ("Unrecognized attribute", child);
  310. WSExtensionConfig wse = new WSExtensionConfig ();
  311. Exception e = wse.SetType (seType);
  312. if (e != null)
  313. ThrowException (e.Message, child);
  314. e = wse.SetPriority (priority);
  315. if (e != null)
  316. ThrowException (e.Message, child);
  317. e = wse.SetGroup (group);
  318. if (e != null)
  319. ThrowException (e.Message, child);
  320. extensions.Add (wse);
  321. continue;
  322. }
  323. ThrowException ("Unexpected element", child);
  324. }
  325. }
  326. static void ConfigFormatExtensionTypes (XmlNode section, WSConfig config)
  327. {
  328. if (section.Attributes != null && section.Attributes.Count != 0)
  329. ThrowException ("Unrecognized attribute", section);
  330. XmlNodeList nodes = section.ChildNodes;
  331. foreach (XmlNode child in nodes) {
  332. XmlNodeType ntype = child.NodeType;
  333. if (ntype == XmlNodeType.Whitespace || ntype == XmlNodeType.Comment)
  334. continue;
  335. if (ntype != XmlNodeType.Element)
  336. ThrowException ("Only elements allowed", child);
  337. string name = child.Name;
  338. if (name == "add") {
  339. string typeName = AttValue ("name", child, false);
  340. if (child.Attributes != null && child.Attributes.Count != 0)
  341. HandlersUtil.ThrowException ("Unrecognized attribute", child);
  342. try {
  343. config.FormatExtensionTypes.Add (Type.GetType (typeName, true));
  344. } catch (Exception e) {
  345. ThrowException (e.Message, child);
  346. }
  347. continue;
  348. }
  349. ThrowException ("Unexpected element", child);
  350. }
  351. }
  352. // To save some typing...
  353. static string AttValue (string name, XmlNode node, bool optional)
  354. {
  355. return HandlersUtil.ExtractAttributeValue (name, node, optional);
  356. }
  357. static string AttValue (string name, XmlNode node)
  358. {
  359. return HandlersUtil.ExtractAttributeValue (name, node, true);
  360. }
  361. static void ThrowException (string message, XmlNode node)
  362. {
  363. HandlersUtil.ThrowException (message, node);
  364. }
  365. //
  366. }
  367. class HandlersUtil
  368. {
  369. private HandlersUtil ()
  370. {
  371. }
  372. static internal string ExtractAttributeValue (string attKey, XmlNode node)
  373. {
  374. return ExtractAttributeValue (attKey, node, false);
  375. }
  376. static internal string ExtractAttributeValue (string attKey, XmlNode node, bool optional)
  377. {
  378. if (node.Attributes == null) {
  379. if (optional)
  380. return null;
  381. ThrowException ("Required attribute not found: " + attKey, node);
  382. }
  383. XmlNode att = node.Attributes.RemoveNamedItem (attKey);
  384. if (att == null) {
  385. if (optional)
  386. return null;
  387. ThrowException ("Required attribute not found: " + attKey, node);
  388. }
  389. string value = att.Value;
  390. if (value == String.Empty) {
  391. string opt = optional ? "Optional" : "Required";
  392. ThrowException (opt + " attribute is empty: " + attKey, node);
  393. }
  394. return value;
  395. }
  396. static internal void ThrowException (string msg, XmlNode node)
  397. {
  398. if (node != null && node.Name != String.Empty)
  399. msg = msg + " (node name: " + node.Name + ") ";
  400. throw new ConfigurationException (msg, node);
  401. }
  402. }
  403. }