XmlSiteMapProvider.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 / XmlSiteMapProvider.cs / 1305376 / XmlSiteMapProvider.cs

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

/* 
 * XmlSiteMapProvider class definition 
 *
 * Copyright (c) 2002 Microsoft Corporation 
 */

namespace System.Web {
 
    using System;
    using System.Collections; 
    using System.Collections.Specialized; 
    using System.ComponentModel;
    using System.ComponentModel.Design; 
    using System.Configuration;
    using System.Configuration.Provider;
    using System.Globalization;
    using System.IO; 
    using System.Resources;
    using System.Security; 
    using System.Security.Permissions; 
    using System.Web.Compilation;
    using System.Web.Configuration; 
    using System.Web.Hosting;
    using System.Web.UI;
    using System.Web.Util;
    using System.Xml; 

    // XmlMapProvider that generates sitemap tree from xml files 
 
    public class XmlSiteMapProvider : StaticSiteMapProvider, IDisposable {
 
        private string _filename;
        private VirtualPath _virtualPath;
        private VirtualPath _normalizedVirtualPath;
        private SiteMapNode _siteMapNode; 
        private XmlDocument _document;
        private bool _initialized; 
        private FileChangeEventHandler _handler; 
        private StringCollection _parentSiteMapFileCollection;
 
        private const string _providerAttribute = "provider";
        private const string _siteMapFileAttribute = "siteMapFile";
        private const string _siteMapNodeName = "siteMapNode";
        private const string _xmlSiteMapFileExtension = ".sitemap"; 
        private const string _resourcePrefix = "$resources:";
        private const int _resourcePrefixLength = 10; 
        private const char _resourceKeySeparator = ','; 
        private static readonly char[] _seperators = new char[] { ';', ',' };
 
        private ArrayList _childProviderList;

        // table containing mappings from child providers to their root nodes.
        private Hashtable _childProviderTable; 

 
        public XmlSiteMapProvider() { 
        }
 
        private ArrayList ChildProviderList {
            get {
                ArrayList returnList = _childProviderList;
                if (returnList == null) { 
                    lock (_lock) {
                        if (_childProviderList == null) { 
                            returnList = ArrayList.ReadOnly(new ArrayList(ChildProviderTable.Keys)); 
                            _childProviderList = returnList;
                        } 
                        else {
                            returnList = _childProviderList;
                        }
                    } 
                }
 
                return returnList; 
            }
        } 

        private Hashtable ChildProviderTable {
            get {
                if (_childProviderTable == null) { 
                    lock (_lock) {
                        if (_childProviderTable == null) { 
                            _childProviderTable = new Hashtable(); 
                        }
                    } 
                }

                return _childProviderTable;
            } 
        }
 
 
        public override SiteMapNode RootNode {
            get { 
                BuildSiteMap();
                return ReturnNodeIfAccessible(_siteMapNode);
            }
        } 

        protected internal override void AddNode(SiteMapNode node, SiteMapNode parentNode) { 
            if (node == null) { 
                throw new ArgumentNullException("node");
            } 

            if (parentNode == null) {
                throw new ArgumentNullException("parentNode");
            } 

            SiteMapProvider ownerProvider = node.Provider; 
            SiteMapProvider parentOwnerProvider = parentNode.Provider; 

            if (ownerProvider != this) { 
                throw new ArgumentException(SR.GetString(SR.XmlSiteMapProvider_cannot_add_node, node.ToString()), "node");
            }

            if (parentOwnerProvider != this) { 
                throw new ArgumentException(SR.GetString(SR.XmlSiteMapProvider_cannot_add_node, parentNode.ToString()), "parentNode");
            } 
 
            lock (_lock) {
                // First remove it from its current location. 
                RemoveNode(node);
                AddNodeInternal(node, parentNode, null);
            }
        } 

        private void AddNodeInternal(SiteMapNode node, SiteMapNode parentNode, XmlNode xmlNode) { 
            lock (_lock) { 
                String url = node.Url;
                String key = node.Key; 

                bool isValidUrl = false;

                // Only add the node to the url table if it's a static node. 
                if (!String.IsNullOrEmpty(url)) {
                    if (UrlTable[url] != null) { 
                        if (xmlNode != null) { 
                            throw new ConfigurationErrorsException(
                                SR.GetString(SR.XmlSiteMapProvider_Multiple_Nodes_With_Identical_Url, url), 
                                xmlNode);
                        }
                        else {
                            throw new InvalidOperationException(SR.GetString( 
                                SR.XmlSiteMapProvider_Multiple_Nodes_With_Identical_Url, url));
                        } 
                    } 

                    isValidUrl = true; 
                }

                if (KeyTable.Contains(key)) {
                    if (xmlNode != null) { 
                        throw new ConfigurationErrorsException(
                            SR.GetString(SR.XmlSiteMapProvider_Multiple_Nodes_With_Identical_Key, key), 
                            xmlNode); 
                    }
                    else { 
                        throw new InvalidOperationException(
                           SR.GetString(SR.XmlSiteMapProvider_Multiple_Nodes_With_Identical_Key, key));
                    }
                } 

                if (isValidUrl) { 
                    UrlTable[url] = node; 
                }
 
                KeyTable[key] = node;

                // Add the new node into parentNode collection
                if (parentNode != null) { 
                    ParentNodeTable[node] = parentNode;
 
                    if (ChildNodeCollectionTable[parentNode] == null) { 
                        ChildNodeCollectionTable[parentNode] = new SiteMapNodeCollection();
                    } 

                    ((SiteMapNodeCollection)ChildNodeCollectionTable[parentNode]).Add(node);
                }
            } 
        }
 
        protected virtual void AddProvider(string providerName, SiteMapNode parentNode) { 
            if (parentNode == null) {
                throw new ArgumentNullException("parentNode"); 
            }

            if (parentNode.Provider != this) {
                throw new ArgumentException(SR.GetString(SR.XmlSiteMapProvider_cannot_add_node, parentNode.ToString()), "parentNode"); 
            }
 
            SiteMapNode node = GetNodeFromProvider(providerName); 
            AddNodeInternal(node, parentNode, null);
        } 


        public override SiteMapNode BuildSiteMap() {
 
            SiteMapNode tempNode = _siteMapNode;
 
            // If siteMap is already constructed, simply returns it. 
            // Child providers will only be updated when the parent providers need to access them.
            if (tempNode != null) { 
                return tempNode;
            }

            XmlDocument document = GetConfigDocument(); 

            lock (_lock) { 
                if (_siteMapNode != null) { 
                    return _siteMapNode;
                } 

                Clear();

                // Need to check if the sitemap file exists before opening it. 
                CheckSiteMapFileExists();
 
                try { 
                    using (Stream stream = _normalizedVirtualPath.OpenFile()) {
                        XmlReader reader = new XmlTextReader(stream); 
                        document.Load(reader);
                    }
                }
                catch (XmlException e) { 
                    string sourceFile = _virtualPath.VirtualPathString;
                    string physicalDir = _normalizedVirtualPath.MapPathInternal(); 
                    if (physicalDir != null && HttpRuntime.HasPathDiscoveryPermission(physicalDir)) { 
                        sourceFile = physicalDir;
                    } 

                    throw new ConfigurationErrorsException(
                        SR.GetString(SR.XmlSiteMapProvider_Error_loading_Config_file, _virtualPath, e.Message),
                            e, sourceFile, e.LineNumber); 
                }
                catch (Exception e) { 
                    throw new ConfigurationErrorsException( 
                        SR.GetString(SR.XmlSiteMapProvider_Error_loading_Config_file, _virtualPath, e.Message), e);
                } 

                XmlNode node = null;
                foreach (XmlNode siteMapMode in document.ChildNodes) {
                    if (String.Equals(siteMapMode.Name, "siteMap", StringComparison.Ordinal)) { 
                        node = siteMapMode;
                        break; 
                    } 
                }
 
                if (node == null)
                    throw new ConfigurationErrorsException(
                        SR.GetString(SR.XmlSiteMapProvider_Top_Element_Must_Be_SiteMap),
                        document); 

                bool enableLocalization = false; 
                HandlerBase.GetAndRemoveBooleanAttribute(node, "enableLocalization", ref enableLocalization); 
                EnableLocalization = enableLocalization;
 
                XmlNode topElement = null;
                foreach (XmlNode subNode in node.ChildNodes) {
                    if (subNode.NodeType == XmlNodeType.Element) {
                        if (!_siteMapNodeName.Equals(subNode.Name)) { 
                            throw new ConfigurationErrorsException(
                                SR.GetString(SR.XmlSiteMapProvider_Only_SiteMapNode_Allowed), 
                                subNode); 
                        }
 
                        if (topElement != null) {
                            throw new ConfigurationErrorsException(
                                SR.GetString(SR.XmlSiteMapProvider_Only_One_SiteMapNode_Required_At_Top),
                                subNode); 
                        }
 
                        topElement = subNode; 
                    }
                } 

                if (topElement == null) {
                    throw new ConfigurationErrorsException(
                         SR.GetString(SR.XmlSiteMapProvider_Only_One_SiteMapNode_Required_At_Top), 
                         node);
                } 
 
                Queue queue = new Queue(50);
 
                // The parentnode of the top node does not exist,
                // simply add a null to satisfy the ConvertFromXmlNode condition.
                queue.Enqueue(null);
                queue.Enqueue(topElement); 
                _siteMapNode = ConvertFromXmlNode(queue);
 
                return _siteMapNode; 
            }
        } 

        private void CheckSiteMapFileExists() {
            if (!System.Web.UI.Util.VirtualFileExistsWithAssert(_normalizedVirtualPath)) {
                throw new InvalidOperationException( 
                    SR.GetString(SR.XmlSiteMapProvider_FileName_does_not_exist, _virtualPath));
            } 
        } 

 
        protected override void Clear() {
            lock (_lock) {
                ChildProviderTable.Clear();
                _siteMapNode = null; 
                _childProviderList = null;
 
                base.Clear(); 
            }
        } 

        // helper method to convert an XmlNode to a SiteMapNode
        private SiteMapNode ConvertFromXmlNode(Queue queue) {
 
            SiteMapNode rootNode = null;
            while (true) { 
                if (queue.Count == 0) { 
                    return rootNode;
                } 

                SiteMapNode parentNode = (SiteMapNode)queue.Dequeue();
                XmlNode xmlNode = (XmlNode)queue.Dequeue();
 
                SiteMapNode node = null;
 
                if (!_siteMapNodeName.Equals(xmlNode.Name)) { 
                    throw new ConfigurationErrorsException(
                        SR.GetString(SR.XmlSiteMapProvider_Only_SiteMapNode_Allowed), 
                        xmlNode);
                }

                string providerName = null; 
                HandlerBase.GetAndRemoveNonEmptyStringAttribute(xmlNode, _providerAttribute, ref providerName);
 
                // If the siteMapNode references another provider 
                if (providerName != null) {
                    node = GetNodeFromProvider(providerName); 

                    // No other attributes or child nodes are allowed on a provider node.
                    HandlerBase.CheckForUnrecognizedAttributes(xmlNode);
                    HandlerBase.CheckForNonCommentChildNodes(xmlNode); 
                }
                else { 
                    string siteMapFile = null; 
                    HandlerBase.GetAndRemoveNonEmptyStringAttribute(xmlNode, _siteMapFileAttribute, ref siteMapFile);
 
                    if (siteMapFile != null) {
                        node = GetNodeFromSiteMapFile(xmlNode, VirtualPath.Create(siteMapFile));
                    }
                    else { 
                        node = GetNodeFromXmlNode(xmlNode, queue);
                    } 
                } 

                AddNodeInternal(node, parentNode, xmlNode); 

                if (rootNode == null) {
                    rootNode = node;
                } 
            }
        } 
 
        protected virtual void Dispose(bool disposing) {
            if (_handler != null) { 
                Debug.Assert(_filename != null);
                HttpRuntime.FileChangesMonitor.StopMonitoringFile(_filename, _handler);
            }
        } 

        public void Dispose() { 
            Dispose(true); 
            GC.SuppressFinalize(this);
        } 

        private void EnsureChildSiteMapProviderUpToDate(SiteMapProvider childProvider) {
            SiteMapNode oldNode = (SiteMapNode)ChildProviderTable[childProvider];
 
            SiteMapNode newNode = childProvider.GetRootNodeCore();
            if (newNode == null) { 
                throw new ProviderException(SR.GetString(SR.XmlSiteMapProvider_invalid_sitemapnode_returned, childProvider.Name)); 
            }
 
            // child providers have been updated.
            if (!oldNode.Equals(newNode)) {

                // If the child provider table has been updated, simply return null. 
                // This will happen when the current provider's sitemap file is changed or Clear() is called;
                if (oldNode == null) { 
                    return; 
                }
 
                lock (_lock) {
                    oldNode = (SiteMapNode)ChildProviderTable[childProvider];
                    // If the child provider table has been updated, simply return null. See above.
                    if (oldNode == null) { 
                        return;
                    } 
 
                    newNode = childProvider.GetRootNodeCore();
                    if (newNode == null) { 
                        throw new ProviderException(SR.GetString(SR.XmlSiteMapProvider_invalid_sitemapnode_returned, childProvider.Name));
                    }

                    if (!oldNode.Equals(newNode)) { 

                        // If the current provider does not contain any nodes but one child provider 
                        // ie. _siteMapNode == oldNode 
                        // the oldNode needs to be removed from Url table and the new node will be added.
                        if (_siteMapNode.Equals(oldNode)) { 
                            UrlTable.Remove(oldNode.Url);
                            KeyTable.Remove(oldNode.Key);

                            UrlTable.Add(newNode.Url, newNode); 
                            KeyTable.Add(newNode.Key, newNode);
 
                            _siteMapNode = newNode; 
                        }
 
                        // First find the parent node
                        SiteMapNode parent = (SiteMapNode)ParentNodeTable[oldNode];

                        // parent is null when the provider does not contain any static nodes, ie. 
                        // it only contains definition to include one child provider.
                        if (parent != null) { 
                            // Update the child nodes table 
                            SiteMapNodeCollection list = (SiteMapNodeCollection)ChildNodeCollectionTable[parent];
 
                            // Add the newNode to where the oldNode is within parent node's collection.
                            int index = list.IndexOf(oldNode);
                            if (index != -1) {
                                list.Remove(oldNode); 
                                list.Insert(index, newNode);
                            } 
                            else { 
                                list.Add(newNode);
                            } 

                            // Update the parent table
                            ParentNodeTable[newNode] = parent;
                            ParentNodeTable.Remove(oldNode); 

                            // Update the Url table 
                            UrlTable.Remove(oldNode.Url); 
                            KeyTable.Remove(oldNode.Key);
 
                            UrlTable.Add(newNode.Url, newNode);
                            KeyTable.Add(newNode.Key, newNode);
                        }
                        else { 
                            // Notify the parent provider to update its child provider collection.
                            XmlSiteMapProvider provider = ParentProvider as XmlSiteMapProvider; 
                            if (provider != null) { 
                                provider.EnsureChildSiteMapProviderUpToDate(this);
                            } 
                        }

                        // Update provider nodes;
                        ChildProviderTable[childProvider] = newNode; 
                        _childProviderList = null;
                    } 
                } 
            }
        } 

        // Returns sitemap node; Search recursively in child providers if not found.

        public override SiteMapNode FindSiteMapNode(string rawUrl) { 
            SiteMapNode node = base.FindSiteMapNode(rawUrl);
 
            if (node == null) { 
                foreach(SiteMapProvider provider in ChildProviderList) {
                    // First make sure the child provider is up-to-date. 
                    EnsureChildSiteMapProviderUpToDate(provider);

                    node = provider.FindSiteMapNode(rawUrl);
                    if (node != null) { 
                        return node;
                    } 
                } 
            }
 
            return node;
        }

        // Returns sitemap node; Search recursively in child providers if not found. 
        public override SiteMapNode FindSiteMapNodeFromKey(string key) {
            SiteMapNode node = base.FindSiteMapNodeFromKey(key); 
 
            if (node == null) {
                foreach (SiteMapProvider provider in ChildProviderList) { 
                    // First make sure the child provider is up-to-date.
                    EnsureChildSiteMapProviderUpToDate(provider);

                    node = provider.FindSiteMapNodeFromKey(key); 
                    if (node != null) {
                        return node; 
                    } 
                }
            } 

            return node;
        }
 
        private XmlDocument GetConfigDocument() {
            if (_document != null) 
                return _document; 

            if (!_initialized) { 
                throw new InvalidOperationException(
                    SR.GetString(SR.XmlSiteMapProvider_Not_Initialized));
            }
 
            // Do the error checking here
            if (_virtualPath == null) { 
                throw new ArgumentException( 
                    SR.GetString(SR.XmlSiteMapProvider_missing_siteMapFile, _siteMapFileAttribute));
            } 

            if (!_virtualPath.Extension.Equals(_xmlSiteMapFileExtension, StringComparison.OrdinalIgnoreCase)) {
                throw new InvalidOperationException(
                    SR.GetString(SR.XmlSiteMapProvider_Invalid_Extension, _virtualPath)); 
            }
 
            _normalizedVirtualPath = _virtualPath.CombineWithAppRoot(); 
            _normalizedVirtualPath.FailIfNotWithinAppRoot();
 
            // Make sure the file exists
            CheckSiteMapFileExists();

            _parentSiteMapFileCollection = new StringCollection(); 
            XmlSiteMapProvider xmlParentProvider = ParentProvider as XmlSiteMapProvider;
            if (xmlParentProvider != null && xmlParentProvider._parentSiteMapFileCollection != null) { 
                if (xmlParentProvider._parentSiteMapFileCollection.Contains(_normalizedVirtualPath.VirtualPathString)) { 
                    throw new InvalidOperationException(
                        SR.GetString(SR.XmlSiteMapProvider_FileName_already_in_use, _virtualPath)); 
                }

                // Copy the sitemapfiles in used from parent provider to current provider.
                foreach (string filename in xmlParentProvider._parentSiteMapFileCollection) { 
                    _parentSiteMapFileCollection.Add(filename);
                } 
            } 

            // Add current sitemap file to the collection 
            _parentSiteMapFileCollection.Add(_normalizedVirtualPath.VirtualPathString);

            _filename = HostingEnvironment.MapPathInternal(_normalizedVirtualPath);
 
            if (!String.IsNullOrEmpty(_filename)) {
                _handler = new FileChangeEventHandler(this.OnConfigFileChange); 
                HttpRuntime.FileChangesMonitor.StartMonitoringFile(_filename, _handler); 
                ResourceKey = (new FileInfo(_filename)).Name;
            } 

            _document = new ConfigXmlDocument();

            return _document; 
        }
 
        private SiteMapNode GetNodeFromProvider(string providerName) { 
            SiteMapProvider provider = GetProviderFromName(providerName);
            SiteMapNode node = null; 

            // Check infinite recursive sitemap files
            if (provider is XmlSiteMapProvider) {
                XmlSiteMapProvider xmlProvider = (XmlSiteMapProvider)provider; 

                StringCollection parentSiteMapFileCollection = new StringCollection(); 
                if (_parentSiteMapFileCollection != null) { 
                    foreach (string filename in _parentSiteMapFileCollection) {
                        parentSiteMapFileCollection.Add(filename); 
                    }
                }

                // Make sure the provider is initialized before adding to the collection. 
                xmlProvider.BuildSiteMap();
 
                parentSiteMapFileCollection.Add(_normalizedVirtualPath.VirtualPathString); 
                if (parentSiteMapFileCollection.Contains(VirtualPath.GetVirtualPathString(xmlProvider._normalizedVirtualPath))) {
                    throw new InvalidOperationException(SR.GetString(SR.XmlSiteMapProvider_FileName_already_in_use, xmlProvider._virtualPath)); 
                }

                xmlProvider._parentSiteMapFileCollection = parentSiteMapFileCollection;
            } 

            node = provider.GetRootNodeCore(); 
            if (node == null) { 
                throw new InvalidOperationException(
                    SR.GetString(SR.XmlSiteMapProvider_invalid_GetRootNodeCore, ((ProviderBase)provider).Name)); 
            }

            ChildProviderTable.Add(provider, node);
            _childProviderList = null; 

            provider.ParentProvider = this; 
 
            return node;
        } 

        private SiteMapNode GetNodeFromSiteMapFile(XmlNode xmlNode, VirtualPath siteMapFile) {

            SiteMapNode node = null; 

            // For external sitemap files, its secuity setting is inherited from parent provider 
            bool secuityTrimmingEnabled = SecurityTrimmingEnabled; 
            HandlerBase.GetAndRemoveBooleanAttribute(xmlNode, _securityTrimmingEnabledAttrName, ref secuityTrimmingEnabled);
 
            // No other attributes or non-comment nodes are allowed on a siteMapFile node
            HandlerBase.CheckForUnrecognizedAttributes(xmlNode);
            HandlerBase.CheckForNonCommentChildNodes(xmlNode);
 
            XmlSiteMapProvider childProvider = new XmlSiteMapProvider();
 
            // siteMapFile was relative to the sitemap file where this xmlnode is defined, make it an application path. 
            siteMapFile = _normalizedVirtualPath.Parent.Combine(siteMapFile);
 
            childProvider.ParentProvider = this;
            childProvider.Initialize(siteMapFile, secuityTrimmingEnabled);
            childProvider.BuildSiteMap();
 
            node = childProvider._siteMapNode;
 
            ChildProviderTable.Add(childProvider, node); 
            _childProviderList = null;
 
            return node;
        }

        private void HandleResourceAttribute(XmlNode xmlNode, ref NameValueCollection collection, 
            string attrName, ref string text, bool allowImplicitResource) {
            if (String.IsNullOrEmpty(text)) { 
                return; 
            }
 
            string resourceKey = null;
            string temp = text.TrimStart(new char[] { ' ' });

            if (temp != null && temp.Length > _resourcePrefixLength) { 
                if (temp.ToLower(CultureInfo.InvariantCulture).StartsWith(_resourcePrefix, StringComparison.Ordinal)) {
                    if (!allowImplicitResource) { 
                        throw new ConfigurationErrorsException( 
                            SR.GetString(SR.XmlSiteMapProvider_multiple_resource_definition, attrName), xmlNode);
                    } 

                    resourceKey = temp.Substring(_resourcePrefixLength + 1);

                    if (resourceKey.Length == 0) { 
                        throw new ConfigurationErrorsException(
                            SR.GetString(SR.XmlSiteMapProvider_resourceKey_cannot_be_empty), xmlNode); 
                    } 

                    // Retrieve className from attribute 
                    string className = null;
                    string key = null;
                    int index = resourceKey.IndexOf(_resourceKeySeparator);
                    if (index == -1) { 
                        throw new ConfigurationErrorsException(
                            SR.GetString( 
                            SR.XmlSiteMapProvider_invalid_resource_key, resourceKey), xmlNode); 
                    }
 
                    className = resourceKey.Substring(0, index);
                    key = resourceKey.Substring(index + 1);

                    // Retrieve resource key and default value from attribute 
                    int defaultIndex = key.IndexOf(_resourceKeySeparator);
                    if (defaultIndex != -1) { 
                        text = key.Substring(defaultIndex + 1); 
                        key = key.Substring(0, defaultIndex);
                    } 
                    else {
                        text = null;
                    }
 
                    if (collection == null) {
                        collection = new NameValueCollection(); 
                    } 

                    collection.Add(attrName, className.Trim()); 
                    collection.Add(attrName, key.Trim());
                }
            }
        } 

        private SiteMapNode GetNodeFromXmlNode(XmlNode xmlNode, Queue queue) { 
            SiteMapNode node = null; 
            // static nodes
            string title = null, url = null, description = null, roles = null, resourceKey = null; 

            // Url attribute is NOT required for a xml node.
            HandlerBase.GetAndRemoveStringAttribute(xmlNode, "url", ref url);
            HandlerBase.GetAndRemoveStringAttribute(xmlNode, "title", ref title); 
            HandlerBase.GetAndRemoveStringAttribute(xmlNode, "description", ref description);
            HandlerBase.GetAndRemoveStringAttribute(xmlNode, "roles", ref roles); 
            HandlerBase.GetAndRemoveStringAttribute(xmlNode, "resourceKey", ref resourceKey); 

            // Do not add the resourceKey if the resource is not valid. 
            if (!String.IsNullOrEmpty(resourceKey) &&
                !ValidateResource(ResourceKey, resourceKey + ".title")) {
                resourceKey = null;
            } 

            HandlerBase.CheckForbiddenAttribute(xmlNode, _securityTrimmingEnabledAttrName); 
 
            NameValueCollection resourceKeyCollection = null;
            bool allowImplicitResourceAttribute = String.IsNullOrEmpty(resourceKey); 
            HandleResourceAttribute(xmlNode, ref resourceKeyCollection,
                "title", ref title, allowImplicitResourceAttribute);
            HandleResourceAttribute(xmlNode, ref resourceKeyCollection,
                "description", ref description, allowImplicitResourceAttribute); 

            ArrayList roleList = new ArrayList(); 
            if (roles != null) { 
                int foundIndex = roles.IndexOf('?');
                if (foundIndex != -1) { 
                    throw new ConfigurationErrorsException(
                        SR.GetString(SR.Auth_rule_names_cant_contain_char,
                            roles[foundIndex].ToString(CultureInfo.InvariantCulture)), xmlNode);
                } 

                foreach (string role in roles.Split(_seperators)) { 
                    string trimmedRole = role.Trim(); 
                    if (trimmedRole.Length > 0) {
                        roleList.Add(trimmedRole); 
                    }
                }
            }
            roleList = ArrayList.ReadOnly(roleList); 

            String key = null; 
 
            // Make urls absolute.
            if (!String.IsNullOrEmpty(url)) { 
                // URL needs to be trimmed. VSWhidbey 411041
                url = url.Trim();

                if (!UrlPath.IsAbsolutePhysicalPath(url)) { 
                    if (UrlPath.IsRelativeUrl(url)) {
                        url = UrlPath.Combine(HttpRuntime.AppDomainAppVirtualPathString, url); 
                    } 
                    // Dev10 445247
                    // Need to add cookieless path segment if it's available. 
                    // This only makes sense in a request context.
                    if (HttpContext.Current != null) {
                        url = HttpContext.Current.Response.ApplyAppPathModifier(url);
                    } 
                }
 
                // VSWhidbey 418056, Reject any suspicious or mal-formed Urls. 
                string decodedUrl = HttpUtility.UrlDecode(url);
                if (!String.Equals(url, decodedUrl, StringComparison.Ordinal)) { 
                    throw new ConfigurationErrorsException(
                        SR.GetString(SR.Property_Had_Malformed_Url, "url", url), xmlNode);
                }
 
                key = url.ToLowerInvariant();
            } 
            else { 
                key = Guid.NewGuid().ToString();
            } 

            // attribute collection does not contain pre-defined properties like title, url, etc.
            ReadOnlyNameValueCollection attributeCollection = new ReadOnlyNameValueCollection();
            attributeCollection.SetReadOnly(false); 
            foreach (XmlAttribute attribute in xmlNode.Attributes) {
                string value = attribute.Value; 
                HandleResourceAttribute(xmlNode, ref resourceKeyCollection, attribute.Name, ref value, allowImplicitResourceAttribute); 
                attributeCollection[attribute.Name] = value;
            } 
            attributeCollection.SetReadOnly(true);

            node = new SiteMapNode(this, key, url, title, description, roleList, attributeCollection, resourceKeyCollection, resourceKey);
            node.ReadOnly = true; 

            foreach (XmlNode subNode in xmlNode.ChildNodes) { 
                if (subNode.NodeType != XmlNodeType.Element) 
                    continue;
 
                queue.Enqueue(node);
                queue.Enqueue(subNode);
            }
 
            return node;
        } 
 
        private SiteMapProvider GetProviderFromName(string providerName) {
            Debug.Assert(providerName != null); 

            SiteMapProvider provider = SiteMap.Providers[providerName];
            if (provider == null) {
                throw new ProviderException(SR.GetString(SR.Provider_Not_Found, providerName)); 
            }
 
            return provider; 
        }
 
        protected internal override SiteMapNode GetRootNodeCore() {
            BuildSiteMap();
            return _siteMapNode;
        } 

 
        public override void Initialize(string name, NameValueCollection attributes) { 
            if (_initialized) {
                throw new InvalidOperationException( 
                    SR.GetString(SR.XmlSiteMapProvider_Cannot_Be_Inited_Twice));
            }

            if (attributes != null) { 
                if (string.IsNullOrEmpty(attributes["description"])) {
                    attributes.Remove("description"); 
                    attributes.Add("description", SR.GetString(SR.XmlSiteMapProvider_Description)); 
                }
 
                string siteMapFile = null;
                ProviderUtil.GetAndRemoveStringAttribute(attributes, _siteMapFileAttribute, name, ref siteMapFile);
                _virtualPath = VirtualPath.CreateAllowNull(siteMapFile);
            } 

            base.Initialize(name, attributes); 
 
            if (attributes != null) {
                ProviderUtil.CheckUnrecognizedAttributes(attributes, name); 
            }

            _initialized = true;
        } 

        private void Initialize(VirtualPath virtualPath, bool secuityTrimmingEnabled) { 
            NameValueCollection coll = new NameValueCollection(); 
            coll.Add(_siteMapFileAttribute, virtualPath.VirtualPathString);
            coll.Add(_securityTrimmingEnabledAttrName, System.Web.UI.Util.GetStringFromBool(secuityTrimmingEnabled)); 

            // Use the siteMapFile virtual path as the provider name
            Initialize(virtualPath.VirtualPathString, coll);
        } 

        private void OnConfigFileChange(Object sender, FileChangeEvent e) { 
            // Notifiy the parent for the change. 
            XmlSiteMapProvider parentProvider = ParentProvider as XmlSiteMapProvider;
            if (parentProvider != null) { 
                parentProvider.OnConfigFileChange(sender, e);
            }

            Clear(); 
        }
 
        protected internal override void RemoveNode(SiteMapNode node) { 
            if (node == null) {
                throw new ArgumentNullException("node"); 
            }

            SiteMapProvider ownerProvider = node.Provider;
 
            if (ownerProvider != this) {
 
                // Only nodes defined in this provider tree can be removed. 
                SiteMapProvider parentProvider = ownerProvider.ParentProvider;
                while (parentProvider != this) { 
                    if (parentProvider == null) {
                        // Cannot remove nodes defined in other providers
                        throw new InvalidOperationException(SR.GetString(
                            SR.XmlSiteMapProvider_cannot_remove_node, node.ToString(), 
                            this.Name, ownerProvider.Name));
                    } 
 
                    parentProvider = parentProvider.ParentProvider;
                } 
            }

            if (node.Equals(ownerProvider.GetRootNodeCore())) {
                throw new InvalidOperationException(SR.GetString(SR.SiteMapProvider_cannot_remove_root_node)); 
            }
 
            if (ownerProvider != this) { 
                // Remove node from the owner provider.
                ownerProvider.RemoveNode(node); 
            }

            base.RemoveNode(node);
        } 

        protected virtual void RemoveProvider(string providerName) { 
            if (providerName == null) { 
                throw new ArgumentNullException("providerName");
            } 

            lock (_lock) {
                SiteMapProvider provider = GetProviderFromName(providerName);
                SiteMapNode rootNode = (SiteMapNode)ChildProviderTable[provider]; 

                if (rootNode == null) { 
                    throw new InvalidOperationException(SR.GetString(SR.XmlSiteMapProvider_cannot_find_provider, provider.Name, this.Name)); 
                }
 
                provider.ParentProvider = null;
                ChildProviderTable.Remove(provider);
                _childProviderList = null;
 
                base.RemoveNode(rootNode);
            } 
        } 

        // VSWhidbey: 493981 Helper method to check if the valid resource type exists. 
        // Note that this only returns false if the classKey cannot be found, regardless of resourceKey.
        private bool ValidateResource(string classKey, string resourceKey) {
            try {
                HttpContext.GetGlobalResourceObject(classKey, resourceKey); 
            }
            catch (MissingManifestResourceException) { 
                return false; 
            }
 
            return true;
        }

        private class ReadOnlyNameValueCollection : NameValueCollection { 

            public ReadOnlyNameValueCollection() { 
                IsReadOnly = true; 
            }
 
            internal void SetReadOnly(bool isReadonly) {
                IsReadOnly = isReadonly;
            }
        } 
    }
} 

// 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