BrowserCapabilitiesCompiler.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / xsp / System / Web / Compilation / BrowserCapabilitiesCompiler.cs / 1305376 / BrowserCapabilitiesCompiler.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Web.Compilation { 
 
    using System;
    using System.CodeDom; 
    using System.Collections;
    using System.Collections.Specialized;
    using System.Configuration;
    using System.CodeDom.Compiler; 
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization; 
    using System.IO; 
    using System.Reflection;
    using System.Security; 
    using System.Security.Permissions;
    using System.Web.Configuration;
    using System.Web.Hosting;
    using System.Web.Util; 
    using System.Web.UI;
    using System.Xml; 
 
    static class BrowserCapabilitiesCompiler {
 
        internal static readonly VirtualPath AppBrowsersVirtualDir =
            HttpRuntime.AppDomainAppVirtualPathObject.SimpleCombineWithDir(HttpRuntime.BrowsersDirectoryName);

        private const string browerCapabilitiesTypeName = "BrowserCapabilities"; 
        private const string browerCapabilitiesCacheKey = "__browserCapabilitiesCompiler";
 
        private static Type _browserCapabilitiesFactoryBaseType; 

        private static BrowserCapabilitiesFactoryBase _browserCapabilitiesFactoryBaseInstance; 
        private static object _lockObject = new object();
        internal static Assembly AspBrowserCapsFactoryAssembly { get; set; }

        static BrowserCapabilitiesCompiler() { 
            Assembly assembly = null;
            String publicKeyToken = BrowserCapabilitiesCodeGenerator.BrowserCapAssemblyPublicKeyToken; 
 
            // If the token file cannot be found, do not load the assembly.
            if (publicKeyToken != null) { 
                try {
                    string version;

                    // If we are targeting previous versions, try loading the 2.0 version of ASP.BrowserCapsFactory 
                    // (Dev10 bug 795509)
                    if (MultiTargetingUtil.IsTargetFramework40OrAbove) { 
                        version = ThisAssembly.Version; 
                    } else {
                        version = "2.0.0.0"; 
                    }
                    assembly = Assembly.Load("ASP.BrowserCapsFactory, Version=" + version + ", Culture=neutral, PublicKeyToken=" + publicKeyToken);
                    AspBrowserCapsFactoryAssembly = assembly;
                } 
                catch (FileNotFoundException) {
                } 
            } 

            // fallback when assembly cannot be found. 
            if((assembly == null) || (!(assembly.GlobalAssemblyCache))) {
                _browserCapabilitiesFactoryBaseType = typeof(System.Web.Configuration.BrowserCapabilitiesFactory);
            }
            else { 
                _browserCapabilitiesFactoryBaseType = assembly.GetType("ASP.BrowserCapabilitiesFactory", true);
            } 
        } 

        internal static BrowserCapabilitiesFactoryBase BrowserCapabilitiesFactory { 
            get {
                if(_browserCapabilitiesFactoryBaseInstance != null) {
                    return _browserCapabilitiesFactoryBaseInstance;
                } 
                Type t = GetBrowserCapabilitiesType();
                lock(_lockObject) { 
                    if(_browserCapabilitiesFactoryBaseInstance == null) { 
                        if (t != null) {
                            _browserCapabilitiesFactoryBaseInstance = 
                                (BrowserCapabilitiesFactoryBase)Activator.CreateInstance(t);
                        }
                    }
                } 
                return _browserCapabilitiesFactoryBaseInstance;
            } 
        } 

        internal static Type GetBrowserCapabilitiesFactoryBaseType() { 
            return _browserCapabilitiesFactoryBaseType;
        }

        internal static Type GetBrowserCapabilitiesType() { 

            //Need to assert here to check directories and files 
            InternalSecurityPermissions.Unrestricted.Assert(); 

            BuildResult result = null; 

            try {
                // Try the cache first, and if it's not there, compile it
                result = BuildManager.GetBuildResultFromCache(browerCapabilitiesCacheKey); 
                if (result == null) {
                    DateTime utcStart = DateTime.UtcNow; 
 
                    VirtualDirectory directory = AppBrowsersVirtualDir.GetDirectory();
 
                    // first try if app browser dir exists
                    string physicalDir = HostingEnvironment.MapPathInternal(AppBrowsersVirtualDir);

                    /* DevDivBugs 173531 
                     * For the App_Browsers scenario, we need to cache the generated browser caps processing
                     * code. We need to add path dependency on all files so that changes to them will 
                     * invalidate the cache entry and cause recompilation. */ 
                    if (directory != null && Directory.Exists(physicalDir)) {
                        ArrayList browserFileList = new ArrayList(); 
                        ArrayList browserFileDependenciesList = new ArrayList();
                        bool hasCustomCaps = AddBrowserFilesToList(directory, browserFileList, false);
                        if (hasCustomCaps) {
                            AddBrowserFilesToList(directory, browserFileDependenciesList, true); 
                        }
                        else { 
                            browserFileDependenciesList = browserFileList; 
                        }
 
                        if (browserFileDependenciesList.Count > 0) {
                            ApplicationBrowserCapabilitiesBuildProvider buildProvider = new ApplicationBrowserCapabilitiesBuildProvider();
                            foreach (string virtualPath in browserFileList) {
                                buildProvider.AddFile(virtualPath); 
                            }
 
                            BuildProvidersCompiler bpc = new BuildProvidersCompiler(null /*configPath*/, 
                                BuildManager.GenerateRandomAssemblyName(BuildManager.AppBrowserCapAssemblyNamePrefix));
 
                            bpc.SetBuildProviders(new SingleObjectCollection(buildProvider));
                            CompilerResults results = bpc.PerformBuild();
                            Assembly assembly = results.CompiledAssembly;
                            // Get the type we want from the assembly 
                            Type t = assembly.GetType(
                                BaseCodeDomTreeGenerator.defaultNamespace + "." + ApplicationBrowserCapabilitiesCodeGenerator.FactoryTypeName); 
                            // Cache it for next time 
                            result = new BuildResultCompiledType(t);
                            result.VirtualPath = AppBrowsersVirtualDir; 
                            result.AddVirtualPathDependencies(browserFileDependenciesList);

                            BuildManager.CacheBuildResult(browerCapabilitiesCacheKey, result, utcStart);
                        } 
                    }
                } 
            } 
            finally {
                CodeAccessPermission.RevertAssert(); 
            }

            // Simply return the global factory type.
            if (result == null) 
                return _browserCapabilitiesFactoryBaseType;
 
            // Return the compiled type 
            return ((BuildResultCompiledType)result).ResultType;
        } 

        [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands",
            Justification="Warning was suppressed for previous version of API (different overload) in FxCop project file.")]
        private static bool AddBrowserFilesToList( 
            VirtualDirectory directory, IList list, bool doRecurse) {
            bool hasCustomCaps = false; 
 
            foreach (VirtualFileBase fileBase in directory.Children) {
 
                // Recursive into subdirectories.
                if (fileBase.IsDirectory) {
                    if (doRecurse) {
                        AddBrowserFilesToList((VirtualDirectory)fileBase, list, true); 
                    }
                    hasCustomCaps = true; 
                    continue; 
                }
 
                string extension = Path.GetExtension(fileBase.Name);
                if (StringUtil.EqualsIgnoreCase(extension, ".browser")) {
                    list.Add(fileBase.VirtualPath);
                } 
            }
            return hasCustomCaps; 
        } 
    }
 
    internal class ApplicationBrowserCapabilitiesCodeGenerator : BrowserCapabilitiesCodeGenerator {
        internal const string FactoryTypeName = "ApplicationBrowserCapabilitiesFactory";
        private OrderedDictionary _browserOverrides;
        private OrderedDictionary _defaultBrowserOverrides; 
        private BrowserCapabilitiesFactoryBase _baseInstance;
        private BuildProvider _buildProvider; 
 
        internal ApplicationBrowserCapabilitiesCodeGenerator(BuildProvider buildProvider) {
            _browserOverrides = new OrderedDictionary(); 
            _defaultBrowserOverrides = new OrderedDictionary();
            _buildProvider = buildProvider;
        }
 
        internal override bool GenerateOverrides { get { return false; } }
 
        internal override string TypeName { 
            get {
                return FactoryTypeName; 
            }
        }

        public override void Create() { 
            throw new NotSupportedException();
        } 
 
        private static void AddStringToHashtable(OrderedDictionary table, object key, String content, bool before) {
            ArrayList list = (ArrayList)table[key]; 
            if (list == null) {
                list = new ArrayList(1);
                table[key] = list;
            } 

            if (before) { 
                list.Insert(0, content); 
            }
            else { 
                list.Add(content);
            }
        }
 
        private static string GetFirstItemFromKey(OrderedDictionary table, object key) {
            ArrayList list = (ArrayList)table[key]; 
 
            if (list != null && list.Count > 0) {
                return list[0] as String; 
            }

            return null;
        } 

        internal override void HandleUnRecognizedParentElement(BrowserDefinition bd, bool isDefault) { 
            // Use the valid type name so we can find the corresponding parent node. 
            String parentName = bd.ParentName;
            int hashKey = bd.GetType().GetHashCode() ^ parentName.GetHashCode(); 

            // Add the refID in front of the list so they gets to be called first.
            if (isDefault) {
                AddStringToHashtable(_defaultBrowserOverrides, hashKey, bd.Name, bd.IsRefID); 
            } else {
                AddStringToHashtable(_browserOverrides, hashKey, bd.Name, bd.IsRefID); 
            } 
        }
 
        //generate the code from the parsed BrowserDefinitionTree
        //compile it, and install it in the gac
        internal void GenerateCode(AssemblyBuilder assemblyBuilder) {
 
            ProcessBrowserFiles(true /*useVirtualPath*/, BrowserCapabilitiesCompiler.AppBrowsersVirtualDir.VirtualPathString);
            ProcessCustomBrowserFiles(true /*useVirtualPath*/, BrowserCapabilitiesCompiler.AppBrowsersVirtualDir.VirtualPathString); 
 
            CodeCompileUnit ccu = new CodeCompileUnit();
 
            Debug.Assert(BrowserTree != null);
            ArrayList customTreeRoots = new ArrayList();
            for (int i = 0; i < CustomTreeNames.Count; i++) {
                customTreeRoots.Add((BrowserDefinition)(((BrowserTree)CustomTreeList[i])[CustomTreeNames[i]])); 
            }
 
            // namespace ASP 
            CodeNamespace cnamespace = new CodeNamespace(BaseCodeDomTreeGenerator.defaultNamespace);
            //GEN: using System; 
            cnamespace.Imports.Add(new CodeNamespaceImport("System"));
            //GEN: using System.Web;
            cnamespace.Imports.Add(new CodeNamespaceImport("System.Web"));
            //GEN: using System.Web.Configuration; 
            cnamespace.Imports.Add(new CodeNamespaceImport("System.Web.Configuration"));
            //GEN: using System.Reflection; 
            cnamespace.Imports.Add(new CodeNamespaceImport("System.Reflection")); 
            //GEN: class BrowserCapabilitiesFactory
            ccu.Namespaces.Add(cnamespace); 

            Type baseType = BrowserCapabilitiesCompiler.GetBrowserCapabilitiesFactoryBaseType();

            CodeTypeDeclaration factoryType = new CodeTypeDeclaration(); 
            factoryType.Attributes = MemberAttributes.Private;
            factoryType.IsClass = true; 
            factoryType.Name = TypeName; 
            factoryType.BaseTypes.Add(new CodeTypeReference(baseType));
            cnamespace.Types.Add(factoryType); 

            BindingFlags flags = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.NonPublic;

            BrowserDefinition bd = null; 
            //GEN: protected override object ConfigureBrowserCapabilities(NameValueCollection headers, HttpBrowserCapabilities browserCaps)
            CodeMemberMethod method = new CodeMemberMethod(); 
            method.Attributes = MemberAttributes.Override | MemberAttributes.Public; 
            method.ReturnType = new CodeTypeReference(typeof(void));
            method.Name = "ConfigureCustomCapabilities"; 
            CodeParameterDeclarationExpression cpde = new CodeParameterDeclarationExpression(typeof(NameValueCollection), "headers");
            method.Parameters.Add(cpde);
            cpde = new CodeParameterDeclarationExpression(typeof(HttpBrowserCapabilities), "browserCaps");
            method.Parameters.Add(cpde); 
            factoryType.Members.Add(method);
 
            for (int i = 0; i < customTreeRoots.Count; i++) { 
                GenerateSingleProcessCall((BrowserDefinition)customTreeRoots[i], method);
            } 

            foreach (DictionaryEntry entry in _browserOverrides) {
                object key = entry.Key;
                BrowserDefinition firstBrowserDefinition = (BrowserDefinition)BrowserTree[GetFirstItemFromKey(_browserOverrides, key)]; 

                string parentName = firstBrowserDefinition.ParentName; 
 
                //
 


                if ((!TargetFrameworkUtil.HasMethod(baseType, parentName + "ProcessBrowsers", flags)) ||
                    (!TargetFrameworkUtil.HasMethod(baseType, parentName + "ProcessGateways", flags))) { 
                    String parentID = firstBrowserDefinition.ParentID;
 
                    if (firstBrowserDefinition != null) { 
                        throw new ConfigurationErrorsException(SR.GetString(SR.Browser_parentID_Not_Found, parentID), firstBrowserDefinition.XmlNode);
                    } else { 
                        throw new ConfigurationErrorsException(SR.GetString(SR.Browser_parentID_Not_Found, parentID));
                    }
                }
 
                bool isBrowserDefinition = true;
                if (firstBrowserDefinition is GatewayDefinition) { 
                    isBrowserDefinition = false; 
                }
 
                //GenerateMethodsToOverrideBrowsers
                //Gen: protected override void Xxx_ProcessChildBrowsers(bool ignoreApplicationBrowsers, MNameValueCollection headers, HttpBrowserCapabilities browserCaps) ;

                string methodName = parentName + (isBrowserDefinition ? "ProcessBrowsers" : "ProcessGateways"); 
                CodeMemberMethod cmm = new CodeMemberMethod();
                cmm.Name = methodName; 
                cmm.ReturnType = new CodeTypeReference(typeof(void)); 
                cmm.Attributes = MemberAttributes.Family | MemberAttributes.Override;
 
                if (isBrowserDefinition) {
                    cpde = new CodeParameterDeclarationExpression(typeof(bool), BrowserCapabilitiesCodeGenerator.IgnoreApplicationBrowserVariableName);
                    cmm.Parameters.Add(cpde);
                } 
                cpde = new CodeParameterDeclarationExpression(typeof(NameValueCollection), "headers");
                cmm.Parameters.Add(cpde); 
                cpde = new CodeParameterDeclarationExpression(typeof(HttpBrowserCapabilities), browserCapsVariable); 
                cmm.Parameters.Add(cpde);
 
                factoryType.Members.Add(cmm);

                ArrayList overrides = (ArrayList)_browserOverrides[key];
                CodeStatementCollection statements = cmm.Statements; 

                bool ignoreApplicationBrowsersVarRefGenerated = false; 
 
                foreach (string browserID in overrides) {
                    bd = (BrowserDefinition)BrowserTree[browserID]; 
                    if (bd is GatewayDefinition || bd.IsRefID) {
                        GenerateSingleProcessCall(bd, cmm);
                    }
                    else { 
                        if (!ignoreApplicationBrowsersVarRefGenerated) {
                            Debug.Assert(isBrowserDefinition); 
 
                            // Gen: if (ignoreApplicationBrowsers) {
                            //      } 
                            //      else {
                            //          ...
                            //      }
                            CodeConditionStatement istatement = new CodeConditionStatement(); 

                            istatement.Condition = new CodeVariableReferenceExpression(BrowserCapabilitiesCodeGenerator.IgnoreApplicationBrowserVariableName); 
 
                            cmm.Statements.Add(istatement);
                            statements = istatement.FalseStatements; 

                            ignoreApplicationBrowsersVarRefGenerated = true;
                        }
                        statements = GenerateTrackedSingleProcessCall(statements, bd, cmm); 
                        if (_baseInstance == null) {
                            // If we are targeting 4.0 or using the ASP.BrowserCapsFactory assembly generated by 
                            // aspnet_regbrowsers.exe, we can simply just instantiate the type. 
                            // If not, then we need to use the type BrowserCapabilitiesFactory35 that contains code
                            // from the 2.0 version of BrowserCapabilitiesFactory. This is because "baseType" is the 4.0 type 
                            // that contains the new 4.0 definitions.
                            // (Dev10 bug 795509)
                            if (MultiTargetingUtil.IsTargetFramework40OrAbove ||
                                baseType.Assembly == BrowserCapabilitiesCompiler.AspBrowserCapsFactoryAssembly) { 
                                _baseInstance = (BrowserCapabilitiesFactoryBase)Activator.CreateInstance(baseType);
                            } 
                            else { 
                                _baseInstance = new BrowserCapabilitiesFactory35();
                            } 
                        }
                        int parentDepth = (int)((Triplet)_baseInstance.InternalGetBrowserElements()[parentName]).Third;
                        AddBrowserToCollectionRecursive(bd, parentDepth + 1);
                    } 
                }
 
            } 

            foreach (DictionaryEntry entry in _defaultBrowserOverrides) { 
                object key = entry.Key;

                BrowserDefinition firstDefaultBrowserDefinition = (BrowserDefinition)DefaultTree[GetFirstItemFromKey(_defaultBrowserOverrides, key)];
                string parentName = firstDefaultBrowserDefinition.ParentName; 

                if (baseType.GetMethod("Default" + parentName + "ProcessBrowsers", flags) == null) { 
                    String parentID = firstDefaultBrowserDefinition.ParentID; 
                    if (firstDefaultBrowserDefinition != null) {
                        throw new ConfigurationErrorsException(SR.GetString(SR.DefaultBrowser_parentID_Not_Found, parentID), firstDefaultBrowserDefinition.XmlNode); 
                    }
                }

                string methodName = "Default" + parentName + "ProcessBrowsers"; 
                CodeMemberMethod cmm = new CodeMemberMethod();
                cmm.Name = methodName; 
                cmm.ReturnType = new CodeTypeReference(typeof(void)); 
                cmm.Attributes = MemberAttributes.Family | MemberAttributes.Override;
                cpde = new CodeParameterDeclarationExpression(typeof(bool), BrowserCapabilitiesCodeGenerator.IgnoreApplicationBrowserVariableName); 
                cmm.Parameters.Add(cpde);
                cpde = new CodeParameterDeclarationExpression(typeof(NameValueCollection), "headers");
                cmm.Parameters.Add(cpde);
                cpde = new CodeParameterDeclarationExpression(typeof(HttpBrowserCapabilities), browserCapsVariable); 
                cmm.Parameters.Add(cpde);
                factoryType.Members.Add(cmm); 
 
                ArrayList overrides = (ArrayList)_defaultBrowserOverrides[key];
 
                CodeConditionStatement istatement = new CodeConditionStatement();
                istatement.Condition = new CodeVariableReferenceExpression(BrowserCapabilitiesCodeGenerator.IgnoreApplicationBrowserVariableName);

                cmm.Statements.Add(istatement); 
                CodeStatementCollection statements = istatement.FalseStatements;
 
                foreach(string browserID in overrides) { 
                    bd = (BrowserDefinition)DefaultTree[browserID];
                    Debug.Assert(!(bd is GatewayDefinition)); 

                    if(bd.IsRefID) {
                        GenerateSingleProcessCall(bd, cmm, "Default");
                    } 
                    else {
                        statements = GenerateTrackedSingleProcessCall(statements, bd, cmm, "Default"); 
                    } 
                }
            } 

            // Generate process method for the browser elements
            foreach (DictionaryEntry entry in BrowserTree) {
                bd = entry.Value as BrowserDefinition; 
                Debug.Assert(bd != null);
                GenerateProcessMethod(bd, factoryType); 
            } 

            for (int i = 0; i < customTreeRoots.Count; i++) { 
                foreach (DictionaryEntry entry in (BrowserTree)CustomTreeList[i]) {
                    bd = entry.Value as BrowserDefinition;
                    Debug.Assert(bd != null);
                    GenerateProcessMethod(bd, factoryType); 
                }
            } 
 
            // Generate process method for the default browser elements
            foreach (DictionaryEntry entry in DefaultTree) { 
                bd = entry.Value as BrowserDefinition;
                Debug.Assert(bd != null);
                GenerateProcessMethod(bd, factoryType, "Default");
            } 
            GenerateOverrideMatchedHeaders(factoryType);
            GenerateOverrideBrowserElements(factoryType); 
 
            Assembly assembly = BrowserCapabilitiesCompiler.GetBrowserCapabilitiesFactoryBaseType().Assembly;
            assemblyBuilder.AddAssemblyReference(assembly, ccu); 
            assemblyBuilder.AddCodeCompileUnit(_buildProvider, ccu);
        }

        internal override void ProcessBrowserNode(XmlNode node, BrowserTree browserTree) { 
            if (node.Name == "defaultBrowser") {
                throw new ConfigurationErrorsException(SR.GetString(SR.Browser_Not_Allowed_InAppLevel, node.Name), node); 
            } 

            base.ProcessBrowserNode(node, browserTree); 
        }
    }

    internal class ApplicationBrowserCapabilitiesBuildProvider : BuildProvider { 

        private ApplicationBrowserCapabilitiesCodeGenerator _codeGenerator; 
 
        internal ApplicationBrowserCapabilitiesBuildProvider() {
            _codeGenerator = new ApplicationBrowserCapabilitiesCodeGenerator(this); 
        }

        internal void AddFile(string virtualPath) {
            String filePath = HostingEnvironment.MapPathInternal(virtualPath); 
            _codeGenerator.AddFile(filePath);
        } 
 
        public override void GenerateCode(AssemblyBuilder assemblyBuilder) {
            _codeGenerator.GenerateCode(assemblyBuilder); 
        }
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK