New test.
[mono.git] / mcs / class / System.Web / System.Web / XmlSiteMapProvider.cs
1 //
2 // System.Web.XmlSiteMapProvider
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.Configuration;
37 using System.Text;
38 using System.Xml;
39 using System.Web.Util;
40 using System.IO;
41
42 namespace System.Web
43 {
44         public class XmlSiteMapProvider : StaticSiteMapProvider, IDisposable
45         {
46                 static readonly char [] seperators = { ';', ',' };
47                 bool building;
48                 string file;
49                 SiteMapNode root = null;
50 #if !TARGET_JVM // Java platform does not support file notifications
51                 FileSystemWatcher watcher;
52 #endif
53
54                 [MonoTODO]
55                 protected internal override void AddNode (SiteMapNode node, SiteMapNode parentNode)
56                 {
57                         base.AddNode (node, parentNode);
58                 }
59
60                 protected virtual void AddProvider (string providerName, SiteMapNode parentNode)
61                 {
62                         throw new NotImplementedException ();
63                 }
64
65                 public override SiteMapNode BuildSiteMap ()
66                 {
67                         if (root != null)
68                                 return root;
69                         // Whenever you call AddNode, it tries to find dups, and will call this method
70                         // Is this a bug in MS??
71                         if (building)
72                                 return null;
73                         
74                         lock (this) {
75                                 try {
76                                         building = true;
77                                         if (root != null)
78                                                 return root;
79                                         XmlDocument d = new XmlDocument ();
80                                         d.Load (file);
81                                         
82                                         XmlNode nod = d.DocumentElement ["siteMapNode"];
83                                         if (nod == null)
84                                                 throw new HttpException ("Invalid site map file: " + Path.GetFileName (file));
85                                                 
86                                         root = BuildSiteMapRecursive (nod);
87                                                 
88                                         AddNode (root);
89                                 } finally {
90                                         building = false;
91                                 }
92                                 return root;
93                         }
94                 }
95                 
96                 string GetNonEmptyOptionalAttribute (XmlNode n, string name)
97                 {
98                         return System.Web.Configuration.HandlersUtil.ExtractAttributeValue (name, n, true);
99                 }
100                 
101                 string GetOptionalAttribute (XmlNode n, string name)
102                 {
103                         return System.Web.Configuration.HandlersUtil.ExtractAttributeValue (name, n, true, true);
104                 }
105                 
106                 [MonoTODO]
107                 SiteMapNode BuildSiteMapRecursive (XmlNode xmlNode)
108                 {
109                         if (xmlNode.Name != "siteMapNode")
110                                 throw new ConfigurationException ("incorrect element name", xmlNode);
111                         
112                         string provider = GetNonEmptyOptionalAttribute (xmlNode, "provider");
113                         string siteMapFile = GetNonEmptyOptionalAttribute (xmlNode, "siteMapFile");
114                         
115                         if (provider != null) {
116                                 throw new NotImplementedException ();
117                         } else if (siteMapFile != null) {
118                                 throw new NotImplementedException ();
119                         } else {
120
121                                 string url = GetOptionalAttribute (xmlNode, "url");
122                                 string title = GetOptionalAttribute (xmlNode, "title");
123                                 string description = GetOptionalAttribute (xmlNode, "description");
124                                 string keywords = GetOptionalAttribute (xmlNode, "keywords");
125                                 string roles = GetOptionalAttribute (xmlNode, "roles");
126                                 
127                                 ArrayList keywordsList = new ArrayList ();
128                                 if (keywords != null && keywords.Length > 0) {
129                                         foreach (string s in keywords.Split (seperators)) {
130                                                 string ss = s.Trim ();
131                                                 if (ss.Length > 0)
132                                                         keywordsList.Add (ss);
133                                         }
134                                 }
135                                 
136                                 ArrayList rolesList = new ArrayList ();
137                                 if (roles != null && roles.Length > 0) {
138                                         foreach (string s in roles.Split (seperators)) {
139                                                 string ss = s.Trim ();
140                                                 if (ss.Length > 0)
141                                                         rolesList.Add (ss);
142                                         }
143                                 }
144
145                                 if (!string.IsNullOrEmpty (url)) {
146                                         if (UrlUtils.IsRelativeUrl (url))
147                                                 url = UrlUtils.Combine (HttpRuntime.AppDomainAppVirtualPath, url);
148                                 }
149                                 
150                                 SiteMapNode node = new SiteMapNode (this, url, url, title, description,
151                                         /*ArrayList.ReadOnly (keywordsList), */ArrayList.ReadOnly (rolesList), null,
152                                         null, null); // TODO what do they want for attributes
153                                         
154                                 foreach (XmlNode child in xmlNode.ChildNodes) {
155                                         if (child.NodeType != XmlNodeType.Element)
156                                                 continue;
157                                         AddNode (BuildSiteMapRecursive (child), node);
158                                 }
159                                 
160                                 return node;
161                         }
162                 }
163
164                 protected override void Clear ()
165                 {
166                         base.Clear ();
167                         root = null;
168                 }
169
170                 protected virtual void Dispose (bool disposing)
171                 {
172 #if !TARGET_JVM // Java platform does not support file notifications
173                         if (disposing)
174                                 watcher.Dispose ();
175 #endif
176                 }
177
178                 public void Dispose ()
179                 {
180                         Dispose (true);
181                 }
182                 
183                 [MonoTODO]
184                 public override SiteMapNode FindSiteMapNode (string rawUrl)
185                 {
186                         return base.FindSiteMapNode (rawUrl); // why did they override this method!?
187                 }
188
189                 [MonoTODO]
190                 public override SiteMapNode FindSiteMapNodeFromKey (string key)
191                 {
192                         return base.FindSiteMapNodeFromKey (key); // why did they override this method!?
193                 }
194
195                 public override void Initialize (string name, NameValueCollection attributes)
196                 {
197
198                         base.Initialize (name, attributes);
199                         file = attributes ["siteMapFile"];
200
201                         if (file == null && file.Length == 0)
202                                 throw new ArgumentException ("you must provide a file");
203                         
204                         if (UrlUtils.IsRelativeUrl (file))
205                                 file = Path.Combine(HttpRuntime.AppDomainAppPath, file);
206                         else
207                                 file = UrlUtils.ResolvePhysicalPathFromAppAbsolute (file);
208
209 #if !TARGET_JVM // Java platform does not support file notifications
210                         if (File.Exists (file)) {
211                                 watcher = new FileSystemWatcher ();
212                                 watcher.Path = Path.GetFullPath (Path.GetDirectoryName (file));
213                                 watcher.Filter = Path.GetFileName (file);
214                                 watcher.Changed += new FileSystemEventHandler (OnFileChanged);
215                                 watcher.EnableRaisingEvents = true;
216                         }
217 #endif
218                 }
219
220                 [MonoTODO]
221                 protected override void RemoveNode (SiteMapNode node)
222                 {
223                         base.RemoveNode (node);
224                 }
225
226                 [MonoTODO]
227                 protected virtual void RemoveProvider (string providerName)
228                 {
229                         throw new NotImplementedException ();
230                 }
231 #if !TARGET_JVM
232                 void OnFileChanged (object sender, FileSystemEventArgs args)
233                 {
234                         Clear ();
235                 }
236 #endif
237                 public override SiteMapNode RootNode {
238                         get {
239                                 BuildSiteMap ();
240                                 return root;
241                         }
242                 }
243                 
244                 protected internal override SiteMapNode GetRootNodeCore ()
245                 {
246                         return BuildSiteMap ();
247                 }
248         }
249
250 }
251 #endif
252