protected void ProcessBrowserFiles(bool useVirtualPath, string virtualDir) {
            _browserTree = new BrowserTree();
            _defaultTree = new BrowserTree();
            _customTreeNames = new ArrayList();

            if (_browserFileList == null) {
                _browserFileList = new ArrayList();
            }

            _browserFileList.Sort();
//#if OPTIMIZE_FOR_DESKTOP_BROWSER
            string mozillaFile = null;
            string ieFile = null;
            string operaFile = null;

            // DevDivBugs 180962
            // IE, Mozilla and Opera are first-class browsers. Their User-Agent profiles need to be compared to the UA profile
            // of the HTTP request before other browsers. We put them to the head of the list so that the generated browser capabilities 
            // code will try to match them before other browsers.
            foreach (String filePath in _browserFileList) {
                if (filePath.EndsWith("ie.browser", StringComparison.OrdinalIgnoreCase)) {
                    ieFile = filePath;
                }
                else if (filePath.EndsWith("mozilla.browser", StringComparison.OrdinalIgnoreCase)) {
                    mozillaFile = filePath;
                }
                else if (filePath.EndsWith("opera.browser", StringComparison.OrdinalIgnoreCase)) {
                    operaFile = filePath;
                    break;
                }
            }

            if (ieFile != null) {
                _browserFileList.Remove(ieFile);
                _browserFileList.Insert(0, ieFile);
            }

            if (mozillaFile != null) {
                _browserFileList.Remove(mozillaFile);
                _browserFileList.Insert(1, mozillaFile);
            }

            if (operaFile != null) {
                _browserFileList.Remove(operaFile);
                _browserFileList.Insert(2, operaFile);
            }
//#endif
            foreach (string fileName in _browserFileList) {
                XmlDocument doc = new ConfigXmlDocument();
                try {
                    doc.Load(fileName);

                    XmlNode rootNode = doc.DocumentElement;
                    if(rootNode.Name != "browsers") {
                        if(useVirtualPath) {
                            throw new HttpParseException(SR.GetString(SR.Invalid_browser_root), null /*innerException*/, virtualDir + "/" + NoPathFileName(fileName), null /*sourceCode*/, 1);
                        }
                        else {
                            throw new HttpParseException(SR.GetString(SR.Invalid_browser_root), null /*innerException*/, fileName, null /*sourceCode*/, 1);
                        }
                    }

                    foreach (XmlNode node in rootNode.ChildNodes) {
                        if (node.NodeType != XmlNodeType.Element)
                            continue;
                        if (node.Name == "browser" || node.Name == "gateway") { 
                            ProcessBrowserNode(node, _browserTree);
                        }
                        else if (node.Name == "defaultBrowser") {
                            ProcessBrowserNode(node, _defaultTree);
                        }
                        else {
                            HandlerBase.ThrowUnrecognizedElement(node);
                        }
                    }
                }
                catch (XmlException e) {
                    if(useVirtualPath) {
                        throw new HttpParseException(e.Message, null /*innerException*/, virtualDir + "/" + NoPathFileName(fileName), null /*sourceCode*/, e.LineNumber);
                    }
                    else {
                        throw new HttpParseException(e.Message, null /*innerException*/, fileName, null /*sourceCode*/, e.LineNumber);
                    }
                }
                catch (XmlSchemaException e) {
                    if(useVirtualPath) {
                        throw new HttpParseException(e.Message, null /*innerException*/, virtualDir + "/" + NoPathFileName(fileName), null /*sourceCode*/, e.LineNumber);
                    }
                    else {
                        throw new HttpParseException(e.Message, null /*innerException*/, fileName, null /*sourceCode*/, e.LineNumber);
                    }
                }
            }
            NormalizeAndValidateTree(_browserTree, false);
            NormalizeAndValidateTree(_defaultTree, true);

            BrowserDefinition defaultBrowser = (BrowserDefinition)_browserTree["Default"];

            if (defaultBrowser != null) {
                AddBrowserToCollectionRecursive(defaultBrowser, 0);
            }
        }
        internal void ProcessCustomBrowserFiles(bool useVirtualPath, string virtualDir) {
            //get all custom browser files and put them in the "tree"
            DirectoryInfo browserDirInfo = null;
            DirectoryInfo[] browserSubDirectories = null;
            DirectoryInfo[] allBrowserSubDirectories = null;
            ArrayList customBrowserFileNames;
            _customTreeList = new ArrayList();
            _customBrowserFileLists = new ArrayList();
            _customBrowserDefinitionCollections = new ArrayList();

            /* Machine Level Custom Browsers */
            if (useVirtualPath == false) {
                browserDirInfo = new DirectoryInfo(_browsersDirectory);
            }
            /* Application Level Custom Browsers */
            else {
                browserDirInfo = new DirectoryInfo(HostingEnvironment.MapPathInternal(virtualDir));
            }

            allBrowserSubDirectories = browserDirInfo.GetDirectories();
            
            int j = 0;
            int length = allBrowserSubDirectories.Length;
            browserSubDirectories = new DirectoryInfo[length];
            for (int i = 0; i < length; i++) {
                if ((allBrowserSubDirectories[i].Attributes & FileAttributes.Hidden) != FileAttributes.Hidden) {
                    browserSubDirectories[j] = allBrowserSubDirectories[i];
                    j++;
                }
            }
            Array.Resize(ref browserSubDirectories, j);

            for (int i = 0; i < browserSubDirectories.Length; i++) {
                /* Recursively Into Subdirectories */
                FileInfo[] browserFiles = GetFilesNotHidden(browserSubDirectories[i], browserDirInfo);

                if (browserFiles == null || browserFiles.Length == 0) {
                    continue;
                }
                BrowserTree customTree = new BrowserTree();
                _customTreeList.Add(customTree);
                _customTreeNames.Add(browserSubDirectories[i].Name);
                customBrowserFileNames = new ArrayList();

                foreach (FileInfo browserFile in browserFiles) {
                    customBrowserFileNames.Add(browserFile.FullName);
                }
                _customBrowserFileLists.Add(customBrowserFileNames);
            }
            for (int i = 0; i < _customBrowserFileLists.Count; i++) {
                ArrayList fileNames = (ArrayList)_customBrowserFileLists[i];
                foreach (string fileName in fileNames) {
                    XmlDocument doc = new ConfigXmlDocument();
                    try {
                        doc.Load(fileName);
 
                        XmlNode rootNode = doc.DocumentElement;
                        if (rootNode.Name != "browsers") {
                            if (useVirtualPath) {
                                throw new HttpParseException(SR.GetString(SR.Invalid_browser_root), null /*innerException*/, virtualDir + "/" + NoPathFileName(fileName), null /*sourceCode*/, 1);
                            }
                            else {
                                throw new HttpParseException(SR.GetString(SR.Invalid_browser_root), null /*innerException*/, fileName, null /*sourceCode*/, 1);
                            }
                        }
                        foreach (XmlNode node in rootNode.ChildNodes) {
                            if (node.NodeType != XmlNodeType.Element) {
                                continue;
                            }
                            if (node.Name == "browser" || node.Name == "gateway") {
                                ProcessBrowserNode(node, (BrowserTree)_customTreeList[i]);
                            }
                            else {
                                HandlerBase.ThrowUnrecognizedElement(node);
                            }
                        }
                    }
                    catch (XmlException e) {
                        if (useVirtualPath) {
                            throw new HttpParseException(e.Message, null /*innerException*/, virtualDir + "/" + NoPathFileName(fileName), null /*sourceCode*/, e.LineNumber);
                        }
                        else {
                            throw new HttpParseException(e.Message, null /*innerException*/, fileName, null /*sourceCode*/, e.LineNumber);
                        }
                    }
                    catch (XmlSchemaException e) {
                        if (useVirtualPath) {
                            throw new HttpParseException(e.Message, null /*innerException*/, virtualDir + "/" + NoPathFileName(fileName), null /*sourceCode*/, e.LineNumber);
                        }
                        else {
                            throw new HttpParseException(e.Message, null /*innerException*/, fileName, null /*sourceCode*/, e.LineNumber);
                        }
                    }
                }
                SetCustomTreeRoots((BrowserTree)_customTreeList[i], i);
                NormalizeAndValidateTree((BrowserTree)_customTreeList[i], false, true);
                _customBrowserDefinitionCollections.Add(new BrowserDefinitionCollection());
                AddCustomBrowserToCollectionRecursive((BrowserDefinition)(((BrowserTree)_customTreeList[i])[_customTreeNames[i]]), 0, i);
            }
        }
 private void SetCustomTreeRoots(BrowserTree browserTree, int index) {
     foreach (DictionaryEntry entry in browserTree) {
         BrowserDefinition bd = (BrowserDefinition)entry.Value;
         if (bd.ParentName == null) {
             _customTreeNames[index] = bd.Name;
             break;
         }
     }
 }      
        private void NormalizeAndValidateTree(BrowserTree browserTree, bool isDefaultBrowser, bool isCustomBrowser) {
            //normalize the tree
            foreach (DictionaryEntry entry in browserTree) {
                BrowserDefinition bd = (BrowserDefinition)entry.Value;
                string parentName = bd.ParentName;
                BrowserDefinition parentBrowser = null;

                if (IsRootNode(bd.Name)) {
                    continue;
                }

                if (parentName.Length > 0) {
                    parentBrowser = (BrowserDefinition)browserTree[parentName];
                }

                if (parentBrowser != null) {
                    if (bd.IsRefID) {
                        if (bd is GatewayDefinition) {
                            parentBrowser.RefGateways.Add(bd);
                        }
                        else {
                            parentBrowser.RefBrowsers.Add(bd);
                        }
                    }
                    else if (bd is GatewayDefinition) {
                        parentBrowser.Gateways.Add(bd);
                    }
                    else {
                        parentBrowser.Browsers.Add(bd);
                    }
                }
                else {
                    if (isCustomBrowser) {
                        throw new ConfigurationErrorsException(SR.GetString(SR.Browser_parentID_Not_Found, bd.ParentID), bd.XmlNode);
                    }
                    else {
                        HandleUnRecognizedParentElement(bd, isDefaultBrowser);
                    }
                }
            }

            //validate the tree
            //loop check
            foreach (DictionaryEntry entry in browserTree) {
                BrowserDefinition bd = (BrowserDefinition)entry.Value;
                Hashtable loopCheck = new Hashtable();
                BrowserDefinition currentBrowser = bd;
                string currentId = currentBrowser.Name;
                while (!IsRootNode(currentId)) {
                    if (loopCheck[currentId] != null) {
                        throw new ConfigurationErrorsException(SR.GetString(SR.Browser_Circular_Reference, currentId), currentBrowser.XmlNode);
                    }
                    loopCheck[currentId] = currentId;
                    currentBrowser = (BrowserDefinition)browserTree[currentBrowser.ParentName];
                    //in app-level, parent can exist in machine level
                    if (currentBrowser == null) {
                        break;
                    }

                    currentId = currentBrowser.Name;
                }
            }
        }
 private void NormalizeAndValidateTree(BrowserTree browserTree, bool isDefaultBrowser) {
     NormalizeAndValidateTree(browserTree, isDefaultBrowser, false);
 }
        internal virtual void ProcessBrowserNode(XmlNode node, BrowserTree browserTree) {

            BrowserDefinition browserInfo = null;

            if (node.Name == "gateway") {
                browserInfo = new GatewayDefinition(node);
            }
            else if (node.Name == "browser") {
                browserInfo = new BrowserDefinition(node);
            }
            else {
                Debug.Assert(node.Name == "defaultBrowser");
                browserInfo = new BrowserDefinition(node, true);
            }

            BrowserDefinition oldNode = (BrowserDefinition)browserTree[browserInfo.Name];

            if (oldNode != null) {
                if (browserInfo.IsRefID) {
                    oldNode.MergeWithDefinition(browserInfo);
                }
                else {
                    throw new ConfigurationErrorsException(SR.GetString(SR.Duplicate_browser_id, browserInfo.ID), node);
                }
            }
            else {
                browserTree[browserInfo.Name] = browserInfo;
            }
        }
        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);
        }