2008-03-13 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / XmlDataSource.cs
1 //
2 // System.Web.UI.WebControls.XmlDataSource
3 //
4 // Authors:
5 //      Ben Maurer (bmaurer@users.sourceforge.net)
6 //      Chris Toshok (toshok@ximian.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.Xml;
38 using System.Xml.Xsl;
39 using System.ComponentModel;
40 using System.IO;
41 using System.Web.Caching;
42 using System.Security.Permissions;
43
44 namespace System.Web.UI.WebControls {
45
46         // CAS
47         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
48         [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
49         // attributes
50         [DesignerAttribute ("System.Web.UI.Design.WebControls.XmlDataSourceDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
51         [DefaultProperty ("DataFile")]
52         [DefaultEvent ("Transforming")]
53         [ParseChildren (true)]
54         [PersistChildren (false)]
55         [WebSysDescription ("Connect to an XML file.")]
56 //      [WebSysDisplayName ("XML file")]
57         public class XmlDataSource : HierarchicalDataSourceControl, IDataSource, IListSource {
58
59                 private string _data = string.Empty;
60                 private string _transform = string.Empty;
61                 private string _xpath = string.Empty;
62                 private string _dataFile = string.Empty;
63                 private string _transformFile = string.Empty;
64                 private string _cacheKeyDependency = string.Empty;
65                 private bool _enableCaching = true;
66                 private int _cacheDuration = 0;
67                 private DataSourceCacheExpiry _cacheExpirationPolicy = DataSourceCacheExpiry.Absolute;
68                 static readonly string [] emptyNames = new string [] { "DefaultView" };
69                 
70                 event EventHandler IDataSource.DataSourceChanged {
71                         add { ((IHierarchicalDataSource)this).DataSourceChanged += value; }
72                         remove { ((IHierarchicalDataSource)this).DataSourceChanged -= value; }
73                 }
74                 
75                 static object EventTransforming = new object ();
76                 public event EventHandler Transforming {
77                         add { Events.AddHandler (EventTransforming, value); }
78                         remove { Events.RemoveHandler (EventTransforming, value); }
79                 }
80                 
81                 protected virtual void OnTransforming (EventArgs e)
82                 {
83                         EventHandler eh = Events [EventTransforming] as EventHandler;
84                         if (eh != null)
85                                 eh (this, e);
86                 }
87                 
88                 XmlDocument xmlDocument;
89                 public XmlDocument GetXmlDocument ()
90                 {
91                         if (xmlDocument == null && EnableCaching)
92                                 xmlDocument = GetXmlDocumentFromCache ();
93
94                         if (xmlDocument == null) {
95                                 xmlDocument = LoadXmlDocument ();
96                                 UpdateCache ();
97                         }
98
99                         return xmlDocument;
100                 }
101
102                 [MonoTODO ("schema")]
103                 XmlDocument LoadXmlDocument ()
104                 {
105                         XmlDocument document = LoadFileOrData (DataFile, Data);
106
107                         if (TransformFile == "" && Transform == "")
108                                 return document;
109
110                         XslTransform xslTransform = new XslTransform ();
111                         XmlDocument xsl = LoadFileOrData (TransformFile, Transform);
112                         xslTransform.Load (xsl);
113
114                         OnTransforming (EventArgs.Empty);
115
116                         XmlDocument transofrResult = new XmlDocument ();
117                         transofrResult.Load (xslTransform.Transform (document, TransformArgumentList));
118
119                         return transofrResult;
120                 }
121
122                 XmlDocument LoadFileOrData (string filename, string data)
123                 {
124                         XmlDocument document = new XmlDocument ();
125                         if (filename != "")
126                                 document.Load (MapPathSecure (filename));
127                         else
128                                 document.LoadXml (data);
129
130                         return document;
131                 }
132
133                 XmlDocument GetXmlDocumentFromCache ()
134                 {
135                         if (DataCache != null)
136                                 return (XmlDocument) DataCache [GetDataKey ()];
137
138                         return null;
139                 }
140
141                 string GetDataKey ()
142                 {
143                         return TemplateSourceDirectory + "_" + Page.ToString () + "_" + ID;
144                 }
145
146                 Cache DataCache
147                 {
148                         get
149                         {
150                                 if (HttpContext.Current != null)
151                                         return HttpContext.Current.InternalCache;
152
153                                 return null;
154                         }
155                 }
156
157                 void UpdateCache ()
158                 {
159                         if (!EnableCaching)
160                                 return;
161
162                         if (DataCache == null)
163                                 return;
164
165                         if (DataCache [GetDataKey ()] != null)
166                                 DataCache.Remove (GetDataKey ());
167
168                         DateTime absoluteExpiration = Cache.NoAbsoluteExpiration;
169                         TimeSpan slidindExpiraion = Cache.NoSlidingExpiration;
170
171                         if (CacheDuration > 0) {
172                                 if (CacheExpirationPolicy == DataSourceCacheExpiry.Absolute)
173                                         absoluteExpiration = DateTime.Now.AddSeconds (CacheDuration);
174                                 else
175                                         slidindExpiraion = new TimeSpan (CacheDuration * 10000);
176                         }
177
178                         CacheDependency dependency = null;
179                         if (CacheKeyDependency.Length > 0)
180                                 dependency = new CacheDependency (new string [] { }, new string [] { CacheKeyDependency });
181                         else
182                                 dependency = new CacheDependency (new string [] { }, new string [] { });
183
184                         DataCache.Add (GetDataKey (), xmlDocument, dependency,
185                                 absoluteExpiration, slidindExpiraion, CacheItemPriority.Default, null);
186                 }
187
188                 public void Save ()
189                 {
190                         if (!CanBeSaved)
191                                 throw new InvalidOperationException ();
192                         
193                         xmlDocument.Save (MapPathSecure (DataFile));
194                 }
195                 
196                 bool CanBeSaved {
197                         get {
198                                 return Transform == "" && TransformFile == "" && DataFile != "";
199                         }
200                 }
201                 
202                 protected override HierarchicalDataSourceView GetHierarchicalView (string viewPath)
203                 {
204                         XmlNode doc = this.GetXmlDocument ();
205                         XmlNodeList ret = null;
206                         
207                         if (viewPath != "") {
208                                 XmlNode n = doc.SelectSingleNode (viewPath);
209                                 if (n != null)
210                                         ret = n.ChildNodes;
211                         } else if (XPath != "") {
212                                 ret = doc.SelectNodes (XPath);
213                         } else {
214                                 ret = doc.ChildNodes;
215                         }
216                         
217                         return new XmlHierarchicalDataSourceView (ret);
218                 }
219                 
220                 IList IListSource.GetList ()
221                 {
222                         return ListSourceHelper.GetList (this);
223                 }
224                 
225                 bool IListSource.ContainsListCollection {
226                         get { return ListSourceHelper.ContainsListCollection (this); }
227                 }
228                 
229                 DataSourceView IDataSource.GetView (string viewName)
230                 {
231                         if (viewName == "")
232                                 viewName = "DefaultView";
233                         
234                         return new XmlDataSourceView (this, viewName);
235                 }
236                 
237                 ICollection IDataSource.GetViewNames ()
238                 {
239                         return emptyNames;
240                 }
241                 
242                 [DefaultValue (0)]
243                 //[TypeConverter (typeof(DataSourceCacheDurationConverter))]
244                 public virtual int CacheDuration {
245                         get {
246                                 return _cacheDuration;
247                         }
248                         set {
249                                 _cacheDuration = value;
250                         }
251                 }
252
253                 [DefaultValue (DataSourceCacheExpiry.Absolute)]
254                 public virtual DataSourceCacheExpiry CacheExpirationPolicy {
255                         get {
256                                 return _cacheExpirationPolicy;
257                         }
258                         set {
259                                 _cacheExpirationPolicy = value;
260                         }
261                 }
262
263                 [DefaultValue ("")]
264                 public virtual string CacheKeyDependency {
265                         get {
266                                 return _cacheKeyDependency;
267                         }
268                         set {
269                                 _cacheKeyDependency = value;
270                         }
271                 }
272
273                 [DefaultValue (true)]
274                 public virtual bool EnableCaching {
275                         get {
276                                 return _enableCaching;
277                         }
278                         set {
279                                 _enableCaching = value;
280                         }
281                 }
282
283                 [DefaultValue ("")]
284                 [PersistenceMode (PersistenceMode.InnerProperty)]
285                 [WebSysDescription ("Inline XML data.")]
286                 [WebCategory ("Data")]
287                 [EditorAttribute ("System.ComponentModel.Design.MultilineStringEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
288 //              [TypeConverter (typeof(MultilineStringConverter))]
289                 public virtual string Data {
290                         get { return _data; }
291                         set {
292                                 if (_data != value) {
293                                         _data = value;
294                                         xmlDocument = null;
295                                         OnDataSourceChanged(EventArgs.Empty);
296                                 }
297                         }
298                 }
299                 
300                 [DefaultValueAttribute ("")]
301                 [EditorAttribute ("System.Web.UI.Design.XmlDataFileEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
302                 [MonoLimitation ("Absolute path to the file system is not supported; use a relative URI instead.")]
303                 public virtual string DataFile {
304                         get { return _dataFile; }
305                         set {
306                                 if (_dataFile != value) {
307                                         _dataFile = value;
308                                         xmlDocument = null;
309                                         OnDataSourceChanged(EventArgs.Empty);
310                                 }
311                         }
312                 }
313                 
314                 XsltArgumentList transformArgumentList;
315                 
316                 [BrowsableAttribute (false)]
317                 public virtual XsltArgumentList TransformArgumentList {
318                         get { return transformArgumentList; }
319                         set { transformArgumentList = value; }
320                 }
321                 
322                 [PersistenceModeAttribute (PersistenceMode.InnerProperty)]
323                 [EditorAttribute ("System.ComponentModel.Design.MultilineStringEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
324                 [DefaultValueAttribute ("")]
325 //              [TypeConverterAttribute (typeof(System.ComponentModel.MultilineStringConverter))]
326                 public virtual string Transform {
327                         get { return _transform; }
328                         set {
329                                 if (_transform != value) {
330                                         _transform = value;
331                                         xmlDocument = null;
332                                         OnDataSourceChanged(EventArgs.Empty);
333                                 }
334                         }
335                 }
336                 
337                 [EditorAttribute ("System.Web.UI.Design.XslTransformFileEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
338                 [DefaultValueAttribute ("")]
339                 [MonoLimitation ("Absolute path to the file system is not supported; use a relative URI instead.")]
340                 public virtual string TransformFile {
341                         get { return _transformFile; }
342                         set {
343                                 if (_transformFile != value) {
344                                         _transformFile = value;
345                                         xmlDocument = null;
346                                         OnDataSourceChanged(EventArgs.Empty);
347                                 }
348                         }
349                 }
350                 
351                 [DefaultValueAttribute ("")]
352                 public virtual string XPath {
353                         get { return _xpath; }
354                         set {
355                                 if (_xpath != value) {
356                                         _xpath = value;
357                                         OnDataSourceChanged(EventArgs.Empty);
358                                 }
359                         }
360                 }
361         }
362 }
363 #endif
364