//generate the code from the parsed BrowserDefinitionTree
        //compile it, and install it in the gac
        private void GenerateAssembly() {
            Debug.Assert(_browserTree != null);
            BrowserDefinition root = (BrowserDefinition)_browserTree["Default"];
            BrowserDefinition defaultRoot = (BrowserDefinition)_defaultTree["Default"];
            ArrayList customTreeRoots = new ArrayList();
            for (int i = 0; i < _customTreeNames.Count; i++) {
                customTreeRoots.Add((BrowserDefinition)(((BrowserTree)_customTreeList[i])[_customTreeNames[i]]));
            }

            //create a CodeCompileUnit
            //add a CodeNamespace object to the CodeCompileUnit
            //add a CodeTypeDeclaration to the CodeNamespace
            //add all the members of the type/class to the CodeTypeDeclaration
            //use a CodeGenerator to generate code from the CodeCompileUnit
            //a CodeDomProvider can provide a CodeGenerator

            //translate the BrowserDefinition tree to code
            CSharpCodeProvider cscp = new CSharpCodeProvider();

            // namespace System.Web.BrowserCapsFactory
            CodeCompileUnit ccu = new CodeCompileUnit();

            //add strong-name key pair for
            CodeAttributeDeclaration declaration = new CodeAttributeDeclaration(
                "System.Reflection.AssemblyKeyFile",
                new CodeAttributeArgument[] {
                    new CodeAttributeArgument(new CodePrimitiveExpression(_strongNameKeyFileName))});

            CodeAttributeDeclaration aptca = new CodeAttributeDeclaration(
                "System.Security.AllowPartiallyTrustedCallers");
            ccu.AssemblyCustomAttributes.Add(aptca);

            ccu.AssemblyCustomAttributes.Add(declaration);
            //add version number for it so it can distinguished in future versions
            declaration = new CodeAttributeDeclaration(
                "System.Reflection.AssemblyVersion",
                new CodeAttributeArgument[] {
                    new CodeAttributeArgument(new CodePrimitiveExpression(ThisAssembly.Version))});
            ccu.AssemblyCustomAttributes.Add(declaration);

            CodeNamespace cnamespace = new CodeNamespace("ASP");
            //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);

            CodeTypeDeclaration factoryType = new CodeTypeDeclaration("BrowserCapabilitiesFactory");
            factoryType.Attributes = MemberAttributes.Private;
            factoryType.IsClass = true;
            factoryType.Name = TypeName;
            factoryType.BaseTypes.Add(new CodeTypeReference("System.Web.Configuration.BrowserCapabilitiesFactoryBase"));
            cnamespace.Types.Add(factoryType);

            //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 = "ConfigureBrowserCapabilities";

            CodeParameterDeclarationExpression cpde = new CodeParameterDeclarationExpression(typeof(NameValueCollection), _headersRefName);
            method.Parameters.Add(cpde);
            cpde = new CodeParameterDeclarationExpression(typeof(HttpBrowserCapabilities), browserCapsVariable);
            method.Parameters.Add(cpde);
            factoryType.Members.Add(method);

            GenerateSingleProcessCall(root, method);
            
            for (int i = 0; i < customTreeRoots.Count; i++) {
                GenerateSingleProcessCall((BrowserDefinition)customTreeRoots[i], method);
            }

            //GEN: if(this.IsBrowserUnknown(browserCaps) == false) return;            
            CodeConditionStatement istatement = new CodeConditionStatement();

            CodeMethodInvokeExpression cmie = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "IsBrowserUnknown");
            cmie.Parameters.Add(_browserCapsRefExpr);
            istatement.Condition = new CodeBinaryOperatorExpression(cmie, CodeBinaryOperatorType.ValueEquality, new CodePrimitiveExpression(false));
            istatement.TrueStatements.Add(new CodeMethodReturnStatement());
            method.Statements.Add(istatement);

            if(defaultRoot != null) {
                GenerateSingleProcessCall(defaultRoot, method, "Default");
            }

            for (int i = 0; i < customTreeRoots.Count; i++) {
                foreach (DictionaryEntry entry in (BrowserTree)_customTreeList[i]) {
                    BrowserDefinition bd = entry.Value as BrowserDefinition;
                    Debug.Assert(bd != null);
                    GenerateProcessMethod(bd, factoryType);
                }
            }

            //GenerateCallsToProcessMethods(root, method);
            foreach (DictionaryEntry entry in _browserTree) {
                BrowserDefinition bd = entry.Value as BrowserDefinition;
                Debug.Assert(bd != null);
                GenerateProcessMethod(bd, factoryType);
            }

            foreach (DictionaryEntry entry in _defaultTree) {
                BrowserDefinition bd = entry.Value as BrowserDefinition;
                Debug.Assert(bd != null);
                GenerateProcessMethod(bd, factoryType, "Default");
            }

            GenerateOverrideMatchedHeaders(factoryType);
            GenerateOverrideBrowserElements(factoryType);

            //TODO: don't actually generate the code, just compile it in memory
            TextWriter twriter = new StreamWriter(new FileStream(_browsersDirectory + "\\BrowserCapsFactory.cs", FileMode.Create));
            try {
                cscp.GenerateCodeFromCompileUnit(ccu, twriter, null);
            }
            finally {
                if(twriter != null)
                    twriter.Close();
            }

            CompilationSection compConfig = MTConfigUtil.GetCompilationAppConfig();

            bool debug = compConfig.Debug;

#if !PLATFORM_UNIX // File system paths must account for UNIX
            string strongNameFile = _browsersDirectory + "\\" + _strongNameKeyFileName;
#else // !PLATFORM_UNIX
            string strongNameFile = _browsersDirectory + "/" + _strongNameKeyFileName;
#endif // !PLATFORM_UNIX

            // Generate strong name file
            StrongNameUtility.GenerateStrongNameFile(strongNameFile);

            //TODO: do not use interim file:  CompileAssemblyFromDom instead
            string[] referencedAssemblies = new string[2] { "System.dll", "System.Web.dll" };
            CompilerParameters compilerParameters = new CompilerParameters(referencedAssemblies, "ASP.BrowserCapsFactory", debug /* includeDebugInformation */ );
            compilerParameters.GenerateInMemory = false;
            compilerParameters.OutputAssembly = _browsersDirectory + "\\ASP.BrowserCapsFactory.dll";
            CompilerResults results = null;

            try {
                results = cscp.CompileAssemblyFromFile(compilerParameters, _browsersDirectory + "\\BrowserCapsFactory.cs");
            }
            finally {
                if (File.Exists(strongNameFile)) {
                    File.Delete(strongNameFile);
                }
            }

            if (results.NativeCompilerReturnValue != 0 || results.Errors.HasErrors) {
                foreach (CompilerError error in results.Errors) {
                    if (!error.IsWarning) {
                        throw new HttpCompileException(error.ErrorText);
                    }
                }

                throw new HttpCompileException(SR.GetString(SR.Browser_compile_error));
            }

            Assembly resultAssembly = results.CompiledAssembly;

            GacUtil gacutil = new GacUtil();
            gacutil.GacInstall(resultAssembly.Location);

            SavePublicKeyTokenFile(_publicKeyTokenFile, resultAssembly.GetName().GetPublicKeyToken());
        }
 internal bool UninstallInternal()
 {
     if (File.Exists(_publicKeyTokenFile))
     {
         File.Delete(_publicKeyTokenFile);
     }
     GacUtil util = new GacUtil();
     if (!util.GacUnInstall("ASP.BrowserCapsFactory, Version=4.0.0.0, Culture=neutral"))
     {
         return false;
     }
     return true;
 }
        internal bool UninstallInternal() {
            // Remove existing strong name public token file
            if (File.Exists(_publicKeyTokenFile)) {
                File.Delete(_publicKeyTokenFile);
            }

            // Removing existing copy from GAC
            GacUtil gacutil = new GacUtil();
            bool assemblyRemoved = gacutil.GacUnInstall("ASP.BrowserCapsFactory, Version=" + ThisAssembly.Version + ", Culture=neutral");
            if (!assemblyRemoved) {
                return false;
            }

            return true;
        }