You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			548 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			548 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| //------------------------------------------------------------------------------
 | |
| // <copyright file="BuildProvider.cs" company="Microsoft">
 | |
| //     Copyright (c) Microsoft Corporation.  All rights reserved.
 | |
| // </copyright>
 | |
| //------------------------------------------------------------------------------
 | |
| 
 | |
| 
 | |
| 
 | |
| /*********************************
 | |
| 
 | |
| Class hierarchy
 | |
| 
 | |
| BuildProvider
 | |
|     ProfileBuildProvider
 | |
|     BaseResourcesBuildProvider
 | |
|         ResXBuildProvider
 | |
|         ResourcesBuildProvider
 | |
|     XsdBuildProvider
 | |
|     WsdlBuildProvider
 | |
|     InternalBuildProvider
 | |
|         SourceFileBuildProvider
 | |
|         SimpleHandlerBuildProvider
 | |
|             WebServiceBuildProvider
 | |
|             WebHandlerBuildProvider
 | |
|             ImageGeneratorBuildProvider
 | |
|         BaseTemplateBuildProvider
 | |
|             ApplicationBuildProvider
 | |
|             TemplateControlBuildProvider
 | |
|                 PageBuildProvider
 | |
|                 UserControlBuildProvider
 | |
|                     MasterPageBuildProvider
 | |
|             PageThemeBuildProvider
 | |
|                 GlobalPageThemeBuildProvider
 | |
| 
 | |
| **********************************/
 | |
| 
 | |
| 
 | |
| namespace System.Web.Compilation {
 | |
| 
 | |
| using System;
 | |
| using System.Security.Permissions;
 | |
| using System.IO;
 | |
| using System.Collections;
 | |
| using System.Collections.Generic;
 | |
| using System.Collections.Specialized;
 | |
| using System.CodeDom;
 | |
| using System.CodeDom.Compiler;
 | |
| using System.Web.Util;
 | |
| using System.Web.UI;
 | |
| using System.Web.Hosting;
 | |
| 
 | |
| // Flags returned from BuildProvider.GetResultFlags
 | |
| [Flags]
 | |
| public enum BuildProviderResultFlags {
 | |
|     Default = 0,
 | |
|     ShutdownAppDomainOnChange = 1,
 | |
| }
 | |
| 
 | |
| 
 | |
| /// <devdoc>
 | |
| ///    <para>
 | |
| ///       Base class for build providers that want to participate in a compilation.
 | |
| ///       It should be used by build providers that process files based on a virtual path.
 | |
| ///    </para>
 | |
| /// </devdoc>
 | |
| public abstract class BuildProvider {
 | |
| 
 | |
|     private static Dictionary<string, BuildProviderInfo> s_dynamicallyRegisteredProviders = new Dictionary<string, BuildProviderInfo>();
 | |
| 
 | |
|     //
 | |
|     // Public interface
 | |
|     //
 | |
| 
 | |
| 
 | |
|     /// <devdoc>
 | |
|     ///     Returns the CompilerType for the language that this build provider
 | |
|     ///     needs to use, or null of it can use any language.
 | |
|     /// </devdoc>
 | |
|     public virtual CompilerType CodeCompilerType { get { return null; } }
 | |
| 
 | |
| 
 | |
|     /// <devdoc>
 | |
|     ///     Asks this build provider to generate any code that it needs, using the various
 | |
|     ///     methods on the passed in BuildProvider.
 | |
|     /// </devdoc>
 | |
|     public virtual void GenerateCode(AssemblyBuilder assemblyBuilder) {}
 | |
| 
 | |
| 
 | |
|     /// <devdoc>
 | |
|     ///     Returns the class generated by this buildprovider
 | |
|     /// </devdoc>
 | |
|     public virtual Type GetGeneratedType(CompilerResults results) {
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /// <devdoc>
 | |
|     ///     Returns a string that the provider wants to have persisted with the compiled assembly.
 | |
|     /// </devdoc>
 | |
|     public virtual string GetCustomString(CompilerResults results) {
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /// <devdoc>
 | |
|     ///     Returns some flags that drives the behavior of the persisted result.
 | |
|     /// </devdoc>
 | |
|     public virtual BuildProviderResultFlags GetResultFlags(CompilerResults results) {
 | |
|         return BuildProviderResultFlags.Default;
 | |
|     }
 | |
| 
 | |
|     /// <devdoc>
 | |
|     ///     Give the BuildProvider a chance to look at the compile errors, and possibly tweak them
 | |
|     /// </devdoc>
 | |
|     public virtual void ProcessCompileErrors(CompilerResults results) {
 | |
|     }
 | |
| 
 | |
|     /// <devdoc>
 | |
|     ///     Returns the list of files (virtual paths) that this provider depends on.
 | |
|     ///     Those files need to be built before this BuildProvider.  The resulting assemblies
 | |
|     ///     are added as references when compiling this BuildProvider.
 | |
|     ///     This does not include things like server side includes, which don't directly
 | |
|     ///     produce a BuildResult.
 | |
|     ///     This is used to implement batching by separating BuildProviders
 | |
|     /// </devdoc>
 | |
|     internal virtual ICollection GetBuildResultVirtualPathDependencies() { return null; }
 | |
| 
 | |
|     public virtual ICollection VirtualPathDependencies {
 | |
|         get {
 | |
|             // By default, return the virtual path as its only dependency
 | |
|             return new SingleObjectCollection(VirtualPath);
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /// <devdoc>
 | |
|     ///     Returns the virtual path that this build provider handles
 | |
|     /// </devdoc>
 | |
|     protected internal string VirtualPath {
 | |
|         get { return System.Web.VirtualPath.GetVirtualPathString(_virtualPath); }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /// <devdoc>
 | |
|     ///     Returns the virtual path object that this build provider handles
 | |
|     /// </devdoc>
 | |
|     internal VirtualPath VirtualPathObject {
 | |
|         get { return _virtualPath; }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /// <devdoc>
 | |
|     ///     Opens a stream for the virtual file handled by this provider
 | |
|     /// </devdoc>
 | |
|     protected Stream OpenStream() {
 | |
|         return OpenStream(VirtualPath);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /// <devdoc>
 | |
|     ///     Opens a stream for a virtual file
 | |
|     /// </devdoc>
 | |
|     protected Stream OpenStream(string virtualPath) {
 | |
|         return VirtualPathProvider.OpenFile(virtualPath);
 | |
|     }
 | |
| 
 | |
|     internal /*protected*/ Stream OpenStream(VirtualPath virtualPath) {
 | |
|         return virtualPath.OpenFile();
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /// <devdoc>
 | |
|     ///     Opens a reader for the virtual file handled by this provider
 | |
|     /// </devdoc>
 | |
|     protected TextReader OpenReader() {
 | |
|         return OpenReader(VirtualPathObject);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /// <devdoc>
 | |
|     ///     Opens a reader for a virtual file
 | |
|     /// </devdoc>
 | |
|     protected TextReader OpenReader(string virtualPath) {
 | |
|         return OpenReader(System.Web.VirtualPath.Create(virtualPath));
 | |
|     }
 | |
| 
 | |
|     internal /*protected*/ TextReader OpenReader(VirtualPath virtualPath) {
 | |
|         Stream stream = OpenStream(virtualPath);
 | |
|         return Util.ReaderFromStream(stream, virtualPath);
 | |
|     }
 | |
| 
 | |
|     public static void RegisterBuildProvider(string extension, Type providerType) {
 | |
|         if (String.IsNullOrEmpty(extension)) {
 | |
|             throw ExceptionUtil.ParameterNullOrEmpty("extension");
 | |
|         }
 | |
|         if (providerType == null) {
 | |
|             throw new ArgumentNullException("providerType");
 | |
|         }
 | |
|         if (!typeof(BuildProvider).IsAssignableFrom(providerType)) {
 | |
|             // 
 | |
|             throw ExceptionUtil.ParameterInvalid("providerType");
 | |
|         }
 | |
|         BuildManager.ThrowIfPreAppStartNotRunning();
 | |
| 
 | |
|         // Last call wins. If a user wants to use a different provider they can always provide an
 | |
|         // override in the app's config.
 | |
|         s_dynamicallyRegisteredProviders[extension] = new CompilationBuildProviderInfo(providerType);
 | |
|     }
 | |
| 
 | |
|     internal static BuildProviderInfo GetBuildProviderInfo(System.Web.Configuration.CompilationSection config, string extension) {
 | |
|         Debug.Assert(extension != null);
 | |
|         var entry = config.BuildProviders[extension];
 | |
|         if (entry != null) {
 | |
|             return entry.BuildProviderInfo;
 | |
|         }
 | |
| 
 | |
|         BuildProviderInfo info = null;
 | |
|         s_dynamicallyRegisteredProviders.TryGetValue(extension, out info);
 | |
|         return info;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /// <devdoc>
 | |
|     ///     Returns a collection of assemblies that the build provider will be compiled with.
 | |
|     /// </devdoc>
 | |
|     protected ICollection ReferencedAssemblies {
 | |
|         get { return _referencedAssemblies; }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /// <devdoc>
 | |
|     ///     Returns the default CompilerType to be used for a specific language
 | |
|     /// </devdoc>
 | |
|     protected CompilerType GetDefaultCompilerTypeForLanguage(string language) {
 | |
|         return CompilationUtil.GetCompilerInfoFromLanguage(VirtualPathObject, language);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /// <devdoc>
 | |
|     ///     Returns the default CompilerType to be used for the default language
 | |
|     /// </devdoc>
 | |
|     protected CompilerType GetDefaultCompilerType() {
 | |
|         return CompilationUtil.GetDefaultLanguageCompilerInfo(null /*compConfig*/, VirtualPathObject);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     //
 | |
|     // Internal code
 | |
|     //
 | |
| 
 | |
|     #pragma warning disable 0649
 | |
|     internal SimpleBitVector32 flags;
 | |
|     #pragma warning restore 0649
 | |
| 
 | |
|     // const masks into the BitVector32
 | |
|     internal const int isDependedOn                 = 0x00000001;
 | |
|     internal const int noBuildResult                = 0x00000002;
 | |
|     internal const int ignoreParseErrors            = 0x00000004;
 | |
|     internal const int ignoreControlProperties      = 0x00000008;
 | |
|     internal const int dontThrowOnFirstParseError   = 0x00000010;
 | |
|     internal const int contributedCode              = 0x00000020;
 | |
| 
 | |
|     private VirtualPath _virtualPath;
 | |
| 
 | |
|     private ICollection _referencedAssemblies;
 | |
| 
 | |
|     private BuildProviderSet _buildProviderDependencies;
 | |
|     internal BuildProviderSet BuildProviderDependencies {
 | |
|         get {
 | |
|             return _buildProviderDependencies;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // Is any other BuildProvider depending on this BuildProvider
 | |
|     internal bool IsDependedOn { get { return flags[isDependedOn]; } }
 | |
| 
 | |
|     internal void SetNoBuildResult() {
 | |
|         flags[noBuildResult] = true;
 | |
|     }
 | |
| 
 | |
|     // Remember that this BuildProvider has contributed to the compilation
 | |
|     internal void SetContributedCode() {
 | |
|         flags[contributedCode] = true;
 | |
|     }
 | |
| 
 | |
|     internal void SetVirtualPath(VirtualPath virtualPath) {
 | |
|         _virtualPath = virtualPath;
 | |
|     }
 | |
| 
 | |
|     internal void SetReferencedAssemblies(ICollection referencedAssemblies) {
 | |
|         _referencedAssemblies = referencedAssemblies;
 | |
|     }
 | |
| 
 | |
|     internal void AddBuildProviderDependency(BuildProvider dependentBuildProvider) {
 | |
|         if (_buildProviderDependencies == null)
 | |
|             _buildProviderDependencies = new BuildProviderSet();
 | |
| 
 | |
|         _buildProviderDependencies.Add(dependentBuildProvider);
 | |
| 
 | |
|         dependentBuildProvider.flags[isDependedOn] = true;
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * Return the culture name for this provider (e.g. "fr" or "fr-fr").
 | |
|      * If no culture applies, return null.
 | |
|      */
 | |
|     internal string GetCultureName() {
 | |
|         return Util.GetCultureName(VirtualPath);
 | |
|     }
 | |
| 
 | |
|     internal BuildResult GetBuildResult(CompilerResults results) {
 | |
| 
 | |
|         BuildResult result = CreateBuildResult(results);
 | |
|         if (result == null)
 | |
|             return null;
 | |
| 
 | |
|         result.VirtualPath = VirtualPathObject;
 | |
|         SetBuildResultDependencies(result);
 | |
| 
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     internal virtual BuildResult CreateBuildResult(CompilerResults results) {
 | |
| 
 | |
|         // If the build provider is not supposed to have a build result, just return
 | |
|         if (flags[noBuildResult])
 | |
|             return null;
 | |
| 
 | |
|         // Access the CompiledAssembly property to make sure the assembly gets loaded
 | |
|         // Otherwise, the user code in GetGeneratedType() will fail to load it in medium trust since
 | |
|         // they don't have access to the codegen folder
 | |
|         if (!BuildManagerHost.InClientBuildManager && results != null) {
 | |
|             // The ClientBuildManager runs in full trust, so we skip this statement 
 | |
|             // to avoid unnecessary loading of the assembly.
 | |
|             var assembly = results.CompiledAssembly;
 | |
|         }
 | |
| 
 | |
|         // Ask the build provider if it wants to persist a Type
 | |
|         Type type = GetGeneratedType(results);
 | |
| 
 | |
|         BuildResult result;
 | |
| 
 | |
|         if (type != null) {
 | |
|             // Create a BuildResult for it
 | |
|             BuildResultCompiledType resultCompiledType = CreateBuildResult(type);
 | |
| 
 | |
|             if (!resultCompiledType.IsDelayLoadType) {
 | |
|                 // If the returned type doesn't come from the generated assembly, set a flag
 | |
|                 if (results == null || type.Assembly != results.CompiledAssembly)
 | |
|                     resultCompiledType.UsesExistingAssembly = true;
 | |
|             }
 | |
| 
 | |
|             result = resultCompiledType;
 | |
|         }
 | |
|         else {
 | |
|             // Ask the build provider if it instead wants to persist a custom string
 | |
|             string customString = GetCustomString(results);
 | |
| 
 | |
|             // If it does, persist it
 | |
|             if (customString != null) {
 | |
|                 // Only preserve an assembly if the BuildProvider has actually contributed code
 | |
|                 // to the compilation.
 | |
|                 result = new BuildResultCustomString(
 | |
|                     flags[contributedCode] ? results.CompiledAssembly : null,
 | |
|                     customString);
 | |
|             }
 | |
|             else {
 | |
|                 // Nothing was built: nothing to persist
 | |
|                 if (results == null)
 | |
|                     return null;
 | |
| 
 | |
|                 // Otherwise, just persist the assembly, if any
 | |
|                 result = new BuildResultCompiledAssembly(results.CompiledAssembly);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // Ask the provider it it wants to set some flags on the result
 | |
|         int resultFlags = (int) GetResultFlags(results);
 | |
|         if (resultFlags != 0) {
 | |
|             // Make sure only the lower bits are set
 | |
|             Debug.Assert((resultFlags & 0xFFFF0000) == 0);
 | |
|             resultFlags &= 0x0000FFFF;
 | |
| 
 | |
|             result.Flags |= resultFlags;
 | |
|         }
 | |
| 
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     internal virtual BuildResultCompiledType CreateBuildResult(Type t) {
 | |
|         return new BuildResultCompiledType(t);
 | |
|     }
 | |
| 
 | |
|     internal void SetBuildResultDependencies(BuildResult result) {
 | |
| 
 | |
|         result.AddVirtualPathDependencies(VirtualPathDependencies);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     //
 | |
|     // Helper methods
 | |
|     //
 | |
| 
 | |
|     internal static CompilerType GetCompilerTypeFromBuildProvider(
 | |
|         BuildProvider buildProvider) {
 | |
| 
 | |
|         HttpContext context = null;
 | |
|         if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && (context = HttpContext.Current) != null)
 | |
|             EtwTrace.Trace(EtwTraceType.ETW_TYPE_PARSE_ENTER, context.WorkerRequest);
 | |
| 
 | |
|         try {
 | |
|             CompilerType compilerType = buildProvider.CodeCompilerType;
 | |
|             if (compilerType != null) {
 | |
|                 CompilationUtil.CheckCompilerOptionsAllowed(compilerType.CompilerParameters.CompilerOptions,
 | |
|                     false /*config*/, null, 0);
 | |
|             }
 | |
|             return compilerType;
 | |
|         }
 | |
|         finally {
 | |
|             if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null)
 | |
|                 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PARSE_LEAVE, context.WorkerRequest);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Return a 'friendly' string that identifies the build provider
 | |
|     //
 | |
|     internal static string GetDisplayName(BuildProvider buildProvider) {
 | |
| 
 | |
|         // If it has a VirtualPath, use it
 | |
|         if (buildProvider.VirtualPath != null) {
 | |
|             return buildProvider.VirtualPath;
 | |
|         }
 | |
| 
 | |
|         // Otherwise, the best we can do is the type name
 | |
|         return buildProvider.GetType().Name;
 | |
|     }
 | |
| 
 | |
|     internal virtual ICollection GetGeneratedTypeNames() {
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     #region Methods from InternalBuildProvider
 | |
| 
 | |
|     // Protected internal methods: IgnoreParseErrors and GetCodeCompileUnit
 | |
| 
 | |
|     // When this is set, we ignore parse errors and keep on processing the page as
 | |
|     // well as possible.  This is used for the Venus CBM scenario
 | |
|     internal virtual bool IgnoreParseErrors {
 | |
|         get { return flags[ignoreParseErrors]; }
 | |
|         set { flags[ignoreParseErrors] = value; }
 | |
|     }
 | |
| 
 | |
|     // This is used in CBM to instruct the control builders to skip control properties
 | |
|     internal bool IgnoreControlProperties {
 | |
|         get { return flags[ignoreControlProperties]; }
 | |
|         set { flags[ignoreControlProperties] = value; }
 | |
|     }
 | |
| 
 | |
|     // Indicates whether the parser should continue processing for more errors.
 | |
|     // This is used in both CBM and aspnet_compiler tool.
 | |
|     internal bool ThrowOnFirstParseError {
 | |
|         get { return !flags[dontThrowOnFirstParseError]; }
 | |
|         set { flags[dontThrowOnFirstParseError] = !value; }
 | |
|     }
 | |
| 
 | |
|     // This is used in the CBM scenario only
 | |
|     internal virtual IAssemblyDependencyParser AssemblyDependencyParser {
 | |
|         get { return null; }
 | |
|     }
 | |
| 
 | |
|     // This is used in the CBM scenario only
 | |
|     /// <devdoc>
 | |
|     /// Returns the CodeCompileUnit and sets the associated dictionary containing the line pragmas.
 | |
|     /// </devdoc>
 | |
|     protected internal virtual CodeCompileUnit GetCodeCompileUnit(out IDictionary linePragmasTable) {
 | |
| 
 | |
|         // Default implementation with code at line 1
 | |
| 
 | |
|         string sourceString = Util.StringFromVirtualPath(VirtualPathObject);
 | |
|         CodeSnippetCompileUnit snippetCompileUnit = new CodeSnippetCompileUnit(sourceString);
 | |
| 
 | |
|         LinePragmaCodeInfo codeInfo = new LinePragmaCodeInfo(1 /* startLine */, 1 /* startColumn */, 1 /* startGeneratedColumn */, -1 /* codeLength */, false /* isCodeNuggest */);
 | |
|         linePragmasTable = new Hashtable();
 | |
|         linePragmasTable[1] = codeInfo;
 | |
| 
 | |
|         return snippetCompileUnit;
 | |
|     }
 | |
| 
 | |
|     internal virtual ICollection GetCompileWithDependencies() { return null; }
 | |
| 
 | |
|     #endregion Methods from InternalBuildProvider
 | |
| 
 | |
|     private class CompilationBuildProviderInfo : BuildProviderInfo {
 | |
| 
 | |
|         private readonly Type _type;
 | |
| 
 | |
|         public CompilationBuildProviderInfo(Type type) {
 | |
|             Debug.Assert(type != null);
 | |
|             _type = type;
 | |
|         }
 | |
| 
 | |
|         internal override Type Type {
 | |
|             get {
 | |
|                 return _type;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| // The InternalBuildProvider class is still retained to internally distinguish between
 | |
| // buildProviders that actually implement the required methods and those that don't, and
 | |
| // also to minimize code change where possible.
 | |
| internal abstract class InternalBuildProvider: BuildProvider {
 | |
| 
 | |
| }
 | |
| 
 | |
| internal abstract class BuildProviderInfo {
 | |
|     // AppliesTo value from the BuildProviderAppliesToAttribute
 | |
|     private BuildProviderAppliesTo _appliesTo;
 | |
| 
 | |
|     internal abstract Type Type { get; }
 | |
| 
 | |
|     internal BuildProviderAppliesTo AppliesTo {
 | |
|         get {
 | |
|             if (_appliesTo != 0)
 | |
|                 return _appliesTo;
 | |
| 
 | |
|             // Check whether the control builder's class exposes an AppliesTo attribute
 | |
|             object[] attrs = Type.GetCustomAttributes(
 | |
|                 typeof(BuildProviderAppliesToAttribute), /*inherit*/ true);
 | |
| 
 | |
|             if ((attrs != null) && (attrs.Length > 0)) {
 | |
|                 Debug.Assert(attrs[0] is BuildProviderAppliesToAttribute);
 | |
|                 _appliesTo = ((BuildProviderAppliesToAttribute)attrs[0]).AppliesTo;
 | |
|             }
 | |
|             else {
 | |
|                 // Default to applying to All
 | |
|                 _appliesTo = BuildProviderAppliesTo.All;
 | |
|             }
 | |
| 
 | |
|             return _appliesTo;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| }
 |