[asp.net] Do not duplicate assembly references passed to mcs
[mono.git] / mcs / class / System.Web / System.Web / StaticSiteMapProvider.cs
1 //
2 // System.Web.StaticSiteMapProvider.cs
3 //
4 // Authors:
5 //      Lluis Sanchez Gual (lluis@novell.com)
6 //      Ben Maurer (bmaurer@users.sourceforge.net)
7 //      Juraj Skripsky (js@hotfeet.ch)
8 //
9 // (C) 2003 Ben Maurer
10 // (C) 2005 Novell, Inc (http://www.novell.com)
11 // (C) 2007 HotFeet GmbH (http://www.hotfeet.ch)
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using System.Collections.Generic;
34 using System.Web.Util;
35
36 namespace System.Web
37 {
38         public abstract class StaticSiteMapProvider : SiteMapProvider
39         {
40                 Dictionary<string, SiteMapNode> keyToNode;
41                 Dictionary<SiteMapNode, SiteMapNode> nodeToParent;
42                 Dictionary<SiteMapNode, SiteMapNodeCollection> nodeToChildren;
43                 Dictionary<string, SiteMapNode> urlToNode;
44                 
45                 protected StaticSiteMapProvider ()
46                 {
47                         keyToNode = new Dictionary<string, SiteMapNode> ();
48                         nodeToParent = new Dictionary<SiteMapNode, SiteMapNode> ();
49                         nodeToChildren = new Dictionary<SiteMapNode, SiteMapNodeCollection> ();
50                         urlToNode = new Dictionary<string, SiteMapNode> (StringComparer.InvariantCultureIgnoreCase);
51                 }
52
53                 internal protected override void AddNode (SiteMapNode node, SiteMapNode parentNode)
54                 {
55                         if (node == null)
56                                 throw new ArgumentNullException ("node");
57
58                         lock (this_lock) {
59                                 string nodeKey = node.Key;
60                                 if (FindSiteMapNodeFromKey (nodeKey) != null && node.Provider == this)
61                                         throw new InvalidOperationException (string.Format ("A node with key '{0}' already exists.",nodeKey));
62
63                                 string nodeUrl = node.Url;
64                                 if (!String.IsNullOrEmpty (nodeUrl)) {
65                                         string url = MapUrl (nodeUrl);
66                                         SiteMapNode foundNode = FindSiteMapNode (url);
67                                         if (foundNode != null && String.Compare (foundNode.Url, url, RuntimeHelpers.StringComparison) == 0)
68                                                 throw new InvalidOperationException (String.Format (
69                                                         "Multiple nodes with the same URL '{0}' were found. " + 
70                                                         "StaticSiteMapProvider requires that sitemap nodes have unique URLs.",
71                                                         node.Url
72                                                 ));
73
74                                         urlToNode.Add (url, node);
75                                 }
76                                 keyToNode.Add (nodeKey, node);
77
78                                 if (node == RootNode)
79                                         return;
80
81                                 if (parentNode == null)
82                                         parentNode = RootNode;
83
84                                 nodeToParent.Add (node, parentNode);
85
86                                 SiteMapNodeCollection children;
87                                 if (!nodeToChildren.TryGetValue (parentNode, out children)) 
88                                         nodeToChildren.Add (parentNode, children = new SiteMapNodeCollection ());
89
90                                 children.Add (node);
91                         }
92                 }
93                 
94                 protected virtual void Clear ()
95                 {
96                         lock (this_lock) {
97                                 urlToNode.Clear ();
98                                 nodeToChildren.Clear ();
99                                 nodeToParent.Clear ();
100                                 keyToNode.Clear ();
101                         }
102                 }
103
104                 public override SiteMapNode FindSiteMapNode (string rawUrl)
105                 {
106                         if (rawUrl == null)
107                                 throw new ArgumentNullException ("rawUrl");
108                         
109                         if (rawUrl == String.Empty)
110                                 return null;                    
111                         
112                         BuildSiteMap();
113                         SiteMapNode node;
114                         if (VirtualPathUtility.IsAppRelative (rawUrl))
115                                 rawUrl = VirtualPathUtility.ToAbsolute (rawUrl, HttpRuntime.AppDomainAppVirtualPath, false);
116
117                         if (!urlToNode.TryGetValue (rawUrl, out node))
118                                 return null;
119
120                         return CheckAccessibility (node);
121                 }
122
123                 public override SiteMapNodeCollection GetChildNodes (SiteMapNode node)
124                 {
125                         if (node == null)
126                                 throw new ArgumentNullException ("node");
127                         
128                         BuildSiteMap();
129                         SiteMapNodeCollection col;
130                         if (!nodeToChildren.TryGetValue (node, out col))
131                                 return SiteMapNodeCollection.EmptyCollection;
132                         
133                         SiteMapNodeCollection ret = null;
134                         for (int n=0; n<col.Count; n++) {
135                                 if (!IsAccessibleToUser (HttpContext.Current, col[n])) {
136                                         if (ret == null) {
137                                                 ret = new SiteMapNodeCollection ();
138                                                 for (int m=0; m<n; m++)
139                                                         ret.Add (col[m]);
140                                         }
141                                 } else if (ret != null)
142                                         ret.Add (col[n]);
143                         }
144
145                         if (ret == null)
146                                 return SiteMapNodeCollection.ReadOnly (col);
147                         else if (ret.Count > 0)
148                                 return SiteMapNodeCollection.ReadOnly (ret);
149                         else
150                                 return SiteMapNodeCollection.EmptyCollection;
151                 }
152                 
153                 public override SiteMapNode GetParentNode (SiteMapNode node)
154                 {
155                         if (node == null)
156                                 throw new ArgumentNullException ("node");
157
158                         BuildSiteMap();
159                         SiteMapNode parent;
160                         nodeToParent.TryGetValue (node, out parent);
161                         return CheckAccessibility (parent);
162                 }
163                 
164                 protected override void RemoveNode (SiteMapNode node)
165                 {
166                         if (node == null)
167                                 throw new ArgumentNullException("node");
168
169                         string key = node.Key;
170                         string url;
171                         
172                         lock (this_lock) {
173                                 if (keyToNode.ContainsKey (key))
174                                         keyToNode.Remove (key);
175                                 url = node.Url;
176                                 if (!String.IsNullOrEmpty (url)) {
177                                         url = MapUrl (url);
178                                         if (urlToNode.ContainsKey (url))
179                                                 urlToNode.Remove (url);
180                                 }
181                                 
182                                 if (node == RootNode)
183                                         return;
184
185                                 SiteMapNode parent;
186                                 if (nodeToParent.TryGetValue (node, out parent)) {
187                                         nodeToParent.Remove (node);
188
189                                         if (nodeToChildren.ContainsKey (parent))
190                                                 nodeToChildren [parent].Remove (node);
191                                 }
192                         }
193                 }
194                 
195                 public override SiteMapNode FindSiteMapNodeFromKey (string key)
196                 {
197                         if (key == null)
198                                 throw new ArgumentNullException ("key");
199                         
200                         SiteMapNode ret;
201                         keyToNode.TryGetValue (key, out ret);
202                         return CheckAccessibility (ret);
203                 }
204
205                 public abstract SiteMapNode BuildSiteMap ();
206                 
207                 SiteMapNode CheckAccessibility (SiteMapNode node) {
208                         return (node != null && IsAccessibleToUser (HttpContext.Current, node)) ? node : null;
209                 }
210
211                 internal string MapUrl (string url)
212                 {
213                         if (String.IsNullOrEmpty (url))
214                                 return url;
215
216                         string appVPath = HttpRuntime.AppDomainAppVirtualPath;
217                         if (String.IsNullOrEmpty (appVPath))
218                                 appVPath = "/";
219                         
220                         if (VirtualPathUtility.IsAppRelative (url))
221                                 return VirtualPathUtility.ToAbsolute (url, appVPath, true);
222                         else
223                                 return VirtualPathUtility.ToAbsolute (UrlUtils.Combine (appVPath, url), appVPath, true);
224                 }
225         }
226 }
227
228