BrowserCapabilitiesCompiler.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / xsp / System / Web / Compilation / BrowserCapabilitiesCompiler.cs / 1 / 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 Type _browserCapabilitiesFactoryType;
 
        private static BrowserCapabilitiesFactoryBase _browserCapabilitiesFactoryBaseInstance;
        private static object _lockObject = new object();

        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 {
                    assembly = Assembly.Load("ASP.BrowserCapsFactory, Version=" + ThisAssembly.Version + ", Culture=neutral, PublicKeyToken=" + publicKeyToken);
                }
                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;
                }
                lock(_lockObject) { 
                    if(_browserCapabilitiesFactoryBaseInstance == null) {
                        _browserCapabilitiesFactoryType = GetBrowserCapabilitiesType(); 
                        if(_browserCapabilitiesFactoryType != null) { 
                            _browserCapabilitiesFactoryBaseInstance =
                                (BrowserCapabilitiesFactoryBase)Activator.CreateInstance(_browserCapabilitiesFactoryType); 
                        }
                    }
                }
                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 ((baseType.GetMethod(parentName + "ProcessBrowsers", flags) == null) ||
                    (baseType.GetMethod(parentName + "ProcessGateways", flags) == null)) { 
                    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) {
                            _baseInstance = (BrowserCapabilitiesFactoryBase)Activator.CreateInstance(baseType);
                        }
                        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.
//------------------------------------------------------------------------------ 
// 
//     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 Type _browserCapabilitiesFactoryType;
 
        private static BrowserCapabilitiesFactoryBase _browserCapabilitiesFactoryBaseInstance;
        private static object _lockObject = new object();

        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 {
                    assembly = Assembly.Load("ASP.BrowserCapsFactory, Version=" + ThisAssembly.Version + ", Culture=neutral, PublicKeyToken=" + publicKeyToken);
                }
                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;
                }
                lock(_lockObject) { 
                    if(_browserCapabilitiesFactoryBaseInstance == null) {
                        _browserCapabilitiesFactoryType = GetBrowserCapabilitiesType(); 
                        if(_browserCapabilitiesFactoryType != null) { 
                            _browserCapabilitiesFactoryBaseInstance =
                                (BrowserCapabilitiesFactoryBase)Activator.CreateInstance(_browserCapabilitiesFactoryType); 
                        }
                    }
                }
                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 ((baseType.GetMethod(parentName + "ProcessBrowsers", flags) == null) ||
                    (baseType.GetMethod(parentName + "ProcessGateways", flags) == null)) { 
                    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) {
                            _baseInstance = (BrowserCapabilitiesFactoryBase)Activator.CreateInstance(baseType);
                        }
                        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