// Authors:
// Lluis Sanchez Gual (lluis@novell.com)
// Ben Maurer (bmaurer@users.sourceforge.net)
+// Juraj Skripsky (js@hotfeet.ch)
//
// (C) 2003 Ben Maurer
// (C) 2005 Novell, Inc (http://www.novell.com)
+// (C) 2007 HotFeet GmbH (http://www.hotfeet.ch)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-
-#if NET_2_0
-using System.Collections;
-using System.Collections.Specialized;
-using System.Text;
-using System.Configuration.Provider;
+using System.Collections.Generic;
using System.Web.Util;
-using System.Globalization;
namespace System.Web
{
public abstract class StaticSiteMapProvider : SiteMapProvider
{
- Hashtable nodeToParent;
- Hashtable nodeToChildren;
- Hashtable urlToNode;
- Hashtable keyToNode;
+ Dictionary<string, SiteMapNode> keyToNode;
+ Dictionary<SiteMapNode, SiteMapNode> nodeToParent;
+ Dictionary<SiteMapNode, SiteMapNodeCollection> nodeToChildren;
+ Dictionary<string, SiteMapNode> urlToNode;
+ protected StaticSiteMapProvider ()
+ {
+ keyToNode = new Dictionary<string, SiteMapNode> ();
+ nodeToParent = new Dictionary<SiteMapNode, SiteMapNode> ();
+ nodeToChildren = new Dictionary<SiteMapNode, SiteMapNodeCollection> ();
+ urlToNode = new Dictionary<string, SiteMapNode> (StringComparer.InvariantCultureIgnoreCase);
+ }
+
internal protected override void AddNode (SiteMapNode node, SiteMapNode parentNode)
{
if (node == null)
throw new ArgumentNullException ("node");
-
- lock (this) {
- string url = node.Url;
- if (url != null && url.Length > 0) {
- if (UrlUtils.IsRelativeUrl (url))
- url = UrlUtils.Combine (HttpRuntime.AppDomainAppVirtualPath, url);
- else
- url = UrlUtils.ResolveVirtualPathFromAppAbsolute (url);
-
- if (FindSiteMapNode (url) != null)
- throw new InvalidOperationException ();
-
- UrlToNode [url] = node;
- }
-
- if (FindSiteMapNodeFromKey (node.Key) != null)
- throw new InvalidOperationException (string.Format ("A node with key {0} already exists.",node.Key));
- KeyToNode [node.Key] = node;
-
- if (parentNode != null) {
- NodeToParent [node] = parentNode;
- if (NodeToChildren [parentNode] == null)
- NodeToChildren [parentNode] = new SiteMapNodeCollection ();
-
- ((SiteMapNodeCollection) NodeToChildren [parentNode]).Add (node);
- }
- }
- }
-
- Hashtable NodeToParent {
- get {
- lock (this) {
- if (nodeToParent == null)
- nodeToParent = new Hashtable ();
- }
- return nodeToParent;
- }
- }
-
- Hashtable NodeToChildren {
- get {
- lock (this) {
- if (nodeToChildren == null)
- nodeToChildren = new Hashtable ();
- }
- return nodeToChildren;
- }
- }
-
- Hashtable UrlToNode {
- get {
- lock (this) {
- if (urlToNode == null) {
- urlToNode = new Hashtable (
- CaseInsensitiveHashCodeProvider.DefaultInvariant,
- CaseInsensitiveComparer.DefaultInvariant
- );
- }
- }
- return urlToNode;
- }
- }
-
- Hashtable KeyToNode {
- get {
- lock (this) {
- if (keyToNode == null)
- keyToNode = new Hashtable ();
+
+ lock (this_lock) {
+ string nodeKey = node.Key;
+ if (FindSiteMapNodeFromKey (nodeKey) != null && node.Provider == this)
+ throw new InvalidOperationException (string.Format ("A node with key '{0}' already exists.",nodeKey));
+
+ string nodeUrl = node.Url;
+ if (!String.IsNullOrEmpty (nodeUrl)) {
+ string url = MapUrl (nodeUrl);
+ SiteMapNode foundNode = FindSiteMapNode (url);
+ if (foundNode != null && String.Compare (foundNode.Url, url, RuntimeHelpers.StringComparison) == 0)
+ throw new InvalidOperationException (String.Format (
+ "Multiple nodes with the same URL '{0}' were found. " +
+ "StaticSiteMapProvider requires that sitemap nodes have unique URLs.",
+ node.Url
+ ));
+
+ urlToNode.Add (url, node);
}
- return keyToNode;
+ keyToNode.Add (nodeKey, node);
+
+ if (node == RootNode)
+ return;
+
+ if (parentNode == null)
+ parentNode = RootNode;
+
+ nodeToParent.Add (node, parentNode);
+
+ SiteMapNodeCollection children;
+ if (!nodeToChildren.TryGetValue (parentNode, out children))
+ nodeToChildren.Add (parentNode, children = new SiteMapNodeCollection ());
+
+ children.Add (node);
}
}
protected virtual void Clear ()
{
- lock (this) {
- if (urlToNode != null)
- urlToNode.Clear ();
- if (nodeToChildren != null)
- nodeToChildren.Clear ();
- if (nodeToParent != null)
- nodeToParent.Clear ();
- if (keyToNode != null)
- keyToNode.Clear ();
+ lock (this_lock) {
+ urlToNode.Clear ();
+ nodeToChildren.Clear ();
+ nodeToParent.Clear ();
+ keyToNode.Clear ();
}
}
if (rawUrl == null)
throw new ArgumentNullException ("rawUrl");
- if (rawUrl.Length > 0) {
- this.BuildSiteMap();
- rawUrl = UrlUtils.ResolveVirtualPathFromAppAbsolute (rawUrl);
- SiteMapNode node = (SiteMapNode) UrlToNode [rawUrl];
- if (node != null && IsAccessibleToUser (HttpContext.Current, node))
- return node;
- }
- return null;
+ if (rawUrl == String.Empty)
+ return null;
+
+ BuildSiteMap();
+ SiteMapNode node;
+ if (VirtualPathUtility.IsAppRelative (rawUrl))
+ rawUrl = VirtualPathUtility.ToAbsolute (rawUrl, HttpRuntime.AppDomainAppVirtualPath, false);
+
+ if (!urlToNode.TryGetValue (rawUrl, out node))
+ return null;
+
+ return CheckAccessibility (node);
}
public override SiteMapNodeCollection GetChildNodes (SiteMapNode node)
if (node == null)
throw new ArgumentNullException ("node");
- this.BuildSiteMap();
- SiteMapNodeCollection col = (SiteMapNodeCollection) NodeToChildren [node];
- if (col == null) return SiteMapNodeCollection.EmptyCollection;
+ BuildSiteMap();
+ SiteMapNodeCollection col;
+ if (!nodeToChildren.TryGetValue (node, out col))
+ return SiteMapNodeCollection.EmptyCollection;
SiteMapNodeCollection ret = null;
for (int n=0; n<col.Count; n++) {
} else if (ret != null)
ret.Add (col[n]);
}
-
- if (ret != null) {
- if (ret.Count > 0)
- return SiteMapNodeCollection.ReadOnly (ret);
- } else
+
+ if (ret == null)
return SiteMapNodeCollection.ReadOnly (col);
-
- return null;
+ else if (ret.Count > 0)
+ return SiteMapNodeCollection.ReadOnly (ret);
+ else
+ return SiteMapNodeCollection.EmptyCollection;
}
public override SiteMapNode GetParentNode (SiteMapNode node)
{
if (node == null)
throw new ArgumentNullException ("node");
- this.BuildSiteMap();
- SiteMapNode parent = (SiteMapNode) NodeToParent [node];
- return parent != null && IsAccessibleToUser (HttpContext.Current, parent) ? parent : null;
+
+ BuildSiteMap();
+ SiteMapNode parent;
+ nodeToParent.TryGetValue (node, out parent);
+ return CheckAccessibility (parent);
}
- public override void RemoveNode (SiteMapNode node)
+ protected override void RemoveNode (SiteMapNode node)
{
if (node == null)
throw new ArgumentNullException("node");
+
+ string key = node.Key;
+ string url;
- lock (this) {
- SiteMapNode parent = (SiteMapNode) NodeToParent [node];
- if (NodeToParent.Contains (node))
- NodeToParent.Remove (node);
-
- if (node.Url != null && node.Url.Length > 0 && UrlToNode.Contains (node.Url))
- UrlToNode.Remove (node.Url);
+ lock (this_lock) {
+ if (keyToNode.ContainsKey (key))
+ keyToNode.Remove (key);
+ url = node.Url;
+ if (!String.IsNullOrEmpty (url)) {
+ url = MapUrl (url);
+ if (urlToNode.ContainsKey (url))
+ urlToNode.Remove (url);
+ }
- if (parent != null) {
- SiteMapNodeCollection siblings = (SiteMapNodeCollection) NodeToChildren [node];
- if (siblings != null && siblings.Contains (node))
- siblings.Remove (node);
+ if (node == RootNode)
+ return;
+
+ SiteMapNode parent;
+ if (nodeToParent.TryGetValue (node, out parent)) {
+ nodeToParent.Remove (node);
+
+ if (nodeToChildren.ContainsKey (parent))
+ nodeToChildren [parent].Remove (node);
}
}
}
if (key == null)
throw new ArgumentNullException ("key");
- SiteMapNode ret = (SiteMapNode) KeyToNode [key];
- return ret != null && IsAccessibleToUser (HttpContext.Current, ret) ? ret : null;
+ SiteMapNode ret;
+ keyToNode.TryGetValue (key, out ret);
+ return CheckAccessibility (ret);
}
public abstract SiteMapNode BuildSiteMap ();
+
+ SiteMapNode CheckAccessibility (SiteMapNode node) {
+ return (node != null && IsAccessibleToUser (HttpContext.Current, node)) ? node : null;
+ }
+
+ internal string MapUrl (string url)
+ {
+ if (String.IsNullOrEmpty (url))
+ return url;
+
+ string appVPath = HttpRuntime.AppDomainAppVirtualPath;
+ if (String.IsNullOrEmpty (appVPath))
+ appVPath = "/";
+
+ if (VirtualPathUtility.IsAppRelative (url))
+ return VirtualPathUtility.ToAbsolute (url, appVPath, true);
+ else
+ return VirtualPathUtility.ToAbsolute (UrlUtils.Combine (appVPath, url), appVPath, true);
+ }
}
}
-#endif
+