2006-03-11 Miguel de Icaza <miguel@novell.com>
[mono.git] / mcs / class / System / System.CodeDom.Compiler / CodeDomConfigurationHandler.cs
1 //
2 // System.Configuration.CodeDomConfigurationHandler
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //
7 // Copyright (c) 2005 Novell, Inc (http://www.novell.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 #if NET_2_0
32 using System;
33 using System.Collections;
34 using System.Configuration;
35 using System.IO;
36 #if XML_DEP
37 using System.Xml;
38 #endif
39
40 namespace System.CodeDom.Compiler
41 {
42 #if XML_DEP
43         class CodeDomConfigurationHandler : IConfigurationSectionHandler
44         {
45                 public object Create (object parent, object context, XmlNode section)
46                 {
47                         return new CompilationConfigurationHandler ().Create (parent, context, section);
48                 }
49         }
50
51         class CompilationConfigurationHandler : IConfigurationSectionHandler
52         {
53                 public object Create (object parent, object context, XmlNode section)
54                 {
55                         CompilationConfiguration config = new CompilationConfiguration (parent);
56
57                         config.TempDirectory = AttValue ("tempDirectory", section, true);
58                         config.DefaultLanguage = AttValue ("defaultLanguage", section);
59                         if (config.DefaultLanguage == null)
60                                 config.DefaultLanguage = "c#";
61
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);
71
72                         if (section.Attributes != null && section.Attributes.Count != 0)
73                                 ThrowException ("Unrecognized attribute.", section);
74
75                         XmlNodeList authNodes = section.ChildNodes;
76                         foreach (XmlNode child in authNodes) {
77                                 XmlNodeType ntype = child.NodeType;
78                                 if (ntype != XmlNodeType.Element)
79                                         continue;
80                                 
81                                 if (child.Name == "compilers") {
82                                         ReadCompilers (child.ChildNodes, config);
83                                         continue;
84                                 }
85
86                                 ThrowException ("Unexpected element", child);
87                         }
88
89                         return config;
90                 }
91
92                 static void ReadCompilers (XmlNodeList nodes, CompilationConfiguration config)
93                 {
94                         foreach (XmlNode child in nodes) {
95                                 XmlNodeType ntype = child.NodeType;
96                                 if (ntype != XmlNodeType.Element)
97                                         continue;
98
99                                 if (child.Name != "compiler")
100                                         ThrowException ("Unexpected element", child);
101
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;
109                         }
110                 }
111
112                 static string AttValue (string name, XmlNode node, bool optional)
113                 {
114                         return AttValue (name, node, optional, false);
115                 }
116                 
117                 static string AttValue (string name, XmlNode node, bool optional, bool allowEmpty)
118                 {
119                         return ExtractAttributeValue (name, node, optional, allowEmpty);
120                 }
121
122                 static bool AttBoolValue (string name, XmlNode node, bool _default)
123                 {
124                         string v = AttValue (name, node, true);
125                         if (v == null)
126                                 return _default;
127
128                         bool result = (v == "true");
129                         if (!result && v != "false")
130                                 ThrowException ("Invalid boolean value in " + name, node);
131
132                         return result;
133                 }
134
135                 static int AttUIntValue (string name, XmlNode node, int _default)
136                 {
137                         string v = AttValue (name, node, true);
138                         if (v == null)
139                                 return _default;
140
141                         int result = 0;
142                         try {
143                                 result = (int) UInt32.Parse (v);
144                         } catch {
145                                 ThrowException ("Invalid number in " + name, node);
146                         }
147
148                         return result;
149                 }
150
151                 static string AttValue (string name, XmlNode node)
152                 {
153                         return ExtractAttributeValue (name, node, true);
154                 }
155
156 #if false
157                 // Not used for now
158                 
159                 static string ShortAsmName (string long_name)
160                 {
161                         int i = long_name.IndexOf (',');
162                         if (i < 0)
163                                 return long_name + ".dll";
164                         return long_name.Substring (0, i) + ".dll";
165                 }
166 #endif
167                 
168                 static void ThrowException (string message, XmlNode node)
169                 {
170                         ThrowException (message, node);
171                 }
172
173                 static internal string ExtractAttributeValue (string attKey, XmlNode node)
174                 {
175                         return ExtractAttributeValue (attKey, node, false);
176                 }
177                         
178                 static internal string ExtractAttributeValue (string attKey, XmlNode node, bool optional)
179                 {
180                         return ExtractAttributeValue (attKey, node, optional, false);
181                 }
182                 
183                 static internal string ExtractAttributeValue (string attKey, XmlNode node, bool optional,
184                                                               bool allowEmpty)
185                 {
186                         if (node.Attributes == null) {
187                                 if (optional)
188                                         return null;
189
190                                 ThrowException ("Required attribute not found: " + attKey, node);
191                         }
192
193                         XmlNode att = node.Attributes.RemoveNamedItem (attKey);
194                         if (att == null) {
195                                 if (optional)
196                                         return null;
197                                 ThrowException ("Required attribute not found: " + attKey, node);
198                         }
199
200                         string value = att.Value;
201                         if (!allowEmpty && value == String.Empty) {
202                                 string opt = optional ? "Optional" : "Required";
203                                 ThrowException (opt + " attribute is empty: " + attKey, node);
204                         }
205
206                         return value;
207                 }
208         }
209
210 #endif // XML_DEP
211
212         sealed class CompilationConfiguration
213         {
214                 bool debug;
215                 bool batch;
216                 int batch_timeout;
217                 string default_language = "c#";
218                 bool _explicit = true;
219                 int max_batch_size = 30;
220                 int max_batch_file_size = 3000;
221                 int num_recompiles_before_app_restart = 15;
222                 bool strict;
223                 string temp_directory;
224                 CompilerCollection compilers;
225
226                 /* Only the config. handler should create instances of this. Use GetInstance (context) */
227                 public CompilationConfiguration (object p)
228                 {
229                         CompilationConfiguration parent = p as CompilationConfiguration;
230                         if (parent != null)
231                                 Init (parent);
232
233                         if (compilers == null)
234                                 compilers = new CompilerCollection ();
235
236                         if (temp_directory == null)
237                                 temp_directory = Path.GetTempPath ();
238                 }
239
240                 public CompilerInfo GetCompilerInfo (string language)
241                 {
242                         return Compilers [language];
243                 }
244
245                 void Init (CompilationConfiguration parent)
246                 {
247                         debug = parent.debug;
248                         batch = parent.batch;
249                         batch_timeout = parent.batch_timeout;
250                         default_language = parent.default_language;
251                         _explicit = parent._explicit;
252                         max_batch_size = parent.max_batch_size;
253                         max_batch_file_size = parent.max_batch_file_size;
254                         num_recompiles_before_app_restart = parent.num_recompiles_before_app_restart;
255                         strict = parent.strict;
256                         temp_directory = parent.temp_directory;
257                         compilers = new CompilerCollection (parent.compilers);
258                 }
259
260                 public bool Debug {
261                         get { return debug; }
262                         set { debug = value; }
263                 }
264
265                 public bool Batch {
266                         get { return batch; }
267                         set { batch = value; }
268                 }
269
270                 public int BatchTimeout {
271                         get { return batch_timeout; }
272                         set { batch_timeout = value; }
273                 }
274
275                 public string DefaultLanguage {
276                         get { return default_language; }
277                         set { default_language = value; }
278                 }
279
280                 public bool Explicit {
281                         get { return _explicit; }
282                         set { _explicit = value; }
283                 }
284
285                 public int MaxBatchSize {
286                         get { return max_batch_size; }
287                         set { max_batch_size = value; }
288                 }
289
290                 public int MaxBatchFileSize {
291                         get { return max_batch_file_size; }
292                         set { max_batch_file_size = value; }
293                 }
294
295                 public int NumRecompilesBeforeAppRestart {
296                         get { return num_recompiles_before_app_restart; }
297                         set { num_recompiles_before_app_restart = value; }
298                 }
299
300                 public bool Strict {
301                         get { return strict; }
302                         set { strict = value; }
303                 }
304
305                 public string TempDirectory {
306                         get { return temp_directory; }
307                         set {
308                                 if (value != null && !Directory.Exists (value))
309                                         throw new ArgumentException ("Directory does not exist");
310
311                                 temp_directory = value;
312                         }
313                 }
314
315                 public CompilerCollection Compilers {
316                         get { return compilers; }
317                 }
318         }
319
320         sealed class CompilerCollection
321         {
322                 Hashtable compilers;
323
324                 public CompilerCollection () : this (null) {}
325
326                 public CompilerCollection (CompilerCollection parent)
327                 {
328                         compilers = new Hashtable (CaseInsensitiveHashCodeProvider.Default,
329                                                    CaseInsensitiveComparer.Default);
330
331                         if (parent != null && parent.compilers != null) {
332                                 foreach (DictionaryEntry entry in parent.compilers)
333                                         compilers [entry.Key] = entry.Value;
334                         }
335                 }
336
337                 public CompilerInfo this [string language] {
338                         get { return compilers [language] as CompilerInfo; }
339                         set {
340                                 compilers [language] = value;
341                                 string [] langs = language.Split (';');
342                                 foreach (string s in langs) {
343                                         string x = s.Trim ();
344                                         if (x != "")
345                                                 compilers [x] = value;
346                                 }
347                         }
348                 }
349
350                 internal Hashtable Hash {
351                         get { return compilers; }
352                 }
353         }
354 }
355
356 #endif // NET_2_0
357