2 // System.Configuration.CodeDomConfigurationHandler
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // Copyright (c) 2005 Novell, Inc (http://www.novell.com)
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:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
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.
33 using System.Collections;
34 using System.Configuration;
40 namespace System.CodeDom.Compiler
43 class CodeDomConfigurationHandler : IConfigurationSectionHandler
45 public object Create (object parent, object context, XmlNode section)
47 return new CompilationConfigurationHandler ().Create (parent, context, section);
51 class CompilationConfigurationHandler : IConfigurationSectionHandler
53 public object Create (object parent, object context, XmlNode section)
55 CompilationConfiguration config = new CompilationConfiguration (parent);
57 config.TempDirectory = AttValue ("tempDirectory", section, true);
58 config.DefaultLanguage = AttValue ("defaultLanguage", section);
59 if (config.DefaultLanguage == null)
60 config.DefaultLanguage = "c#";
62 config.Debug = AttBoolValue ("debug", section, false);
63 config.Batch = AttBoolValue ("batch", section, false);
64 config.Explicit = AttBoolValue ("explicit", section, true);
65 config.Strict = AttBoolValue ("strict", section, false);
66 config.BatchTimeout = AttUIntValue ("batchTimeout", section, 0);
67 config.MaxBatchSize = AttUIntValue ("maxBatchSize", section, 0);
68 config.MaxBatchFileSize = AttUIntValue ("maxBatchFileSize", section, 0);
69 config.NumRecompilesBeforeAppRestart =
70 AttUIntValue ("numRecompilesBeforeAppRestart", section, 15);
72 if (section.Attributes != null && section.Attributes.Count != 0)
73 ThrowException ("Unrecognized attribute.", section);
75 XmlNodeList authNodes = section.ChildNodes;
76 foreach (XmlNode child in authNodes) {
77 XmlNodeType ntype = child.NodeType;
78 if (ntype != XmlNodeType.Element)
81 if (child.Name == "compilers") {
82 ReadCompilers (child.ChildNodes, config);
86 ThrowException ("Unexpected element", child);
92 static void ReadCompilers (XmlNodeList nodes, CompilationConfiguration config)
94 foreach (XmlNode child in nodes) {
95 XmlNodeType ntype = child.NodeType;
96 if (ntype != XmlNodeType.Element)
99 if (child.Name != "compiler")
100 ThrowException ("Unexpected element", child);
102 CompilerInfo compiler = new CompilerInfo ();
103 compiler.Languages = AttValue ("language", child);
104 compiler.Extensions = AttValue ("extension", child);
105 compiler.TypeName = AttValue ("type", child);
106 compiler.CompilerOptions = AttValue ("compilerOptions", child, true, true);
107 compiler.WarningLevel = AttUIntValue ("warningLevel", child, 0);
108 config.Compilers [compiler.Languages] = compiler;
112 static string AttValue (string name, XmlNode node, bool optional)
114 return AttValue (name, node, optional, false);
117 static string AttValue (string name, XmlNode node, bool optional, bool allowEmpty)
119 return ExtractAttributeValue (name, node, optional, allowEmpty);
122 static bool AttBoolValue (string name, XmlNode node, bool _default)
124 string v = AttValue (name, node, true);
128 bool result = (v == "true");
129 if (!result && v != "false")
130 ThrowException ("Invalid boolean value in " + name, node);
135 static int AttUIntValue (string name, XmlNode node, int _default)
137 string v = AttValue (name, node, true);
143 result = (int) UInt32.Parse (v);
145 ThrowException ("Invalid number in " + name, node);
151 static string AttValue (string name, XmlNode node)
153 return ExtractAttributeValue (name, node, true);
156 static string ShortAsmName (string long_name)
158 int i = long_name.IndexOf (',');
160 return long_name + ".dll";
161 return long_name.Substring (0, i) + ".dll";
164 static void ThrowException (string message, XmlNode node)
166 ThrowException (message, node);
169 static internal string ExtractAttributeValue (string attKey, XmlNode node)
171 return ExtractAttributeValue (attKey, node, false);
174 static internal string ExtractAttributeValue (string attKey, XmlNode node, bool optional)
176 return ExtractAttributeValue (attKey, node, optional, false);
179 static internal string ExtractAttributeValue (string attKey, XmlNode node, bool optional,
182 if (node.Attributes == null) {
186 ThrowException ("Required attribute not found: " + attKey, node);
189 XmlNode att = node.Attributes.RemoveNamedItem (attKey);
193 ThrowException ("Required attribute not found: " + attKey, node);
196 string value = att.Value;
197 if (!allowEmpty && value == String.Empty) {
198 string opt = optional ? "Optional" : "Required";
199 ThrowException (opt + " attribute is empty: " + attKey, node);
208 sealed class CompilationConfiguration
213 string default_language = "c#";
214 bool _explicit = true;
215 int max_batch_size = 30;
216 int max_batch_file_size = 3000;
217 int num_recompiles_before_app_restart = 15;
219 string temp_directory;
220 CompilerCollection compilers;
222 /* Only the config. handler should create instances of this. Use GetInstance (context) */
223 public CompilationConfiguration (object p)
225 CompilationConfiguration parent = p as CompilationConfiguration;
229 if (compilers == null)
230 compilers = new CompilerCollection ();
232 if (temp_directory == null)
233 temp_directory = Path.GetTempPath ();
236 public CompilerInfo GetCompilerInfo (string language)
238 return Compilers [language];
241 void Init (CompilationConfiguration parent)
243 debug = parent.debug;
244 batch = parent.batch;
245 batch_timeout = parent.batch_timeout;
246 default_language = parent.default_language;
247 _explicit = parent._explicit;
248 max_batch_size = parent.max_batch_size;
249 max_batch_file_size = parent.max_batch_file_size;
250 num_recompiles_before_app_restart = parent.num_recompiles_before_app_restart;
251 strict = parent.strict;
252 temp_directory = parent.temp_directory;
253 compilers = new CompilerCollection (parent.compilers);
257 get { return debug; }
258 set { debug = value; }
262 get { return batch; }
263 set { batch = value; }
266 public int BatchTimeout {
267 get { return batch_timeout; }
268 set { batch_timeout = value; }
271 public string DefaultLanguage {
272 get { return default_language; }
273 set { default_language = value; }
276 public bool Explicit {
277 get { return _explicit; }
278 set { _explicit = value; }
281 public int MaxBatchSize {
282 get { return max_batch_size; }
283 set { max_batch_size = value; }
286 public int MaxBatchFileSize {
287 get { return max_batch_file_size; }
288 set { max_batch_file_size = value; }
291 public int NumRecompilesBeforeAppRestart {
292 get { return num_recompiles_before_app_restart; }
293 set { num_recompiles_before_app_restart = value; }
297 get { return strict; }
298 set { strict = value; }
301 public string TempDirectory {
302 get { return temp_directory; }
304 if (value != null && !Directory.Exists (value))
305 throw new ArgumentException ("Directory does not exist");
307 temp_directory = value;
311 public CompilerCollection Compilers {
312 get { return compilers; }
316 sealed class CompilerCollection
320 public CompilerCollection () : this (null) {}
322 public CompilerCollection (CompilerCollection parent)
324 compilers = new Hashtable (CaseInsensitiveHashCodeProvider.Default,
325 CaseInsensitiveComparer.Default);
327 if (parent != null && parent.compilers != null) {
328 foreach (DictionaryEntry entry in parent.compilers)
329 compilers [entry.Key] = entry.Value;
333 public CompilerInfo this [string language] {
334 get { return compilers [language] as CompilerInfo; }
336 compilers [language] = value;
337 string [] langs = language.Split (';');
338 foreach (string s in langs) {
339 string x = s.Trim ();
341 compilers [x] = value;
346 internal Hashtable Hash {
347 get { return compilers; }