* roottypes.cs: Rename from tree.cs.
[mono.git] / mcs / class / System.Web / System.Web / SiteMapProvider.cs
1 //
2 // System.Web.SiteMapProvider
3 //
4 // Authors:
5 //      Ben Maurer (bmaurer@users.sourceforge.net)
6 //      Lluis Sanchez Gual (lluis@novell.com)
7 //
8 // (C) 2003 Ben Maurer
9 // (C) 2005 Novell, Inc (http://www.novell.com)
10 //
11
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 #if NET_2_0
34 using System.Collections;
35 using System.Collections.Specialized;
36 using System.Text;
37 using System.Configuration.Provider;
38 using System.Web.Util;
39 using System.Globalization;
40
41 namespace System.Web {
42         public abstract class SiteMapProvider : ProviderBase {
43                 
44                 bool enableLocalization;
45                 SiteMapProvider parentProvider;
46                 SiteMapProvider rootProviderCache;
47                 bool securityTrimming;
48                 object resolveLock = new Object();
49                 bool resolving;
50                 
51                 protected virtual void AddNode (SiteMapNode node)
52                 {
53                         AddNode (node, null);
54                 }
55                 
56                 internal protected virtual void AddNode (SiteMapNode node, SiteMapNode parentNode)
57                 {
58                         throw new NotImplementedException ();
59                 }
60
61                 public virtual SiteMapNode FindSiteMapNode (HttpContext context)
62                 {
63                         if (context == null)
64                                 return null;
65                         
66                         SiteMapNode ret = this.FindSiteMapNode (context.Request.RawUrl);
67                         if (ret == null)
68                                 ret = this.FindSiteMapNode (context.Request.Path);
69                         return ret;
70                 }
71
72                 public abstract SiteMapNode FindSiteMapNode (string rawUrl);
73                 
74                 public virtual SiteMapNode FindSiteMapNodeFromKey (string key)
75                 {
76                         /* msdn2 says this function always returns
77                          * null, but it seems to just call
78                          * FindSiteMapNode(string rawUrl) */
79                         return FindSiteMapNode (key);
80                 }
81
82                 public abstract SiteMapNodeCollection GetChildNodes (SiteMapNode node);
83                 
84                 public virtual SiteMapNode GetCurrentNodeAndHintAncestorNodes (int upLevel)
85                 {
86                         if (upLevel < -1) throw new ArgumentOutOfRangeException ("upLevel");
87
88                         return CurrentNode;
89                 }
90                 
91                 public virtual SiteMapNode GetCurrentNodeAndHintNeighborhoodNodes (int upLevel, int downLevel)
92                 {
93                         if (upLevel < -1) throw new ArgumentOutOfRangeException ("upLevel");
94                         if (downLevel < -1) throw new ArgumentOutOfRangeException ("downLevel");
95                         
96                         return CurrentNode;
97                 }
98
99                 public abstract SiteMapNode GetParentNode (SiteMapNode node);
100                 
101                 public virtual SiteMapNode GetParentNodeRelativeToCurrentNodeAndHintDownFromParent (int walkupLevels, int relativeDepthFromWalkup)
102                 {
103                         if (walkupLevels < 0) throw new ArgumentOutOfRangeException ("walkupLevels");
104                         if (relativeDepthFromWalkup < 0) throw new ArgumentOutOfRangeException ("relativeDepthFromWalkup");
105                         
106                         SiteMapNode node = GetCurrentNodeAndHintAncestorNodes (walkupLevels);
107                         for (int n=0; n<walkupLevels && node != null; n++)
108                                 node = GetParentNode (node);
109                                 
110                         if (node == null) return null;
111
112                         HintNeighborhoodNodes (node, 0, relativeDepthFromWalkup);
113                         return node;
114                 }
115                 
116                 public virtual SiteMapNode GetParentNodeRelativeToNodeAndHintDownFromParent (SiteMapNode node, int walkupLevels, int relativeDepthFromWalkup)
117                 {
118                         if (walkupLevels < 0) throw new ArgumentOutOfRangeException ("walkupLevels");
119                         if (relativeDepthFromWalkup < 0) throw new ArgumentOutOfRangeException ("relativeDepthFromWalkup");
120                         if (node == null) throw new ArgumentNullException ("node");
121                         
122                         HintAncestorNodes (node, walkupLevels);
123                         for (int n=0; n<walkupLevels && node != null; n++)
124                                 node = GetParentNode (node);
125                                 
126                         if (node == null) return null;
127                         
128                         HintNeighborhoodNodes (node, 0, relativeDepthFromWalkup);
129                         return node;
130                 }
131                 
132                 protected internal abstract SiteMapNode GetRootNodeCore ();
133                 
134                 protected static SiteMapNode GetRootNodeCoreFromProvider (SiteMapProvider provider)
135                 {
136                         return provider.GetRootNodeCore ();
137                 }
138                 
139                 public virtual void HintAncestorNodes (SiteMapNode node, int upLevel)
140                 {
141                         if (upLevel < -1) throw new ArgumentOutOfRangeException ("upLevel");
142                         if (node == null) throw new ArgumentNullException ("node");
143                 }
144                 
145                 public virtual void HintNeighborhoodNodes (SiteMapNode node, int upLevel, int downLevel)
146                 {
147                         if (upLevel < -1) throw new ArgumentOutOfRangeException ("upLevel");
148                         if (downLevel < -1) throw new ArgumentOutOfRangeException ("downLevel");
149                         if (node == null) throw new ArgumentNullException ("node");
150                 }
151                 
152                 protected virtual void RemoveNode (SiteMapNode node)
153                 {
154                         throw new NotImplementedException ();
155                 }
156
157                 public override void Initialize (string name, NameValueCollection attributes)
158                 {
159                         base.Initialize (name, attributes);
160                         if (attributes["securityTrimmingEnabled"] != null)
161                                 securityTrimming = (bool) Convert.ChangeType (attributes ["securityTrimmingEnabled"], typeof(bool));
162                 }
163                 
164                 [MonoTODO ("need to implement cases 2 and 3")]
165                 public virtual bool IsAccessibleToUser (HttpContext context, SiteMapNode node)
166                 {
167                         if (context == null) throw new ArgumentNullException ("context");
168                         if (node == null) throw new ArgumentNullException ("node");
169
170                         /* the node is accessible (according to msdn2)
171                          * if:
172                          *
173                          * 1. the current user is in the node's Roles.
174                          *
175                          * 2. the current thread's WindowsIdentity has
176                          * file access to the url. (and the url is
177                          * located within the current application).
178                          *
179                          * 3. the <authorization> configuration element
180                          * lists the current user as being authorized
181                          * for the node's url. (and the url is located
182                          * within the current application)
183                         */
184
185                         /* 1. */
186                         foreach (string rolename in node.Roles)
187                                 if (context.User.IsInRole (rolename))
188                                         return true;
189
190                         /* 2. */
191                         /* XXX */
192
193                         /* 3. */
194                         /* XXX */
195
196                         return true; // the default should be false.
197                 }
198                 
199                 public virtual SiteMapNode CurrentNode {
200                         get {
201                                 if (HttpContext.Current != null) {
202                                         SiteMapNode ret = ResolveSiteMapNode (HttpContext.Current);
203                                         if (ret != null) return ret;
204                                         return FindSiteMapNode (HttpContext.Current);
205                                 } else
206                                         return null;
207                         }
208                 }
209                 
210                 public virtual SiteMapProvider ParentProvider {
211                         get { return parentProvider; }
212                         set { parentProvider = value; }
213                 }
214                 
215                 public virtual SiteMapProvider RootProvider {
216                         get {
217                                 lock (this) {
218                                         if (rootProviderCache == null) {
219                                                 SiteMapProvider current = this;
220                                                 while (current.ParentProvider != null)
221                                                         current = current.ParentProvider;
222                                                 
223                                                 rootProviderCache = current;
224                                         }
225                                 }
226                                 return rootProviderCache;
227                         }
228                 }
229                 
230                 protected SiteMapNode ResolveSiteMapNode (HttpContext context)
231                 {
232                         SiteMapResolveEventArgs args = new SiteMapResolveEventArgs (context, this);
233                         if (SiteMapResolve != null) {
234                                 lock (resolveLock) {
235                                         if (resolving) return null;
236                                         resolving = true;
237                                         SiteMapNode r = SiteMapResolve (this, args);
238                                         resolving = false;
239                                         return r;
240                                 }
241                         }
242                         else
243                                 return null;
244                 }
245                 
246                 public bool EnableLocalization {
247                         get { return enableLocalization; }
248                         set { enableLocalization = value; }
249                 }
250                 
251                 public bool SecurityTrimmingEnabled {
252                         get { return securityTrimming; }
253                 }
254
255                 string resourceKey;
256                 public string ResourceKey {
257                         get { return resourceKey; }
258                         set { resourceKey = value; }
259                 }
260
261                 public virtual SiteMapNode RootNode {
262                         get {
263                                 SiteMapNode node = GetRootNodeCore ();
264                                 return ReturnNodeIfAccessible (node);
265                         }
266                 }
267
268                 public event SiteMapResolveEventHandler SiteMapResolve;
269
270                 internal static SiteMapNode ReturnNodeIfAccessible (SiteMapNode node)
271                 {
272                         if (node.IsAccessibleToUser (HttpContext.Current))
273                                 return node;
274                         else
275                                 throw new InvalidOperationException (); /* need
276                                                                          * a
277                                                                          * message
278                                                                          * here */
279                 }
280         }
281 }
282 #endif
283