Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / xsp / System / Web / Compilation / BuildManagerHost.cs / 1305376 / BuildManagerHost.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- /************************************************************************************************************/ namespace System.Web.Compilation { using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.Globalization; using System.IO; using System.Text; using System.Threading; using System.Reflection; using System.CodeDom; using System.CodeDom.Compiler; using System.Web; using System.Web.Caching; using System.Web.Util; using System.Web.UI; using System.Web.Hosting; using Debug=System.Web.Util.Debug; using System.Web.Configuration; using System.Security.Permissions; // // Instances of this class are created in the ASP.NET app domain. The class // methods are called by ClientBuildManager (cross app domain) // internal class BuildManagerHost : MarshalByRefObject, IRegisteredObject { private ClientBuildManager _client; private BuildManager _buildManager; private int _pendingCallsCount; private EventHandler _onAppDomainUnload; private bool _ignorePendingCalls; private IDictionary _assemblyCollection; private object _lock = new object(); private static bool _inClientBuildManager; internal static bool InClientBuildManager { get { return _inClientBuildManager; } set { _inClientBuildManager = true; } } ////// Returns whether there is support for multitargeting. This is usually only true in VS as they will supply a /// TypeDescriptionProvider that is required for correctly reflecting over types in the target framework. /// When running in the 4.0 runtime application pool, or when running from aspnet_compiler, this value /// will be false. /// internal static bool SupportsMultiTargeting { get; set; } private ClientVirtualPathProvider _virtualPathProvider; public BuildManagerHost() { HostingEnvironment.RegisterObject(this); AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(this.ResolveAssembly); } void IRegisteredObject.Stop(bool immediate) { // Make sure all the pending calls complete WaitForPendingCallsToFinish(); HostingEnvironment.UnregisterObject(this); } internal IApplicationHost ApplicationHost { get { return HostingEnvironment.ApplicationHostInternal; } } internal string CodeGenDir { get { // Add a pending call to make sure our thread doesn't get killed AddPendingCall(); try { return HttpRuntime.CodegenDirInternal; } finally { RemovePendingCall(); } } } internal void RegisterAssembly(String assemblyName, String assemblyLocation) { Debug.Trace("BuildManagerHost", "RegisterAssembly '" + assemblyName + "','" + assemblyLocation + "'"); if (_assemblyCollection == null) { lock (_lock) { if (_assemblyCollection == null) { _assemblyCollection = Hashtable.Synchronized(new Hashtable()); } } } AssemblyName asmName = new AssemblyName(assemblyName); _assemblyCollection[asmName.FullName] = assemblyLocation; } [PermissionSet(SecurityAction.Assert, Unrestricted = true)] private Assembly ResolveAssembly(object sender, ResolveEventArgs e) { Debug.Trace("BuildManagerHost", "ResolveAssembly '" + e.Name + "'"); if (_assemblyCollection == null) return null; String assemblyLocation = (String)_assemblyCollection[e.Name]; if (assemblyLocation == null) return null; Debug.Trace("BuildManagerHost", "ResolveAssembly: found"); return Assembly.LoadFrom(assemblyLocation); } /* * Make sure all the (non-request based) pending calls complete */ private void WaitForPendingCallsToFinish() { for (;;) { if (_pendingCallsCount <= 0 || _ignorePendingCalls) break; Thread.Sleep(250); } } internal void AddPendingCall() { Interlocked.Increment(ref _pendingCallsCount); } internal void RemovePendingCall() { Interlocked.Decrement(ref _pendingCallsCount); } private void OnAppDomainShutdown(object o, BuildManagerHostUnloadEventArgs args) { _client.OnAppDomainShutdown(args.Reason); } internal void CompileApplicationDependencies() { // Add a pending call to make sure our thread doesn't get killed AddPendingCall(); try { _buildManager.EnsureTopLevelFilesCompiled(); } finally { RemovePendingCall(); } } internal void PrecompileApp(ClientBuildManagerCallback callback) { // Add a pending call to make sure our thread doesn't get killed AddPendingCall(); try { _buildManager.PrecompileApp(callback); } finally { RemovePendingCall(); } } internal IDictionary GetBrowserDefinitions() { // Add a pending call to make sure our thread doesn't get killed AddPendingCall(); try { return BrowserCapabilitiesCompiler.BrowserCapabilitiesFactory.InternalGetBrowserElements(); } finally { RemovePendingCall(); } } internal string[] GetVirtualCodeDirectories() { // Add a pending call to make sure our thread doesn't get killed AddPendingCall(); try { return _buildManager.GetCodeDirectories(); } finally { RemovePendingCall(); } } [PermissionSet(SecurityAction.Assert, Unrestricted = true)] internal void GetCodeDirectoryInformation(VirtualPath virtualCodeDir, out Type codeDomProviderType, out CompilerParameters compParams, out string generatedFilesDir) { // Add a pending call to make sure our thread doesn't get killed AddPendingCall(); try { BuildManager.SkipTopLevelCompilationExceptions = true; _buildManager.EnsureTopLevelFilesCompiled(); // Treat it as relative to the app root virtualCodeDir = virtualCodeDir.CombineWithAppRoot(); _buildManager.GetCodeDirectoryInformation(virtualCodeDir, out codeDomProviderType, out compParams, out generatedFilesDir); } finally { BuildManager.SkipTopLevelCompilationExceptions = false; RemovePendingCall(); } } internal void GetCompilerParams(VirtualPath virtualPath, out Type codeDomProviderType, out CompilerParameters compParams) { // Add a pending call to make sure our thread doesn't get killed AddPendingCall(); try { BuildManager.SkipTopLevelCompilationExceptions = true; _buildManager.EnsureTopLevelFilesCompiled(); // Ignore the BuildProvider return value GetCompilerParamsAndBuildProvider(virtualPath, out codeDomProviderType, out compParams); // This is the no-compile case if (compParams == null) return; FixupReferencedAssemblies(virtualPath, compParams); } finally { BuildManager.SkipTopLevelCompilationExceptions = false; RemovePendingCall(); } } internal string[] GetCompiledTypeAndAssemblyName(VirtualPath virtualPath, ClientBuildManagerCallback callback) { // Add a pending call to make sure our thread doesn't get killed AddPendingCall(); try { // Treat it as relative to the app root virtualPath.CombineWithAppRoot(); Type t = BuildManager.GetCompiledType(virtualPath, callback); if (t == null) return null; string assemblyPath = Util.GetAssemblyPathFromType(t); return new string[] { t.FullName, assemblyPath }; } finally { RemovePendingCall(); } } internal string GetGeneratedSourceFile(VirtualPath virtualPath) { // Add a pending call to make sure our thread doesn't get killed AddPendingCall(); Type codeDomProviderType; CompilerParameters compilerParameters; string generatedFilesDir; try { if (!virtualPath.DirectoryExists()) { throw new ArgumentException(SR.GetString(SR.GetGeneratedSourceFile_Directory_Only, virtualPath.VirtualPathString), "virtualPath"); } // Calls GetCodeDirectoryInformation to ensure the source files are created for the // directory specified by virtualPath GetCodeDirectoryInformation(virtualPath, out codeDomProviderType, out compilerParameters, out generatedFilesDir); return BuildManager.GenerateFileTable[virtualPath.VirtualPathStringNoTrailingSlash]; } finally { RemovePendingCall(); } } internal string GetGeneratedFileVirtualPath(string filePath) { // Add a pending call to make sure our thread doesn't get killed AddPendingCall(); try { // Performs reverse hashtable lookup to find the filePath in the Value collection. Dictionary.Enumerator e = BuildManager.GenerateFileTable.GetEnumerator(); while (e.MoveNext()) { KeyValuePair pair = e.Current; if (filePath.Equals(pair.Value, StringComparison.Ordinal)) { return pair.Key; } } return null; } finally { RemovePendingCall(); } } /* * Returns an array of the assemblies defined in the bin and assembly reference config section */ internal String[] GetTopLevelAssemblyReferences(VirtualPath virtualPath) { // Add a pending call to make sure our thread doesn't get killed AddPendingCall(); List assemblyList = new List (); try { // Treat it as relative to the app root virtualPath.CombineWithAppRoot(); CompilationSection compConfig = MTConfigUtil.GetCompilationConfig(virtualPath); // Add all the config assemblies to the list foreach (AssemblyInfo assemblyInfo in compConfig.Assemblies) { Assembly[] assemblies = assemblyInfo.AssemblyInternal; for (int i = 0; i < assemblies.Length; i++) { if (assemblies[i] != null) { assemblyList.Add(assemblies[i]); } } } } finally { RemovePendingCall(); } StringCollection paths = new StringCollection(); Util.AddAssembliesToStringCollection(assemblyList, paths); string[] references = new string[paths.Count]; paths.CopyTo(references, 0); return references; } [PermissionSet(SecurityAction.Assert, Unrestricted = true)] internal string GenerateCode( VirtualPath virtualPath, string virtualFileString, out IDictionary linePragmasTable) { AddPendingCall(); try { string code = null; Type codeDomProviderType; CompilerParameters compilerParameters; CodeCompileUnit ccu = GenerateCodeCompileUnit(virtualPath, virtualFileString, out codeDomProviderType, out compilerParameters, out linePragmasTable); if (ccu != null && codeDomProviderType != null) { CodeDomProvider codeProvider = CompilationUtil.CreateCodeDomProvider(codeDomProviderType); CodeGeneratorOptions codeGeneratorOptions = new CodeGeneratorOptions(); codeGeneratorOptions.BlankLinesBetweenMembers = false; codeGeneratorOptions.IndentString = string.Empty; StringWriter sw = new StringWriter(CultureInfo.InvariantCulture); codeProvider.GenerateCodeFromCompileUnit(ccu, sw, codeGeneratorOptions); code = sw.ToString(); } return code; } finally { RemovePendingCall(); } } [PermissionSet(SecurityAction.Assert, Unrestricted = true)] internal CodeCompileUnit GenerateCodeCompileUnit( VirtualPath virtualPath, string virtualFileString, out Type codeDomProviderType, out CompilerParameters compilerParameters, out IDictionary linePragmasTable) { // Add a pending call to make sure our thread doesn't get killed AddPendingCall(); try { BuildManager.SkipTopLevelCompilationExceptions = true; _buildManager.EnsureTopLevelFilesCompiled(); // Get the virtual file content so that we can use the correct hash code. if (virtualFileString == null) { using (Stream stream = virtualPath.OpenFile()) { TextReader reader = Util.ReaderFromStream(stream, virtualPath); virtualFileString = reader.ReadToEnd(); } } _virtualPathProvider.RegisterVirtualFile(virtualPath, virtualFileString); string cacheKey = BuildManager.GetCacheKeyFromVirtualPath(virtualPath) + "_CBMResult"; BuildResultCodeCompileUnit result = (BuildResultCodeCompileUnit)BuildManager.GetBuildResultFromCache(cacheKey, virtualPath); if (result == null) { lock (_lock) { // Don't need to check the result again since it's very unlikely in CBM scenarios. DateTime utcStart = DateTime.UtcNow; BuildProvider internalBuildProvider = GetCompilerParamsAndBuildProvider( virtualPath, out codeDomProviderType, out compilerParameters); // This is the no-compile case if (internalBuildProvider == null) { linePragmasTable = null; return null; } CodeCompileUnit ccu = internalBuildProvider.GetCodeCompileUnit(out linePragmasTable); result = new BuildResultCodeCompileUnit(codeDomProviderType, ccu, compilerParameters, linePragmasTable); result.VirtualPath = virtualPath; result.SetCacheKey(cacheKey); FixupReferencedAssemblies(virtualPath, compilerParameters); // CodeCompileUnit could be null, do not try to fix referenced assemblies. // This happens for example when an .asmx file does not contain any code. if (ccu != null) { // VSWhidbey 501260 Add all the referenced assemblies to the CodeCompileUnit // in case the CodeDom provider needs them for code generation foreach (String assemblyString in compilerParameters.ReferencedAssemblies) { ccu.ReferencedAssemblies.Add(assemblyString); } } // Add all the dependencies, so that the ccu gets cached correctly (VSWhidbey 275091) ICollection dependencies = internalBuildProvider.VirtualPathDependencies; if (dependencies != null) result.AddVirtualPathDependencies(dependencies); BuildManager.CacheBuildResult(cacheKey, result, utcStart); return ccu; } } codeDomProviderType = result.CodeDomProviderType; compilerParameters = result.CompilerParameters; linePragmasTable = result.LinePragmasTable; FixupReferencedAssemblies(virtualPath, compilerParameters); return result.CodeCompileUnit; } finally { if (virtualFileString != null) { _virtualPathProvider.RevertVirtualFile(virtualPath); } BuildManager.SkipTopLevelCompilationExceptions = false; RemovePendingCall(); } } internal bool IsCodeAssembly(string assemblyName) { return BuildManager.GetNormalizedCodeAssemblyName(assemblyName) != null; } // Add the referenced assemblies into the compileParameters. Notice that buildProviders do not have // the correct referenced assemblies and we don't cache them since the assemblies could change // between appdomains. (removing assemblies from bin, etc) private void FixupReferencedAssemblies(VirtualPath virtualPath, CompilerParameters compilerParameters) { CompilationSection compConfig = MTConfigUtil.GetCompilationConfig(virtualPath); ICollection referencedAssemblies = BuildManager.GetReferencedAssemblies(compConfig); Util.AddAssembliesToStringCollection(referencedAssemblies, compilerParameters.ReferencedAssemblies); } private BuildProvider GetCompilerParamsAndBuildProvider(VirtualPath virtualPath, out Type codeDomProviderType, out CompilerParameters compilerParameters) { virtualPath.CombineWithAppRoot(); CompilationSection compConfig = MTConfigUtil.GetCompilationConfig(virtualPath); ICollection referencedAssemblies = BuildManager.GetReferencedAssemblies(compConfig); // Create the buildprovider for the passed in virtualPath BuildProvider buildProvider = null; // Special case global asax build provider here since we do not want to compile every files with ".asax" extension. if (StringUtil.EqualsIgnoreCase(virtualPath.VirtualPathString, BuildManager.GlobalAsaxVirtualPath.VirtualPathString)) { ApplicationBuildProvider provider = new ApplicationBuildProvider(); provider.SetVirtualPath(virtualPath); provider.SetReferencedAssemblies(referencedAssemblies); buildProvider = provider; } else { buildProvider = BuildManager.CreateBuildProvider(virtualPath, compConfig, referencedAssemblies, true /*failIfUnknown*/); } // DevDiv 69017 // The methods restricted to internalBuildProvider have been moved up to BuildProvider // to allow WCFBuildProvider to support .svc syntax highlighting. // Ignore parse errors, since they should not break the designer buildProvider.IgnoreParseErrors = true; // Ignore all control properties, since we do not generate code for the properties buildProvider.IgnoreControlProperties = true; // Process as many errors as possible, do not rethrow on first error buildProvider.ThrowOnFirstParseError = false; // Get the language (causes the file to be parsed) CompilerType compilerType = buildProvider.CodeCompilerType; // compilerType could be null in the no-compile case (VSWhidbey 221749) if (compilerType == null) { codeDomProviderType = null; compilerParameters = null; return null; } // Return the provider type and compiler params codeDomProviderType = compilerType.CodeDomProviderType; compilerParameters = compilerType.CompilerParameters; IAssemblyDependencyParser parser = buildProvider.AssemblyDependencyParser; // Add all the assemblies that the page depends on (e.g. user controls) if (parser != null && parser.AssemblyDependencies != null) { Util.AddAssembliesToStringCollection(parser.AssemblyDependencies, compilerParameters.ReferencedAssemblies); } // Make any fix up adjustments to the CompilerParameters to work around some issues AssemblyBuilder.FixUpCompilerParameters(codeDomProviderType, compilerParameters); return buildProvider; } public override Object InitializeLifetimeService() { return null; // never expire lease } internal void Configure(ClientBuildManager client) { // Add a pending call to make sure our thread doesn't get killed AddPendingCall(); try { _virtualPathProvider = new ClientVirtualPathProvider(); HostingEnvironment.RegisterVirtualPathProviderInternal(_virtualPathProvider); _client = client; // Type description provider required for multitargeting compilation support in VS. if (_client.CBMTypeDescriptionProviderBridge != null) { TargetFrameworkUtil.CBMTypeDescriptionProviderBridge = _client.CBMTypeDescriptionProviderBridge; } // start watching for app domain unloading _onAppDomainUnload = new EventHandler(OnAppDomainUnload); Thread.GetDomain().DomainUnload += _onAppDomainUnload; _buildManager = BuildManager.TheBuildManager; // Listen to appdomain shutdown. HttpRuntime.AppDomainShutdown += new BuildManagerHostUnloadEventHandler(this.OnAppDomainShutdown); } finally { RemovePendingCall(); } } internal Exception InitializationException { get { return HostingEnvironment.InitializationException; } } private void OnAppDomainUnload(Object unusedObject, EventArgs unusedEventArgs) { Thread.GetDomain().DomainUnload -= _onAppDomainUnload; if (_client != null) { _client.OnAppDomainUnloaded(HttpRuntime.ShutdownReason); _client = null; } } internal bool UnloadAppDomain() { _ignorePendingCalls = true; // Make sure HttpRuntime does not ignore the appdomain shutdown. HttpRuntime.SetUserForcedShutdown(); // Force unload the appdomain when called from client return HttpRuntime.ShutdownAppDomain(ApplicationShutdownReason.UnloadAppDomainCalled, "CBM called UnloadAppDomain"); } // This provider is created in the hosted appdomain for faster access of the virtual file content. // Note this is used both in CBM and the aspnet precompilation tool internal class ClientVirtualPathProvider : VirtualPathProvider { private IDictionary _stringDictionary; internal ClientVirtualPathProvider() { _stringDictionary = new HybridDictionary(true); } public override bool FileExists(string virtualPath) { if (_stringDictionary.Contains(virtualPath)) { return true; } return base.FileExists(virtualPath); } public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart) { if (virtualPath != null) { virtualPath = UrlPath.MakeVirtualPathAppAbsolute(virtualPath); // Return now so the build result will be invalidated based on hashcode. // This is for the case that Venus passed in the file content so we don't // get file change notification if (_stringDictionary.Contains(virtualPath)) { return null; } } // otherwise creates a cachedependency using MapPathBasedVirtualPathProvider return base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart); } public override VirtualFile GetFile(string virtualPath) { String _virtualFileString = (String)_stringDictionary[virtualPath]; return _virtualFileString != null? new ClientVirtualFile(virtualPath, _virtualFileString) : base.GetFile(virtualPath); } public override string GetFileHash(string virtualPath, IEnumerable virtualPathDependencies) { HashCodeCombiner hashCodeCombiner = null; ArrayList clonedPaths = new ArrayList(); foreach (string virtualDependency in virtualPathDependencies) { // if the virtual path is previously cached, add the actual content to // the hash code combiner. if (_stringDictionary.Contains(virtualDependency)) { if (hashCodeCombiner == null) { hashCodeCombiner = new HashCodeCombiner(); } hashCodeCombiner.AddInt(_stringDictionary[virtualDependency].GetHashCode()); continue; } // Otherwise move it to the cloned collection and use the base class (previous provider) // to get the hash code. clonedPaths.Add(virtualDependency); } if (hashCodeCombiner == null) { return base.GetFileHash(virtualPath, virtualPathDependencies); } hashCodeCombiner.AddObject(base.GetFileHash(virtualPath, clonedPaths)); return hashCodeCombiner.CombinedHashString; } internal void RegisterVirtualFile(VirtualPath virtualPath, String virtualFileString) { _stringDictionary[virtualPath.VirtualPathString] = virtualFileString; } internal void RevertVirtualFile(VirtualPath virtualPath) { _stringDictionary.Remove(virtualPath.VirtualPathString); } internal class ClientVirtualFile : VirtualFile { String _virtualFileString; internal ClientVirtualFile(string virtualPath, String virtualFileString) : base(virtualPath) { _virtualFileString = virtualFileString; } public override Stream Open() { Stream stream = new MemoryStream(); StreamWriter writer = new StreamWriter(stream, Encoding.Unicode); writer.Write(_virtualFileString); writer.Flush(); stream.Seek(0, SeekOrigin.Begin); return stream; } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Vector3DCollectionConverter.cs
- MetafileHeaderWmf.cs
- DataBinding.cs
- CheckedPointers.cs
- Camera.cs
- DataServiceProviderMethods.cs
- AggregateNode.cs
- HwndStylusInputProvider.cs
- TextBoxBaseDesigner.cs
- ListBox.cs
- Vector3D.cs
- sqlmetadatafactory.cs
- RepeaterItem.cs
- XmlSecureResolver.cs
- BookmarkUndoUnit.cs
- PartialTrustVisibleAssemblyCollection.cs
- HandlerBase.cs
- PresentationAppDomainManager.cs
- TypeDelegator.cs
- BaseInfoTable.cs
- _BufferOffsetSize.cs
- ToolStripLocationCancelEventArgs.cs
- BeginStoryboard.cs
- BaseDataListPage.cs
- ReferenceTypeElement.cs
- TextPointerBase.cs
- RegexInterpreter.cs
- CaseStatementSlot.cs
- AuthenticationModuleElementCollection.cs
- XamlNamespaceHelper.cs
- PersonalizationStateInfoCollection.cs
- CodeBinaryOperatorExpression.cs
- RectAnimationClockResource.cs
- InheritablePropertyChangeInfo.cs
- TypeUtils.cs
- ScriptControlDescriptor.cs
- BindToObject.cs
- ResourceType.cs
- LineInfo.cs
- BaseUriWithWildcard.cs
- NameSpaceExtractor.cs
- XmlObjectSerializerReadContext.cs
- ConstructorArgumentAttribute.cs
- WebServiceMethodData.cs
- COM2ExtendedBrowsingHandler.cs
- SoundPlayer.cs
- ModuleElement.cs
- FileLogRecord.cs
- Style.cs
- GridItemProviderWrapper.cs
- MultiBinding.cs
- Variable.cs
- Delegate.cs
- ToolStripScrollButton.cs
- WhitespaceRuleReader.cs
- ManifestResourceInfo.cs
- TextTreeTextBlock.cs
- CodeTypeReferenceCollection.cs
- CriticalExceptions.cs
- FormatConvertedBitmap.cs
- XmlNavigatorFilter.cs
- WebScriptMetadataMessageEncoderFactory.cs
- FormsIdentity.cs
- SR.cs
- ValueConversionAttribute.cs
- ReadOnlyHierarchicalDataSource.cs
- XmlSchemaValidator.cs
- TypeConverters.cs
- validationstate.cs
- ImageCodecInfoPrivate.cs
- MsmqIntegrationBindingElement.cs
- WebPartZoneBase.cs
- BrowserTree.cs
- ParserContext.cs
- TableItemStyle.cs
- DBDataPermission.cs
- UserControlBuildProvider.cs
- QilList.cs
- UnicastIPAddressInformationCollection.cs
- TemplateControl.cs
- GradientBrush.cs
- OleDbParameter.cs
- StrokeCollectionConverter.cs
- Metadata.cs
- EventLogInternal.cs
- DataGridViewCellToolTipTextNeededEventArgs.cs
- XmlSchemaGroup.cs
- DataFormats.cs
- ASCIIEncoding.cs
- SmtpFailedRecipientsException.cs
- NextPreviousPagerField.cs
- VScrollProperties.cs
- MenuItemStyleCollection.cs
- AstNode.cs
- DbModificationCommandTree.cs
- ChooseAction.cs
- TextEditorCopyPaste.cs
- HttpApplication.cs
- DataGridTextBoxColumn.cs
- LoginStatusDesigner.cs