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