2 // System.Web.UI.WebControls.XmlDataSource
5 // Ben Maurer (bmaurer@users.sourceforge.net)
6 // Chris Toshok (toshok@ximian.com)
9 // (C) 2005 Novell, Inc (http://www.novell.com)
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:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
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.
33 using System.Collections;
34 using System.Collections.Specialized;
39 using System.ComponentModel;
41 using System.Web.Caching;
42 using System.Security.Permissions;
44 namespace System.Web.UI.WebControls {
47 [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
48 [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
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")]
58 public class XmlDataSource : HierarchicalDataSourceControl, IDataSource, IListSource {
60 string _data = string.Empty;
61 string _transform = string.Empty;
62 string _xpath = string.Empty;
63 string _dataFile = string.Empty;
64 string _transformFile = string.Empty;
65 string _cacheKeyDependency = string.Empty;
66 bool _enableCaching = true;
67 int _cacheDuration = 0;
68 bool _documentNeedsUpdate;
70 DataSourceCacheExpiry _cacheExpirationPolicy = DataSourceCacheExpiry.Absolute;
71 static readonly string [] emptyNames = new string [] { "DefaultView" };
73 event EventHandler IDataSource.DataSourceChanged {
74 add { ((IHierarchicalDataSource)this).DataSourceChanged += value; }
75 remove { ((IHierarchicalDataSource)this).DataSourceChanged -= value; }
78 static object EventTransforming = new object ();
79 public event EventHandler Transforming {
80 add { Events.AddHandler (EventTransforming, value); }
81 remove { Events.RemoveHandler (EventTransforming, value); }
84 protected virtual void OnTransforming (EventArgs e)
86 EventHandler eh = Events [EventTransforming] as EventHandler;
91 XmlDocument xmlDocument;
92 public XmlDocument GetXmlDocument ()
94 if (_documentNeedsUpdate)
97 if (xmlDocument == null && EnableCaching)
98 xmlDocument = GetXmlDocumentFromCache ();
100 if (xmlDocument == null) {
101 xmlDocument = LoadXmlDocument ();
108 [MonoTODO ("schema")]
109 XmlDocument LoadXmlDocument ()
111 XmlDocument document = LoadFileOrData (DataFile, Data);
112 if (String.IsNullOrEmpty (TransformFile) && String.IsNullOrEmpty (Transform))
115 XslTransform xslTransform = new XslTransform ();
116 XmlDocument xsl = LoadFileOrData (TransformFile, Transform);
117 xslTransform.Load (xsl);
119 OnTransforming (EventArgs.Empty);
121 XmlDocument transofrResult = new XmlDocument ();
122 transofrResult.Load (xslTransform.Transform (document, TransformArgumentList));
124 return transofrResult;
127 XmlDocument LoadFileOrData (string filename, string data)
129 XmlDocument document = new XmlDocument ();
130 if (!String.IsNullOrEmpty (filename)) {
132 if (Uri.TryCreate (filename, UriKind.Absolute, out uri))
133 document.Load (filename);
135 document.Load (MapPathSecure (filename));
137 if (!String.IsNullOrEmpty (data))
138 document.LoadXml (data);
142 XmlDocument GetXmlDocumentFromCache ()
144 if (DataCache != null)
145 return (XmlDocument) DataCache [GetDataKey ()];
152 if (String.IsNullOrEmpty (DataFile) && !String.IsNullOrEmpty (Data)) {
153 string key = CacheKeyContext;
154 if (!String.IsNullOrEmpty (key))
158 string p = page != null ? page.ToString () : "NullPage";
160 return TemplateSourceDirectory + "_" + p + "_" + ID;
167 if (HttpContext.Current != null)
168 return HttpContext.Current.InternalCache;
179 if (DataCache == null)
182 string dataKey = GetDataKey ();
183 if (DataCache [dataKey] != null)
184 DataCache.Remove (dataKey);
186 DateTime absoluteExpiration = Cache.NoAbsoluteExpiration;
187 TimeSpan slidindExpiraion = Cache.NoSlidingExpiration;
189 if (CacheDuration > 0) {
190 if (CacheExpirationPolicy == DataSourceCacheExpiry.Absolute)
191 absoluteExpiration = DateTime.Now.AddSeconds (CacheDuration);
193 slidindExpiraion = new TimeSpan (CacheDuration * 10000L);
196 CacheDependency dependency = null;
197 if (CacheKeyDependency.Length > 0)
198 dependency = new CacheDependency (new string [] { }, new string [] { CacheKeyDependency });
200 dependency = new CacheDependency (new string [] { }, new string [] { });
202 DataCache.Add (dataKey, xmlDocument, dependency,
203 absoluteExpiration, slidindExpiraion, CacheItemPriority.Default, null);
206 // If datafile changed, then DO NOT USE the cached data, but update it.
209 xmlDocument = LoadXmlDocument ();
211 _documentNeedsUpdate = false;
217 throw new InvalidOperationException ();
219 if (xmlDocument != null)
220 xmlDocument.Save (MapPathSecure (DataFile));
225 return Transform == String.Empty && TransformFile == String.Empty && DataFile != String.Empty;
229 protected override HierarchicalDataSourceView GetHierarchicalView (string viewPath)
231 XmlNode doc = this.GetXmlDocument ();
232 XmlNodeList ret = null;
234 if (!String.IsNullOrEmpty (viewPath)) {
235 XmlNode n = doc.SelectSingleNode (viewPath);
238 } else if (!String.IsNullOrEmpty (XPath)) {
239 ret = doc.SelectNodes (XPath);
241 ret = doc.ChildNodes;
244 return new XmlHierarchicalDataSourceView (ret);
247 IList IListSource.GetList ()
249 return ListSourceHelper.GetList (this);
252 bool IListSource.ContainsListCollection {
253 get { return ListSourceHelper.ContainsListCollection (this); }
256 DataSourceView IDataSource.GetView (string viewName)
258 if (String.IsNullOrEmpty (viewName))
259 viewName = "DefaultView";
261 return new XmlDataSourceView (this, viewName);
264 ICollection IDataSource.GetViewNames ()
270 [TypeConverter (typeof(DataSourceCacheDurationConverter))]
271 public virtual int CacheDuration {
273 return _cacheDuration;
276 _cacheDuration = value;
280 [DefaultValue (DataSourceCacheExpiry.Absolute)]
281 public virtual DataSourceCacheExpiry CacheExpirationPolicy {
283 return _cacheExpirationPolicy;
286 _cacheExpirationPolicy = value;
291 public virtual string CacheKeyDependency {
293 return _cacheKeyDependency;
296 _cacheKeyDependency = value;
300 [DefaultValue (true)]
301 public virtual bool EnableCaching {
303 return _enableCaching;
306 _enableCaching = value;
311 [PersistenceMode (PersistenceMode.InnerProperty)]
312 [WebSysDescription ("Inline XML data.")]
313 [WebCategory ("Data")]
314 [EditorAttribute ("System.ComponentModel.Design.MultilineStringEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
315 [TypeConverter (typeof(MultilineStringConverter))]
316 public virtual string Data {
317 get { return _data; }
319 if (_data != value) {
321 _documentNeedsUpdate = true;
322 OnDataSourceChanged(EventArgs.Empty);
327 [DefaultValueAttribute ("")]
328 [EditorAttribute ("System.Web.UI.Design.XmlDataFileEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
329 [MonoLimitation ("Absolute path to the file system is not supported; use a relative URI instead.")]
330 public virtual string DataFile {
331 get { return _dataFile; }
333 if (_dataFile != value) {
335 _documentNeedsUpdate = true;
336 OnDataSourceChanged(EventArgs.Empty);
341 XsltArgumentList transformArgumentList;
343 [BrowsableAttribute (false)]
344 public virtual XsltArgumentList TransformArgumentList {
345 get { return transformArgumentList; }
346 set { transformArgumentList = value; }
349 [PersistenceModeAttribute (PersistenceMode.InnerProperty)]
350 [EditorAttribute ("System.ComponentModel.Design.MultilineStringEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
351 [DefaultValueAttribute ("")]
352 [TypeConverterAttribute (typeof(MultilineStringConverter))]
353 public virtual string Transform {
354 get { return _transform; }
356 if (_transform != value) {
358 _documentNeedsUpdate = true;
359 OnDataSourceChanged(EventArgs.Empty);
364 [EditorAttribute ("System.Web.UI.Design.XslTransformFileEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
365 [DefaultValueAttribute ("")]
366 [MonoLimitation ("Absolute path to the file system is not supported; use a relative URI instead.")]
367 public virtual string TransformFile {
368 get { return _transformFile; }
370 if (_transformFile != value) {
371 _transformFile = value;
372 _documentNeedsUpdate = true;
373 OnDataSourceChanged(EventArgs.Empty);
378 [DefaultValueAttribute ("")]
379 public virtual string XPath {
380 get { return _xpath; }
382 if (_xpath != value) {
384 OnDataSourceChanged(EventArgs.Empty);
389 public virtual string CacheKeyContext {
390 get { return ViewState.GetString ("CacheKeyContext", String.Empty); }
391 set { ViewState ["CacheKeyContext"] = value; }