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 using System.Collections; 34 using System.Collections.Specialized; 35 using System.Drawing; 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 [ToolboxBitmap ("")] 58 public class XmlDataSource : HierarchicalDataSourceControl, IDataSource, IListSource { 59 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; 69 70 DataSourceCacheExpiry _cacheExpirationPolicy = DataSourceCacheExpiry.Absolute; 71 static readonly string [] emptyNames = new string [] { "DefaultView" }; 72 73 event EventHandler IDataSource.DataSourceChanged { 74 add { ((IHierarchicalDataSource)this).DataSourceChanged += value; } 75 remove { ((IHierarchicalDataSource)this).DataSourceChanged -= value; } 76 } 77 78 static object EventTransforming = new object (); 79 public event EventHandler Transforming { 80 add { Events.AddHandler (EventTransforming, value); } 81 remove { Events.RemoveHandler (EventTransforming, value); } 82 } 83 OnTransforming(EventArgs e)84 protected virtual void OnTransforming (EventArgs e) 85 { 86 EventHandler eh = Events [EventTransforming] as EventHandler; 87 if (eh != null) 88 eh (this, e); 89 } 90 91 XmlDocument xmlDocument; GetXmlDocument()92 public XmlDocument GetXmlDocument () 93 { 94 if (_documentNeedsUpdate) 95 UpdateXml (); 96 97 if (xmlDocument == null && EnableCaching) 98 xmlDocument = GetXmlDocumentFromCache (); 99 100 if (xmlDocument == null) { 101 xmlDocument = LoadXmlDocument (); 102 UpdateCache (); 103 } 104 105 return xmlDocument; 106 } 107 108 [MonoTODO ("schema")] LoadXmlDocument()109 XmlDocument LoadXmlDocument () 110 { 111 XmlDocument document = LoadFileOrData (DataFile, Data); 112 if (String.IsNullOrEmpty (TransformFile) && String.IsNullOrEmpty (Transform)) 113 return document; 114 115 XslTransform xslTransform = new XslTransform (); 116 XmlDocument xsl = LoadFileOrData (TransformFile, Transform); 117 xslTransform.Load (xsl); 118 119 OnTransforming (EventArgs.Empty); 120 121 XmlDocument transofrResult = new XmlDocument (); 122 transofrResult.Load (xslTransform.Transform (document, TransformArgumentList)); 123 124 return transofrResult; 125 } 126 LoadFileOrData(string filename, string data)127 XmlDocument LoadFileOrData (string filename, string data) 128 { 129 XmlDocument document = new XmlDocument (); 130 if (!String.IsNullOrEmpty (filename)) { 131 Uri uri; 132 if (Uri.TryCreate (filename, UriKind.Absolute, out uri)) 133 document.Load (filename); 134 else 135 document.Load (MapPathSecure (filename)); 136 } else 137 if (!String.IsNullOrEmpty (data)) 138 document.LoadXml (data); 139 return document; 140 } 141 GetXmlDocumentFromCache()142 XmlDocument GetXmlDocumentFromCache () 143 { 144 if (DataCache != null) 145 return (XmlDocument) DataCache [GetDataKey ()]; 146 147 return null; 148 } 149 GetDataKey()150 string GetDataKey () 151 { 152 if (String.IsNullOrEmpty (DataFile) && !String.IsNullOrEmpty (Data)) { 153 string key = CacheKeyContext; 154 if (!String.IsNullOrEmpty (key)) 155 return key; 156 } 157 Page page = Page; 158 string p = page != null ? page.ToString () : "NullPage"; 159 160 return TemplateSourceDirectory + "_" + p + "_" + ID; 161 } 162 163 Cache DataCache 164 { 165 get 166 { 167 if (HttpContext.Current != null) 168 return HttpContext.Current.InternalCache; 169 170 return null; 171 } 172 } 173 UpdateCache()174 void UpdateCache () 175 { 176 if (!EnableCaching) 177 return; 178 179 if (DataCache == null) 180 return; 181 182 string dataKey = GetDataKey (); 183 if (DataCache [dataKey] != null) 184 DataCache.Remove (dataKey); 185 186 DateTime absoluteExpiration = Cache.NoAbsoluteExpiration; 187 TimeSpan slidindExpiraion = Cache.NoSlidingExpiration; 188 189 if (CacheDuration > 0) { 190 if (CacheExpirationPolicy == DataSourceCacheExpiry.Absolute) 191 absoluteExpiration = DateTime.Now.AddSeconds (CacheDuration); 192 else 193 slidindExpiraion = new TimeSpan (CacheDuration * 10000L); 194 } 195 196 CacheDependency dependency = null; 197 if (CacheKeyDependency.Length > 0) 198 dependency = new CacheDependency (new string [] { }, new string [] { CacheKeyDependency }); 199 else 200 dependency = new CacheDependency (new string [] { }, new string [] { }); 201 202 DataCache.Add (dataKey, xmlDocument, dependency, 203 absoluteExpiration, slidindExpiraion, CacheItemPriority.Default, null); 204 } 205 206 // If datafile changed, then DO NOT USE the cached data, but update it. UpdateXml()207 void UpdateXml() 208 { 209 xmlDocument = LoadXmlDocument (); 210 UpdateCache (); 211 _documentNeedsUpdate = false; 212 } 213 Save()214 public void Save () 215 { 216 if (!CanBeSaved) 217 throw new InvalidOperationException (); 218 219 if (xmlDocument != null) 220 xmlDocument.Save (MapPathSecure (DataFile)); 221 } 222 223 bool CanBeSaved { 224 get { 225 return Transform == String.Empty && TransformFile == String.Empty && DataFile != String.Empty; 226 } 227 } 228 GetHierarchicalView(string viewPath)229 protected override HierarchicalDataSourceView GetHierarchicalView (string viewPath) 230 { 231 XmlNode doc = this.GetXmlDocument (); 232 XmlNodeList ret = null; 233 234 if (!String.IsNullOrEmpty (viewPath)) { 235 XmlNode n = doc.SelectSingleNode (viewPath); 236 if (n != null) 237 ret = n.ChildNodes; 238 } else if (!String.IsNullOrEmpty (XPath)) { 239 ret = doc.SelectNodes (XPath); 240 } else { 241 ret = doc.ChildNodes; 242 } 243 244 return new XmlHierarchicalDataSourceView (ret); 245 } 246 IListSource.GetList()247 IList IListSource.GetList () 248 { 249 return ListSourceHelper.GetList (this); 250 } 251 252 bool IListSource.ContainsListCollection { 253 get { return ListSourceHelper.ContainsListCollection (this); } 254 } 255 IDataSource.GetView(string viewName)256 DataSourceView IDataSource.GetView (string viewName) 257 { 258 if (String.IsNullOrEmpty (viewName)) 259 viewName = "DefaultView"; 260 261 return new XmlDataSourceView (this, viewName); 262 } 263 IDataSource.GetViewNames()264 ICollection IDataSource.GetViewNames () 265 { 266 return emptyNames; 267 } 268 269 [DefaultValue (0)] 270 [TypeConverter (typeof(DataSourceCacheDurationConverter))] 271 public virtual int CacheDuration { 272 get { 273 return _cacheDuration; 274 } 275 set { 276 _cacheDuration = value; 277 } 278 } 279 280 [DefaultValue (DataSourceCacheExpiry.Absolute)] 281 public virtual DataSourceCacheExpiry CacheExpirationPolicy { 282 get { 283 return _cacheExpirationPolicy; 284 } 285 set { 286 _cacheExpirationPolicy = value; 287 } 288 } 289 290 [DefaultValue ("")] 291 public virtual string CacheKeyDependency { 292 get { 293 return _cacheKeyDependency; 294 } 295 set { 296 _cacheKeyDependency = value; 297 } 298 } 299 300 [DefaultValue (true)] 301 public virtual bool EnableCaching { 302 get { 303 return _enableCaching; 304 } 305 set { 306 _enableCaching = value; 307 } 308 } 309 310 [DefaultValue ("")] 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; } 318 set { 319 if (_data != value) { 320 _data = value; 321 _documentNeedsUpdate = true; 322 OnDataSourceChanged(EventArgs.Empty); 323 } 324 } 325 } 326 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; } 332 set { 333 if (_dataFile != value) { 334 _dataFile = value; 335 _documentNeedsUpdate = true; 336 OnDataSourceChanged(EventArgs.Empty); 337 } 338 } 339 } 340 341 XsltArgumentList transformArgumentList; 342 343 [BrowsableAttribute (false)] 344 public virtual XsltArgumentList TransformArgumentList { 345 get { return transformArgumentList; } 346 set { transformArgumentList = value; } 347 } 348 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; } 355 set { 356 if (_transform != value) { 357 _transform = value; 358 _documentNeedsUpdate = true; 359 OnDataSourceChanged(EventArgs.Empty); 360 } 361 } 362 } 363 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; } 369 set { 370 if (_transformFile != value) { 371 _transformFile = value; 372 _documentNeedsUpdate = true; 373 OnDataSourceChanged(EventArgs.Empty); 374 } 375 } 376 } 377 378 [DefaultValueAttribute ("")] 379 public virtual string XPath { 380 get { return _xpath; } 381 set { 382 if (_xpath != value) { 383 _xpath = value; 384 OnDataSourceChanged(EventArgs.Empty); 385 } 386 } 387 } 388 [DefaultValue ("")] 389 public virtual string CacheKeyContext { 390 get { return ViewState.GetString ("CacheKeyContext", String.Empty); } 391 set { ViewState ["CacheKeyContext"] = value; } 392 } 393 } 394 } 395 396