PageRenderTime 74ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/tools/mconfig/Mono.MonoConfig/Configuration.cs

https://bitbucket.org/danipen/mono
C# | 337 lines | 245 code | 64 blank | 28 comment | 56 complexity | dc6f2475de0ee71b605a69afe847f139 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. //
  2. // Authors:
  3. // Marek Habersack (mhabersack@novell.com)
  4. //
  5. // (C) 2007 Novell, Inc
  6. //
  7. //
  8. // Permission is hereby granted, free of charge, to any person obtaining
  9. // a copy of this software and associated documentation files (the
  10. // "Software"), to deal in the Software without restriction, including
  11. // without limitation the rights to use, copy, modify, merge, publish,
  12. // distribute, sublicense, and/or sell copies of the Software, and to
  13. // permit persons to whom the Software is furnished to do so, subject to
  14. // the following conditions:
  15. //
  16. // The above copyright notice and this permission notice shall be
  17. // included in all copies or substantial portions of the Software.
  18. //
  19. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  20. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  21. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  22. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  23. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  24. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  25. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26. //
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Xml;
  30. using System.Xml.XPath;
  31. namespace Mono.MonoConfig
  32. {
  33. class HandlerDescription
  34. {
  35. Type handlerType;
  36. Type handlerStorageType;
  37. string section;
  38. object handler;
  39. object storage;
  40. public object Handler {
  41. get {
  42. if (handler != null)
  43. return handler;
  44. handler = Activator.CreateInstance (handlerType);
  45. return handler;
  46. }
  47. }
  48. public object Storage {
  49. get {
  50. if (storage != null)
  51. return storage;
  52. storage = Activator.CreateInstance (handlerStorageType);
  53. return storage;
  54. }
  55. }
  56. public string Section {
  57. get { return section; }
  58. }
  59. public bool Implements (string interfaceName)
  60. {
  61. return handlerType.GetInterface (interfaceName) != null;
  62. }
  63. public HandlerDescription (string handlerTypeName, string handlerStorageTypeName, string section)
  64. {
  65. handlerType = Type.GetType (handlerTypeName, true);
  66. if (handlerType.GetInterface ("Mono.MonoConfig.IDocumentNodeHandler") == null)
  67. throw new ApplicationException (
  68. String.Format ("Handler for section '{0}' must implement the '{1}' interface",
  69. section, typeof (Mono.MonoConfig.IDocumentNodeHandler)));
  70. handlerStorageType = Type.GetType (handlerStorageTypeName, true);
  71. this.section = section;
  72. }
  73. }
  74. public class Configuration
  75. {
  76. string[] configs;
  77. Dictionary <string, HandlerDescription> section_handlers;
  78. List <HandlerDescription> section_handlers_ordered;
  79. List <XPathDocument> config_documents;
  80. bool loaded;
  81. public Configuration () : this (null)
  82. {}
  83. public Configuration (string[] configs)
  84. {
  85. this.configs = configs;
  86. section_handlers = new Dictionary <string, HandlerDescription> ();
  87. section_handlers_ordered = new List <HandlerDescription> ();
  88. config_documents = new List <XPathDocument> (configs != null ? configs.Length : 1);
  89. }
  90. public void WriteDefaultConfigFile (string name, string path, FeatureTarget target)
  91. {
  92. AssertLoaded ();
  93. if (String.IsNullOrEmpty (name))
  94. throw new ArgumentException ("name", "Must not be null or empty");
  95. IDefaultConfigFileContainer[] containers = GetHandlersForInterface <IDefaultConfigFileContainer> ();
  96. if (containers == null || containers.Length == 0)
  97. throw new ApplicationException ("Cannot find any handler for writing default config files");
  98. IDefaultContainer[] defaults = GetHandlersForInterface <IDefaultContainer> ();
  99. bool written = false;
  100. foreach (IDefaultConfigFileContainer container in containers) {
  101. if (container.HasDefaultConfigFile (name, target)) {
  102. container.WriteDefaultConfigFile (name, target, path, defaults);
  103. written = true;
  104. break;
  105. }
  106. }
  107. if (!written)
  108. throw new ApplicationException (
  109. String.Format ("Definition of default config file '{0}' for target '{1}' not found.",
  110. name, target));
  111. }
  112. public string[] DefaultConfigFiles {
  113. get {
  114. AssertLoaded ();
  115. IDefaultConfigFileContainer[] containers = GetHandlersForInterface <IDefaultConfigFileContainer> ();
  116. if (containers == null || containers.Length == 0)
  117. return null;
  118. List <string> defaults = new List <string> ();
  119. foreach (IDefaultConfigFileContainer container in containers)
  120. defaults.AddRange (container.DefaultConfigFiles);
  121. defaults.Sort ();
  122. return defaults.ToArray ();
  123. }
  124. }
  125. public void AddFeature (string configFilePath, FeatureTarget target, string featureName)
  126. {
  127. AssertLoaded ();
  128. if (String.IsNullOrEmpty (configFilePath))
  129. throw new ArgumentException ("configFilePath", "Must not be null or empty");
  130. if (String.IsNullOrEmpty (featureName))
  131. throw new ArgumentException ("featureName", "Must not be null or empty");
  132. IFeatureGenerator[] generators = GetHandlersForInterface <IFeatureGenerator> ();
  133. if (generators == null || generators.Length == 0)
  134. throw new ApplicationException ("Cannot find any feature generator");
  135. IDefaultContainer[] defaults = GetHandlersForInterface <IDefaultContainer> ();
  136. IConfigBlockContainer[] configBlocks = GetHandlersForInterface <IConfigBlockContainer> ();
  137. bool added = false;
  138. foreach (IFeatureGenerator generator in generators) {
  139. if (generator.HasFeature (featureName)) {
  140. generator.AddFeature (configFilePath, featureName, target, defaults, configBlocks);
  141. added = true;
  142. break;
  143. }
  144. }
  145. if (!added)
  146. throw new ApplicationException (
  147. String.Format ("Definition of feature '{0}' for target '{1}' not found.",
  148. featureName, target));
  149. }
  150. public string[] Features {
  151. get {
  152. AssertLoaded ();
  153. IFeatureGenerator[] generators = GetHandlersForInterface <IFeatureGenerator> ();
  154. if (generators == null || generators.Length == 0)
  155. return null;
  156. List <string> features = new List <string> ();
  157. foreach (IFeatureGenerator generator in generators)
  158. features.AddRange (generator.Features);
  159. features.Sort ();
  160. return features.ToArray ();
  161. }
  162. }
  163. public void Load (string[] configs)
  164. {
  165. this.configs = configs;
  166. Load ();
  167. }
  168. public void Load ()
  169. {
  170. if (configs == null || configs.Length == 0)
  171. return;
  172. if (loaded) {
  173. section_handlers.Clear ();
  174. section_handlers_ordered.Clear ();
  175. config_documents.Clear ();
  176. loaded = false;
  177. }
  178. XPathDocument doc;
  179. foreach (string config in configs) {
  180. if (String.IsNullOrEmpty (config))
  181. continue;
  182. try {
  183. doc = new XPathDocument (config);
  184. config_documents.Add (doc);
  185. } catch (XmlException ex) {
  186. throw new ApplicationException (
  187. String.Format ("Failed to parse config file '{0}'.", config),
  188. ex);
  189. } catch (Exception) {
  190. continue;
  191. }
  192. }
  193. XPathNavigator nav;
  194. XPathNodeIterator iter;
  195. // First configure section handlers
  196. List <HandlerDescription> handlers_from_file = new List <HandlerDescription> ();
  197. foreach (XPathDocument xpdoc in config_documents) {
  198. handlers_from_file.Clear ();
  199. nav = xpdoc.CreateNavigator ();
  200. iter = nav.Select ("//mconfig/configuration/handlers/handler[string-length (@section) > 0]");
  201. while (iter.MoveNext ())
  202. AddSectionHandler (iter.Current, handlers_from_file);
  203. section_handlers_ordered.InsertRange (0, handlers_from_file);
  204. }
  205. // Process all configs looking for all sections with known handlers
  206. foreach (XPathDocument xpdoc in config_documents) {
  207. nav = xpdoc.CreateNavigator ();
  208. iter = nav.Select ("//mconfig/*");
  209. while (iter.MoveNext ())
  210. HandleTopLevelNode (iter.Current);
  211. }
  212. loaded = true;
  213. }
  214. public T[] GetHandlersForInterface <T> ()
  215. {
  216. AssertLoaded ();
  217. string typeName = typeof (T).ToString ();
  218. object handler;
  219. List <T> handlers = null;
  220. foreach (HandlerDescription hd in section_handlers_ordered) {
  221. if (hd.Implements (typeName)) {
  222. if (handlers == null)
  223. handlers = new List <T> (1);
  224. handler = hd.Handler;
  225. if (handler is IStorageConsumer)
  226. ((IStorageConsumer) handler).SetStorage (hd.Storage);
  227. handlers.Add ((T)handler);
  228. }
  229. }
  230. if (handlers == null)
  231. return null;
  232. return handlers.ToArray ();
  233. }
  234. void HandleTopLevelNode (XPathNavigator nav)
  235. {
  236. string section = nav.LocalName;
  237. if (!section_handlers.ContainsKey (section))
  238. return;
  239. HandlerDescription hd = section_handlers [section];
  240. if (hd == null)
  241. return;
  242. IDocumentNodeHandler handler = hd.Handler as IDocumentNodeHandler;
  243. object storage = hd.Storage;
  244. if (handler == null || storage == null)
  245. return;
  246. if (handler is IStorageConsumer)
  247. ((IStorageConsumer) handler).SetStorage (storage);
  248. handler.ReadConfiguration (nav);
  249. handler.StoreConfiguration ();
  250. }
  251. void AddSectionHandler (XPathNavigator nav, List <HandlerDescription> handlers)
  252. {
  253. string section = Helpers.GetRequiredNonEmptyAttribute (nav, "section");
  254. HandlerDescription hd = new HandlerDescription (Helpers.GetRequiredNonEmptyAttribute (nav, "type"),
  255. Helpers.GetRequiredNonEmptyAttribute (nav, "storageType"),
  256. section);
  257. if (section_handlers.ContainsKey (section)) {
  258. HandlerDescription old = section_handlers [section];
  259. section_handlers [section] = hd;
  260. handlers.Remove (old);
  261. handlers.Add (hd);
  262. } else {
  263. section_handlers.Add (section, hd);
  264. handlers.Add (hd);
  265. }
  266. }
  267. void AssertLoaded ()
  268. {
  269. if (!loaded)
  270. throw new ApplicationException ("Configuration not loaded yet");
  271. }
  272. }
  273. }