1 //------------------------------------------------------------------------------
2 // <copyright file="CompilationSection.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6 
7 namespace System.Web.Configuration {
8     using System;
9     using System.Xml;
10     using System.Configuration;
11     using System.Collections.Concurrent;
12     using System.Collections.Specialized;
13     using System.Collections;
14     using System.Globalization;
15     using System.IO;
16     using System.Text;
17     using System.Web.Compilation;
18     using System.Reflection;
19     using System.Web.Hosting;
20     using System.Web.UI;
21     using System.CodeDom.Compiler;
22     using System.Web.Util;
23     using System.Threading;
24     using System.ComponentModel;
25     using System.Security.Permissions;
26 
27     /*
28         <!-- compilation Attributes:
29           tempDirectory="directory"
30           debug="[true|false]"      // Default: false
31           strict="[true|false]"     // Default: false
32           explicit="[true|false]"   // Default: true   !!! This follow how it was defined in Machine.config
33           batch="[true|false]"      // Default: true
34           batchTimeout="timeout in seconds"     // Default: 15 seconds
35           maxBatchSize="max number of pages per batched compilation"    // Default: 1000 classes
36           maxBatchGeneratedFileSize="max combined size (in KB) of the generated source files per batched compilation"   // Default: 3000KB
37           numRecompilesBeforeAppRestart="max number of recompilations before appdomain is cycled"    // Default: 15 recomplations
38           defaultLanguage="name of a language as specified in a <compiler/> tag below"      // Default: VB
39           urlLinePragmas="[true|false]"     // Default: false, meaning pragmas use physical paths
40           targetFramework="target framework moniker" eg ".NET Framework,Version=v4.0" // Default: null
41           controlBuilderInterceptorType="type name of ControlBuilderInterceptor implementation"  //Default: ""
42           disableObsoleteWarnings="[true|false]" // Default: true
43           maxConcurrentCompilations="max number of concurrent assemblyBuilder compilations" // Default: 1
44         -->
45         <compilation debug="false" explicit="true" defaultLanguage="vb">
46 
47             <!-- codeSubDirectories example:
48             Note that this section is only valid in web.config in the application root.
49             <codeSubDirectories>
50                 <add directoryName="CodeSubDir1" />
51                 <add directoryName="CodeSubDir2" />
52             </codeSubDirectories>
53             -->
54 
55             <buildProviders>
56                 <add extension=".aspx" type="System.Web.Compilation.PageBuildProvider" />
57                 <add extension=".ascx" type="System.Web.Compilation.UserControlBuildProvider" />
58                 <add extension=".master" type="System.Web.Compilation.MasterPageBuildProvider" />
59                 <add extension=".asix" type="System.Web.Compilation.ImageGeneratorBuildProvider" />
60                 <add extension=".asmx" type="System.Web.Compilation.WebServiceBuildProvider" />
61                 <add extension=".ashx" type="System.Web.Compilation.WebHandlerBuildProvider" />
62                 <add extension=".soap" type="System.Web.Compilation.WebServiceBuildProvider" />
63                 <add extension=".resx" type="System.Web.Compilation.ResXBuildProvider" />
64                 <add extension=".resources" type="System.Web.Compilation.ResourcesBuildProvider" />
65                 <add extension=".wsdl" type="System.Web.Compilation.WsdlBuildProvider" />
66                 <add extension=".xsd" type="System.Web.Compilation.XsdBuildProvider" />
67             </buildProviders>
68 
69             <!-- folderLevelBuildProviders example:
70             <folderLevelBuildProviders>
71                 <add type="MyBuildProvider, MyAssembly,Version=1.0.0.0,PublicKeyToken=TOKEN" />
72             </folderLevelBuildProviders>
73             -->
74 
75             <assemblies>
76                 <add assembly="mscorlib" />
77                 <add assembly="System, Version=%ASSEMBLY_VERSION%, Culture=neutral, PublicKeyToken=%ECMA_PUBLICKEY%" />
78                 <add assembly="System.Configuration, Version=%ASSEMBLY_VERSION%, Culture=neutral, PublicKeyToken=%MICROSOFT_PUBLICKEY%" />
79                 <add assembly="System.Web, Version=%ASSEMBLY_VERSION%, Culture=neutral, PublicKeyToken=%MICROSOFT_PUBLICKEY%" />
80                 <add assembly="System.Data, Version=%ASSEMBLY_VERSION%, Culture=neutral, PublicKeyToken=%ECMA_PUBLICKEY%" />
81                 <add assembly="System.Web.Services, Version=%ASSEMBLY_VERSION%, Culture=neutral, PublicKeyToken=%MICROSOFT_PUBLICKEY%" />
82                 <add assembly="System.Xml, Version=%ASSEMBLY_VERSION%, Culture=neutral, PublicKeyToken=%ECMA_PUBLICKEY%" />
83                 <add assembly="System.Drawing, Version=%ASSEMBLY_VERSION%, Culture=neutral, PublicKeyToken=%MICROSOFT_PUBLICKEY%" />
84                 <add assembly="System.EnterpriseServices, Version=%ASSEMBLY_VERSION%, Culture=neutral, PublicKeyToken=%MICROSOFT_PUBLICKEY%" />
85                 <add assembly="System.Web.Mobile, Version=%ASSEMBLY_VERSION%, Culture=neutral, PublicKeyToken=%MICROSOFT_PUBLICKEY%" />
86                 <add assembly="*" />
87             </assemblies>
88 
89             <expressionBuilders>
90                 <add expressionPrefix="Resources" type="System.Web.Compilation.ResourceExpressionBuilder" />
91                 <add expressionPrefix="ConnectionStrings" type="System.Web.Compilation.ConnectionStringsExpressionBuilder" />
92                 <add expressionPrefix="AppSettings" type="System.Web.Compilation.AppSettingsExpressionBuilder" />
93             </expressionBuilders>
94 
95         </compilation>
96 */
97 
98     public sealed class CompilationSection : ConfigurationSection {
99         private const string tempDirectoryAttributeName = "tempDirectory";
100         private const string assemblyPostProcessorTypeAttributeName = "assemblyPostProcessorType";
101         private const string controlBuilderInterceptorTypeAttributeName = "controlBuilderInterceptorType";
102 
103         private static ConfigurationPropertyCollection _properties;
104         private static readonly ConfigurationProperty _propTempDirectory =
105             new ConfigurationProperty(tempDirectoryAttributeName, typeof(string),
106                                         String.Empty, ConfigurationPropertyOptions.None);
107         private static readonly ConfigurationProperty _propDebug =
108             new ConfigurationProperty("debug", typeof(bool), false, ConfigurationPropertyOptions.None);
109         private static readonly ConfigurationProperty _propStrict =
110             new ConfigurationProperty("strict", typeof(bool), false, ConfigurationPropertyOptions.None);
111         private static readonly ConfigurationProperty _propExplicit =
112             new ConfigurationProperty("explicit", typeof(bool), true, ConfigurationPropertyOptions.None);
113         private static readonly ConfigurationProperty _propBatch =
114             new ConfigurationProperty("batch", typeof(bool), true, ConfigurationPropertyOptions.None);
115         private static readonly ConfigurationProperty _propOptimizeCompilations =
116             new ConfigurationProperty("optimizeCompilations", typeof(bool), false, ConfigurationPropertyOptions.None);
117         private static readonly ConfigurationProperty _propBatchTimeout =
118             new ConfigurationProperty("batchTimeout",
119                                         typeof(TimeSpan),
120                                         TimeSpan.FromMinutes(15.0),
121                                         StdValidatorsAndConverters.TimeSpanSecondsOrInfiniteConverter,
122                                         StdValidatorsAndConverters.PositiveTimeSpanValidator,
123                                         ConfigurationPropertyOptions.None);
124         private static readonly ConfigurationProperty _propMaxBatchSize =
125             new ConfigurationProperty("maxBatchSize", typeof(int), 1000, ConfigurationPropertyOptions.None);
126         private static readonly ConfigurationProperty _propMaxBatchGeneratedFileSize =
127             new ConfigurationProperty("maxBatchGeneratedFileSize", typeof(int), 1000, ConfigurationPropertyOptions.None);
128         private static readonly ConfigurationProperty _propNumRecompilesBeforeAppRestart =
129             new ConfigurationProperty("numRecompilesBeforeAppRestart", typeof(int), 15, ConfigurationPropertyOptions.None);
130 #if !FEATURE_PAL // FEATURE_PAL does not support VisualBasic
131         private static readonly ConfigurationProperty _propDefaultLanguage =
132             new ConfigurationProperty("defaultLanguage", typeof(string), "vb", ConfigurationPropertyOptions.None);
133 #else // !FEATURE_PAL
134         private static readonly ConfigurationProperty _propDefaultLanguage =
135             new ConfigurationProperty("defaultLanguage", typeof(string),"c#",ConfigurationPropertyFlags.None);
136 #endif // !FEATURE_PAL
137         private static readonly ConfigurationProperty _propTargetFramework =
138             new ConfigurationProperty("targetFramework", typeof(string), null, ConfigurationPropertyOptions.None);
139 
140         private static readonly ConfigurationProperty _propCompilers =
141             new ConfigurationProperty("compilers", typeof(CompilerCollection), null, ConfigurationPropertyOptions.IsDefaultCollection);
142         private static readonly ConfigurationProperty _propAssemblies =
143             new ConfigurationProperty("assemblies", typeof(AssemblyCollection), null, ConfigurationPropertyOptions.IsDefaultCollection);
144         private static readonly ConfigurationProperty _propBuildProviders =
145             new ConfigurationProperty("buildProviders", typeof(BuildProviderCollection),
146                                         null, ConfigurationPropertyOptions.IsDefaultCollection);
147         private static readonly ConfigurationProperty _propFolderLevelBuildProviders =
148             new ConfigurationProperty("folderLevelBuildProviders", typeof(FolderLevelBuildProviderCollection),
149                                         null, ConfigurationPropertyOptions.IsDefaultCollection);
150         private static readonly ConfigurationProperty _propExpressionBuilders =
151             new ConfigurationProperty("expressionBuilders", typeof(ExpressionBuilderCollection),
152                                         null, ConfigurationPropertyOptions.IsDefaultCollection);
153         private static readonly ConfigurationProperty _propUrlLinePragmas =
154             new ConfigurationProperty("urlLinePragmas", typeof(bool), false, ConfigurationPropertyOptions.None);
155         private static readonly ConfigurationProperty _propCodeSubDirs =
156             new ConfigurationProperty("codeSubDirectories", typeof(CodeSubDirectoriesCollection),
157                                         null, ConfigurationPropertyOptions.IsDefaultCollection);
158         private static readonly ConfigurationProperty _propAssemblyPreprocessorType =
159             new ConfigurationProperty(assemblyPostProcessorTypeAttributeName, typeof(string),
160                                         String.Empty, ConfigurationPropertyOptions.None);
161         private static readonly ConfigurationProperty _propEnablePrefetchOptimization =
162             new ConfigurationProperty("enablePrefetchOptimization", typeof(bool), false, ConfigurationPropertyOptions.None);
163         private static readonly ConfigurationProperty _propProfileGuidedOptimizations =
164             new ConfigurationProperty("profileGuidedOptimizations", typeof(ProfileGuidedOptimizationsFlags),
165                                         ProfileGuidedOptimizationsFlags.All, ConfigurationPropertyOptions.None);
166         private static readonly ConfigurationProperty _propControlBuilderInterceptorType =
167             new ConfigurationProperty(controlBuilderInterceptorTypeAttributeName, typeof(string),
168                                         String.Empty, ConfigurationPropertyOptions.None);
169         private static readonly ConfigurationProperty _propDisableObsoleteWarnings =
170             new ConfigurationProperty("disableObsoleteWarnings", typeof(bool),
171                                         true, ConfigurationPropertyOptions.None);
172         private static readonly ConfigurationProperty _propMaxConcurrentCompilations =
173             new ConfigurationProperty("maxConcurrentCompilations", typeof(int), 1, ConfigurationPropertyOptions.None);
174 
175         const char fieldSeparator = ';';
176 
177         private bool _referenceSet;
178 
179         // _compilerLanguages : Hashtable <string, CompilerType>
180         // NOTE: This hashtable may contain either Compiler objects or CompilerType objects.
181         // It'll contain the later if the data has been read from config, but the particular
182         // language compiler type hasn't been resolved yet.  Otherwise, it'll contain CompilerType objects.
183         private Hashtable _compilerLanguages;
184 
185         // _compilerExtensions : Hashtable <string, CompilerType>
186         // NOTE: This hashtable may contain either Compiler objects or CompilerType objects.
187         // It'll contain the later if the data has been read from config, but the particular
188         // language compiler type hasn't been resolved yet.  Otherwise, it'll contain CompilerType objects.
189         private Hashtable _compilerExtensions;
190 
191         private long _recompilationHash = -1;
192 
193         private bool _isRuntimeObject = false;
194 
195         private Type _assemblyPostProcessorType;
196         private Type _controlBuilderInterceptorType;
197 
198         private static readonly Lazy<ConcurrentDictionary<Assembly, string>> _assemblyNames =
199             new Lazy<ConcurrentDictionary<Assembly, string>>();
200 
CompilationSection()201         static CompilationSection() {
202             // Property initialization
203             _properties = new ConfigurationPropertyCollection();
204             _properties.Add(_propTempDirectory);
205             _properties.Add(_propDebug);
206             _properties.Add(_propStrict);
207             _properties.Add(_propExplicit);
208             _properties.Add(_propBatch);
209             _properties.Add(_propOptimizeCompilations);
210             _properties.Add(_propBatchTimeout);
211             _properties.Add(_propMaxBatchSize);
212             _properties.Add(_propMaxBatchGeneratedFileSize);
213             _properties.Add(_propNumRecompilesBeforeAppRestart);
214             _properties.Add(_propDefaultLanguage);
215             _properties.Add(_propTargetFramework);
216             _properties.Add(_propCompilers);
217             _properties.Add(_propAssemblies);
218             _properties.Add(_propBuildProviders);
219             _properties.Add(_propFolderLevelBuildProviders);
220             _properties.Add(_propExpressionBuilders);
221             _properties.Add(_propUrlLinePragmas);
222             _properties.Add(_propCodeSubDirs);
223             _properties.Add(_propAssemblyPreprocessorType);
224             _properties.Add(_propEnablePrefetchOptimization);
225             _properties.Add(_propProfileGuidedOptimizations);
226             _properties.Add(_propControlBuilderInterceptorType);
227             _properties.Add(_propDisableObsoleteWarnings);
228             _properties.Add(_propMaxConcurrentCompilations);
229         }
230 
CompilationSection()231         public CompilationSection() {
232         }
233 
234         protected override ConfigurationPropertyCollection Properties {
235             get {
236                 return _properties;
237             }
238         }
239 
GetRuntimeObject()240         protected override object GetRuntimeObject() {
241             _isRuntimeObject = true;
242             return base.GetRuntimeObject();
243         }
244 
245         [ConfigurationProperty(tempDirectoryAttributeName, DefaultValue = "")]
246         public string TempDirectory {
247             get {
248                 return (string)base[_propTempDirectory];
249             }
250             set {
251                 base[_propTempDirectory] = value;
252             }
253         }
254 
255         // Used for error handling when there is a problem withe the temp dir
GetTempDirectoryErrorInfo(out string tempDirAttribName, out string configFileName, out int configLineNumber)256         internal void GetTempDirectoryErrorInfo(out string tempDirAttribName,
257             out string configFileName, out int configLineNumber) {
258             tempDirAttribName = tempDirectoryAttributeName;
259             configFileName = ElementInformation.Properties[tempDirectoryAttributeName].Source;
260             configLineNumber = ElementInformation.Properties[tempDirectoryAttributeName].LineNumber;
261         }
262 
263         [ConfigurationProperty("debug", DefaultValue = false)]
264         public bool Debug {
265             get {
266                 return (bool)base[_propDebug];
267             }
268             set {
269                 base[_propDebug] = value;
270             }
271         }
272 
273         [ConfigurationProperty("strict", DefaultValue = false)]
274         public bool Strict {
275             get {
276                 return (bool)base[_propStrict];
277             }
278             set {
279                 base[_propStrict] = value;
280             }
281         }
282 
283         [ConfigurationProperty("explicit", DefaultValue = true)]
284         public bool Explicit {
285             get {
286                 return (bool)base[_propExplicit];
287             }
288             set {
289                 base[_propExplicit] = value;
290             }
291         }
292 
293         [ConfigurationProperty("batch", DefaultValue = true)]
294         public bool Batch {
295             get {
296                 return (bool)base[_propBatch];
297             }
298             set {
299                 base[_propBatch] = value;
300             }
301         }
302 
303         [ConfigurationProperty("optimizeCompilations", DefaultValue = false)]
304         public bool OptimizeCompilations {
305             get {
306                 return (bool)base[_propOptimizeCompilations];
307             }
308             set {
309                 base[_propOptimizeCompilations] = value;
310             }
311         }
312 
313         [ConfigurationProperty("urlLinePragmas", DefaultValue = false)]
314         public bool UrlLinePragmas {
315             get {
316                 return (bool)base[_propUrlLinePragmas];
317             }
318             set {
319                 base[_propUrlLinePragmas] = value;
320             }
321         }
322 
323         [ConfigurationProperty("batchTimeout", DefaultValue = "00:15:00")]
324         [TimeSpanValidator(MinValueString="00:00:00", MaxValueString=TimeSpanValidatorAttribute.TimeSpanMaxValue)]
325         [TypeConverter(typeof(TimeSpanSecondsOrInfiniteConverter))]
326         public TimeSpan BatchTimeout {
327             get {
328                 return (TimeSpan)base[_propBatchTimeout];
329             }
330             set {
331                 base[_propBatchTimeout] = value;
332             }
333         }
334 
335         [ConfigurationProperty("maxBatchSize", DefaultValue = 1000)]
336         public int MaxBatchSize {
337             get {
338                 return (int)base[_propMaxBatchSize];
339             }
340             set {
341                 base[_propMaxBatchSize] = value;
342             }
343         }
344 
345         [ConfigurationProperty("maxBatchGeneratedFileSize", DefaultValue = 1000)]
346         public int MaxBatchGeneratedFileSize {
347             get {
348                 return (int)base[_propMaxBatchGeneratedFileSize];
349             }
350             set {
351                 base[_propMaxBatchGeneratedFileSize] = value;
352             }
353         }
354 
355         [ConfigurationProperty("numRecompilesBeforeAppRestart", DefaultValue = 15)]
356         public int NumRecompilesBeforeAppRestart {
357             get {
358                 return (int)base[_propNumRecompilesBeforeAppRestart];
359             }
360             set {
361                 base[_propNumRecompilesBeforeAppRestart] = value;
362             }
363         }
364 
365         [ConfigurationProperty("defaultLanguage", DefaultValue = "vb")]
366         public string DefaultLanguage {
367             get {
368                 return (string)base[_propDefaultLanguage];
369             }
370             set {
371                 base[_propDefaultLanguage] = value;
372             }
373         }
374 
375         [ConfigurationProperty("targetFramework", DefaultValue = null)]
376         public string TargetFramework {
377             get {
378                 return (string)base[_propTargetFramework];
379             }
380             set {
381                 base[_propTargetFramework] = value;
382             }
383         }
384 
385         [ConfigurationProperty("compilers")]
386         public CompilerCollection Compilers {
387             get {
388                 return (CompilerCollection)base[_propCompilers];
389             }
390         }
391 
392         [ConfigurationProperty("assemblies")]
393         public AssemblyCollection Assemblies {
394             get {
395                 if (_isRuntimeObject || BuildManagerHost.InClientBuildManager) {
396                     EnsureReferenceSet();
397                 }
398                 return GetAssembliesCollection();
399             }
400         }
401 
GetAssembliesCollection()402         private AssemblyCollection GetAssembliesCollection() {
403             return (AssemblyCollection)base[_propAssemblies];
404         }
405 
406         [ConfigurationProperty("buildProviders")]
407         public BuildProviderCollection BuildProviders {
408             get {
409                 return (BuildProviderCollection)base[_propBuildProviders];
410             }
411         }
412 
GetFolderLevelBuildProviders()413         private FolderLevelBuildProviderCollection GetFolderLevelBuildProviders() {
414             return (FolderLevelBuildProviderCollection)base[_propFolderLevelBuildProviders];
415         }
416 
417         [ConfigurationProperty("folderLevelBuildProviders")]
418         public FolderLevelBuildProviderCollection FolderLevelBuildProviders {
419             get {
420                 return GetFolderLevelBuildProviders();
421             }
422         }
423 
424         [ConfigurationProperty("expressionBuilders")]
425         public ExpressionBuilderCollection ExpressionBuilders {
426             get {
427                 return (ExpressionBuilderCollection)base[_propExpressionBuilders];
428             }
429 
430         }
431 
432         [ConfigurationProperty(assemblyPostProcessorTypeAttributeName, DefaultValue = "")]
433         public string AssemblyPostProcessorType {
434             get {
435                 return (string)base[_propAssemblyPreprocessorType];
436             }
437             set {
438                 base[_propAssemblyPreprocessorType] = value;
439             }
440         }
441 
442         internal Type AssemblyPostProcessorTypeInternal {
443             get {
444                 if (_assemblyPostProcessorType == null && !String.IsNullOrEmpty(AssemblyPostProcessorType)) {
445                     lock (this) {
446                         if (_assemblyPostProcessorType == null) {
447 
448                             // Only allow this in full trust
449                             if (!HttpRuntime.HasUnmanagedPermission()) {
450                                 throw new ConfigurationErrorsException(SR.GetString(SR.Insufficient_trust_for_attribute, assemblyPostProcessorTypeAttributeName),
451                                     ElementInformation.Properties[assemblyPostProcessorTypeAttributeName].Source,
452                                     ElementInformation.Properties[assemblyPostProcessorTypeAttributeName].LineNumber);
453                             }
454 
455                             Type assemblyPostProcessorType = ConfigUtil.GetType(AssemblyPostProcessorType, assemblyPostProcessorTypeAttributeName, this);
456                             ConfigUtil.CheckBaseType(typeof(System.Web.Compilation.IAssemblyPostProcessor),
457                                 assemblyPostProcessorType, "assemblyPostProcessorType", this);
458                             _assemblyPostProcessorType = assemblyPostProcessorType;
459                         }
460                     }
461                 }
462 
463                 return _assemblyPostProcessorType;
464             }
465         }
466 
467         [ConfigurationProperty("codeSubDirectories")]
468         public CodeSubDirectoriesCollection CodeSubDirectories {
469             get {
470                 return (CodeSubDirectoriesCollection)base[_propCodeSubDirs];
471             }
472 
473         }
474 
475         [ConfigurationProperty("enablePrefetchOptimization", DefaultValue = false)]
476         public bool EnablePrefetchOptimization {
477             get {
478                 return (bool)base[_propEnablePrefetchOptimization];
479             }
480             set {
481                 base[_propEnablePrefetchOptimization] = value;
482             }
483         }
484 
485         [ConfigurationProperty("profileGuidedOptimizations", DefaultValue = ProfileGuidedOptimizationsFlags.All)]
486         public ProfileGuidedOptimizationsFlags ProfileGuidedOptimizations {
487             get {
488                 return (ProfileGuidedOptimizationsFlags)base[_propProfileGuidedOptimizations];
489             }
490             set {
491                 base[_propProfileGuidedOptimizations] = value;
492             }
493         }
494 
495         [ConfigurationProperty(controlBuilderInterceptorTypeAttributeName, DefaultValue = "")]
496         public string ControlBuilderInterceptorType {
497             get {
498                 return (string)base[_propControlBuilderInterceptorType];
499             }
500             set {
501                 base[_propControlBuilderInterceptorType] = value;
502             }
503         }
504 
505         [ConfigurationProperty("disableObsoleteWarnings", DefaultValue = true)]
506         public bool DisableObsoleteWarnings {
507             get {
508                 return (bool)base[_propDisableObsoleteWarnings];
509             }
510             set {
511                 base[_propDisableObsoleteWarnings] = value;
512             }
513         }
514 
515         [ConfigurationProperty("maxConcurrentCompilations", DefaultValue = 1)]
516         public int MaxConcurrentCompilations {
517             get {
518                 return (int)base[_propMaxConcurrentCompilations];
519             }
520             set {
521                 base[_propMaxConcurrentCompilations] = value;
522             }
523         }
524 
EnsureCompilerCacheInit()525         private void EnsureCompilerCacheInit() {
526             if (_compilerLanguages == null) {
527                 lock (this) {
528                     if (_compilerLanguages == null) {
529                         Hashtable compilerLanguages = new Hashtable(StringComparer.OrdinalIgnoreCase);
530                         _compilerExtensions = new Hashtable(StringComparer.OrdinalIgnoreCase);
531 
532                         foreach (Compiler compiler in Compilers) {
533                             // Parse the semicolon separated lists
534                             string[] languageList = compiler.Language.Split(fieldSeparator);
535                             string[] extensionList = compiler.Extension.Split(fieldSeparator);
536 
537                             foreach (string language in languageList) {
538                                 compilerLanguages[language] = compiler;
539                             }
540 
541                             foreach (string extension in extensionList) {
542                                 _compilerExtensions[extension] = compiler;
543                             }
544                         }
545 
546                         // Only assign it at the end to make sure everything was successful
547                         _compilerLanguages = compilerLanguages;
548                     }
549                 }
550             }
551         }
552 
553         /*
554          * Return a CompilerType that a extension maps to.
555          */
GetCompilerInfoFromExtension(string extension, bool throwOnFail)556         internal CompilerType GetCompilerInfoFromExtension(string extension, bool throwOnFail) {
557             EnsureCompilerCacheInit();
558 
559             // First, try the cache (i.e. old <compilers> section)
560             CompilerType compilerType;
561             object obj = _compilerExtensions[extension];
562             Compiler compiler = obj as Compiler;
563 
564             if (compiler != null) {
565                 compilerType = compiler.CompilerTypeInternal;
566                 _compilerExtensions[extension] = compilerType;
567             }
568             else {
569                 compilerType = obj as CompilerType;
570             }
571 
572             if (compilerType == null) {
573 
574                 // If not, try the <codedom> section
575 
576                 if (CodeDomProvider.IsDefinedExtension(extension)) {
577                     string language = CodeDomProvider.GetLanguageFromExtension(extension);
578 
579                     CompilerInfo ci = CodeDomProvider.GetCompilerInfo(language);
580 
581                     compilerType = new CompilerType(
582                         ci.CodeDomProviderType, ci.CreateDefaultCompilerParameters());
583 
584                     // Cache it
585                     _compilerExtensions[extension] = compilerType;
586                 }
587             }
588 
589             if (compilerType == null) {
590                 if (!throwOnFail) return null;
591 
592                 // Unsupported extension: throw an exception
593                 throw new HttpException(SR.GetString(SR.Invalid_lang_extension, extension));
594             }
595 
596             // Clone it so the original is not modified
597             compilerType = compilerType.Clone();
598 
599             // Set the value of the debug flag in the copy
600             compilerType.CompilerParameters.IncludeDebugInformation = Debug;
601 
602             return compilerType;
603         }
604 
605         /*
606          * Return a CompilerType that a language maps to.
607          */
GetCompilerInfoFromLanguage(string language)608         internal CompilerType GetCompilerInfoFromLanguage(string language) {
609             EnsureCompilerCacheInit();
610 
611             // First, try the cache (i.e. old <compilers> section)
612             CompilerType compilerType;
613             object obj = _compilerLanguages[language];
614             Compiler compiler = obj as Compiler;
615 
616             if (compiler != null) {
617                 compilerType = compiler.CompilerTypeInternal;
618                 _compilerLanguages[language] = compilerType;
619             }
620             else {
621                 compilerType = obj as CompilerType;
622             }
623 
624             if (compilerType == null) {
625 
626                 // Try the <codedom> section
627 
628                 if (CodeDomProvider.IsDefinedLanguage(language)) {
629                     CompilerInfo ci = CodeDomProvider.GetCompilerInfo(language);
630 
631                     compilerType = new CompilerType(ci.CodeDomProviderType,
632                         ci.CreateDefaultCompilerParameters());
633 
634                     // Cache it
635                     _compilerLanguages[language] = compilerType;
636                 }
637             }
638 
639             if (compilerType == null) {
640 
641                 // Unsupported language: throw an exception
642                 throw new HttpException(SR.GetString(SR.Invalid_lang, language));
643             }
644 
645             // Only allow the use of compilerOptions when we have UnmanagedCode access (ASURT 73678)
646             CompilationUtil.CheckCompilerOptionsAllowed(compilerType.CompilerParameters.CompilerOptions,
647                 true /*config*/, null, 0);
648 
649             // Clone it so the original is not modified
650             compilerType = compilerType.Clone();
651 
652             // Set the value of the debug flag in the copy
653             compilerType.CompilerParameters.IncludeDebugInformation = Debug;
654 
655             return compilerType;
656         }
657 
658 
659         // This will only set the section pointer
EnsureReferenceSet()660         private void EnsureReferenceSet() {
661             if (!_referenceSet) {
662                 foreach (AssemblyInfo ai in GetAssembliesCollection()) {
663                     ai.SetCompilationReference(this);
664                 }
665                 _referenceSet = true;
666             }
667         }
668 
669         /// <summary>
670         /// Returns the original assembly name associated with the loaded assembly.
671         /// Returns Assembly.FullName if not found.
672         /// </summary>
673         /// <param name="a"></param>
674         /// <returns></returns>
GetOriginalAssemblyName(Assembly a)675         internal static string GetOriginalAssemblyName(Assembly a) {
676             string name = null;
677             if (!_assemblyNames.Value.TryGetValue(a, out name)) {
678                 // If the assembly is not found in the dictionary, just
679                 // return Assembly.FullName.
680                 name = a.FullName;
681             }
682             return name;
683         }
684 
LoadAssembly(AssemblyInfo ai)685         internal Assembly[] LoadAssembly(AssemblyInfo ai) {
686             Assembly[] assemblies = null;
687             if (ai.Assembly == "*") {
688                 assemblies = LoadAllAssembliesFromAppDomainBinDirectory();
689             }
690             else {
691                 Assembly a;
692                 a = LoadAssemblyHelper(ai.Assembly, false);
693                 if (a != null) {
694                     assemblies = new Assembly[1];
695                     assemblies[0] = a;
696                     RecordAssembly(ai.Assembly, a);
697                 }
698             }
699             return assemblies;
700         }
701 
LoadAndRecordAssembly(AssemblyName name)702         internal static Assembly LoadAndRecordAssembly(AssemblyName name) {
703             Assembly a = Assembly.Load(name);
704             RecordAssembly(name.FullName, a);
705             return a;
706         }
707 
RecordAssembly(string assemblyName, Assembly a)708         internal static void RecordAssembly(string assemblyName, Assembly a) {
709             // For each Assembly that we load, keep track of its original
710             // full name as specified in the config.
711             if (!_assemblyNames.Value.ContainsKey(a)) {
712                 _assemblyNames.Value.TryAdd(a, assemblyName);
713             }
714         }
715 
LoadAssembly(string assemblyName, bool throwOnFail)716         internal Assembly LoadAssembly(string assemblyName, bool throwOnFail) {
717 
718             // The trust should always be set before we load any assembly (VSWhidbey 317295)
719             System.Web.Util.Debug.Assert(HttpRuntime.TrustLevel != null);
720 
721             try {
722                 // First, try to just load the assembly
723                 Assembly a = Assembly.Load(assemblyName);
724                 // Record the original assembly name that was used to load this assembly.
725                 RecordAssembly(assemblyName, a);
726                 return a;
727             }
728             catch {
729                 AssemblyName asmName = new AssemblyName(assemblyName);
730 
731                 // Check if it's simply named
732                 Byte[] publicKeyToken = asmName.GetPublicKeyToken();
733                 if ((publicKeyToken == null || publicKeyToken.Length == 0) && asmName.Version == null) {
734 
735                     EnsureReferenceSet();
736 
737                     // It is simply named.  Go through all the assemblies from
738                     // the <assemblies> section, and if we find one that matches
739                     // the simple name, return it (ASURT 100546)
740                     foreach (AssemblyInfo ai in GetAssembliesCollection()) {
741                         Assembly[] a = ai.AssemblyInternal;
742                         if (a != null) {
743                             for (int i = 0; i < a.Length; i++) {
744                                 // use new AssemblyName(FullName).Name
745                                 // instead of a.GetName().Name, because GetName() does not work in medium trust
746                                 if (StringUtil.EqualsIgnoreCase(asmName.Name, new AssemblyName(a[i].FullName).Name)) {
747                                     return a[i];
748                                 }
749                             }
750                         }
751                     }
752                 }
753 
754                 if (throwOnFail) {
755                     throw;
756                 }
757             }
758 
759             return null;
760         }
761 
LoadAssemblyHelper(string assemblyName, bool starDirective)762         private Assembly LoadAssemblyHelper(string assemblyName, bool starDirective) {
763             // The trust should always be set before we load any assembly (VSWhidbey 317295)
764             System.Web.Util.Debug.Assert(HttpRuntime.TrustLevel != null);
765 
766             Assembly retAssembly = null;
767             // Load the assembly and add it to the dictionary.
768             try {
769                 retAssembly = System.Reflection.Assembly.Load(assemblyName);
770             }
771             catch (Exception e) {
772 
773                 // Check if this assembly came from the '*' directive
774                 bool ignoreException = false;
775 
776                 if (starDirective) {
777                     int hresult = System.Runtime.InteropServices.Marshal.GetHRForException(e);
778 
779                     // This is expected to fail for unmanaged DLLs that happen
780                     // to be in the bin dir.  Ignore them.
781 
782                     // Also, if the DLL is not an assembly, ignore the exception (ASURT 93073, VSWhidbey 319486)
783 
784                     // Test for COR_E_ASSEMBLYEXPECTED=0x80131018=-2146234344
785                     if (hresult == -2146234344) {
786                         ignoreException = true;
787                     }
788                 }
789 
790                 if (BuildManager.IgnoreBadImageFormatException) {
791                     var badImageFormatException = e as BadImageFormatException;
792                     if (badImageFormatException != null) {
793                         ignoreException = true;
794                     }
795                 }
796 
797                 if (!ignoreException) {
798                     string Message = e.Message;
799                     if (String.IsNullOrEmpty(Message)) {
800                         // try and make a better message than empty string
801                         if (e is FileLoadException) {
802                             Message = SR.GetString(SR.Config_base_file_load_exception_no_message, "assembly");
803                         }
804                         else if (e is BadImageFormatException) {
805                             Message = SR.GetString(SR.Config_base_bad_image_exception_no_message, assemblyName);
806                         }
807                         else {
808                             Message = SR.GetString(SR.Config_base_report_exception_type, e.GetType().ToString()); // at least this is better than no message
809                         }
810                     }
811                     // default to section if the assembly is not in the collection
812                     // which may happen it the assembly is being loaded from the bindir
813                     // and not named in configuration.
814                     String source = ElementInformation.Properties["assemblies"].Source;
815                     int lineNumber = ElementInformation.Properties["assemblies"].LineNumber;
816 
817                     // If processing the * directive, look up the line information for it
818                     if (starDirective)
819                         assemblyName = "*";
820 
821                     if (Assemblies[assemblyName] != null) {
822                         source = Assemblies[assemblyName].ElementInformation.Source;
823                         lineNumber = Assemblies[assemblyName].ElementInformation.LineNumber;
824                     }
825                     throw new ConfigurationErrorsException(Message, e, source, lineNumber);
826                 }
827             }
828 
829             System.Web.Util.Debug.Trace("LoadAssembly", "Successfully loaded assembly '" + assemblyName + "'");
830 
831             return retAssembly;
832         }
833 
LoadAllAssembliesFromAppDomainBinDirectory()834         internal Assembly[] LoadAllAssembliesFromAppDomainBinDirectory() {
835             // Get the path to the bin directory
836             string binPath = HttpRuntime.BinDirectoryInternal;
837             FileInfo[] binDlls;
838             Assembly assembly = null;
839             Assembly[] assemblies = null;
840             ArrayList list;
841 
842             if (!FileUtil.DirectoryExists(binPath)) {
843                 // This is expected to fail if there is no 'bin' dir
844                 System.Web.Util.Debug.Trace("Template", "Failed to access bin dir \"" + binPath + "\"");
845             }
846             else {
847                 DirectoryInfo binPathDirectory = new DirectoryInfo(binPath);
848                 // Get a list of all the DLL's in the bin directory
849                 binDlls = binPathDirectory.GetFiles("*.dll");
850 
851                 if (binDlls.Length > 0) {
852                     list = new ArrayList(binDlls.Length);
853 
854                     for (int i = 0; i < binDlls.Length; i++) {
855                         string assemblyName = Util.GetAssemblyNameFromFileName(binDlls[i].Name);
856 
857                         // Don't autoload generated assemblies in bin (VSWhidbey 467936)
858                         if (assemblyName.StartsWith(BuildManager.WebAssemblyNamePrefix, StringComparison.Ordinal))
859                             continue;
860 
861                         if (!GetAssembliesCollection().IsRemoved(assemblyName)) {
862                             assembly = LoadAssemblyHelper(assemblyName, true);
863                         }
864                         if (assembly != null) {
865                             list.Add(assembly);
866                         }
867                     }
868                     assemblies = (System.Reflection.Assembly[])list.ToArray(typeof(System.Reflection.Assembly));
869                 }
870             }
871 
872             if (assemblies == null) {
873                 // If there were no assemblies loaded, return a zero-length array
874                 assemblies = new Assembly[0];
875             }
876 
877             return assemblies;
878         }
879 
880         internal long RecompilationHash {
881             get {
882                 if (_recompilationHash == -1) {
883                     lock (this) {
884                         if (_recompilationHash == -1) {
885                             _recompilationHash = CompilationUtil.GetRecompilationHash(this);
886                         }
887                     }
888                 }
889 
890                 return _recompilationHash;
891             }
892         }
893 
PostDeserialize()894         protected override void PostDeserialize() {
895             // check to see if the _propCodeSubDirs was defined below the app level
896             WebContext context = EvaluationContext.HostingContext as WebContext;
897             if (context != null) {
898                 if (context.ApplicationLevel == WebApplicationLevel.BelowApplication) {
899                     if (CodeSubDirectories.ElementInformation.IsPresent) {
900                         throw new ConfigurationErrorsException(
901                             SR.GetString(SR.Config_element_below_app_illegal,
902                                          _propCodeSubDirs.Name), CodeSubDirectories.ElementInformation.Source, CodeSubDirectories.ElementInformation.LineNumber);
903                     }
904                     if (BuildProviders.ElementInformation.IsPresent) {
905                         throw new ConfigurationErrorsException(
906                             SR.GetString(SR.Config_element_below_app_illegal,
907                                          _propBuildProviders.Name), BuildProviders.ElementInformation.Source, BuildProviders.ElementInformation.LineNumber);
908                     }
909 
910                     if (FolderLevelBuildProviders.ElementInformation.IsPresent) {
911                         throw new ConfigurationErrorsException(
912                             SR.GetString(SR.Config_element_below_app_illegal,
913                                          _propFolderLevelBuildProviders.Name), FolderLevelBuildProviders.ElementInformation.Source, FolderLevelBuildProviders.ElementInformation.LineNumber);
914                     }
915                 }
916 
917             }
918         }
919 
920         internal Type ControlBuilderInterceptorTypeInternal {
921             get {
922                 if (_controlBuilderInterceptorType == null && !String.IsNullOrWhiteSpace(ControlBuilderInterceptorType)) {
923                     lock (this) {
924                         if (_controlBuilderInterceptorType == null) {
925                             _controlBuilderInterceptorType = CompilationUtil.LoadTypeWithChecks(ControlBuilderInterceptorType, typeof(ControlBuilderInterceptor), null, this, controlBuilderInterceptorTypeAttributeName);
926                         }
927                     }
928                 }
929                 return _controlBuilderInterceptorType;
930             }
931         }
932 
933         // This is called as the last step of the deserialization process before the newly created section is seen by the consumer.
934         // We can use it to change defaults on-the-fly.
SetReadOnly()935         protected override void SetReadOnly() {
936             // Unless overridden, set <compilation targetFramework="4.5" />
937             ConfigUtil.SetFX45DefaultValue(this, _propTargetFramework, BinaryCompatibility.Current.TargetFramework.ToString());
938 
939             base.SetReadOnly();
940         }
941     }
942 }
943