internal void AddSourceDependency(VirtualPath fileName) { if (this._sourceDependencies == null) { this._sourceDependencies = new CaseInsensitiveStringSet(); } this._sourceDependencies.Add(fileName.VirtualPathString); }
protected void AddDependency(VirtualPath virtualPath) { virtualPath = ResolveVirtualPath(virtualPath); Debug.Trace("Template", "Parsed dependency: " + _virtualPath + " depends on " + virtualPath); if (_virtualPathDependencies == null) _virtualPathDependencies = new CaseInsensitiveStringSet(); _virtualPathDependencies.Add(virtualPath.VirtualPathString); }
protected void AddDependency(VirtualPath virtualPath) { virtualPath = base.ResolveVirtualPath(virtualPath); if (this._virtualPathDependencies == null) { this._virtualPathDependencies = new CaseInsensitiveStringSet(); } this._virtualPathDependencies.Add(virtualPath.VirtualPathString); }
/* * Add a file as a dependency of the file we're parsing */ private void AddSourceDependency2(VirtualPath fileName) { if (_sourceDependencies == null) _sourceDependencies = new CaseInsensitiveStringSet(); _sourceDependencies.Add(fileName.VirtualPathString); }
private bool ProcessBeginTag(Match match, string inputText) { string tagName = match.Groups["tagname"].Value; // Get all the attributes into a bag ParsedAttributeCollection attribs; string duplicateAttribute; ProcessAttributes(inputText, match, out attribs, false /*fDirective*/, out duplicateAttribute); // Check if the tag is self closed bool fSelfClosed = match.Groups["empty"].Success; // Is it a server side script tag? if (StringUtil.EqualsIgnoreCase(tagName, "script") && flags[isServerTag]) { ProcessScriptTag(match, inputText, attribs, fSelfClosed); return true; } // Process the settings that may come from config when the first non-trivial tag is parsed. VS Whidbey 141882 if (!flags[mainDirectiveHandled]) { ProcessMainDirective(_mainDirectiveConfigSettings); flags[mainDirectiveHandled] = true; } ControlBuilder parentBuilder = null; ControlBuilder subBuilder = null; Type childType = null; // This could be a property of an object that is filterable string realTagName; string filter = Util.ParsePropertyDeviceFilter(tagName, out realTagName); // Check if the parent builder wants to create a subcontrol for this tag. if (BuilderStack.Count > 1) { parentBuilder = ((BuilderStackEntry) _builderStack.Peek())._builder; // If the parent builder is a StringPropertyBuilder, we want to treat everything // in it as a literal, so we always return false here (VSWhidbey 285429) if (parentBuilder is StringPropertyBuilder) return false; subBuilder = parentBuilder.CreateChildBuilder(filter, realTagName, attribs, this, parentBuilder, _id, _lineNumber, CurrentVirtualPath, ref childType, false); } // If not, use the root builder if runat=server is there. if (subBuilder == null && flags[isServerTag]) { subBuilder = RootBuilder.CreateChildBuilder(filter, realTagName, attribs, this, parentBuilder, _id, _lineNumber, CurrentVirtualPath, ref childType, false); } // In case we find that the top stack item has the same name as the // current tag, we increase a count on the stack item. This way, we // know that we need to ignore the corresponding closing tag (ASURT 50795) if (subBuilder == null && _builderStack.Count > 1 && !fSelfClosed) { BuilderStackEntry stackEntry = (BuilderStackEntry) _builderStack.Peek(); if (StringUtil.EqualsIgnoreCase(tagName, stackEntry._tagName)) stackEntry._repeatCount++; } // We could not get the type of a server control from that tag if (subBuilder == null) { // If it wasn't marked as runat=server, ignore if (!flags[isServerTag] || IgnoreParseErrors) return false; // If it was marked as runat=server, fail ProcessError(SR.GetString(SR.Unknown_server_tag, tagName)); return true; } // We have a server control // If we have a control type filter, make sure the child control is allowed if (_pageParserFilter != null) { Debug.Assert(childType != null); if (!_pageParserFilter.AllowControlInternal(childType, subBuilder)) { ProcessError(SR.GetString(SR.Control_type_not_allowed, childType.FullName)); return true; } } // Make sure it doesn't have duplicated attributes if (duplicateAttribute != null) { ProcessError(SR.GetString(SR.Duplicate_attr_in_tag, duplicateAttribute)); } // Get the id from the builder. Note that it may be null even if _id was not initially null, // if the builder is not for a Control (VSWhidbey 406302) _id = subBuilder.ID; // If it has an id, enforce validity and uniqueness if (_id != null) { if (!System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(_id)) { ProcessError(SR.GetString(SR.Invalid_identifier, _id)); return true; } if (_idList.Contains(_id)) { ProcessError(SR.GetString(SR.Id_already_used, _id)); return true; } _idList.Add(_id); } else if (flags[isServerTag]) { // Make sure that cached controls always have a fixed id to prevent // unpredictable behavior (ASURT 83402) PartialCachingAttribute cacheAttrib = (PartialCachingAttribute) TypeDescriptor.GetAttributes(childType)[typeof(PartialCachingAttribute)]; // If we are parsing a theme file, the controls do not have an ID, // and we should not be adding one. (Dev10 if (!(subBuilder.Parser is PageThemeParser) && cacheAttrib != null) { _id = "_ctrl_" + _controlCount.ToString(NumberFormatInfo.InvariantInfo); subBuilder.ID = _id; _controlCount++; // Controls can't be filtered, so use the default filter subBuilder.PreprocessAttribute(String.Empty, "id", _id, false /*mainDirectiveMode*/); } } // Take care of the previous literal string ProcessLiteral(); if (childType != null) { // Update the hash code with the name of the control's type UpdateTypeHashCode(childType.FullName); } // If the server control has a body, and if it didn't self-close // (i.e. wasn't terminated with "/>"), put it on the stack of controls. if (!fSelfClosed && subBuilder.HasBody()) { // If it's a template, push a new ID list (ASURT 72773) if (subBuilder is TemplateBuilder && ((TemplateBuilder)subBuilder).AllowMultipleInstances) { _idListStack.Push(_idList); _idList = new CaseInsensitiveStringSet(); } _builderStack.Push(new BuilderStackEntry(subBuilder, tagName, CurrentVirtualPathString, _lineNumber, inputText, match.Index + match.Length)); // Optionally record begin tag position data ParseRecorders.RecordBeginTag(subBuilder, match); } else { // Append the sub builder to the current builder parentBuilder = ((BuilderStackEntry) _builderStack.Peek())._builder; AppendSubBuilder(parentBuilder, subBuilder); // Tell the builder that we're done parsing its control subBuilder.CloseControl(); // Optionally record empty tag position data ParseRecorders.RecordEmptyTag(subBuilder, match); } return true; }
private bool MaybeTerminateControl(string tagName, Match match) { BuilderStackEntry stackEntry = (BuilderStackEntry) BuilderStack.Peek(); ControlBuilder builder = stackEntry._builder; // If the tag doesn't match, return false if (stackEntry._tagName == null || !StringUtil.EqualsIgnoreCase(stackEntry._tagName, tagName)) { return false; } // If the repeat count is non-zero, just decrease it if (stackEntry._repeatCount > 0) { stackEntry._repeatCount--; return false; } // Take care of the previous literal string ProcessLiteral(); // If the builder wants the raw text of the tag, give it to it if (builder.NeedsTagInnerText()) { try { builder.SetTagInnerText(stackEntry._inputText.Substring( stackEntry._textPos, match.Index - stackEntry._textPos)); } catch (Exception e) { if (!IgnoreParseErrors) { // Reset the line number to the beginning of the tag if there is an error _lineNumber = builder.Line; ProcessException(e); return true; } } } // If it's ending a template, pop the idList (ASURT 72773) if (builder is TemplateBuilder && ((TemplateBuilder)builder).AllowMultipleInstances) _idList = (StringSet) _idListStack.Pop(); // Pop the top entry from the stack _builderStack.Pop(); // Give the builder to its parent AppendSubBuilder(((BuilderStackEntry) _builderStack.Peek())._builder, builder); // Tell the builder that we're done parsing its control builder.CloseControl(); // Optionally record end tag position data ParseRecorders.RecordEndTag(builder, match); return true; }
/* * Perform initialization work that should only be done once (per app domain). */ private void Initialize() { Debug.Assert(_caches == null); // Register an AssemblyResolve event AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(this.ResolveAssembly); _globalAsaxVirtualPath = HttpRuntime.AppDomainAppVirtualPathObject.SimpleCombine( HttpApplicationFactory.applicationFileName); _webHashFilePath = Path.Combine(HttpRuntime.CodegenDirInternal, "hash\\hash.web"); // Indicate whether we should ignore the top level compilation exceptions. // In CBM case, we want to continue processing the page and return partial info even // if the code files fail to compile. _skipTopLevelCompilationExceptions = BuildManagerHost.InClientBuildManager; // Deal with precompilation if we're in that mode SetPrecompilationInfo(HostingEnvironment.HostingParameters); MultiTargetingUtil.EnsureFrameworkNamesInitialized(); // The init code depends on whether we're precompiling or running an app if (_precompTargetPhysicalDir != null) { // If the app is already precompiled, fail FailIfPrecompiledApp(); PrecompilationModeInitialize(); } else { // Check if this application has been precompiled by aspnet_compiler.exe if (IsPrecompiledApp) { PrecompiledAppRuntimeModeInitialize(); } else { RegularAppRuntimeModeInitialize(); } } _scriptVirtualDir = Util.GetScriptLocation(); // Top level directories that have a special semantic _excludedTopLevelDirectories = new CaseInsensitiveStringSet(); _excludedTopLevelDirectories.Add(HttpRuntime.BinDirectoryName); _excludedTopLevelDirectories.Add(HttpRuntime.CodeDirectoryName); _excludedTopLevelDirectories.Add(HttpRuntime.ResourcesDirectoryName); _excludedTopLevelDirectories.Add(HttpRuntime.LocalResourcesDirectoryName); _excludedTopLevelDirectories.Add(HttpRuntime.WebRefDirectoryName); _excludedTopLevelDirectories.Add(HttpRuntime.ThemesDirectoryName); // Top level directories that are not requestable // It's the same as _excludedTopLevelDirectories, except that we allow // the bin directory to avoid a v1 breaking change (VSWhidbey 465018) _forbiddenTopLevelDirectories = new CaseInsensitiveStringSet(); _forbiddenTopLevelDirectories.Add(HttpRuntime.CodeDirectoryName); _forbiddenTopLevelDirectories.Add(HttpRuntime.ResourcesDirectoryName); _forbiddenTopLevelDirectories.Add(HttpRuntime.LocalResourcesDirectoryName); _forbiddenTopLevelDirectories.Add(HttpRuntime.WebRefDirectoryName); _forbiddenTopLevelDirectories.Add(HttpRuntime.ThemesDirectoryName); LoadLicensesAssemblyIfExists(); }
// excludedSubdirectories contains a list of subdirectory names that should not be // recursively included in the compilation (they'll instead be compiled into their // own assemblies). private Assembly CompileCodeDirectory(VirtualPath virtualDir, CodeDirectoryType dirType, string assemblyName, StringSet excludedSubdirectories) { Debug.Trace("BuildManager", "CompileCodeDirectory(" + virtualDir.VirtualPathString + ")"); bool isDirectoryAllowed = true; if (IsPrecompiledApp) { // Most special dirs are not allowed in precompiled apps. App_LocalResources is // an exception, as it is allowed in updatable precompiled apps. if (IsUpdatablePrecompiledAppInternal && dirType == CodeDirectoryType.LocalResources) isDirectoryAllowed = true; else isDirectoryAllowed = false; } // Remember the referenced assemblies based on the current count. AssemblyReferenceInfo info = new AssemblyReferenceInfo(_topLevelReferencedAssemblies.Count); _topLevelAssembliesIndexTable[virtualDir.VirtualPathString] = info; Assembly codeAssembly = CodeDirectoryCompiler.GetCodeDirectoryAssembly( virtualDir, dirType, assemblyName, excludedSubdirectories, isDirectoryAllowed); if (codeAssembly != null) { // Remember the generated assembly info.Assembly = codeAssembly; // Page resource assemblies are not added to the top level list if (dirType != CodeDirectoryType.LocalResources) { _topLevelReferencedAssemblies.Add(codeAssembly); if (dirType == CodeDirectoryType.MainCode || dirType == CodeDirectoryType.SubCode) { if (_codeAssemblies == null) { _codeAssemblies = new ArrayList(); } _codeAssemblies.Add(codeAssembly); } // Add it to the list of assembly name that we resolve, so that users can // refer to the assemblies by their fixed name (even though they // random names). (VSWhidbey 276776) if (_assemblyResolveMapping == null) { _assemblyResolveMapping = new Hashtable(StringComparer.OrdinalIgnoreCase); } _assemblyResolveMapping[assemblyName] = codeAssembly; if (dirType == CodeDirectoryType.MainCode) { // Profile gets built in the same assembly as the main code dir, so // see whether we can get its type from the assembly. _profileType = ProfileBuildProvider.GetProfileTypeFromAssembly( codeAssembly, IsPrecompiledApp); // To avoid breaking earlier Whidbey apps, allows the name "__code" // to be used for the main code assembly. // _assemblyResolveMapping["__code"] = codeAssembly; } } } Debug.Trace("BuildManager", "CompileCodeDirectory generated assembly: " + (codeAssembly == null ? "None" : codeAssembly.ToString())); return codeAssembly; }
protected override void BuildInitStatements(CodeStatementCollection trueStatements, CodeStatementCollection topLevelStatements) { CodeMemberField field; base.BuildInitStatements(trueStatements, topLevelStatements); field = new CodeMemberField(typeof(object), "__fileDependencies") { Attributes = field.Attributes | MemberAttributes.Static }; base._sourceDataClass.Members.Add(field); CodeVariableDeclarationStatement statement = new CodeVariableDeclarationStatement { Type = new CodeTypeReference(typeof(string[])), Name = "dependencies" }; topLevelStatements.Insert(0, statement); StringSet set = new StringSet(); set.AddCollection(this.Parser.SourceDependencies); CodeAssignStatement statement2 = new CodeAssignStatement { Left = new CodeVariableReferenceExpression("dependencies"), Right = new CodeArrayCreateExpression(typeof(string), set.Count) }; trueStatements.Add(statement2); int num = 0; foreach (string str in (IEnumerable) set) { CodeAssignStatement statement3 = new CodeAssignStatement { Left = new CodeArrayIndexerExpression(new CodeVariableReferenceExpression("dependencies"), new CodeExpression[] { new CodePrimitiveExpression(num++) }) }; string str2 = UrlPath.MakeVirtualPathAppRelative(str); statement3.Right = new CodePrimitiveExpression(str2); trueStatements.Add(statement3); } CodeAssignStatement statement4 = new CodeAssignStatement { Left = new CodeFieldReferenceExpression(base._classTypeExpr, "__fileDependencies") }; CodeMethodInvokeExpression expression = new CodeMethodInvokeExpression { Method = { TargetObject = new CodeThisReferenceExpression(), MethodName = "GetWrappedFileDependencies" } }; expression.Parameters.Add(new CodeVariableReferenceExpression("dependencies")); statement4.Right = expression; trueStatements.Add(statement4); }
// Compute the list of subdirectories that should not be compiled with // the top level Code private void EnsureExcludedCodeSubDirectoriesComputed() { if (_excludedCodeSubdirectories != null) return; _excludedCodeSubdirectories = new CaseInsensitiveStringSet(); // Get the list of sub directories that will be compiled separately CodeSubDirectoriesCollection codeSubDirectories = CompilationUtil.GetCodeSubDirectories(); // Add them to the exclusion list of the top level code directory if (codeSubDirectories != null) { foreach (CodeSubDirectory entry in codeSubDirectories) { _excludedCodeSubdirectories.Add(entry.DirectoryName); } } }
/* * Do some initialization before the parsing */ internal virtual void PrepareParse() { if (_circularReferenceChecker == null) _circularReferenceChecker = new CaseInsensitiveStringSet(); _baseType = DefaultBaseType; // Initialize the main directive _mainDirectiveConfigSettings = CreateEmptyAttributeBag(); // Get the config sections we care about if (!FInDesigner) { _compConfig = MTConfigUtil.GetCompilationConfig(CurrentVirtualPath); _pagesConfig = MTConfigUtil.GetPagesConfig(CurrentVirtualPath); } // Get default settings from config ProcessConfigSettings(); // Initialize the type mapper // This must follow processing of config, so it can use the results _typeMapper = new MainTagNameToTypeMapper(this as BaseTemplateParser); // Register the <object> tag _typeMapper.RegisterTag("object", typeof(System.Web.UI.ObjectTag)); _sourceDependencies = new CaseInsensitiveStringSet(); // Create and seed the stack of ID lists. _idListStack = new Stack(); _idList = new CaseInsensitiveStringSet(); _scriptList = new ArrayList(); // Optionally collect additional parse data for render tracing InitializeParseRecorders(); }
internal static Assembly GetCodeDirectoryAssembly(VirtualPath virtualDir, CodeDirectoryType dirType, string assemblyName, StringSet excludedSubdirectories, bool isDirectoryAllowed) { string path = virtualDir.MapPath(); if (!isDirectoryAllowed && Directory.Exists(path)) { throw new HttpException(System.Web.SR.GetString("Bar_dir_in_precompiled_app", new object[] { virtualDir })); } bool supportLocalization = IsResourceCodeDirectoryType(dirType); string cacheKey = assemblyName; BuildResult buildResultFromCache = BuildManager.GetBuildResultFromCache(cacheKey); Assembly a = null; if ((buildResultFromCache != null) && (buildResultFromCache is BuildResultCompiledAssembly)) { if (buildResultFromCache is BuildResultMainCodeAssembly) { _mainCodeBuildResult = (BuildResultMainCodeAssembly) buildResultFromCache; } a = ((BuildResultCompiledAssembly) buildResultFromCache).ResultAssembly; if (!supportLocalization) { return a; } if (!isDirectoryAllowed) { return a; } BuildResultResourceAssembly assembly2 = (BuildResultResourceAssembly) buildResultFromCache; if (HashCodeCombiner.GetDirectoryHash(virtualDir) == assembly2.ResourcesDependenciesHash) { return a; } } if (!isDirectoryAllowed) { return null; } if ((dirType != CodeDirectoryType.LocalResources) && !StringUtil.StringStartsWithIgnoreCase(path, HttpRuntime.AppDomainAppPathInternal)) { throw new HttpException(System.Web.SR.GetString("Virtual_codedir", new object[] { virtualDir.VirtualPathString })); } if (!Directory.Exists(path)) { if (dirType != CodeDirectoryType.MainCode) { return null; } if (!ProfileBuildProvider.HasCompilableProfile) { return null; } } BuildManager.ReportDirectoryCompilationProgress(virtualDir); DateTime utcNow = DateTime.UtcNow; CodeDirectoryCompiler compiler = new CodeDirectoryCompiler(virtualDir, dirType, excludedSubdirectories); string outputAssemblyName = null; if (a != null) { outputAssemblyName = a.GetName().Name; compiler._onlyBuildLocalizedResources = true; } else { outputAssemblyName = BuildManager.GenerateRandomAssemblyName(assemblyName); } BuildProvidersCompiler compiler2 = new BuildProvidersCompiler(virtualDir, supportLocalization, outputAssemblyName); compiler._bpc = compiler2; compiler.FindBuildProviders(); compiler2.SetBuildProviders(compiler._buildProviders); CompilerResults results = compiler2.PerformBuild(); if (results != null) { DateTime time2 = DateTime.UtcNow.AddMilliseconds(3000.0); do { if (UnsafeNativeMethods.GetModuleHandle(results.PathToAssembly) == IntPtr.Zero) { a = results.CompiledAssembly; goto Label_01E6; } Thread.Sleep(250); } while (DateTime.UtcNow <= time2); throw new HttpException(System.Web.SR.GetString("Assembly_already_loaded", new object[] { results.PathToAssembly })); } Label_01E6: if (a == null) { return null; } if (dirType == CodeDirectoryType.MainCode) { _mainCodeBuildResult = new BuildResultMainCodeAssembly(a); buildResultFromCache = _mainCodeBuildResult; } else if (supportLocalization) { buildResultFromCache = new BuildResultResourceAssembly(a); } else { buildResultFromCache = new BuildResultCompiledAssembly(a); } buildResultFromCache.VirtualPath = virtualDir; if (BuildManager.OptimizeCompilations && (dirType != CodeDirectoryType.LocalResources)) { buildResultFromCache.AddVirtualPathDependencies(new SingleObjectCollection(virtualDir.AppRelativeVirtualPathString)); } if (dirType != CodeDirectoryType.LocalResources) { buildResultFromCache.CacheToMemory = false; } BuildManager.CacheBuildResult(cacheKey, buildResultFromCache, utcNow); return a; }
/// <devdoc> /// Creates a new resource that will be added to the compilation. The build provider /// can write to it using the returned Stream. /// The build provider should close the Stream when it is done writing to it. /// The build provider should pass itself as a parameter to this method. /// </devdoc> public Stream CreateEmbeddedResource(BuildProvider buildProvider, string name) { // Make sure it's just a valid simple file name if (!Util.IsValidFileName(name)) { throw new ArgumentException(null, name); } string resourceDir = BuildManager.CodegenResourceDir; string resourceFile = Path.Combine(resourceDir, name); CreateTempResourceDirectoryIfNecessary(); _tempFiles.AddFile(resourceFile, _tempFiles.KeepFiles); if (_embeddedResourceFiles == null) _embeddedResourceFiles = new StringSet(); _embeddedResourceFiles.Add(resourceFile); // Assert to be able to create the file in the temp dir InternalSecurityPermissions.FileWriteAccess(resourceDir).Assert(); return File.OpenWrite(resourceFile); }
internal static void GetCodeDirectoryInformation( VirtualPath virtualDir, CodeDirectoryType dirType, StringSet excludedSubdirectories, int index, out Type codeDomProviderType, out CompilerParameters compilerParameters, out string generatedFilesDir) { // Compute the full path to the directory we'll use to generate all // the code files generatedFilesDir = HttpRuntime.CodegenDirInternal + "\\" + sourcesDirectoryPrefix + virtualDir.FileName; bool supportLocalization = IsResourceCodeDirectoryType(dirType); // the index is used to retrieve the correct referenced assemblies BuildProvidersCompiler bpc = new BuildProvidersCompiler(virtualDir, supportLocalization, generatedFilesDir, index); CodeDirectoryCompiler cdc = new CodeDirectoryCompiler(virtualDir, dirType, excludedSubdirectories); cdc._bpc = bpc; // Find all the build provider we want to compile from the code directory cdc.FindBuildProviders(); // Give them to the BuildProvidersCompiler bpc.SetBuildProviders(cdc._buildProviders); // Generate all the sources into the directory generatedFilesDir bpc.GenerateSources(out codeDomProviderType, out compilerParameters); }
public Stream CreateEmbeddedResource(System.Web.Compilation.BuildProvider buildProvider, string name) { if (!Util.IsValidFileName(name)) { throw new ArgumentException(null, name); } string codegenResourceDir = BuildManager.CodegenResourceDir; string fileName = Path.Combine(codegenResourceDir, name); this.CreateTempResourceDirectoryIfNecessary(); this._tempFiles.AddFile(fileName, this._tempFiles.KeepFiles); if (this._embeddedResourceFiles == null) { this._embeddedResourceFiles = new StringSet(); } this._embeddedResourceFiles.Add(fileName); InternalSecurityPermissions.FileWriteAccess(codegenResourceDir).Assert(); return File.OpenWrite(fileName); }
internal static Assembly GetCodeDirectoryAssembly(VirtualPath virtualDir, CodeDirectoryType dirType, string assemblyName, StringSet excludedSubdirectories, bool isDirectoryAllowed) { string physicalDir = virtualDir.MapPath(); if (!isDirectoryAllowed) { // The directory should never exist in a precompiled app if (Directory.Exists(physicalDir)) { throw new HttpException(SR.GetString(SR.Bar_dir_in_precompiled_app, virtualDir)); } } bool supportLocalization = IsResourceCodeDirectoryType(dirType); // Determine the proper cache key based on the type of directory we're processing string cacheKey = assemblyName; // Try the cache first BuildResult result = BuildManager.GetBuildResultFromCache(cacheKey); Assembly resultAssembly = null; // If it's cached, just return it if (result != null) { // It should always be a BuildResultCompiledAssembly, though if there is // a VirtualPathProvider doing very bad things, it may not (VSWhidbey 341701) Debug.Assert(result is BuildResultCompiledAssembly); if (result is BuildResultCompiledAssembly) { // If it's the main code assembly, keep track of it so we can later call // the AppInitialize method if (result is BuildResultMainCodeAssembly) { Debug.Assert(dirType == CodeDirectoryType.MainCode); Debug.Assert(_mainCodeBuildResult == null); _mainCodeBuildResult = (BuildResultMainCodeAssembly) result; } resultAssembly = ((BuildResultCompiledAssembly)result).ResultAssembly; if (!supportLocalization) return resultAssembly; // We found a preserved resource assembly. However, we may not be done, // as the culture specific files may have changed. // But don't make any further checks if the directory is not allowed (precomp secenario). // In that case, we should always return the assembly (VSWhidbey 533498) if (!isDirectoryAllowed) return resultAssembly; BuildResultResourceAssembly buildResultResAssembly = (BuildResultResourceAssembly)result; string newResourcesDependenciesHash = HashCodeCombiner.GetDirectoryHash(virtualDir); // If the resources hash (which includes satellites) is up to date, we're done if (newResourcesDependenciesHash == buildResultResAssembly.ResourcesDependenciesHash) return resultAssembly; } } // If app was precompiled, don't attempt compilation if (!isDirectoryAllowed) return null; // Check whether the virtual dir is mapped to a different application, // which we don't support (VSWhidbey 218603). But don't do this for LocalResource (VSWhidbey 237935) if (dirType != CodeDirectoryType.LocalResources && !StringUtil.StringStartsWithIgnoreCase(physicalDir, HttpRuntime.AppDomainAppPathInternal)) { throw new HttpException(SR.GetString(SR.Virtual_codedir, virtualDir.VirtualPathString)); } // If the directory doesn't exist, we may be done if (!Directory.Exists(physicalDir)) { // We're definitely done if it's not the main code dir if (dirType != CodeDirectoryType.MainCode) return null; // If it is the main code dir, we're only done is there is no profile to compile // since the profice gets built as part of the main assembly. if (!ProfileBuildProvider.HasCompilableProfile) return null; } // Otherwise, compile it BuildManager.ReportDirectoryCompilationProgress(virtualDir); DateTime utcStart = DateTime.UtcNow; CodeDirectoryCompiler cdc = new CodeDirectoryCompiler(virtualDir, dirType, excludedSubdirectories); string outputAssemblyName = null; if (resultAssembly != null) { // If resultAssembly is not null, we are in the case where we just need to build // the localized resx file in a resources dir (local or global) Debug.Assert(supportLocalization); outputAssemblyName = resultAssembly.GetName().Name; cdc._onlyBuildLocalizedResources = true; } else { outputAssemblyName = BuildManager.GenerateRandomAssemblyName(assemblyName); } BuildProvidersCompiler bpc = new BuildProvidersCompiler(virtualDir, supportLocalization, outputAssemblyName); cdc._bpc = bpc; // Find all the build provider we want to compile from the code directory cdc.FindBuildProviders(); // Give them to the BuildProvidersCompiler bpc.SetBuildProviders(cdc._buildProviders); // Compile them into an assembly CompilerResults results = bpc.PerformBuild(); // Did we just compile something? if (results != null) { Debug.Assert(result == null); Debug.Assert(resultAssembly == null); // If there is already a loaded module with the same path, try to wait for it to be unloaded. // Otherwise, we would end up loading this old assembly instead of the new one (VSWhidbey 554697) DateTime waitLimit = DateTime.UtcNow.AddMilliseconds(3000); for (;;) { IntPtr hModule = UnsafeNativeMethods.GetModuleHandle(results.PathToAssembly); if (hModule == IntPtr.Zero) break; Debug.Trace("CodeDirectoryCompiler", results.PathToAssembly + " is already loaded. Waiting a bit"); System.Threading.Thread.Sleep(250); // Stop trying if the timeout was reached if (DateTime.UtcNow > waitLimit) { Debug.Trace("CodeDirectoryCompiler", "Timeout waiting for old assembly to unload: " + results.PathToAssembly); throw new HttpException(SR.GetString(SR.Assembly_already_loaded, results.PathToAssembly)); } } resultAssembly = results.CompiledAssembly; } // It is possible that there was nothing to compile (and we're not in the // satellite resources case) if (resultAssembly == null) return null; // For the main code directory, use a special BuildResult that takes care of // calling AppInitialize if it finds one if (dirType == CodeDirectoryType.MainCode) { // Keep track of it so we can later call the AppInitialize method _mainCodeBuildResult = new BuildResultMainCodeAssembly(resultAssembly); result = _mainCodeBuildResult; } else if (supportLocalization) { result = new BuildResultResourceAssembly(resultAssembly); } else { result = new BuildResultCompiledAssembly(resultAssembly); } result.VirtualPath = virtualDir; // If compilations are optimized, we need to include the right dependencies, since we can no longer // rely on everything getting wiped out when something in App_Code changes. // But don't do this for local resources, since they have their own special way of // dealing with dependencies (in BuildResultResourceAssembly.ComputeSourceDependenciesHashCode). // It's crucial *not* to do it as it triggers a tricky infinite recursion due to the fact // that GetBuildResultFromCacheInternal calls EnsureFirstTimeDirectoryInitForDependencies if // there is at least one dependency if (BuildManager.OptimizeCompilations && dirType != CodeDirectoryType.LocalResources) { result.AddVirtualPathDependencies(new SingleObjectCollection(virtualDir.AppRelativeVirtualPathString)); } // Top level assembly should not be cached to memory. But LocalResources are *not* // top level files, and do benefit from memory caching if (dirType != CodeDirectoryType.LocalResources) result.CacheToMemory = false; // Cache it for next time BuildManager.CacheBuildResult(cacheKey, result, utcStart); return resultAssembly; }
private CodeDirectoryCompiler(VirtualPath virtualDir, CodeDirectoryType dirType, StringSet excludedSubdirectories) { _virtualDir = virtualDir; _dirType = dirType; _excludedSubdirectories = excludedSubdirectories; }
/* * Build first-time intialization statements */ protected override void BuildInitStatements(CodeStatementCollection trueStatements, CodeStatementCollection topLevelStatements) { base.BuildInitStatements(trueStatements, topLevelStatements); // CodeMemberField fileDependencies = new CodeMemberField(typeof(object), fileDependenciesName); fileDependencies.Attributes |= MemberAttributes.Static; _sourceDataClass.Members.Add(fileDependencies); // Note: it may look like this local variable declaration is redundant. However it is necessary // to make this init code re-entrant safe. This way, even if two threads enter the contructor // at the same time, they will not add multiple dependencies. // e.g. string[] dependencies; CodeVariableDeclarationStatement dependencies = new CodeVariableDeclarationStatement(); dependencies.Type = new CodeTypeReference(typeof(string[])); dependencies.Name = dependenciesLocalName; // Note: it is important to add all local variables at the top level for CodeDom Subset compliance. topLevelStatements.Insert(0, dependencies); Debug.Assert(Parser.SourceDependencies != null); StringSet virtualDependencies = new StringSet(); virtualDependencies.AddCollection(Parser.SourceDependencies); // e.g. dependencies = new string[{{virtualDependencies.Count}}];; CodeAssignStatement assignDependencies = new CodeAssignStatement(); assignDependencies.Left = new CodeVariableReferenceExpression(dependenciesLocalName); assignDependencies.Right = new CodeArrayCreateExpression(typeof(String), virtualDependencies.Count); trueStatements.Add(assignDependencies); int i = 0; foreach (string virtualDependency in virtualDependencies) { // e.g. dependencies[i] = "~/sub/foo.aspx"; CodeAssignStatement addFileDep = new CodeAssignStatement(); addFileDep.Left = new CodeArrayIndexerExpression( new CodeVariableReferenceExpression(dependenciesLocalName), new CodeExpression[] {new CodePrimitiveExpression(i++)}); string src = UrlPath.MakeVirtualPathAppRelative(virtualDependency); addFileDep.Right = new CodePrimitiveExpression(src); trueStatements.Add(addFileDep); } // e.g. __fileDependencies = this.GetWrappedFileDependencies(dependencies); CodeAssignStatement initFile = new CodeAssignStatement(); initFile.Left = new CodeFieldReferenceExpression(_classTypeExpr, fileDependenciesName); CodeMethodInvokeExpression createWrap = new CodeMethodInvokeExpression(); createWrap.Method.TargetObject = new CodeThisReferenceExpression(); createWrap.Method.MethodName = "GetWrappedFileDependencies"; createWrap.Parameters.Add(new CodeVariableReferenceExpression(dependenciesLocalName)); initFile.Right = createWrap; #if DBG AppendDebugComment(trueStatements); #endif trueStatements.Add(initFile); }
internal static void GetCodeDirectoryInformation(VirtualPath virtualDir, CodeDirectoryType dirType, StringSet excludedSubdirectories, int index, out Type codeDomProviderType, out CompilerParameters compilerParameters, out string generatedFilesDir) { generatedFilesDir = HttpRuntime.CodegenDirInternal + @"\Sources_" + virtualDir.FileName; bool supportLocalization = IsResourceCodeDirectoryType(dirType); BuildProvidersCompiler compiler = new BuildProvidersCompiler(virtualDir, supportLocalization, generatedFilesDir, index); CodeDirectoryCompiler compiler2 = new CodeDirectoryCompiler(virtualDir, dirType, excludedSubdirectories) { _bpc = compiler }; compiler2.FindBuildProviders(); compiler.SetBuildProviders(compiler2._buildProviders); compiler.GenerateSources(out codeDomProviderType, out compilerParameters); }