Files
linux-packaging-mono/external/aspnetwebstack/src/System.Web.WebPages.Razor/RazorBuildProvider.cs
Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

255 lines
8.8 KiB
C#

// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security;
using System.Web.Compilation;
using System.Web.Razor;
using System.Web.Razor.Generator;
using System.Web.Razor.Parser.SyntaxTree;
namespace System.Web.WebPages.Razor
{
[BuildProviderAppliesTo(BuildProviderAppliesTo.Web | BuildProviderAppliesTo.Code)]
public class RazorBuildProvider : BuildProvider
{
private static bool? _isFullTrust;
private CodeCompileUnit _generatedCode = null;
private WebPageRazorHost _host = null;
private IList _virtualPathDependencies;
private IAssemblyBuilder _assemblyBuilder;
public static event EventHandler<CodeGenerationCompleteEventArgs> CodeGenerationCompleted;
internal event EventHandler<CodeGenerationCompleteEventArgs> CodeGenerationCompletedInternal
{
add { _codeGenerationCompletedInternal += value; }
remove { _codeGenerationCompletedInternal -= value; }
}
public static event EventHandler CodeGenerationStarted;
/// <summary>
/// For unit testing.
/// </summary>
internal event EventHandler CodeGenerationStartedInternal
{
add { _codeGenerationStartedInternal += value; }
remove { _codeGenerationStartedInternal -= value; }
}
public static event EventHandler<CompilingPathEventArgs> CompilingPath;
/// <summary>
/// For unit testing
/// </summary>
private event EventHandler<CodeGenerationCompleteEventArgs> _codeGenerationCompletedInternal;
private event EventHandler _codeGenerationStartedInternal;
internal WebPageRazorHost Host
{
get
{
if (_host == null)
{
_host = CreateHost();
}
return _host;
}
set { _host = value; }
}
// Returns the base dependencies and any dependencies added via AddVirtualPathDependencies
public override ICollection VirtualPathDependencies
{
get
{
if (_virtualPathDependencies != null)
{
// Return a readonly wrapper so as to prevent users from modifying the collection directly.
return ArrayList.ReadOnly(_virtualPathDependencies);
}
else
{
return base.VirtualPathDependencies;
}
}
}
public new string VirtualPath
{
get { return base.VirtualPath; }
}
public AssemblyBuilder AssemblyBuilder
{
get
{
var wrapper = _assemblyBuilder as AssemblyBuilderWrapper;
if (wrapper != null)
{
return wrapper.InnerBuilder;
}
else
{
return null;
}
}
}
// For unit testing
internal IAssemblyBuilder AssemblyBuilderInternal
{
get { return _assemblyBuilder; }
}
internal CodeCompileUnit GeneratedCode
{
get
{
EnsureGeneratedCode();
return _generatedCode;
}
set { _generatedCode = value; }
}
public override CompilerType CodeCompilerType
{
get
{
EnsureGeneratedCode();
CompilerType compilerType = GetDefaultCompilerTypeForLanguage(Host.CodeLanguage.LanguageName);
if (_isFullTrust != false && Host.DefaultDebugCompilation)
{
try
{
SetIncludeDebugInfoFlag(compilerType);
_isFullTrust = true;
}
catch (SecurityException)
{
_isFullTrust = false;
}
}
return compilerType;
}
}
public void AddVirtualPathDependency(string dependency)
{
if (_virtualPathDependencies == null)
{
// Initialize the collection containing the base dependencies
_virtualPathDependencies = new ArrayList(base.VirtualPathDependencies);
}
_virtualPathDependencies.Add(dependency);
}
public override Type GetGeneratedType(CompilerResults results)
{
return results.CompiledAssembly.GetType(String.Format(CultureInfo.CurrentCulture, "{0}.{1}", Host.DefaultNamespace, Host.DefaultClassName));
}
public override void GenerateCode(AssemblyBuilder assemblyBuilder)
{
GenerateCodeCore(new AssemblyBuilderWrapper(assemblyBuilder));
}
internal virtual void GenerateCodeCore(IAssemblyBuilder assemblyBuilder)
{
OnCodeGenerationStarted(assemblyBuilder);
assemblyBuilder.AddCodeCompileUnit(this, GeneratedCode);
assemblyBuilder.GenerateTypeFactory(String.Format(CultureInfo.InvariantCulture, "{0}.{1}", Host.DefaultNamespace, Host.DefaultClassName));
}
protected internal virtual TextReader InternalOpenReader()
{
return OpenReader();
}
protected internal virtual WebPageRazorHost CreateHost()
{
// Get the host from config
WebPageRazorHost configuredHost = GetHostFromConfig();
// Fire the event
CompilingPathEventArgs args = new CompilingPathEventArgs(VirtualPath, configuredHost);
OnBeforeCompilePath(args);
// Return the host provided in the args, which may have been changed by the handler
return args.Host;
}
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "This method performs significant work and a property would not be appropriate")]
protected internal virtual WebPageRazorHost GetHostFromConfig()
{
return WebRazorHostFactory.CreateHostFromConfig(VirtualPath);
}
protected virtual void OnBeforeCompilePath(CompilingPathEventArgs args)
{
EventHandler<CompilingPathEventArgs> handler = CompilingPath;
if (handler != null)
{
handler(this, args);
}
}
private void OnCodeGenerationStarted(IAssemblyBuilder assemblyBuilder)
{
_assemblyBuilder = assemblyBuilder;
EventHandler handler = _codeGenerationStartedInternal ?? CodeGenerationStarted;
if (handler != null)
{
handler(this, null);
}
}
private void OnCodeGenerationCompleted(CodeCompileUnit generatedCode)
{
EventHandler<CodeGenerationCompleteEventArgs> handler = _codeGenerationCompletedInternal ?? CodeGenerationCompleted;
if (handler != null)
{
handler(this, new CodeGenerationCompleteEventArgs(Host.VirtualPath, Host.PhysicalPath, generatedCode));
}
}
private void EnsureGeneratedCode()
{
if (_generatedCode == null)
{
RazorTemplateEngine engine = new RazorTemplateEngine(Host);
GeneratorResults results = null;
using (TextReader reader = InternalOpenReader())
{
results = engine.GenerateCode(reader, className: null, rootNamespace: null, sourceFileName: Host.PhysicalPath);
}
if (!results.Success)
{
throw CreateExceptionFromParserError(results.ParserErrors.Last(), VirtualPath);
}
_generatedCode = results.GeneratedCode;
// Run the code gen complete event
OnCodeGenerationCompleted(_generatedCode);
}
}
private static HttpParseException CreateExceptionFromParserError(RazorError error, string virtualPath)
{
return new HttpParseException(error.Message + Environment.NewLine, null, virtualPath, null, error.Location.LineIndex + 1);
}
[SuppressMessage("Microsoft.Security", "CA2141:TransparentMethodsMustNotSatisfyLinkDemandsFxCopRule", Justification = "We are catching the SecurityException to detect medium trust")]
private static void SetIncludeDebugInfoFlag(CompilerType compilerType)
{
compilerType.CompilerParameters.IncludeDebugInformation = true;
}
}
}