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