merge -r 58060:58217
[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                 static string ShortAsmName (string long_name)
157                 {
158                         int i = long_name.IndexOf (',');
159                         if (i < 0)
160                                 return long_name + ".dll";
161                         return long_name.Substring (0, i) + ".dll";
162                 }
163                 
164                 static void ThrowException (string message, XmlNode node)
165                 {
166                         ThrowException (message, node);
167                 }
168
169                 static internal string ExtractAttributeValue (string attKey, XmlNode node)
170                 {
171                         return ExtractAttributeValue (attKey, node, false);
172                 }
173                         
174                 static internal string ExtractAttributeValue (string attKey, XmlNode node, bool optional)
175                 {
176                         return ExtractAttributeValue (attKey, node, optional, false);
177                 }
178                 
179                 static internal string ExtractAttributeValue (string attKey, XmlNode node, bool optional,
180                                                               bool allowEmpty)
181                 {
182                         if (node.Attributes == null) {
183                                 if (optional)
184                                         return null;
185
186                                 ThrowException ("Required attribute not found: " + attKey, node);
187                         }
188
189                         XmlNode att = node.Attributes.RemoveNamedItem (attKey);
190                         if (att == null) {
191                                 if (optional)
192                                         return null;
193                                 ThrowException ("Required attribute not found: " + attKey, node);
194                         }
195
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);
200                         }
201
202                         return value;
203                 }
204         }
205
206 #endif // XML_DEP
207
208         sealed class CompilationConfiguration
209         {
210                 bool debug;
211                 bool batch;
212                 int batch_timeout;
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;
218                 bool strict;
219                 string temp_directory;
220                 CompilerCollection compilers;
221
222                 /* Only the config. handler should create instances of this. Use GetInstance (context) */
223                 public CompilationConfiguration (object p)
224                 {
225                         CompilationConfiguration parent = p as CompilationConfiguration;
226                         if (parent != null)
227                                 Init (parent);
228
229                         if (compilers == null)
230                                 compilers = new CompilerCollection ();
231
232                         if (temp_directory == null)
233                                 temp_directory = Path.GetTempPath ();
234                 }
235
236                 public CompilerInfo GetCompilerInfo (string language)
237                 {
238                         return Compilers [language];
239                 }
240
241                 void Init (CompilationConfiguration parent)
242                 {
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);
254                 }
255
256                 public bool Debug {
257                         get { return debug; }
258                         set { debug = value; }
259                 }
260
261                 public bool Batch {
262                         get { return batch; }
263                         set { batch = value; }
264                 }
265
266                 public int BatchTimeout {
267                         get { return batch_timeout; }
268                         set { batch_timeout = value; }
269                 }
270
271                 public string DefaultLanguage {
272                         get { return default_language; }
273                         set { default_language = value; }
274                 }
275
276                 public bool Explicit {
277                         get { return _explicit; }
278                         set { _explicit = value; }
279                 }
280
281                 public int MaxBatchSize {
282                         get { return max_batch_size; }
283                         set { max_batch_size = value; }
284                 }
285
286                 public int MaxBatchFileSize {
287                         get { return max_batch_file_size; }
288                         set { max_batch_file_size = value; }
289                 }
290
291                 public int NumRecompilesBeforeAppRestart {
292                         get { return num_recompiles_before_app_restart; }
293                         set { num_recompiles_before_app_restart = value; }
294                 }
295
296                 public bool Strict {
297                         get { return strict; }
298                         set { strict = value; }
299                 }
300
301                 public string TempDirectory {
302                         get { return temp_directory; }
303                         set {
304                                 if (value != null && !Directory.Exists (value))
305                                         throw new ArgumentException ("Directory does not exist");
306
307                                 temp_directory = value;
308                         }
309                 }
310
311                 public CompilerCollection Compilers {
312                         get { return compilers; }
313                 }
314         }
315
316         sealed class CompilerCollection
317         {
318                 Hashtable compilers;
319
320                 public CompilerCollection () : this (null) {}
321
322                 public CompilerCollection (CompilerCollection parent)
323                 {
324                         compilers = new Hashtable (CaseInsensitiveHashCodeProvider.Default,
325                                                    CaseInsensitiveComparer.Default);
326
327                         if (parent != null && parent.compilers != null) {
328                                 foreach (DictionaryEntry entry in parent.compilers)
329                                         compilers [entry.Key] = entry.Value;
330                         }
331                 }
332
333                 public CompilerInfo this [string language] {
334                         get { return compilers [language] as CompilerInfo; }
335                         set {
336                                 compilers [language] = value;
337                                 string [] langs = language.Split (';');
338                                 foreach (string s in langs) {
339                                         string x = s.Trim ();
340                                         if (x != "")
341                                                 compilers [x] = value;
342                                 }
343                         }
344                 }
345
346                 internal Hashtable Hash {
347                         get { return compilers; }
348                 }
349         }
350 }
351
352 #endif // NET_2_0
353